ExternalBytes.st
changeset 19860 324edacff5cc
parent 19512 e31128e0b135
child 19863 513bd7237fe7
child 20138 cd6fdc7534e4
equal deleted inserted replaced
19859:000d1c4aa7e6 19860:324edacff5cc
    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
    61     int found = 0;
    61     int found = 0;
    62 
    62 
    63     if (@global(DebugMalloc) != true) return;
    63     if (@global(DebugMalloc) != true) return;
    64 
    64 
    65     if (ptr) {
    65     if (ptr) {
    66         found = 0;
    66 	found = 0;
    67         for (this=mallocList, prev=0; this; this=next) {
    67 	for (this=mallocList, prev=0; this; this=next) {
    68             next = this->next;
    68 	    next = this->next;
    69             if (this->chunk == ptr) {
    69 	    if (this->chunk == ptr) {
    70                 if (prev) {
    70 		if (prev) {
    71                     prev->next = next;
    71 		    prev->next = next;
    72                 } else {
    72 		} else {
    73                     mallocList = next;
    73 		    mallocList = next;
    74                 }
    74 		}
    75                 free(this);
    75 		free(this);
    76                 found++;
    76 		found++;
    77                 mallocCount--;
    77 		mallocCount--;
    78             } else {
    78 	    } else {
    79                 prev = this;
    79 		prev = this;
    80             }
    80 	    }
    81         }
    81 	}
    82         if (! found) {
    82 	if (! found) {
    83             console_printf("ExternalBytes [warning]: **** free: alien %"_lx_" (allocated somewhere else ?))\n", (INT)ptr);
    83 	    console_printf("ExternalBytes [warning]: **** free: alien %"_lx_" (allocated somewhere else ?))\n", (INT)ptr);
    84         }
    84 	}
    85     }
    85     }
    86 }
    86 }
    87 
    87 
    88 static void
    88 static void
    89 addToMallocList(char *ptr, size_t nBytes)
    89 addToMallocList(char *ptr, size_t nBytes)
    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 !
   475     nChars := aString size.
   475     nChars := aString size.
   476     self assert:(aString bitsPerCharacter <= 16).
   476     self assert:(aString bitsPerCharacter <= 16).
   477 
   477 
   478     extBytes := self new:((nChars+1)*2).
   478     extBytes := self new:((nChars+1)*2).
   479     1 to:nChars do:[:i |
   479     1 to:nChars do:[:i |
   480         extBytes unsignedInt16At:(i*2) put:(aString at:i) codePoint.
   480 	extBytes unsignedInt16At:(i*2) put:(aString at:i) codePoint.
   481     ].
   481     ].
   482     extBytes unsignedInt16At:((nChars+1)*2) put:0.
   482     extBytes unsignedInt16At:((nChars+1)*2) put:0.
   483     ^ extBytes
   483     ^ extBytes
   484 
   484 
   485     "Modified (comment): / 31-03-2016 / 11:05:37 / cg"
   485     "Modified (comment): / 31-03-2016 / 11:05:37 / cg"
   686 sizeofLongDouble
   686 sizeofLongDouble
   687     "return the number of bytes used by the machine's native longdouble.
   687     "return the number of bytes used by the machine's native longdouble.
   688      If the machine does not support them, return nil."
   688      If the machine does not support them, return nil."
   689 
   689 
   690 %{  /* NOCONTEXT */
   690 %{  /* NOCONTEXT */
   691 #if defined(__GNUC__) || defined(WIN32)
   691 #if defined(__GNUC__) || defined(__CLANG__) || defined(__win32__)
   692     RETURN (__mkSmallInteger( sizeof(long double)));
   692     RETURN (__mkSmallInteger( sizeof(long double)));
   693 #endif
   693 #endif
   694 %}.
   694 %}.
   695     ^ nil
   695     ^ nil
   696 
   696 
   883     |idx word s|
   883     |idx word s|
   884 
   884 
   885     idx := 1.
   885     idx := 1.
   886     s := WriteStream on:Unicode16String new.
   886     s := WriteStream on:Unicode16String new.
   887     [(word := self unsignedInt16At:idx) ~~ 0] whileTrue:[
   887     [(word := self unsignedInt16At:idx) ~~ 0] whileTrue:[
   888         s nextPut:(Character value:word).
   888 	s nextPut:(Character value:word).
   889         idx := idx + 2.
   889 	idx := idx + 2.
   890     ].
   890     ].
   891     ^ s contents
   891     ^ s contents
   892 !
   892 !
   893 
   893 
   894 instVarAt:index
   894 instVarAt:index
  1100 
  1100 
  1101 replaceNullTerminatedFromString:aString
  1101 replaceNullTerminatedFromString:aString
  1102     "replace elements from aString, and add a 0-byte at the end"
  1102     "replace elements from aString, and add a 0-byte at the end"
  1103 
  1103 
  1104     |nChars|
  1104     |nChars|
  1105     
  1105 
  1106     nChars := aString size.
  1106     nChars := aString size.
  1107     self replaceBytesFrom:1 to:nChars with:aString startingAt:1.
  1107     self replaceBytesFrom:1 to:nChars with:aString startingAt:1.
  1108     self at:nChars+1 put:0.
  1108     self at:nChars+1 put:0.
  1109 ! !
  1109 ! !
  1110 
  1110 
  1143      free the associated heap memory with it"
  1143      free the associated heap memory with it"
  1144 
  1144 
  1145 %{  /* NOCONTEXT */
  1145 %{  /* NOCONTEXT */
  1146     char *mem = (char *)__INST(address_);
  1146     char *mem = (char *)__INST(address_);
  1147     if (mem && (OBJ)mem != nil) {
  1147     if (mem && (OBJ)mem != nil) {
  1148         __stx_free(mem);
  1148 	__stx_free(mem);
  1149     }
  1149     }
  1150     __INST(address_) = __INST(size) = nil;
  1150     __INST(address_) = __INST(size) = nil;
  1151 %}
  1151 %}
  1152 ! !
  1152 ! !
  1153 
  1153 
  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