1 /************************* toolbox/memory.c ************************************
3 Copyright (c) 1997 A. Krall, R. Grafl, M. Gschwind, M. Probst
5 See file COPYRIGHT for information on usage and disclaimer of warranties
7 Not documented, see memory.h.
9 Authors: Reinhard Grafl EMAIL: cacao@complang.tuwien.ac.at
11 Last Change: 1996/10/03
13 *******************************************************************************/
28 /********* general types, variables and auxiliary functions *********/
30 #define DUMPBLOCKSIZE (2<<21)
33 typedef struct dumplist {
34 struct dumplist *prev;
40 long int memoryusage = 0;
42 long int dumpsize = 0;
43 long int dumpspace = 0;
44 dumplist *topdumpblock = NULL;
46 long int maxmemusage = 0;
47 long int maxdumpsize = 0;
49 /* #define TRACECALLARGS */
52 static char nomallocmem[16777216];
53 static char *nomalloctop = nomallocmem + 16777216;
54 static char *nomallocptr = nomallocmem;
56 static void *lit_checked_alloc (int length)
60 nomallocptr = (void*) ALIGN ((long) nomallocptr, ALIGNSIZE);
63 nomallocptr += length;
64 if (nomallocptr > nomalloctop) panic ("Out of memory");
70 static void *lit_checked_alloc (int length)
72 void *m = malloc(length);
73 if (!m) panic ("Out of memory");
80 static void *checked_alloc (int length)
82 void *m = malloc(length);
83 if (!m) panic ("Out of memory");
87 static int mmapcodesize = 0;
88 static void *mmapcodeptr = NULL;
90 void *mem_mmap(int length)
94 length = (ALIGN(length,ALIGNSIZE));
95 if (length > mmapcodesize) {
96 mmapcodesize = 0x10000;
97 if (length > mmapcodesize)
98 mmapcodesize = length;
99 mmapcodesize = (ALIGN(mmapcodesize, getpagesize()));
100 mmapcodeptr = mmap (NULL, (size_t) mmapcodesize,
101 PROT_READ | PROT_WRITE | PROT_EXEC,
102 MAP_PRIVATE | MAP_ANONYMOUS, -1, (off_t) 0);
103 if (mmapcodeptr == (void*) -1)
104 panic ("Out of memory");
106 retptr = mmapcodeptr;
107 mmapcodeptr = (void*) ((char*) mmapcodeptr + length);
108 mmapcodesize -= length;
115 /************ Memory manager, safe version **************/
118 typedef struct memblock {
119 struct memblock *prev,*next;
123 #define BLOCKOFFSET (ALIGN(sizeof(memblock),ALIGNSIZE))
125 struct memblock *firstmemblock;
129 void *mem_alloc(int length)
133 if (length==0) return NULL;
134 mb = checked_alloc (length + BLOCKOFFSET);
137 mb -> next = firstmemblock;
138 mb -> length = length;
140 if (firstmemblock) firstmemblock -> prev = mb;
143 memoryusage += length;
144 if (memoryusage > maxmemusage) maxmemusage = memoryusage;
146 return ((char*) mb) + BLOCKOFFSET;
150 void *lit_mem_alloc(int length)
154 if (length==0) return NULL;
155 mb = lit_checked_alloc (length + BLOCKOFFSET);
158 mb -> next = firstmemblock;
159 mb -> length = length;
161 if (firstmemblock) firstmemblock -> prev = mb;
164 memoryusage += length;
165 if (memoryusage > maxmemusage) maxmemusage = memoryusage;
167 return ((char*) mb) + BLOCKOFFSET;
171 void mem_free(void *m, int length)
175 if (length==0) return;
176 panic ("returned memoryblock with address NULL, length != 0");
179 mb = (memblock*) (((char*) m) - BLOCKOFFSET);
181 if (mb->length != length) {
183 "Memory block of size %d has been return as size %d",
188 if (mb->prev) mb->prev->next = mb->next;
189 else firstmemblock = mb->next;
190 if (mb->next) mb->next->prev = mb->prev;
194 memoryusage -= length;
198 void lit_mem_free(void *m, int length)
202 if (length==0) return;
203 panic ("returned memoryblock with address NULL, length != 0");
206 mb = (memblock*) (((char*) m) - BLOCKOFFSET);
208 if (mb->length != length) {
210 "Memory block of size %d has been return as size %d",
215 if (mb->prev) mb->prev->next = mb->next;
216 else firstmemblock = mb->next;
217 if (mb->next) mb->next->prev = mb->prev;
224 memoryusage -= length;
228 void *mem_realloc (void *m1, int len1, int len2)
232 m2 = mem_alloc (len2);
233 memcpy (m2, m1, len1);
242 static void mem_characterlog (unsigned char *m, int len)
247 for (z=0; z<len; z+=LINESIZE) {
248 sprintf (logtext, " ");
250 for (i=z; i<(z+LINESIZE) && i<len; i++) {
251 sprintf (logtext+strlen(logtext), "%2x ", m[i]);
253 for (; i<(z+LINESIZE); i++) {
254 sprintf (logtext+strlen(logtext), " ");
257 sprintf (logtext+strlen(logtext)," ");
258 for (i=z; i<(z+LINESIZE) && i<len; i++) {
259 sprintf (logtext+strlen(logtext),
260 "%c", (m[i]>=' ' && m[i]<=127) ? m[i] : '.');
268 /******* Memory manager, fast version ******/
271 void *mem_alloc(int length)
273 if (length==0) return NULL;
275 memoryusage += length;
276 if (memoryusage > maxmemusage) maxmemusage = memoryusage;
278 return checked_alloc (length);
282 void *lit_mem_alloc(int length)
284 if (length==0) return NULL;
286 memoryusage += length;
287 if (memoryusage > maxmemusage) maxmemusage = memoryusage;
289 return lit_checked_alloc (length);
293 void mem_free(void *m, int length)
296 if (length==0) return;
297 panic ("returned memoryblock with address NULL, length != 0");
300 memoryusage -= length;
306 void lit_mem_free(void *m, int length)
309 if (length==0) return;
310 panic ("returned memoryblock with address NULL, length != 0");
313 memoryusage -= length;
322 void *mem_realloc (void *m1, int len1, int len2)
328 panic ("reallocating memoryblock with address NULL, length != 0");
331 memoryusage = (memoryusage - len1) + len2;
333 m2 = realloc (m1, len2);
334 if (!m2) panic ("Out of memory");
341 /******* common memory manager parts ******/
354 void *dump_alloc(int length)
358 if (length==0) return NULL;
360 length = ALIGN (length, ALIGNSIZE);
362 assert (length <= DUMPBLOCKSIZE);
365 if (dumpsize + length > dumpspace) {
366 dumplist *newdumpblock = checked_alloc (sizeof(dumplist));
368 newdumpblock -> prev = topdumpblock;
369 topdumpblock = newdumpblock;
371 newdumpblock -> dumpmem = checked_alloc (DUMPBLOCKSIZE);
373 dumpsize = dumpspace;
374 dumpspace += DUMPBLOCKSIZE;
377 m = topdumpblock -> dumpmem + DUMPBLOCKSIZE - (dumpspace - dumpsize);
380 if (dumpsize > maxdumpsize) {
381 maxdumpsize = dumpsize;
388 void *dump_realloc(void *ptr, int len1, int len2)
390 void *p2 = dump_alloc (len2);
391 memcpy (p2, ptr, len1);
402 void dump_release(long int size)
404 assert (size >= 0 && size <= dumpsize);
408 while (dumpspace > dumpsize + DUMPBLOCKSIZE) {
409 dumplist *oldtop = topdumpblock;
411 topdumpblock = oldtop -> prev;
412 dumpspace -= DUMPBLOCKSIZE;
416 free (oldtop -> dumpmem);
425 void mem_usagelog (int givewarnings)
427 if ((memoryusage!=0) && givewarnings) {
428 sprintf (logtext, "Allocated memory not returned: %d",
434 memblock *mb = firstmemblock;
436 sprintf (logtext, " Memory block size: %d",
439 mem_characterlog ( ((unsigned char*)mb) + BLOCKOFFSET, mb->length);
447 if ((dumpsize!=0) && givewarnings) {
448 sprintf (logtext, "Dump memory not returned: %d",(int)dumpsize);
453 sprintf (logtext, "Random/Dump - memory usage: %dK/%dK",
454 (int)((maxmemusage+1023)/1024),
455 (int)((maxdumpsize+1023)/1024) );