114 char * |
114 char * |
115 __stx_malloc(size_t nBytes) { |
115 __stx_malloc(size_t nBytes) { |
116 char *ptr = malloc(nBytes); |
116 char *ptr = malloc(nBytes); |
117 |
117 |
118 if (@global(TraceMalloc) == true) { |
118 if (@global(TraceMalloc) == true) { |
119 console_printf("ExternalBytes [info]: allocated %d bytes at: %016"_lx_"\n", nBytes, (INT)ptr); |
119 console_printf("ExternalBytes [info]: allocated %ld bytes at: %p\n", (long)nBytes, ptr); |
120 } |
120 } |
121 addToMallocList(ptr, nBytes); |
121 addToMallocList(ptr, nBytes); |
122 |
122 |
123 return ptr; |
123 return ptr; |
124 } |
124 } |
140 removeFromMallocList(ptr); |
140 removeFromMallocList(ptr); |
141 newPtr = realloc(ptr, nBytes); |
141 newPtr = realloc(ptr, nBytes); |
142 addToMallocList(newPtr, nBytes); |
142 addToMallocList(newPtr, nBytes); |
143 |
143 |
144 if (@global(TraceMalloc) == true) { |
144 if (@global(TraceMalloc) == true) { |
145 console_printf("ExternalBytes [info]: realloc %d bytes for %"_lx_" at: %"_lx_"\n", nBytes, (INT)ptr, (INT)newPtr); |
145 console_printf("ExternalBytes [info]: realloc %ld bytes for %p at: %p\n", (long)nBytes, ptr, newPtr); |
146 } |
146 } |
147 return newPtr; |
147 return newPtr; |
148 } |
148 } |
149 |
149 |
150 void |
150 void |
408 "return a new ExternalBytes object to access bytes starting at anAddressInteger. |
408 "return a new ExternalBytes object to access bytes starting at anAddressInteger. |
409 The memory at anAddressInteger has been allocated elsewhere. |
409 The memory at anAddressInteger has been allocated elsewhere. |
410 The size is known, which allows byte accesses to be checked for valid index. |
410 The size is known, which allows byte accesses to be checked for valid index. |
411 Use this, if you get a pointer to a structure from some external source |
411 Use this, if you get a pointer to a structure from some external source |
412 (such as a C-callBack function) and you have to extract things from that. |
412 (such as a C-callBack function) and you have to extract things from that. |
413 The pointer is protected from GC |
413 The pointer is protected from GC |
414 (i.e. I will not free the heap memory, |
414 (i.e. I will not free the heap memory, |
415 once the returned reference is no longer in use). |
415 once the returned reference is no longer in use). |
416 Be careful to avoid memory leaks, when getting malloc'd memory from an external function. |
416 Be careful to avoid memory leaks, when getting malloc'd memory from an external function. |
417 |
417 |
418 DANGER ALERT: this method allows very bad things to be done to the |
418 DANGER ALERT: this method allows very bad things to be done to the |
419 system - use with GREAT care (better: do not use it)" |
419 system - use with GREAT care (better: do not use it)" |
420 |
420 |
421 ^ self basicNew setAddress:anAddressInteger size:size |
421 ^ self basicNew setAddress:anAddressInteger size:size |
422 |
422 |
423 "Modified (comment): / 31-03-2016 / 11:04:27 / cg" |
423 "Modified (comment): / 31-03-2016 / 11:04:27 / cg" |
424 ! |
424 ! |
434 which expect strings simply keep a ref to the passed string - for those, |
434 which expect strings simply keep a ref to the passed string - for those, |
435 an ST/X string-pointer is not the right thing to pass, since ST/X objects |
435 an ST/X string-pointer is not the right thing to pass, since ST/X objects |
436 may change their address. |
436 may change their address. |
437 |
437 |
438 DANGER ALERT: the memory is NOT automatically freed until it is either |
438 DANGER ALERT: the memory is NOT automatically freed until it is either |
439 MANUALLY freed (see #free) or the returned externalBytes object |
439 MANUALLY freed (see #free) or the returned externalBytes object |
440 is unprotected or the classes releaseAllMemory method is called." |
440 is unprotected or the classes releaseAllMemory method is called." |
441 |
441 |
442 "/ ^ self protectedNew:numberOfBytes. |
442 "/ ^ self protectedNew:numberOfBytes. |
443 ^ self unprotectedNew:numberOfBytes. |
443 ^ self unprotectedNew:numberOfBytes. |
444 |
444 |
445 " |
445 " |
497 which expect strings simply keep a ref to the passed string - for those, |
497 which expect strings simply keep a ref to the passed string - for those, |
498 an ST/X string-pointer is not the right thing to pass, since ST/X objects |
498 an ST/X string-pointer is not the right thing to pass, since ST/X objects |
499 may change their address. |
499 may change their address. |
500 |
500 |
501 DANGER ALERT: the memory is NOT automatically freed until it is either |
501 DANGER ALERT: the memory is NOT automatically freed until it is either |
502 MANUALLY freed (see #free) or the returned externalBytes object |
502 MANUALLY freed (see #free) or the returned externalBytes object |
503 is unprotected or the classes releaseAllMemory method is called." |
503 is unprotected or the classes releaseAllMemory method is called." |
504 |
504 |
505 |newInst| |
505 |newInst| |
506 |
506 |
507 newInst := self unprotectedNew:numberOfBytes. |
507 newInst := self unprotectedNew:numberOfBytes. |
508 newInst protectFromGC. |
508 newInst protectFromGC. |
562 dumpMallocChunks |
562 dumpMallocChunks |
563 %{ /* NOCONTEXT */ |
563 %{ /* NOCONTEXT */ |
564 struct mallocList *entry; |
564 struct mallocList *entry; |
565 |
565 |
566 for (entry = mallocList; entry; entry=entry->next) { |
566 for (entry = mallocList; entry; entry=entry->next) { |
567 console_printf(" %"_lx_" (%d)\n", (INT)(entry->chunk), entry->size); |
567 console_printf(" %p (%ld)\n", (entry->chunk), (long)(entry->size)); |
568 } |
568 } |
569 %} |
569 %} |
570 " |
570 " |
571 self dumpMallocChunks |
571 self dumpMallocChunks |
572 " |
572 " |
588 %{ |
588 %{ |
589 struct mallocList *entry; |
589 struct mallocList *entry; |
590 |
590 |
591 while ((entry = mallocList) != (struct mallocList *)0) { |
591 while ((entry = mallocList) != (struct mallocList *)0) { |
592 if (@global(TraceMalloc) == true ) { |
592 if (@global(TraceMalloc) == true ) { |
593 console_printf("ExternalBytes [info]: **** forced free of %"_lx_" (%d)\n", (INT)entry->chunk, entry->size); |
593 console_printf("ExternalBytes [info]: **** forced free of %p (%ld)\n", entry->chunk, (long)(entry->size)); |
594 } |
594 } |
595 __stx_free(entry->chunk); |
595 __stx_free(entry->chunk); |
596 } |
596 } |
597 %} |
597 %} |
598 ! |
598 ! |
805 ! |
805 ! |
806 |
806 |
807 sizeofPointer |
807 sizeofPointer |
808 "return the number of bytes used by the machine's native pointer. |
808 "return the number of bytes used by the machine's native pointer. |
809 Notice: this is inlined by the compiler(s) as a constant, |
809 Notice: this is inlined by the compiler(s) as a constant, |
810 therefore, queries like |
810 therefore, queries like |
811 'ExternalAddress pointerSize == 8' |
811 'ExternalAddress pointerSize == 8' |
812 cost nothing; they are compiled in as a constant |
812 cost nothing; they are compiled in as a constant |
813 (and even conditionals are eliminated)." |
813 (and even conditionals are eliminated)." |
814 |
814 |
815 %{ /* NOCONTEXT */ |
815 %{ /* NOCONTEXT */ |
816 RETURN (__mkSmallInteger( sizeof(char *))); |
816 RETURN (__mkSmallInteger( sizeof(char *))); |
817 %} |
817 %} |
1290 |addr| |
1290 |addr| |
1291 |
1291 |
1292 "/ what a kludge - Dolphin and Squeak mean: printOn: a stream; |
1292 "/ what a kludge - Dolphin and Squeak mean: printOn: a stream; |
1293 "/ old ST80 means: draw-yourself on a GC. |
1293 "/ old ST80 means: draw-yourself on a GC. |
1294 (aGCOrStream isStream) ifFalse:[ |
1294 (aGCOrStream isStream) ifFalse:[ |
1295 ^ super displayOn:aGCOrStream |
1295 ^ super displayOn:aGCOrStream |
1296 ]. |
1296 ]. |
1297 |
1297 |
1298 aGCOrStream nextPutAll:self className. |
1298 aGCOrStream nextPutAll:self className. |
1299 addr := self address. |
1299 addr := self address. |
1300 addr isNil ifTrue:[ |
1300 addr isNil ifTrue:[ |
1301 aGCOrStream nextPutAll:'[free]'. |
1301 aGCOrStream nextPutAll:'[free]'. |
1302 ] ifFalse:[ |
1302 ] ifFalse:[ |
1303 size notNil ifTrue:[ |
1303 size notNil ifTrue:[ |
1304 aGCOrStream nextPutAll:'[sz:'. |
1304 aGCOrStream nextPutAll:'[sz:'. |
1305 size printOn:aGCOrStream. |
1305 size printOn:aGCOrStream. |
1306 aGCOrStream space. |
1306 aGCOrStream space. |
1307 ] ifFalse:[ |
1307 ] ifFalse:[ |
1308 aGCOrStream nextPut:$[. |
1308 aGCOrStream nextPut:$[. |
1309 ]. |
1309 ]. |
1310 aGCOrStream nextPutAll:'@'. |
1310 aGCOrStream nextPutAll:'@'. |
1311 addr printOn:aGCOrStream base:16. |
1311 addr printOn:aGCOrStream base:16. |
1312 aGCOrStream nextPut:$]. |
1312 aGCOrStream nextPut:$]. |
1313 ]. |
1313 ]. |
1314 |
1314 |
1315 " |
1315 " |
1316 self new printString |
1316 self new printString |
1317 (self new:5) displayString |
1317 (self new:5) displayString |
1318 " |
1318 " |
1319 |
1319 |
1320 "Modified: / 24-02-2000 / 19:02:19 / cg" |
1320 "Modified: / 24-02-2000 / 19:02:19 / cg" |
1321 "Modified (comment): / 22-02-2017 / 16:54:08 / cg" |
1321 "Modified (comment): / 22-02-2017 / 16:54:08 / cg" |
1322 ! ! |
1322 ! ! |
1335 setAddress:aNumberOrExternalAddress size:sz |
1335 setAddress:aNumberOrExternalAddress size:sz |
1336 "set the start address and size" |
1336 "set the start address and size" |
1337 |
1337 |
1338 %{ /* NOCONTEXT */ |
1338 %{ /* NOCONTEXT */ |
1339 if (__INST(address_) == nil) { |
1339 if (__INST(address_) == nil) { |
1340 if (aNumberOrExternalAddress == nil) { |
1340 if (aNumberOrExternalAddress == nil) { |
1341 __INST(address_) = nil; |
1341 __INST(address_) = nil; |
1342 } else { |
1342 } else { |
1343 if (__isSmallInteger(aNumberOrExternalAddress)) { |
1343 if (__isSmallInteger(aNumberOrExternalAddress)) { |
1344 __INST(address_) = (OBJ) __intVal(aNumberOrExternalAddress); |
1344 __INST(address_) = (OBJ) __intVal(aNumberOrExternalAddress); |
1345 } else if(__isInteger(aNumberOrExternalAddress)) { |
1345 } else if(__isInteger(aNumberOrExternalAddress)) { |
1346 __INST(address_) = (OBJ) __unsignedLongIntVal(aNumberOrExternalAddress); |
1346 __INST(address_) = (OBJ) __unsignedLongIntVal(aNumberOrExternalAddress); |
1347 } else if(__isExternalAddressLike(aNumberOrExternalAddress)) { |
1347 } else if(__isExternalAddressLike(aNumberOrExternalAddress)) { |
1348 __INST(address_) = __externalAddressVal(aNumberOrExternalAddress); |
1348 __INST(address_) = __externalAddressVal(aNumberOrExternalAddress); |
1349 } |
1349 } |
1350 } |
1350 } |
1351 __INST(size) = sz; |
1351 __INST(size) = sz; |
1352 RETURN (self); |
1352 RETURN (self); |
1353 } |
1353 } |
1354 %}. |
1354 %}. |
1355 ^ self error:'cannot change address' |
1355 ^ self error:'cannot change address' |
1356 |
1356 |
1357 "Modified: / 12-02-2017 / 16:22:47 / cg" |
1357 "Modified: / 12-02-2017 / 16:22:47 / cg" |
1483 |
1483 |
1484 forgetMemory |
1484 forgetMemory |
1485 "forget the underlying memory - i.e. it will NOT be freed by me, |
1485 "forget the underlying memory - i.e. it will NOT be freed by me, |
1486 and actually no reference to the underlying memory is kept. |
1486 and actually no reference to the underlying memory is kept. |
1487 Warning: |
1487 Warning: |
1488 Unless freed by someone else (typically a C-program/client), |
1488 Unless freed by someone else (typically a C-program/client), |
1489 this leads to a memory leak. |
1489 this leads to a memory leak. |
1490 Use this only, if memory which was allocated by me |
1490 Use this only, if memory which was allocated by me |
1491 is given to a C-program which frees the memory." |
1491 is given to a C-program which frees the memory." |
1492 |
1492 |
1493 Lobby unregister:self. "/ prevents finalization |
1493 Lobby unregister:self. "/ prevents finalization |
1494 self unprotectFromGC. "/ no longer remembered |
1494 self unprotectFromGC. "/ no longer remembered |
1495 self setAddress:0 size:0. "/ no longer accessible |
1495 self setAddress:0 size:0. "/ no longer accessible |
1496 |
1496 |
1509 "using a Semaphore can cause a deadlock, since unprotectFromGC may be called by |
1509 "using a Semaphore can cause a deadlock, since unprotectFromGC may be called by |
1510 a finalization method" |
1510 a finalization method" |
1511 |
1511 |
1512 wasBlocked := OperatingSystem blockInterrupts. |
1512 wasBlocked := OperatingSystem blockInterrupts. |
1513 "/ AccessLock critical:[ |
1513 "/ AccessLock critical:[ |
1514 AllocatedInstances isNil ifTrue:[ |
1514 AllocatedInstances isNil ifTrue:[ |
1515 AllocatedInstances := IdentitySet new |
1515 AllocatedInstances := IdentitySet new |
1516 ]. |
1516 ]. |
1517 AllocatedInstances add:self. |
1517 AllocatedInstances add:self. |
1518 "/ ] |
1518 "/ ] |
1519 wasBlocked ifFalse:[OperatingSystem unblockInterrupts]. |
1519 wasBlocked ifFalse:[OperatingSystem unblockInterrupts]. |
1520 |
1520 |
1521 "Modified (format): / 26-07-2017 / 11:21:46 / cg" |
1521 "Modified (format): / 26-07-2017 / 11:21:46 / cg" |
1522 ! |
1522 ! |
1533 "using a Semaphore can cause a deadlock, since protectFromGC may be interrupted by me |
1533 "using a Semaphore can cause a deadlock, since protectFromGC may be interrupted by me |
1534 being called by a finalization method" |
1534 being called by a finalization method" |
1535 |
1535 |
1536 wasBlocked := OperatingSystem blockInterrupts. |
1536 wasBlocked := OperatingSystem blockInterrupts. |
1537 "/ AccessLock critical:[ |
1537 "/ AccessLock critical:[ |
1538 AllocatedInstances notNil ifTrue:[ |
1538 AllocatedInstances notNil ifTrue:[ |
1539 AllocatedInstances remove:self ifAbsent:nil. |
1539 AllocatedInstances remove:self ifAbsent:nil. |
1540 ]. |
1540 ]. |
1541 "/ ] |
1541 "/ ] |
1542 wasBlocked ifFalse:[OperatingSystem unblockInterrupts]. |
1542 wasBlocked ifFalse:[OperatingSystem unblockInterrupts]. |
1543 |
1543 |
1544 "Modified (format): / 26-07-2017 / 11:21:59 / cg" |
1544 "Modified (format): / 26-07-2017 / 11:21:59 / cg" |
1545 ! ! |
1545 ! ! |