ExternalBytes.st
changeset 24043 b37704e992e1
parent 23932 01800d8961bd
child 24056 a7b360193da5
equal deleted inserted replaced
24042:2c4768bb2e89 24043:b37704e992e1
   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 !
   691 pointerAlignment
   691 pointerAlignment
   692     "return the alignement of pointers in structs and unions"
   692     "return the alignement of pointers in structs and unions"
   693 
   693 
   694 %{  /* NOCONTEXT */
   694 %{  /* NOCONTEXT */
   695     struct {
   695     struct {
   696         char c;
   696 	char c;
   697         void* p;
   697 	void* p;
   698     } dummy;
   698     } dummy;
   699     RETURN (__mkSmallInteger( (char *)&dummy.p - (char *)&dummy.c ));
   699     RETURN (__mkSmallInteger( (char *)&dummy.p - (char *)&dummy.c ));
   700 %}
   700 %}
   701     "
   701     "
   702      ExternalBytes pointerAlignment
   702      ExternalBytes pointerAlignment
   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 %}
   935     |idx byte s|
   935     |idx byte s|
   936 
   936 
   937     idx := 1.
   937     idx := 1.
   938     s := WriteStream on:''.
   938     s := WriteStream on:''.
   939     [(byte := self at:idx) ~~ 0] whileTrue:[
   939     [(byte := self at:idx) ~~ 0] whileTrue:[
   940         s nextPut:(Character value:byte).
   940 	s nextPut:(Character value:byte).
   941         idx := idx + 1.
   941 	idx := idx + 1.
   942     ].
   942     ].
   943     ^ s contents
   943     ^ s contents
   944 !
   944 !
   945 
   945 
   946 copyUnicodeStringFromHeap
   946 copyUnicodeStringFromHeap
   985     "speed up string conversions"
   985     "speed up string conversions"
   986 
   986 
   987     |size|
   987     |size|
   988 
   988 
   989     self class == ExternalBytes ifTrue:[
   989     self class == ExternalBytes ifTrue:[
   990         size := self size.
   990 	size := self size.
   991         ^ (String uninitializedNew:size) replaceBytesFrom:1 to:size with:self startingAt:1.
   991 	^ (String uninitializedNew:size) replaceBytesFrom:1 to:size with:self startingAt:1.
   992     ].
   992     ].
   993     ^ super asString.
   993     ^ super asString.
   994 
   994 
   995     "
   995     "
   996       #[16r41 16r42 16r43] asExternalBytes asString
   996       #[16r41 16r42 16r43] asExternalBytes asString
  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 ! !