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);
387 #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);
434 #ifdef ENABLE_MY_SMALL_BLOCK_ALLOC
437 unsigned short dsize;
438 unsigned short rsize;
444 #ifdef ENABLE_MY_SMALL_BLOCK_ALLOC
445 pc=GWEN_MEMORY_GETSTART(oldp);
446 dsize=GWEN_MEMORY_READSIZE(pc);
447 rsize=dsize & GWEN_MEMORY_MASK_LEN;
449 if (!(dsize & GWEN_MEMORY_MASK_MALLOCED)) {
450 fprintf(stderr,
"GWEN error: Block %p already free'd\n", oldp);
454 if (!(dsize & GWEN_MEMORY_MASK_INUSE)) {
455 fprintf(stderr,
"GWEN error: Block %p not in use\n", oldp);
462 memmove(p, oldp, rsize);
466 return realloc(oldp, nsize);
473 #ifdef ENABLE_MY_SMALL_BLOCK_ALLOC
476 unsigned short dsize;
478 pc=GWEN_MEMORY_GETSTART(p);
479 dsize=GWEN_MEMORY_READSIZE(pc);
481 if (!(dsize & GWEN_MEMORY_MASK_MALLOCED)) {
482 fprintf(stderr,
"GWEN error: Block %p already free'd\n", p);
486 if (!(dsize & GWEN_MEMORY_MASK_INUSE)) {
487 fprintf(stderr,
"GWEN error: Block %p not in use\n", p);
492 GWEN_MEMORY_WRITESIZE(pc,
494 ~GWEN_MEMORY_MASK_MALLOCED &
495 ~GWEN_MEMORY_MASK_INUSE));
498 GWEN_MEMORY_WRITESIZE(pc,
500 ~GWEN_MEMORY_MASK_MALLOCED));
503 if (dsize==GWEN_MEMORY_EXTERNAL) {
515 if (gwen_memory__released_since_collect>GWEN_MEMORY_COLLECT_AFTER) {
516 fprintf(stderr,
"GWEN info: collecting free blocks\n");
518 gwen_memory__released_since_collect=0;
531 #ifdef ENABLE_MY_SMALL_BLOCK_ALLOC
537 #ifdef ENABLE_MY_SMALL_BLOCK_ALLOC
542 memmove(p, s, dsize+1);
552 GWEN_MEMORY_TABLE *mt;
564 GWEN_MEMORY_TABLE *mt;
void GWEN_Memory_Table__Dump(GWEN_MEMORY_TABLE *mt)
void GWEN_Memory_Collect(void)
char * GWEN_Memory_strdup(const char *s)
unsigned char * GWEN_Memory_Table__FindFreeBlock(GWEN_MEMORY_TABLE *mt, unsigned short dsize)
GWEN_MEMORY_TABLE * GWEN_Memory_Table_new(void)
void GWEN_Memory_dealloc(void *p)
void GWEN_Memory_Report(void)
static GWEN_MEMORY_TABLE * gwen_memory__first_table
void GWEN_Memory_Dump(void)
void GWEN_Memory_Table_Append(GWEN_MEMORY_TABLE *head, GWEN_MEMORY_TABLE *mt)
void * GWEN_Memory_malloc(size_t wsize)
int GWEN_Memory_ModuleInit(void)
static size_t gwen_memory__allocated_reused
void GWEN_Memory_Table__Collect(GWEN_MEMORY_TABLE *mt)
unsigned char * GWEN_Memory__FindFreeBlock(unsigned short dsize)
void GWEN_Memory_Table_free(GWEN_MEMORY_TABLE *mt)
void GWEN_Memory_Table__CollectAt(GWEN_MEMORY_TABLE *mt, unsigned char *p)
static int gwen_memory__verbous
static size_t gwen_memory__allocated_bytes
#define GWEN_LIKELY(cond)
void * GWEN_Memory_realloc(void *oldp, size_t nsize)
static int gwen_memory__debug
static int gwen_memory__nofree
#define GWEN_UNLIKELY(cond)
void GWEN_Memory_Table_Insert(GWEN_MEMORY_TABLE *mt)
int GWEN_Memory_ModuleFini(void)
static size_t gwen_memory__allocated_calls
void * GWEN_Memory__Malloc(unsigned short dsize)