Make global.h global
[cacao.git] / toolbox / memory.c
1 /************************* toolbox/memory.c ************************************
2
3         Copyright (c) 1997 A. Krall, R. Grafl, M. Gschwind, M. Probst
4
5         See file COPYRIGHT for information on usage and disclaimer of warranties
6
7         Not documented, see memory.h.
8
9         Authors: Reinhard Grafl      EMAIL: cacao@complang.tuwien.ac.at
10
11         Last Change: 1996/10/03
12
13 *******************************************************************************/
14
15 #include <stdio.h>
16 #include <stdlib.h>
17 #include <assert.h>
18 #include <string.h>
19 #include <sys/mman.h>
20 #include <unistd.h>
21
22 #include "global.h"
23 #include "callargs.h"
24 #include "loging.h"
25 #include "memory.h"
26
27
28         /********* general types, variables and auxiliary functions *********/
29
30 #define DUMPBLOCKSIZE  (2<<21)
31 #define ALIGNSIZE           8
32
33 typedef struct dumplist {
34         struct dumplist *prev;
35         char *dumpmem;
36 } dumplist;
37
38
39
40 long int memoryusage = 0;
41
42 long int dumpsize = 0;
43 long int dumpspace = 0;
44 dumplist *topdumpblock = NULL;
45
46 long int maxmemusage = 0;
47 long int maxdumpsize = 0;
48
49 /* #define TRACECALLARGS */
50
51 #ifdef TRACECALLARGS
52 static char  nomallocmem[16777216];
53 static char *nomalloctop = nomallocmem + 16777216;
54 static char *nomallocptr = nomallocmem;
55
56 static void *lit_checked_alloc (int length)
57 {
58         void *m;
59
60         nomallocptr = (void*) ALIGN ((long) nomallocptr, ALIGNSIZE);
61         
62         m = nomallocptr;
63         nomallocptr += length;
64         if (nomallocptr > nomalloctop) panic ("Out of memory");
65         return m;
66 }
67
68 #else
69
70 static void *lit_checked_alloc (int length)
71 {
72         void *m = malloc(length);
73         if (!m) panic ("Out of memory");
74         return m;
75 }
76
77 #endif
78
79
80 static void *checked_alloc (int length)
81 {
82         void *m = malloc(length);
83         if (!m) panic ("Out of memory");
84         return m;
85 }
86
87 static int mmapcodesize = 0;
88 static void *mmapcodeptr = NULL;
89
90 void *mem_mmap(int length)
91 {
92         void *retptr;
93
94         length = (ALIGN(length,ALIGNSIZE));
95         if (length > mmapcodesize) {
96                 mmapcodesize = 0x10000;
97                 if (length > mmapcodesize)
98                         mmapcodesize = length;
99                 mmapcodesize = (ALIGN(mmapcodesize, getpagesize()));
100                 mmapcodeptr = mmap (NULL, (size_t) mmapcodesize,
101                               PROT_READ | PROT_WRITE | PROT_EXEC,
102                               MAP_PRIVATE | MAP_ANONYMOUS, -1, (off_t) 0);
103                 if (mmapcodeptr == (void*) -1)
104                         panic ("Out of memory");
105                 }
106         retptr = mmapcodeptr;
107         mmapcodeptr = (void*) ((char*) mmapcodeptr + length);
108         mmapcodesize -= length;
109         return retptr;
110 }
111
112
113 #ifdef DEBUG
114
115         /************ Memory manager, safe version **************/
116
117
118 typedef struct memblock {
119         struct memblock *prev,*next;
120         int length;
121 } memblock;
122
123 #define BLOCKOFFSET    (ALIGN(sizeof(memblock),ALIGNSIZE))
124
125 struct memblock *firstmemblock;
126
127
128
129 void *mem_alloc(int length)
130 {
131         memblock *mb;
132
133         if (length==0) return NULL;
134         mb = checked_alloc (length + BLOCKOFFSET);
135
136         mb -> prev = NULL;
137         mb -> next = firstmemblock;     
138         mb -> length = length;
139
140         if (firstmemblock) firstmemblock -> prev = mb;
141         firstmemblock = mb;
142
143         memoryusage += length;
144         if (memoryusage > maxmemusage) maxmemusage = memoryusage;
145
146         return ((char*) mb) + BLOCKOFFSET;
147 }
148
149
150 void *lit_mem_alloc(int length)
151 {
152         memblock *mb;
153
154         if (length==0) return NULL;
155         mb = lit_checked_alloc (length + BLOCKOFFSET);
156
157         mb -> prev = NULL;
158         mb -> next = firstmemblock;     
159         mb -> length = length;
160
161         if (firstmemblock) firstmemblock -> prev = mb;
162         firstmemblock = mb;
163
164         memoryusage += length;
165         if (memoryusage > maxmemusage) maxmemusage = memoryusage;
166
167         return ((char*) mb) + BLOCKOFFSET;
168 }
169
170
171 void mem_free(void *m, int length)
172 {
173         memblock *mb;
174         if (!m) {
175                 if (length==0) return;
176                 panic ("returned memoryblock with address NULL, length != 0");
177                 }
178
179         mb = (memblock*) (((char*) m) - BLOCKOFFSET);
180         
181         if (mb->length != length) {
182                 sprintf (logtext, 
183                         "Memory block of size %d has been return as size %d",
184                          mb->length, length);
185                 error();
186                 }
187                 
188         if (mb->prev) mb->prev->next = mb->next;
189                  else firstmemblock = mb->next;
190         if (mb->next) mb->next->prev = mb->prev;
191
192         free (mb);
193
194         memoryusage -= length;
195 }
196
197
198 void lit_mem_free(void *m, int length)
199 {
200         memblock *mb;
201         if (!m) {
202                 if (length==0) return;
203                 panic ("returned memoryblock with address NULL, length != 0");
204                 }
205
206         mb = (memblock*) (((char*) m) - BLOCKOFFSET);
207         
208         if (mb->length != length) {
209                 sprintf (logtext, 
210                         "Memory block of size %d has been return as size %d",
211                          mb->length, length);
212                 error();
213                 }
214                 
215         if (mb->prev) mb->prev->next = mb->next;
216                  else firstmemblock = mb->next;
217         if (mb->next) mb->next->prev = mb->prev;
218
219 #ifdef TRACECALLARGS
220 #else
221         free (mb);
222 #endif
223
224         memoryusage -= length;
225 }
226
227
228 void *mem_realloc (void *m1, int len1, int len2)
229 {
230         void *m2;
231         
232         m2 = mem_alloc (len2);
233         memcpy (m2, m1, len1);
234         mem_free (m1, len1);
235
236         return m2;
237 }
238
239
240
241
242 static void mem_characterlog (unsigned char *m, int len)
243 {
244 #       define LINESIZE 16
245         int z,i;
246         
247         for (z=0; z<len; z+=LINESIZE) {
248                 sprintf (logtext, "   ");
249                         
250                 for (i=z; i<(z+LINESIZE) && i<len; i++) {
251                         sprintf (logtext+strlen(logtext), "%2x ", m[i]);
252                         }
253                 for (; i<(z+LINESIZE); i++) {
254                         sprintf (logtext+strlen(logtext), "   ");
255                         }
256                                         
257                 sprintf (logtext+strlen(logtext),"   ");
258                 for (i=z; i<(z+LINESIZE) && i<len; i++) {
259                         sprintf (logtext+strlen(logtext),
260                              "%c", (m[i]>=' ' && m[i]<=127) ? m[i] : '.');
261                         }
262                         
263                 dolog();
264                 }
265 }
266
267 #else
268                 /******* Memory manager, fast version ******/
269
270
271 void *mem_alloc(int length)
272 {
273         if (length==0) return NULL;
274
275         memoryusage += length;
276         if (memoryusage > maxmemusage) maxmemusage = memoryusage;
277         
278         return checked_alloc (length);
279 }
280
281
282 void *lit_mem_alloc(int length)
283 {
284         if (length==0) return NULL;
285
286         memoryusage += length;
287         if (memoryusage > maxmemusage) maxmemusage = memoryusage;
288         
289         return lit_checked_alloc (length);
290 }
291
292
293 void mem_free(void *m, int length)
294 {
295         if (!m) {
296                 if (length==0) return;
297                 panic ("returned memoryblock with address NULL, length != 0");
298                 }
299
300         memoryusage -= length;
301
302         free (m);
303 }
304
305
306 void lit_mem_free(void *m, int length)
307 {
308         if (!m) {
309                 if (length==0) return;
310                 panic ("returned memoryblock with address NULL, length != 0");
311                 }
312
313         memoryusage -= length;
314
315 #ifdef TRACECALLARGS
316 #else
317         free (m);
318 #endif
319 }
320
321
322 void *mem_realloc (void *m1, int len1, int len2)
323 {
324         void *m2;
325
326         if (!m1) {
327                 if (len1!=0) 
328                   panic ("reallocating memoryblock with address NULL, length != 0");
329                 }
330                 
331         memoryusage = (memoryusage - len1) + len2;
332
333         m2 = realloc (m1, len2);
334         if (!m2) panic ("Out of memory");
335         return m2;
336 }
337
338
339 #endif
340
341                 /******* common memory manager parts ******/
342
343
344
345 long int mem_usage()
346 {
347         return memoryusage;
348 }
349
350
351
352
353
354 void *dump_alloc(int length)
355 {
356         void *m;
357
358         if (length==0) return NULL;
359         
360         length = ALIGN (length, ALIGNSIZE);
361
362         assert (length <= DUMPBLOCKSIZE);
363         assert (length > 0);
364
365         if (dumpsize + length > dumpspace) {
366                 dumplist *newdumpblock = checked_alloc (sizeof(dumplist));
367
368                 newdumpblock -> prev = topdumpblock;
369                 topdumpblock = newdumpblock;
370
371                 newdumpblock -> dumpmem = checked_alloc (DUMPBLOCKSIZE);
372
373                 dumpsize = dumpspace;
374                 dumpspace += DUMPBLOCKSIZE;             
375                 }
376         
377         m = topdumpblock -> dumpmem + DUMPBLOCKSIZE - (dumpspace - dumpsize);
378         dumpsize += length;
379         
380         if (dumpsize > maxdumpsize) {
381                 maxdumpsize = dumpsize;
382                 }
383                 
384         return m;
385 }   
386
387
388 void *dump_realloc(void *ptr, int len1, int len2)
389 {
390         void *p2 = dump_alloc (len2);
391         memcpy (p2, ptr, len1); 
392         return p2;
393 }
394
395
396 long int dump_size()
397 {
398         return dumpsize;
399 }
400
401
402 void dump_release(long int size)
403 {
404         assert (size >= 0 && size <= dumpsize);
405
406         dumpsize = size;
407         
408         while (dumpspace  >  dumpsize + DUMPBLOCKSIZE) {
409                 dumplist *oldtop = topdumpblock;
410                 
411                 topdumpblock = oldtop -> prev;
412                 dumpspace -= DUMPBLOCKSIZE;
413                 
414 #ifdef TRACECALLARGS
415 #else
416                 free (oldtop -> dumpmem);
417                 free (oldtop);
418 #endif
419                 }               
420 }
421
422
423
424
425 void mem_usagelog (int givewarnings)
426 {
427         if ((memoryusage!=0) && givewarnings) {
428                 sprintf (logtext, "Allocated memory not returned: %d",
429                       (int)memoryusage);
430                 dolog();
431
432 #ifdef DEBUG
433                 { 
434                 memblock *mb = firstmemblock;
435                 while (mb) {
436                         sprintf (logtext, "   Memory block size: %d", 
437                           (int)(mb->length) );
438                         dolog();
439                         mem_characterlog ( ((unsigned char*)mb) + BLOCKOFFSET, mb->length);
440                         mb = mb->next;
441                         }
442                 }
443 #endif
444                         
445                 }
446
447         if ((dumpsize!=0) && givewarnings) {
448                 sprintf (logtext, "Dump memory not returned: %d",(int)dumpsize);
449                 dolog();
450                 }
451
452
453         sprintf (logtext, "Random/Dump - memory usage: %dK/%dK", 
454               (int)((maxmemusage+1023)/1024), 
455               (int)((maxdumpsize+1023)/1024) );
456         dolog();
457         
458 }
459