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 730 2003-12-11 21:23:31Z edwin $
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)
276 char logtext[MAXLOGTEXT];
278 for (z = 0; z < len; z += LINESIZE) {
279 sprintf(logtext, " ");
281 for (i = z; i < (z + LINESIZE) && i < len; i++) {
282 sprintf(logtext + strlen(logtext), "%2x ", m[i]);
284 for (; i < (z + LINESIZE); i++) {
285 sprintf(logtext + strlen(logtext), " ");
288 sprintf(logtext + strlen(logtext)," ");
289 for (i = z; i < (z + LINESIZE) && i < len; i++) {
290 sprintf(logtext+strlen(logtext),
291 "%c", (m[i] >= ' ' && m[i] <= 127) ? m[i] : '.');
299 /******* Memory manager, fast version ******/
302 void *mem_alloc(int length)
304 if (length == 0) return NULL;
306 memoryusage += length;
307 if (memoryusage > maxmemusage) maxmemusage = memoryusage;
309 return checked_alloc(length);
313 void *lit_mem_alloc(int length)
315 if (length == 0) return NULL;
317 memoryusage += length;
318 if (memoryusage > maxmemusage) maxmemusage = memoryusage;
320 return lit_checked_alloc(length);
324 void mem_free(void *m, int length)
327 if (length == 0) return;
328 panic("returned memoryblock with address NULL, length != 0");
331 memoryusage -= length;
337 void lit_mem_free(void *m, int length)
340 if (length == 0) return;
341 panic("returned memoryblock with address NULL, length != 0");
344 memoryusage -= length;
353 void *mem_realloc (void *m1, int len1, int len2)
359 panic ("reallocating memoryblock with address NULL, length != 0");
362 memoryusage = (memoryusage - len1) + len2;
364 m2 = realloc (m1, len2);
365 if (!m2) panic ("Out of memory");
372 /******* common memory manager parts ******/
380 void *dump_alloc(int length)
384 if (length == 0) return NULL;
386 length = ALIGN(length, ALIGNSIZE);
388 assert(length <= DUMPBLOCKSIZE);
391 if (dumpsize + length > dumpspace) {
392 dumplist *newdumpblock = checked_alloc(sizeof(dumplist));
394 newdumpblock->prev = topdumpblock;
395 topdumpblock = newdumpblock;
397 newdumpblock->dumpmem = checked_alloc(DUMPBLOCKSIZE);
399 dumpsize = dumpspace;
400 dumpspace += DUMPBLOCKSIZE;
403 m = topdumpblock->dumpmem + DUMPBLOCKSIZE - (dumpspace - dumpsize);
406 if (dumpsize > maxdumpsize) {
407 maxdumpsize = dumpsize;
414 void *dump_realloc(void *ptr, int len1, int len2)
416 void *p2 = dump_alloc(len2);
417 memcpy(p2, ptr, len1);
428 void dump_release(long int size)
430 assert(size >= 0 && size <= dumpsize);
434 while (dumpspace > dumpsize + DUMPBLOCKSIZE) {
435 dumplist *oldtop = topdumpblock;
437 topdumpblock = oldtop->prev;
438 dumpspace -= DUMPBLOCKSIZE;
442 free(oldtop->dumpmem);
449 void mem_usagelog (int givewarnings)
451 if ((memoryusage!=0) && givewarnings) {
452 dolog ("Allocated memory not returned: %d",
457 memblock *mb = firstmemblock;
459 dolog (" Memory block size: %d",
461 mem_characterlog ( ((unsigned char*)mb) + BLOCKOFFSET, mb->length);
469 if ((dumpsize!=0) && givewarnings) {
470 dolog ("Dump memory not returned: %d",(int)dumpsize);
474 dolog("Random/Dump - memory usage: %dK/%dK",
475 (int)((maxmemusage+1023)/1024),
476 (int)((maxdumpsize+1023)/1024) );
482 * These are local overrides for various environment variables in Emacs.
483 * Please do not remove this and leave it at the end of the file, where
484 * Emacs will automagically detect them.
485 * ---------------------------------------------------------------------
488 * indent-tabs-mode: t