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 *******************************************************************************/
22 #include "../callargs.h"
27 /********* allgemeine Typen, Variablen und Hilfsfunktionen *********/
29 #define DUMPBLOCKSIZE (2<<18)
32 typedef struct dumplist {
33 struct dumplist *prev;
39 long int memoryusage = 0;
41 long int dumpsize = 0;
42 long int dumpspace = 0;
43 dumplist *topdumpblock = NULL;
45 long int maxmemusage = 0;
46 long int maxdumpsize = 0;
48 /* #define TRACECALLARGS */
51 static char nomallocmem[16777216];
52 static char *nomalloctop = nomallocmem + 16777216;
53 static char *nomallocptr = nomallocmem;
55 static void *lit_checked_alloc (int length)
59 nomallocptr = (void*) ALIGN ((long) nomallocptr, ALIGNSIZE);
62 nomallocptr += length;
63 if (nomallocptr > nomalloctop) panic ("Out of memory");
69 static void *lit_checked_alloc (int length)
71 void *m = malloc(length);
72 if (!m) panic ("Out of memory");
79 static void *checked_alloc (int length)
81 void *m = malloc(length);
82 if (!m) panic ("Out of memory");
86 static int mmapcodesize = 0;
87 static void *mmapcodeptr = NULL;
89 void *mem_mmap(int length)
93 length = (ALIGN(length,ALIGNSIZE));
94 if (length > mmapcodesize) {
95 mmapcodesize = 0x10000;
96 if (length > mmapcodesize)
97 mmapcodesize = length;
98 mmapcodesize = (ALIGN(mmapcodesize, getpagesize()));
99 mmapcodeptr = mmap (NULL, (size_t) mmapcodesize,
100 PROT_READ | PROT_WRITE | PROT_EXEC,
101 MAP_PRIVATE | MAP_ANONYMOUS, -1, (off_t) 0);
102 if (mmapcodeptr == (void*) -1)
103 panic ("Out of memory");
105 retptr = mmapcodeptr;
106 mmapcodeptr = (void*) ((char*) mmapcodeptr + length);
107 mmapcodesize -= length;
114 /************ Sichere Version des Speichermanages **************/
117 typedef struct memblock {
118 struct memblock *prev,*next;
122 #define BLOCKOFFSET (ALIGN(sizeof(memblock),ALIGNSIZE))
124 struct memblock *firstmemblock;
128 void *mem_alloc(int length)
132 if (length==0) return NULL;
133 mb = checked_alloc (length + BLOCKOFFSET);
136 mb -> next = firstmemblock;
137 mb -> length = length;
139 if (firstmemblock) firstmemblock -> prev = mb;
142 memoryusage += length;
143 if (memoryusage > maxmemusage) maxmemusage = memoryusage;
145 return ((char*) mb) + BLOCKOFFSET;
149 void *lit_mem_alloc(int length)
153 if (length==0) return NULL;
154 mb = lit_checked_alloc (length + BLOCKOFFSET);
157 mb -> next = firstmemblock;
158 mb -> length = length;
160 if (firstmemblock) firstmemblock -> prev = mb;
163 memoryusage += length;
164 if (memoryusage > maxmemusage) maxmemusage = memoryusage;
166 return ((char*) mb) + BLOCKOFFSET;
170 void mem_free(void *m, int length)
174 if (length==0) return;
175 panic ("returned memoryblock with address NULL, length != 0");
178 mb = (memblock*) (((char*) m) - BLOCKOFFSET);
180 if (mb->length != length) {
182 "Memory block of size %d has been return as size %d",
187 if (mb->prev) mb->prev->next = mb->next;
188 else firstmemblock = mb->next;
189 if (mb->next) mb->next->prev = mb->prev;
193 memoryusage -= length;
197 void lit_mem_free(void *m, int length)
201 if (length==0) return;
202 panic ("returned memoryblock with address NULL, length != 0");
205 mb = (memblock*) (((char*) m) - BLOCKOFFSET);
207 if (mb->length != length) {
209 "Memory block of size %d has been return as size %d",
214 if (mb->prev) mb->prev->next = mb->next;
215 else firstmemblock = mb->next;
216 if (mb->next) mb->next->prev = mb->prev;
223 memoryusage -= length;
227 void *mem_realloc (void *m1, int len1, int len2)
231 m2 = mem_alloc (len2);
232 memcpy (m2, m1, len1);
241 static void mem_characterlog (unsigned char *m, int len)
246 for (z=0; z<len; z+=LINESIZE) {
247 sprintf (logtext, " ");
249 for (i=z; i<(z+LINESIZE) && i<len; i++) {
250 sprintf (logtext+strlen(logtext), "%2x ", m[i]);
252 for (; i<(z+LINESIZE); i++) {
253 sprintf (logtext+strlen(logtext), " ");
256 sprintf (logtext+strlen(logtext)," ");
257 for (i=z; i<(z+LINESIZE) && i<len; i++) {
258 sprintf (logtext+strlen(logtext),
259 "%c", (m[i]>=' ' && m[i]<=127) ? m[i] : '.');
267 /******* Schnelle Version des Speichermanagers ******/
270 void *mem_alloc(int length)
272 if (length==0) return NULL;
274 memoryusage += length;
275 if (memoryusage > maxmemusage) maxmemusage = memoryusage;
277 return checked_alloc (length);
281 void *lit_mem_alloc(int length)
283 if (length==0) return NULL;
285 memoryusage += length;
286 if (memoryusage > maxmemusage) maxmemusage = memoryusage;
288 return lit_checked_alloc (length);
292 void mem_free(void *m, int length)
295 if (length==0) return;
296 panic ("returned memoryblock with address NULL, length != 0");
299 memoryusage -= length;
305 void lit_mem_free(void *m, int length)
308 if (length==0) return;
309 panic ("returned memoryblock with address NULL, length != 0");
312 memoryusage -= length;
321 void *mem_realloc (void *m1, int len1, int len2)
327 panic ("reallocating memoryblock with address NULL, length != 0");
330 memoryusage = (memoryusage - len1) + len2;
332 m2 = realloc (m1, len2);
333 if (!m2) panic ("Out of memory");
340 /******* allgemeine Teile des Speichermanagers ******/
353 void *dump_alloc(int length)
357 if (length==0) return NULL;
359 length = ALIGN (length, ALIGNSIZE);
361 assert (length <= DUMPBLOCKSIZE);
364 if (dumpsize + length > dumpspace) {
365 dumplist *newdumpblock = checked_alloc (sizeof(dumplist));
367 newdumpblock -> prev = topdumpblock;
368 topdumpblock = newdumpblock;
370 newdumpblock -> dumpmem = checked_alloc (DUMPBLOCKSIZE);
372 dumpsize = dumpspace;
373 dumpspace += DUMPBLOCKSIZE;
376 m = topdumpblock -> dumpmem + DUMPBLOCKSIZE - (dumpspace - dumpsize);
379 if (dumpsize > maxdumpsize) {
380 maxdumpsize = dumpsize;
387 void *dump_realloc(void *ptr, int len1, int len2)
389 void *p2 = dump_alloc (len2);
390 memcpy (p2, ptr, len1);
401 void dump_release(long int size)
403 assert (size >= 0 && size <= dumpsize);
407 while (dumpspace > dumpsize + DUMPBLOCKSIZE) {
408 dumplist *oldtop = topdumpblock;
410 topdumpblock = oldtop -> prev;
411 dumpspace -= DUMPBLOCKSIZE;
415 free (oldtop -> dumpmem);
424 void mem_usagelog (int givewarnings)
426 if ((memoryusage!=0) && givewarnings) {
427 sprintf (logtext, "Allocated memory not returned: %d",
433 memblock *mb = firstmemblock;
435 sprintf (logtext, " Memory block size: %d",
438 mem_characterlog ( ((unsigned char*)mb) + BLOCKOFFSET, mb->length);
446 if ((dumpsize!=0) && givewarnings) {
447 sprintf (logtext, "Dump memory not returned: %d",(int)dumpsize);
452 sprintf (logtext, "Random/Dump - memory usage: %dK/%dK",
453 (int)((maxmemusage+1023)/1024),
454 (int)((maxdumpsize+1023)/1024) );