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 575 2003-11-09 17:26:53Z twisti $
46 /********* general types, variables and auxiliary functions *********/
48 #define DUMPBLOCKSIZE (2<<21)
51 typedef struct dumplist {
52 struct dumplist *prev;
58 long int memoryusage = 0;
60 long int dumpsize = 0;
61 long int dumpspace = 0;
62 dumplist *topdumpblock = NULL;
64 long int maxmemusage = 0;
65 long int maxdumpsize = 0;
70 static char *nomallocmem = NULL;
71 static char *nomalloctop;
72 static char *nomallocptr;
75 static void *lit_checked_alloc (int length)
80 nomallocmem = malloc(16777216);
81 nomalloctop = nomallocmem + 16777216;
82 nomallocptr = nomallocmem;
85 nomallocptr = (void*) ALIGN((long) nomallocptr, ALIGNSIZE);
88 nomallocptr += length;
89 if (nomallocptr > nomalloctop)
90 panic("Out of memory");
97 static void *lit_checked_alloc(int length)
99 void *m = malloc(length);
100 if (!m) panic ("Out of memory");
107 static void *checked_alloc(int length)
109 void *m = malloc(length);
110 if (!m) panic("Out of memory");
115 static int mmapcodesize = 0;
116 static void *mmapcodeptr = NULL;
119 void *mem_mmap(int length)
123 length = (ALIGN(length,ALIGNSIZE));
124 if (length > mmapcodesize) {
125 mmapcodesize = 0x10000;
126 if (length > mmapcodesize)
127 mmapcodesize = length;
128 mmapcodesize = (ALIGN(mmapcodesize, getpagesize()));
129 mmapcodeptr = mmap (NULL, (size_t) mmapcodesize,
130 PROT_READ | PROT_WRITE | PROT_EXEC,
131 MAP_PRIVATE | MAP_ANONYMOUS, -1, (off_t) 0);
132 if (mmapcodeptr == (void*) -1)
133 panic ("Out of memory");
135 retptr = mmapcodeptr;
136 mmapcodeptr = (void*) ((char*) mmapcodeptr + length);
137 mmapcodesize -= length;
144 /************ Memory manager, safe version **************/
147 typedef struct memblock {
148 struct memblock *prev, *next;
152 #define BLOCKOFFSET (ALIGN(sizeof(memblock),ALIGNSIZE))
154 struct memblock *firstmemblock;
158 void *mem_alloc(int length)
162 if (length == 0) return NULL;
163 mb = checked_alloc(length + BLOCKOFFSET);
166 mb->next = firstmemblock;
169 if (firstmemblock) firstmemblock->prev = mb;
172 memoryusage += length;
173 if (memoryusage > maxmemusage)
174 maxmemusage = memoryusage;
176 return ((char*) mb) + BLOCKOFFSET;
180 void *lit_mem_alloc(int length)
184 if (length == 0) return NULL;
185 mb = lit_checked_alloc(length + BLOCKOFFSET);
188 mb->next = firstmemblock;
191 if (firstmemblock) firstmemblock -> prev = mb;
194 memoryusage += length;
195 if (memoryusage > maxmemusage) maxmemusage = memoryusage;
197 return ((char*) mb) + BLOCKOFFSET;
201 void mem_free(void *m, int length)
205 if (length == 0) return;
206 panic("returned memoryblock with address NULL, length != 0");
209 mb = (memblock*) (((char*) m) - BLOCKOFFSET);
211 if (mb->length != length) {
213 "Memory block of size %d has been return as size %d",
218 if (mb->prev) mb->prev->next = mb->next;
219 else firstmemblock = mb->next;
220 if (mb->next) mb->next->prev = mb->prev;
224 memoryusage -= length;
228 void lit_mem_free(void *m, int length)
232 if (length==0) return;
233 panic("returned memoryblock with address NULL, length != 0");
236 mb = (memblock*) (((char*) m) - BLOCKOFFSET);
238 if (mb->length != length) {
240 "Memory block of size %d has been return as size %d",
245 if (mb->prev) mb->prev->next = mb->next;
246 else firstmemblock = mb->next;
247 if (mb->next) mb->next->prev = mb->prev;
254 memoryusage -= length;
258 void *mem_realloc(void *m1, int len1, int len2)
262 m2 = mem_alloc(len2);
263 memcpy(m2, m1, len1);
272 static void mem_characterlog(unsigned char *m, int len)
277 for (z = 0; z < len; z += LINESIZE) {
278 sprintf(logtext, " ");
280 for (i = z; i < (z + LINESIZE) && i < len; i++) {
281 sprintf(logtext + strlen(logtext), "%2x ", m[i]);
283 for (; i < (z + LINESIZE); i++) {
284 sprintf(logtext + strlen(logtext), " ");
287 sprintf(logtext + strlen(logtext)," ");
288 for (i = z; i < (z + LINESIZE) && i < len; i++) {
289 sprintf(logtext+strlen(logtext),
290 "%c", (m[i] >= ' ' && m[i] <= 127) ? m[i] : '.');
298 /******* Memory manager, fast version ******/
301 void *mem_alloc(int length)
303 if (length == 0) return NULL;
305 memoryusage += length;
306 if (memoryusage > maxmemusage) maxmemusage = memoryusage;
308 return checked_alloc(length);
312 void *lit_mem_alloc(int length)
314 if (length == 0) return NULL;
316 memoryusage += length;
317 if (memoryusage > maxmemusage) maxmemusage = memoryusage;
319 return lit_checked_alloc(length);
323 void mem_free(void *m, int length)
326 if (length == 0) return;
327 panic("returned memoryblock with address NULL, length != 0");
330 memoryusage -= length;
336 void lit_mem_free(void *m, int length)
339 if (length == 0) return;
340 panic("returned memoryblock with address NULL, length != 0");
343 memoryusage -= length;
352 void *mem_realloc (void *m1, int len1, int len2)
358 panic ("reallocating memoryblock with address NULL, length != 0");
361 memoryusage = (memoryusage - len1) + len2;
363 m2 = realloc (m1, len2);
364 if (!m2) panic ("Out of memory");
371 /******* common memory manager parts ******/
379 void *dump_alloc(int length)
383 if (length == 0) return NULL;
385 length = ALIGN(length, ALIGNSIZE);
387 assert(length <= DUMPBLOCKSIZE);
390 if (dumpsize + length > dumpspace) {
391 dumplist *newdumpblock = checked_alloc(sizeof(dumplist));
393 newdumpblock->prev = topdumpblock;
394 topdumpblock = newdumpblock;
396 newdumpblock->dumpmem = checked_alloc(DUMPBLOCKSIZE);
398 dumpsize = dumpspace;
399 dumpspace += DUMPBLOCKSIZE;
402 m = topdumpblock->dumpmem + DUMPBLOCKSIZE - (dumpspace - dumpsize);
405 if (dumpsize > maxdumpsize) {
406 maxdumpsize = dumpsize;
413 void *dump_realloc(void *ptr, int len1, int len2)
415 void *p2 = dump_alloc(len2);
416 memcpy(p2, ptr, len1);
427 void dump_release(long int size)
429 assert(size >= 0 && size <= dumpsize);
433 while (dumpspace > dumpsize + DUMPBLOCKSIZE) {
434 dumplist *oldtop = topdumpblock;
436 topdumpblock = oldtop->prev;
437 dumpspace -= DUMPBLOCKSIZE;
441 free(oldtop->dumpmem);
448 void mem_usagelog (int givewarnings)
450 if ((memoryusage!=0) && givewarnings) {
451 sprintf (logtext, "Allocated memory not returned: %d",
457 memblock *mb = firstmemblock;
459 sprintf (logtext, " Memory block size: %d",
462 mem_characterlog ( ((unsigned char*)mb) + BLOCKOFFSET, mb->length);
470 if ((dumpsize!=0) && givewarnings) {
471 sprintf (logtext, "Dump memory not returned: %d",(int)dumpsize);
476 sprintf(logtext, "Random/Dump - memory usage: %dK/%dK",
477 (int)((maxmemusage+1023)/1024),
478 (int)((maxdumpsize+1023)/1024) );
485 * These are local overrides for various environment variables in Emacs.
486 * Please do not remove this and leave it at the end of the file, where
487 * Emacs will automagically detect them.
488 * ---------------------------------------------------------------------
491 * indent-tabs-mode: t