34 # include <malloc.h> |
34 # include <malloc.h> |
35 # endif |
35 # endif |
36 #endif |
36 #endif |
37 |
37 |
38 extern char *__stx_malloc(size_t); |
38 extern char *__stx_malloc(size_t); |
39 extern char *__stx_calloc(size_t, size_t); |
39 extern char *__stx_calloc(size_t, size_t); |
40 extern char *__stx_realloc(char *, size_t); |
40 extern char *__stx_realloc(char *, size_t); |
41 extern void __stx_free(char *); |
41 extern void __stx_free(char *); |
42 extern void __stx_mallocStatistics(void); |
42 extern void __stx_mallocStatistics(void); |
43 %} |
43 %} |
44 ! ! |
44 ! ! |
45 |
45 |
46 !ExternalBytes primitiveFunctions! |
46 !ExternalBytes primitiveFunctions! |
47 %{ |
47 %{ |
48 |
48 |
49 struct mallocList { |
49 struct mallocList { |
50 char *chunk; |
50 char *chunk; |
51 size_t size; |
51 size_t size; |
52 struct mallocList *next; |
52 struct mallocList *next; |
53 }; |
53 }; |
54 static struct mallocList *mallocList = (struct mallocList *)0; |
54 static struct mallocList *mallocList = (struct mallocList *)0; |
55 static INT mallocCount = 0; |
55 static INT mallocCount = 0; |
56 |
56 |
57 static void |
57 static void |
93 int found; |
93 int found; |
94 |
94 |
95 if (@global(DebugMalloc) != true) return; |
95 if (@global(DebugMalloc) != true) return; |
96 |
96 |
97 if (ptr) { |
97 if (ptr) { |
98 found = 0; |
98 found = 0; |
99 for (this=mallocList; this; this=this->next) { |
99 for (this=mallocList; this; this=this->next) { |
100 if (this->chunk == ptr) { |
100 if (this->chunk == ptr) { |
101 console_printf("ExternalBytes [warning]: **** %016"_lx_" already allocated (freed somewhere else ?)\n", (INT)ptr); |
101 console_printf("ExternalBytes [warning]: **** %016"_lx_" already allocated (freed somewhere else ?)\n", (INT)ptr); |
102 found++; |
102 found++; |
103 } |
103 } |
104 } |
104 } |
105 if (! found) { |
105 if (! found) { |
106 e = (struct mallocList *) malloc(sizeof(struct mallocList)); |
106 e = (struct mallocList *) malloc(sizeof(struct mallocList)); |
107 e->next = mallocList; |
107 e->next = mallocList; |
108 e->chunk = ptr; |
108 e->chunk = ptr; |
109 e->size = nBytes; |
109 e->size = nBytes; |
110 mallocList = e; |
110 mallocList = e; |
111 mallocCount++; |
111 mallocCount++; |
112 } |
112 } |
113 } |
113 } |
114 } |
114 } |
115 |
115 |
116 char * |
116 char * |
117 __stx_malloc(size_t nBytes) { |
117 __stx_malloc(size_t nBytes) { |
118 char *ptr = malloc(nBytes); |
118 char *ptr = malloc(nBytes); |
119 |
119 |
120 if (@global(TraceMalloc) == true) { |
120 if (@global(TraceMalloc) == true) { |
121 console_printf("ExternalBytes [info]: allocated %d bytes at: %016"_lx_"\n", nBytes, (INT)ptr); |
121 console_printf("ExternalBytes [info]: allocated %d bytes at: %016"_lx_"\n", nBytes, (INT)ptr); |
122 } |
122 } |
123 addToMallocList(ptr, nBytes); |
123 addToMallocList(ptr, nBytes); |
124 |
124 |
125 return ptr; |
125 return ptr; |
126 } |
126 } |
127 |
127 |
128 char * |
128 char * |
129 __stx_calloc(size_t n, size_t size) { |
129 __stx_calloc(size_t n, size_t size) { |
130 char *ptr = __stx_malloc(n * size); |
130 char *ptr = __stx_malloc(n * size); |
131 if (ptr != 0) { |
131 if (ptr != 0) { |
132 bzero(ptr, (n * size)); |
132 bzero(ptr, (n * size)); |
133 } |
133 } |
134 return ptr; |
134 return ptr; |
135 } |
135 } |
136 |
136 |
137 char * |
137 char * |
138 __stx_realloc(char *ptr, size_t nBytes) |
138 __stx_realloc(char *ptr, size_t nBytes) |
139 { |
139 { |
140 char *newPtr; |
140 char *newPtr; |
141 |
141 |
142 removeFromMallocList(ptr); |
142 removeFromMallocList(ptr); |
143 newPtr = realloc(ptr, nBytes); |
143 newPtr = realloc(ptr, nBytes); |
144 addToMallocList(newPtr, nBytes); |
144 addToMallocList(newPtr, nBytes); |
145 |
145 |
146 if (@global(TraceMalloc) == true) { |
146 if (@global(TraceMalloc) == true) { |
147 console_printf("ExternalBytes [info]: realloc %d bytes for %"_lx_" at: %"_lx_"\n", nBytes, (INT)ptr, (INT)newPtr); |
147 console_printf("ExternalBytes [info]: realloc %d bytes for %"_lx_" at: %"_lx_"\n", nBytes, (INT)ptr, (INT)newPtr); |
148 } |
148 } |
149 return newPtr; |
149 return newPtr; |
150 } |
150 } |
151 |
151 |
152 void |
152 void |
153 __stx_free(char *ptr) |
153 __stx_free(char *ptr) |
154 { |
154 { |
155 if (@global(TraceMalloc) == true) { |
155 if (@global(TraceMalloc) == true) { |
156 console_printf("ExternalBytes: free bytes at: %"_lx_"\n", (INT)ptr); |
156 console_printf("ExternalBytes: free bytes at: %"_lx_"\n", (INT)ptr); |
157 } |
157 } |
158 removeFromMallocList(ptr); |
158 removeFromMallocList(ptr); |
159 |
159 |
160 free(ptr); |
160 free(ptr); |
161 } |
161 } |
162 |
162 |
163 void |
163 void |
164 __stx_mallocStatistics() { |
164 __stx_mallocStatistics() { |
165 struct mallocList *this; |
165 struct mallocList *this; |
166 int amount = 0; |
166 int amount = 0; |
167 int n = 0; |
167 int n = 0; |
168 |
168 |
169 for (this=mallocList; this; this=this->next) { |
169 for (this=mallocList; this; this=this->next) { |
170 n++; |
170 n++; |
171 amount += this->size; |
171 amount += this->size; |
172 } |
172 } |
173 console_printf("ExternalBytes [info]: allocated %d blocks with %d bytes overall\n", n, amount); |
173 console_printf("ExternalBytes [info]: allocated %d blocks with %d bytes overall\n", n, amount); |
174 } |
174 } |
175 |
175 |
176 %} |
176 %} |
177 ! ! |
177 ! ! |
178 |
178 |
391 |
391 |
392 !ExternalBytes class methodsFor:'instance creation'! |
392 !ExternalBytes class methodsFor:'instance creation'! |
393 |
393 |
394 address:anAddressInteger |
394 address:anAddressInteger |
395 "return a new ExternalBytes object to access bytes starting at anAddressInteger. |
395 "return a new ExternalBytes object to access bytes starting at anAddressInteger. |
396 The memory at anAddressInteger has been allocated elsewhere. |
396 The memory at anAddressInteger has been allocated elsewhere. |
397 The size is not known, therefore byte accesses will NOT be checked for valid index. |
397 The size is not known, therefore byte accesses will NOT be checked for valid index. |
398 Use this, if you get a pointer from some external source (such as a |
398 Use this, if you get a pointer from some external source (such as a |
399 C-callBack function) and you have to extract bytes from that. |
399 C-callBack function) and you have to extract bytes from that. |
400 |
400 |
401 DANGER ALERT: this method allows very bad things to be done to the |
401 DANGER ALERT: this method allows very bad things to be done to the |
402 system - use with GREAT care (better: do not use it)" |
402 system - use with GREAT care (better: do not use it)" |
403 |
403 |
404 ^ self basicNew setAddress:anAddressInteger size:nil |
404 ^ self basicNew setAddress:anAddressInteger size:nil |
405 |
405 |
406 "Modified (comment): / 31-03-2016 / 11:05:07 / cg" |
406 "Modified (comment): / 31-03-2016 / 11:05:07 / cg" |
407 ! |
407 ! |
408 |
408 |
409 address:anAddressInteger size:size |
409 address:anAddressInteger size:size |
410 "return a new ExternalBytes object to access bytes starting at anAddressInteger. |
410 "return a new ExternalBytes object to access bytes starting at anAddressInteger. |
411 The memory at anAddressInteger has been allocated elsewhere. |
411 The memory at anAddressInteger has been allocated elsewhere. |
412 The size is known, which allows byte accesses to be checked for valid index. |
412 The size is known, which allows byte accesses to be checked for valid index. |
413 Use this, if you get a pointer to a structure from some external source |
413 Use this, if you get a pointer to a structure from some external source |
414 (such as a C-callBack function) and you have to extract things from that. |
414 (such as a C-callBack function) and you have to extract things from that. |
415 |
415 |
416 DANGER ALERT: this method allows very bad things to be done to the |
416 DANGER ALERT: this method allows very bad things to be done to the |
417 system - use with GREAT care (better: do not use it)" |
417 system - use with GREAT care (better: do not use it)" |
418 |
418 |
419 ^ self basicNew setAddress:anAddressInteger size:size |
419 ^ self basicNew setAddress:anAddressInteger size:size |
420 |
420 |
421 "Modified (comment): / 31-03-2016 / 11:04:27 / cg" |
421 "Modified (comment): / 31-03-2016 / 11:04:27 / cg" |
422 ! |
422 ! |
1208 |addr| |
1208 |addr| |
1209 |
1209 |
1210 "/ what a kludge - Dolphin and Squeak mean: printOn: a stream; |
1210 "/ what a kludge - Dolphin and Squeak mean: printOn: a stream; |
1211 "/ ST/X (and some old ST80's) mean: draw-yourself on a GC. |
1211 "/ ST/X (and some old ST80's) mean: draw-yourself on a GC. |
1212 (aGCOrStream isStream) ifFalse:[ |
1212 (aGCOrStream isStream) ifFalse:[ |
1213 ^ super displayOn:aGCOrStream |
1213 ^ super displayOn:aGCOrStream |
1214 ]. |
1214 ]. |
1215 |
1215 |
1216 aGCOrStream nextPutAll:self className. |
1216 aGCOrStream nextPutAll:self className. |
1217 addr := self address. |
1217 addr := self address. |
1218 addr isNil ifTrue:[ |
1218 addr isNil ifTrue:[ |
1219 aGCOrStream nextPutAll:'[free]'. |
1219 aGCOrStream nextPutAll:'[free]'. |
1220 ] ifFalse:[ |
1220 ] ifFalse:[ |
1221 size notNil ifTrue:[ |
1221 size notNil ifTrue:[ |
1222 aGCOrStream nextPutAll:'[sz:'. |
1222 aGCOrStream nextPutAll:'[sz:'. |
1223 size printOn:aGCOrStream. |
1223 size printOn:aGCOrStream. |
1224 aGCOrStream space. |
1224 aGCOrStream space. |
1225 ] ifFalse:[ |
1225 ] ifFalse:[ |
1226 aGCOrStream nextPut:$[. |
1226 aGCOrStream nextPut:$[. |
1227 ]. |
1227 ]. |
1228 aGCOrStream nextPutAll:'@'. |
1228 aGCOrStream nextPutAll:'@'. |
1229 addr printOn:aGCOrStream base:16. |
1229 addr printOn:aGCOrStream base:16. |
1230 aGCOrStream nextPut:$]. |
1230 aGCOrStream nextPut:$]. |
1231 ]. |
1231 ]. |
1232 |
1232 |
1233 " |
1233 " |
1234 self new printString |
1234 self new printString |
1235 (self new:5) displayString |
1235 (self new:5) displayString |
1236 " |
1236 " |
1237 |
1237 |
1238 |
1238 |
1239 "Modified: / 24.2.2000 / 19:02:19 / cg" |
1239 "Modified: / 24.2.2000 / 19:02:19 / cg" |
1240 ! ! |
1240 ! ! |
1299 %{ |
1299 %{ |
1300 /* |
1300 /* |
1301 * Fail if already allocated |
1301 * Fail if already allocated |
1302 */ |
1302 */ |
1303 if (__INST(address_) == nil && __isSmallInteger(numberOfBytes)) { |
1303 if (__INST(address_) == nil && __isSmallInteger(numberOfBytes)) { |
1304 INT nBytes = __smallIntegerVal(numberOfBytes); |
1304 INT nBytes = __smallIntegerVal(numberOfBytes); |
1305 if (nBytes > 0) { |
1305 if (nBytes > 0) { |
1306 char *space = __stx_malloc(nBytes); |
1306 char *space = __stx_malloc(nBytes); |
1307 if (space) { |
1307 if (space) { |
1308 if (doClear == true) { |
1308 if (doClear == true) { |
1309 bzero(space, nBytes); |
1309 bzero(space, nBytes); |
1310 } |
1310 } |
1311 __INST(address_) = (OBJ)space; |
1311 __INST(address_) = (OBJ)space; |
1312 __INST(size) = numberOfBytes; |
1312 __INST(size) = numberOfBytes; |
1313 RETURN(self); |
1313 RETURN(self); |
1314 } else { |
1314 } else { |
1315 mallocFailure = true; |
1315 mallocFailure = true; |
1316 } |
1316 } |
1317 } |
1317 } |
1318 } |
1318 } |
1319 %}. |
1319 %}. |
1320 mallocFailure == true ifTrue:[ |
1320 mallocFailure == true ifTrue:[ |
1321 ^ MallocFailure raiseRequestWith:numberOfBytes. |
1321 ^ MallocFailure raiseRequestWith:numberOfBytes. |
1322 ] ifFalse:[ |
1322 ] ifFalse:[ |
1323 self primitiveFailed. |
1323 self primitiveFailed. |
1324 ]. |
1324 ]. |
1325 ! ! |
1325 ! ! |
1326 |
1326 |
1327 !ExternalBytes methodsFor:'queries'! |
1327 !ExternalBytes methodsFor:'queries'! |
1328 |
1328 |
1443 |
1443 |
1444 size == numberOfBytes ifTrue:[^ self]. |
1444 size == numberOfBytes ifTrue:[^ self]. |
1445 |
1445 |
1446 %{ |
1446 %{ |
1447 if (__isSmallInteger(numberOfBytes)) { |
1447 if (__isSmallInteger(numberOfBytes)) { |
1448 INT nBytes = __smallIntegerVal(numberOfBytes); |
1448 INT nBytes = __smallIntegerVal(numberOfBytes); |
1449 if (nBytes > 0) { |
1449 if (nBytes > 0) { |
1450 char *space; |
1450 char *space; |
1451 char *prevSpace = (char *)__INST(address_); |
1451 char *prevSpace = (char *)__INST(address_); |
1452 |
1452 |
1453 if (prevSpace == (char *)nil) |
1453 if (prevSpace == (char *)nil) |
1454 prevSpace = 0; /* allocate from scratch */ |
1454 prevSpace = 0; /* allocate from scratch */ |
1455 space = __stx_realloc(prevSpace, nBytes); |
1455 space = __stx_realloc(prevSpace, nBytes); |
1456 if (space) { |
1456 if (space) { |
1457 __INST(address_) = (OBJ)space; |
1457 __INST(address_) = (OBJ)space; |
1458 __INST(size) = numberOfBytes; |
1458 __INST(size) = numberOfBytes; |
1459 if (space == prevSpace) { |
1459 if (space == prevSpace) { |
1460 /* same address, no re-registration */ |
1460 /* same address, no re-registration */ |
1461 RETURN(self); |
1461 RETURN(self); |
1462 } |
1462 } |
1463 mallocStatus = true; |
1463 mallocStatus = true; |
1464 } else { |
1464 } else { |
1465 mallocStatus = false; |
1465 mallocStatus = false; |
1466 } |
1466 } |
1467 } |
1467 } |
1468 } |
1468 } |
1469 %}. |
1469 %}. |
1470 mallocStatus == true ifTrue:[ |
1470 mallocStatus == true ifTrue:[ |
1471 Lobby registerChange:self. |
1471 Lobby registerChange:self. |
1472 ] ifFalse:[mallocStatus == false ifTrue:[ |
1472 ] ifFalse:[mallocStatus == false ifTrue:[ |
1473 ^ MallocFailure raiseRequestWith:numberOfBytes. |
1473 ^ MallocFailure raiseRequestWith:numberOfBytes. |
1474 ] ifFalse:[ |
1474 ] ifFalse:[ |
1475 self primitiveFailed. |
1475 self primitiveFailed. |
1476 ]]. |
1476 ]]. |
1477 ! ! |
1477 ! ! |
1478 |
1478 |
1479 !ExternalBytes methodsFor:'testing'! |
1479 !ExternalBytes methodsFor:'testing'! |
1480 |
1480 |