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 = NULL;
53 static char *nomalloctop;
54 static char *nomallocptr;
56 static void *lit_checked_alloc (int length)
61 nomallocmem = malloc(16777216);
62 nomalloctop = nomallocmem + 16777216;
63 nomallocptr = nomallocmem;
66 nomallocptr = (void*) ALIGN ((long) nomallocptr, ALIGNSIZE);
69 nomallocptr += length;
70 if (nomallocptr > nomalloctop) panic ("Out of memory");
76 static void *lit_checked_alloc (int length)
78 void *m = malloc(length);
79 if (!m) panic ("Out of memory");
86 static void *checked_alloc (int length)
88 void *m = malloc(length);
89 if (!m) panic ("Out of memory");
93 static int mmapcodesize = 0;
94 static void *mmapcodeptr = NULL;
96 void *mem_mmap(int length)
100 length = (ALIGN(length,ALIGNSIZE));
101 if (length > mmapcodesize) {
102 mmapcodesize = 0x10000;
103 if (length > mmapcodesize)
104 mmapcodesize = length;
105 mmapcodesize = (ALIGN(mmapcodesize, getpagesize()));
106 mmapcodeptr = mmap (NULL, (size_t) mmapcodesize,
107 PROT_READ | PROT_WRITE | PROT_EXEC,
108 MAP_PRIVATE | MAP_ANONYMOUS, -1, (off_t) 0);
109 if (mmapcodeptr == (void*) -1)
110 panic ("Out of memory");
112 retptr = mmapcodeptr;
113 mmapcodeptr = (void*) ((char*) mmapcodeptr + length);
114 mmapcodesize -= length;
121 /************ Memory manager, safe version **************/
124 typedef struct memblock {
125 struct memblock *prev,*next;
129 #define BLOCKOFFSET (ALIGN(sizeof(memblock),ALIGNSIZE))
131 struct memblock *firstmemblock;
135 void *mem_alloc(int length)
139 if (length==0) return NULL;
140 mb = checked_alloc (length + BLOCKOFFSET);
143 mb -> next = firstmemblock;
144 mb -> length = length;
146 if (firstmemblock) firstmemblock -> prev = mb;
149 memoryusage += length;
150 if (memoryusage > maxmemusage) maxmemusage = memoryusage;
152 return ((char*) mb) + BLOCKOFFSET;
156 void *lit_mem_alloc(int length)
160 if (length==0) return NULL;
161 mb = lit_checked_alloc (length + BLOCKOFFSET);
164 mb -> next = firstmemblock;
165 mb -> length = length;
167 if (firstmemblock) firstmemblock -> prev = mb;
170 memoryusage += length;
171 if (memoryusage > maxmemusage) maxmemusage = memoryusage;
173 return ((char*) mb) + BLOCKOFFSET;
177 void mem_free(void *m, int length)
181 if (length==0) return;
182 panic ("returned memoryblock with address NULL, length != 0");
185 mb = (memblock*) (((char*) m) - BLOCKOFFSET);
187 if (mb->length != length) {
189 "Memory block of size %d has been return as size %d",
194 if (mb->prev) mb->prev->next = mb->next;
195 else firstmemblock = mb->next;
196 if (mb->next) mb->next->prev = mb->prev;
200 memoryusage -= length;
204 void lit_mem_free(void *m, int length)
208 if (length==0) return;
209 panic ("returned memoryblock with address NULL, length != 0");
212 mb = (memblock*) (((char*) m) - BLOCKOFFSET);
214 if (mb->length != length) {
216 "Memory block of size %d has been return as size %d",
221 if (mb->prev) mb->prev->next = mb->next;
222 else firstmemblock = mb->next;
223 if (mb->next) mb->next->prev = mb->prev;
230 memoryusage -= length;
234 void *mem_realloc (void *m1, int len1, int len2)
238 m2 = mem_alloc (len2);
239 memcpy (m2, m1, len1);
248 static void mem_characterlog (unsigned char *m, int len)
253 for (z=0; z<len; z+=LINESIZE) {
254 sprintf (logtext, " ");
256 for (i=z; i<(z+LINESIZE) && i<len; i++) {
257 sprintf (logtext+strlen(logtext), "%2x ", m[i]);
259 for (; i<(z+LINESIZE); i++) {
260 sprintf (logtext+strlen(logtext), " ");
263 sprintf (logtext+strlen(logtext)," ");
264 for (i=z; i<(z+LINESIZE) && i<len; i++) {
265 sprintf (logtext+strlen(logtext),
266 "%c", (m[i]>=' ' && m[i]<=127) ? m[i] : '.');
274 /******* Memory manager, fast version ******/
277 void *mem_alloc(int length)
279 if (length==0) return NULL;
281 memoryusage += length;
282 if (memoryusage > maxmemusage) maxmemusage = memoryusage;
284 return checked_alloc (length);
288 void *lit_mem_alloc(int length)
290 if (length==0) return NULL;
292 memoryusage += length;
293 if (memoryusage > maxmemusage) maxmemusage = memoryusage;
295 return lit_checked_alloc (length);
299 void mem_free(void *m, int length)
302 if (length==0) return;
303 panic ("returned memoryblock with address NULL, length != 0");
306 memoryusage -= length;
312 void lit_mem_free(void *m, int length)
315 if (length==0) return;
316 panic ("returned memoryblock with address NULL, length != 0");
319 memoryusage -= length;
328 void *mem_realloc (void *m1, int len1, int len2)
334 panic ("reallocating memoryblock with address NULL, length != 0");
337 memoryusage = (memoryusage - len1) + len2;
339 m2 = realloc (m1, len2);
340 if (!m2) panic ("Out of memory");
347 /******* common memory manager parts ******/
360 void *dump_alloc(int length)
364 if (length==0) return NULL;
366 length = ALIGN (length, ALIGNSIZE);
368 assert (length <= DUMPBLOCKSIZE);
371 if (dumpsize + length > dumpspace) {
372 dumplist *newdumpblock = checked_alloc (sizeof(dumplist));
374 newdumpblock -> prev = topdumpblock;
375 topdumpblock = newdumpblock;
377 newdumpblock -> dumpmem = checked_alloc (DUMPBLOCKSIZE);
379 dumpsize = dumpspace;
380 dumpspace += DUMPBLOCKSIZE;
383 m = topdumpblock -> dumpmem + DUMPBLOCKSIZE - (dumpspace - dumpsize);
386 if (dumpsize > maxdumpsize) {
387 maxdumpsize = dumpsize;
394 void *dump_realloc(void *ptr, int len1, int len2)
396 void *p2 = dump_alloc (len2);
397 memcpy (p2, ptr, len1);
408 void dump_release(long int size)
410 assert (size >= 0 && size <= dumpsize);
414 while (dumpspace > dumpsize + DUMPBLOCKSIZE) {
415 dumplist *oldtop = topdumpblock;
417 topdumpblock = oldtop -> prev;
418 dumpspace -= DUMPBLOCKSIZE;
422 free (oldtop -> dumpmem);
431 void mem_usagelog (int givewarnings)
433 if ((memoryusage!=0) && givewarnings) {
434 sprintf (logtext, "Allocated memory not returned: %d",
440 memblock *mb = firstmemblock;
442 sprintf (logtext, " Memory block size: %d",
445 mem_characterlog ( ((unsigned char*)mb) + BLOCKOFFSET, mb->length);
453 if ((dumpsize!=0) && givewarnings) {
454 sprintf (logtext, "Dump memory not returned: %d",(int)dumpsize);
459 sprintf (logtext, "Random/Dump - memory usage: %dK/%dK",
460 (int)((maxmemusage+1023)/1024),
461 (int)((maxdumpsize+1023)/1024) );