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