3 Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003
4 R. Grafl, A. Krall, C. Kruegel, C. Oates, R. Obermaisser,
5 M. Probst, S. Ring, E. Steiner, C. Thalinger, D. Thuernbeck,
6 P. Tomsich, J. Wenninger
8 This file is part of CACAO.
10 This program is free software; you can redistribute it and/or
11 modify it under the terms of the GNU General Public License as
12 published by the Free Software Foundation; either version 2, or (at
13 your option) any later version.
15 This program is distributed in the hope that it will be useful, but
16 WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
25 Contact: cacao@complang.tuwien.ac.at
27 Authors: Reinhard Grafl
29 $Id: memory.c 799 2003-12-16 22:30:41Z edwin $
46 /********* general types, variables and auxiliary functions *********/
48 #define DUMPBLOCKSIZE (2<<21)
51 typedef struct dumplist {
52 struct dumplist *prev;
59 long int memoryusage = 0;
61 long int dumpsize = 0;
62 long int dumpspace = 0;
63 dumplist *topdumpblock = NULL;
65 long int maxmemusage = 0;
66 long int maxdumpsize = 0;
71 static char *nomallocmem = NULL;
72 static char *nomalloctop;
73 static char *nomallocptr;
76 static void *lit_checked_alloc (int length)
81 nomallocmem = malloc(16777216);
82 nomalloctop = nomallocmem + 16777216;
83 nomallocptr = nomallocmem;
86 nomallocptr = (void*) ALIGN((long) nomallocptr, ALIGNSIZE);
89 nomallocptr += length;
90 if (nomallocptr > nomalloctop)
91 panic("Out of memory");
98 static void *lit_checked_alloc(int length)
100 void *m = malloc(length);
101 if (!m) panic ("Out of memory");
108 static void *checked_alloc(int length)
110 void *m = malloc(length);
111 if (!m) panic("Out of memory");
116 static int mmapcodesize = 0;
117 static void *mmapcodeptr = NULL;
120 void *mem_mmap(int length)
124 length = (ALIGN(length,ALIGNSIZE));
125 if (length > mmapcodesize) {
126 mmapcodesize = 0x10000;
127 if (length > mmapcodesize)
128 mmapcodesize = length;
129 mmapcodesize = (ALIGN(mmapcodesize, getpagesize()));
130 mmapcodeptr = mmap (NULL, (size_t) mmapcodesize,
131 PROT_READ | PROT_WRITE | PROT_EXEC,
132 MAP_PRIVATE | MAP_ANONYMOUS, -1, (off_t) 0);
133 if (mmapcodeptr == (void*) -1)
134 panic ("Out of memory");
136 retptr = mmapcodeptr;
137 mmapcodeptr = (void*) ((char*) mmapcodeptr + length);
138 mmapcodesize -= length;
145 /************ Memory manager, safe version **************/
148 typedef struct memblock {
149 struct memblock *prev, *next;
153 #define BLOCKOFFSET (ALIGN(sizeof(memblock),ALIGNSIZE))
155 struct memblock *firstmemblock;
159 void *mem_alloc(int length)
163 if (length == 0) return NULL;
164 mb = checked_alloc(length + BLOCKOFFSET);
167 mb->next = firstmemblock;
170 if (firstmemblock) firstmemblock->prev = mb;
173 memoryusage += length;
174 if (memoryusage > maxmemusage)
175 maxmemusage = memoryusage;
177 return ((char*) mb) + BLOCKOFFSET;
181 void *lit_mem_alloc(int length)
185 if (length == 0) return NULL;
186 mb = lit_checked_alloc(length + BLOCKOFFSET);
189 mb->next = firstmemblock;
192 if (firstmemblock) firstmemblock -> prev = mb;
195 memoryusage += length;
196 if (memoryusage > maxmemusage) maxmemusage = memoryusage;
198 return ((char*) mb) + BLOCKOFFSET;
202 void mem_free(void *m, int length)
206 if (length == 0) return;
207 panic("returned memoryblock with address NULL, length != 0");
210 mb = (memblock*) (((char*) m) - BLOCKOFFSET);
212 if (mb->length != length) {
214 "Memory block of size %d has been return as size %d",
219 if (mb->prev) mb->prev->next = mb->next;
220 else firstmemblock = mb->next;
221 if (mb->next) mb->next->prev = mb->prev;
225 memoryusage -= length;
229 void lit_mem_free(void *m, int length)
233 if (length==0) return;
234 panic("returned memoryblock with address NULL, length != 0");
237 mb = (memblock*) (((char*) m) - BLOCKOFFSET);
239 if (mb->length != length) {
241 "Memory block of size %d has been return as size %d",
246 if (mb->prev) mb->prev->next = mb->next;
247 else firstmemblock = mb->next;
248 if (mb->next) mb->next->prev = mb->prev;
255 memoryusage -= length;
259 void *mem_realloc(void *m1, int len1, int len2)
263 m2 = mem_alloc(len2);
264 memcpy(m2, m1, len1);
273 static void mem_characterlog(unsigned char *m, int len)
277 char logtext[MAXLOGTEXT];
279 for (z = 0; z < len; z += LINESIZE) {
280 sprintf(logtext, " ");
282 for (i = z; i < (z + LINESIZE) && i < len; i++) {
283 sprintf(logtext + strlen(logtext), "%2x ", m[i]);
285 for (; i < (z + LINESIZE); i++) {
286 sprintf(logtext + strlen(logtext), " ");
289 sprintf(logtext + strlen(logtext)," ");
290 for (i = z; i < (z + LINESIZE) && i < len; i++) {
291 sprintf(logtext+strlen(logtext),
292 "%c", (m[i] >= ' ' && m[i] <= 127) ? m[i] : '.');
300 /******* Memory manager, fast version ******/
303 void *mem_alloc(int length)
305 if (length == 0) return NULL;
307 memoryusage += length;
308 if (memoryusage > maxmemusage) maxmemusage = memoryusage;
310 return checked_alloc(length);
314 void *lit_mem_alloc(int length)
316 if (length == 0) return NULL;
318 memoryusage += length;
319 if (memoryusage > maxmemusage) maxmemusage = memoryusage;
321 return lit_checked_alloc(length);
325 void mem_free(void *m, int length)
328 if (length == 0) return;
329 panic("returned memoryblock with address NULL, length != 0");
332 memoryusage -= length;
338 void lit_mem_free(void *m, int length)
341 if (length == 0) return;
342 panic("returned memoryblock with address NULL, length != 0");
345 memoryusage -= length;
354 void *mem_realloc (void *m1, int len1, int len2)
360 panic ("reallocating memoryblock with address NULL, length != 0");
363 memoryusage = (memoryusage - len1) + len2;
365 m2 = realloc (m1, len2);
366 if (!m2) panic ("Out of memory");
373 /******* common memory manager parts ******/
381 void *dump_alloc(int length)
384 int blocksize = DUMPBLOCKSIZE;
386 if (length == 0) return NULL;
388 length = ALIGN(length, ALIGNSIZE);
390 if (length > DUMPBLOCKSIZE)
394 if (dumpsize + length > dumpspace) {
395 dumplist *newdumpblock = checked_alloc(sizeof(dumplist));
397 newdumpblock->prev = topdumpblock;
398 newdumpblock->size = blocksize;
399 topdumpblock = newdumpblock;
401 newdumpblock->dumpmem = checked_alloc(blocksize);
403 dumpsize = dumpspace;
404 dumpspace += blocksize;
407 m = topdumpblock->dumpmem + blocksize - (dumpspace - dumpsize);
410 if (dumpsize > maxdumpsize) {
411 maxdumpsize = dumpsize;
418 void *dump_realloc(void *ptr, int len1, int len2)
420 void *p2 = dump_alloc(len2);
421 memcpy(p2, ptr, len1);
432 void dump_release(long int size)
434 assert(size >= 0 && size <= dumpsize);
438 while (topdumpblock && (dumpspace - topdumpblock->size >= dumpsize)) {
439 dumplist *oldtop = topdumpblock;
442 /* Keep the first dumpblock if we don't free memory. Otherwise
443 * a new dumpblock is allocated each time and we run out of
446 if (!oldtop->prev) break;
449 dumpspace -= oldtop->size;
450 topdumpblock = oldtop->prev;
454 free(oldtop->dumpmem);
461 void mem_usagelog (int givewarnings)
463 if ((memoryusage!=0) && givewarnings) {
464 dolog ("Allocated memory not returned: %d",
469 memblock *mb = firstmemblock;
471 dolog (" Memory block size: %d",
473 mem_characterlog ( ((unsigned char*)mb) + BLOCKOFFSET, mb->length);
481 if ((dumpsize!=0) && givewarnings) {
482 dolog ("Dump memory not returned: %d",(int)dumpsize);
486 dolog("Random/Dump - memory usage: %dK/%dK",
487 (int)((maxmemusage+1023)/1024),
488 (int)((maxdumpsize+1023)/1024) );
494 * These are local overrides for various environment variables in Emacs.
495 * Please do not remove this and leave it at the end of the file, where
496 * Emacs will automagically detect them.
497 * ---------------------------------------------------------------------
500 * indent-tabs-mode: t