34 #include <gwenhywfar/gwenhywfarapi.h>
35 #include <gwenhywfar/types.h>
36 #include <gwenhywfar/stringlist.h>
58 #ifdef ENABLE_MY_SMALL_BLOCK_ALLOC
59 static size_t gwen_memory__released_since_collect=0;
67 s=getenv(GWEN_MEMORY_ENV_DEBUG);
69 fprintf(stderr,
"Memory debugging is enabled\n");
80 GWEN_MEMORY_TABLE *mt;
84 GWEN_MEMORY_TABLE *next;
113 "GWEN info: %zu %s allocated in %zu calls "
114 "(%zu times reused, average %zu bytes)\n",
135 GWEN_MEMORY_TABLE *mt;
137 unsigned short dsize;
140 fprintf(stderr,
"GWEN info: allocating memory table\n");
141 mt=(GWEN_MEMORY_TABLE*)malloc(
sizeof(GWEN_MEMORY_TABLE));
143 memset(mt, 0,
sizeof(GWEN_MEMORY_TABLE));
144 dsize=GWEN_MEMORY_MAXBLOCK;
146 GWEN_MEMORY_WRITESIZE(p, dsize);
160 end=p+GWEN_MEMORY_TABLE_LEN;
162 unsigned short bsize;
163 unsigned short rsize;
165 bsize=GWEN_MEMORY_READSIZE(p);
166 rsize=bsize & GWEN_MEMORY_MASK_LEN;
167 if (bsize & GWEN_MEMORY_MASK_MALLOCED) {
169 "GWEN warning: Block %p still allocated (%d bytes)\n",
170 GWEN_MEMORY_GETDATA(p),
173 p+=rsize+GWEN_MEMORY_SIZELEN;
183 GWEN_MEMORY_TABLE *last;
204 unsigned short dsize) {
208 end=mt->data+GWEN_MEMORY_TABLE_LEN;
211 unsigned short bsize;
212 unsigned short rsize;
214 bsize=GWEN_MEMORY_READSIZE(p);
215 rsize=bsize & GWEN_MEMORY_MASK_LEN;
220 if (rsize && !(bsize & GWEN_MEMORY_MASK_INUSE)) {
223 rsize>=(dsize+GWEN_MEMORY_SIZELEN+GWEN_MEMORY_MINREMAIN)) {
227 p+=rsize+GWEN_MEMORY_SIZELEN;
238 unsigned short nsize=0;
243 end=mt->data+GWEN_MEMORY_TABLE_LEN;
246 unsigned short bsize;
247 unsigned short rsize;
249 bsize=GWEN_MEMORY_READSIZE(np);
250 rsize=bsize & GWEN_MEMORY_MASK_LEN;
251 if (rsize && !(bsize & GWEN_MEMORY_MASK_INUSE)) {
254 nsize+=GWEN_MEMORY_SIZELEN;
260 np+=rsize+GWEN_MEMORY_SIZELEN;
264 fprintf(stderr,
"GWEN info: collected %u bytes\n", nsize);
265 GWEN_MEMORY_WRITESIZE(p, nsize);
277 end=mt->data+GWEN_MEMORY_TABLE_LEN;
280 unsigned short bsize;
281 unsigned short rsize;
284 bsize=GWEN_MEMORY_READSIZE(p);
285 rsize=bsize & GWEN_MEMORY_MASK_LEN;
286 p+=rsize+GWEN_MEMORY_SIZELEN;
297 end=p+GWEN_MEMORY_TABLE_LEN;
299 unsigned short bsize;
300 unsigned short rsize;
302 bsize=GWEN_MEMORY_READSIZE(p);
303 rsize=bsize & GWEN_MEMORY_MASK_LEN;
305 "GWEN debug: at %5zu: found block with %5u bytes [%p] (%s)\n",
309 (bsize & GWEN_MEMORY_MASK_INUSE)?
"used":
"free");
310 p+=rsize+GWEN_MEMORY_SIZELEN;
317 GWEN_MEMORY_TABLE *mt;
320 if (dsize>GWEN_MEMORY_MAXBLOCK) {
321 fprintf(stderr,
"GWEN error: Memory block too big (%d>%d)\n",
322 dsize, GWEN_MEMORY_MAXBLOCK);
351 unsigned short bsize;
352 unsigned short rsize;
357 bsize=GWEN_MEMORY_READSIZE(p);
358 rsize=bsize & GWEN_MEMORY_MASK_LEN;
362 unsigned short nsize;
365 nsize=rsize-dsize-GWEN_MEMORY_SIZELEN;
366 np=p+GWEN_MEMORY_SIZELEN+dsize;
370 GWEN_MEMORY_WRITESIZE(np, (nsize & GWEN_MEMORY_MASK_LEN));
375 GWEN_MEMORY_WRITESIZE(p, (dsize |
376 GWEN_MEMORY_MASK_INUSE |
377 GWEN_MEMORY_MASK_MALLOCED));
380 return (
void*)GWEN_MEMORY_GETDATA(p);
386 #ifdef ENABLE_MY_SMALL_BLOCK_ALLOC
393 "GWEN error: allocating 0 bytes, maybe a program error\n");
397 #ifdef ENABLE_MY_SMALL_BLOCK_ALLOC
398 dsize=(wsize+GWEN_MEMORY_GRANULARITY-1) & ~(GWEN_MEMORY_GRANULARITY-1);
400 if (dsize<GWEN_MEMORY_MAXBLOCK) {
412 fprintf(stderr,
"GWEN info: Allocating %u bytes externally\n",
414 pc=(
unsigned char*)malloc(dsize+GWEN_MEMORY_SIZELEN);
416 GWEN_MEMORY_WRITESIZE(pc, GWEN_MEMORY_EXTERNAL);
417 p=GWEN_MEMORY_GETDATA(pc);
425 return malloc(wsize);
432 #ifdef ENABLE_MY_SMALL_BLOCK_ALLOC
435 unsigned short dsize;
436 unsigned short rsize;
442 #ifdef ENABLE_MY_SMALL_BLOCK_ALLOC
443 pc=GWEN_MEMORY_GETSTART(oldp);
444 dsize=GWEN_MEMORY_READSIZE(pc);
445 rsize=dsize & GWEN_MEMORY_MASK_LEN;
447 if (!(dsize & GWEN_MEMORY_MASK_MALLOCED)) {
448 fprintf(stderr,
"GWEN error: Block %p already free'd\n", oldp);
452 if (!(dsize & GWEN_MEMORY_MASK_INUSE)) {
453 fprintf(stderr,
"GWEN error: Block %p not in use\n", oldp);
458 memmove(p, oldp, rsize);
462 return realloc(oldp, nsize);
469 #ifdef ENABLE_MY_SMALL_BLOCK_ALLOC
472 unsigned short dsize;
474 pc=GWEN_MEMORY_GETSTART(p);
475 dsize=GWEN_MEMORY_READSIZE(pc);
477 if (!(dsize & GWEN_MEMORY_MASK_MALLOCED)) {
478 fprintf(stderr,
"GWEN error: Block %p already free'd\n", p);
482 if (!(dsize & GWEN_MEMORY_MASK_INUSE)) {
483 fprintf(stderr,
"GWEN error: Block %p not in use\n", p);
488 GWEN_MEMORY_WRITESIZE(pc,
490 ~GWEN_MEMORY_MASK_MALLOCED &
491 ~GWEN_MEMORY_MASK_INUSE));
494 GWEN_MEMORY_WRITESIZE(pc,
496 ~GWEN_MEMORY_MASK_MALLOCED));
499 if (dsize==GWEN_MEMORY_EXTERNAL) {
511 if (gwen_memory__released_since_collect>GWEN_MEMORY_COLLECT_AFTER){
512 fprintf(stderr,
"GWEN info: collecting free blocks\n");
514 gwen_memory__released_since_collect=0;
527 #ifdef ENABLE_MY_SMALL_BLOCK_ALLOC
533 #ifdef ENABLE_MY_SMALL_BLOCK_ALLOC
538 memmove(p, s, dsize+1);
548 GWEN_MEMORY_TABLE *mt;
560 GWEN_MEMORY_TABLE *mt;