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;
68 s=getenv(GWEN_MEMORY_ENV_DEBUG);
70 fprintf(stderr,
"Memory debugging is enabled\n");
82 GWEN_MEMORY_TABLE *mt;
86 GWEN_MEMORY_TABLE *next;
115 "GWEN info: %zu %s allocated in %zu calls " 116 "(%zu times reused, average %zu bytes)\n",
139 GWEN_MEMORY_TABLE *mt;
141 unsigned short dsize;
144 fprintf(stderr,
"GWEN info: allocating memory table\n");
145 mt=(GWEN_MEMORY_TABLE *)malloc(
sizeof(GWEN_MEMORY_TABLE));
147 memset(mt, 0,
sizeof(GWEN_MEMORY_TABLE));
148 dsize=GWEN_MEMORY_MAXBLOCK;
150 GWEN_MEMORY_WRITESIZE(p, dsize);
165 end=p+GWEN_MEMORY_TABLE_LEN;
167 unsigned short bsize;
168 unsigned short rsize;
170 bsize=GWEN_MEMORY_READSIZE(p);
171 rsize=bsize & GWEN_MEMORY_MASK_LEN;
172 if (bsize & GWEN_MEMORY_MASK_MALLOCED) {
174 "GWEN warning: Block %p still allocated (%d bytes)\n",
175 GWEN_MEMORY_GETDATA(p),
178 p+=rsize+GWEN_MEMORY_SIZELEN;
189 GWEN_MEMORY_TABLE *last;
211 unsigned short dsize)
216 end=mt->data+GWEN_MEMORY_TABLE_LEN;
219 unsigned short bsize;
220 unsigned short rsize;
222 bsize=GWEN_MEMORY_READSIZE(p);
223 rsize=bsize & GWEN_MEMORY_MASK_LEN;
228 if (rsize && !(bsize & GWEN_MEMORY_MASK_INUSE)) {
231 rsize>=(dsize+GWEN_MEMORY_SIZELEN+GWEN_MEMORY_MINREMAIN)) {
235 p+=rsize+GWEN_MEMORY_SIZELEN;
247 unsigned short nsize=0;
252 end=mt->data+GWEN_MEMORY_TABLE_LEN;
255 unsigned short bsize;
256 unsigned short rsize;
258 bsize=GWEN_MEMORY_READSIZE(np);
259 rsize=bsize & GWEN_MEMORY_MASK_LEN;
260 if (rsize && !(bsize & GWEN_MEMORY_MASK_INUSE)) {
263 nsize+=GWEN_MEMORY_SIZELEN;
269 np+=rsize+GWEN_MEMORY_SIZELEN;
273 fprintf(stderr,
"GWEN info: collected %u bytes\n", nsize);
274 GWEN_MEMORY_WRITESIZE(p, nsize);
287 end=mt->data+GWEN_MEMORY_TABLE_LEN;
290 unsigned short bsize;
291 unsigned short rsize;
294 bsize=GWEN_MEMORY_READSIZE(p);
295 rsize=bsize & GWEN_MEMORY_MASK_LEN;
296 p+=rsize+GWEN_MEMORY_SIZELEN;
308 end=p+GWEN_MEMORY_TABLE_LEN;
310 unsigned short bsize;
311 unsigned short rsize;
313 bsize=GWEN_MEMORY_READSIZE(p);
314 rsize=bsize & GWEN_MEMORY_MASK_LEN;
316 "GWEN debug: at %5zu: found block with %5u bytes [%p] (%s)\n",
320 (bsize & GWEN_MEMORY_MASK_INUSE)?
"used":
"free");
321 p+=rsize+GWEN_MEMORY_SIZELEN;
329 GWEN_MEMORY_TABLE *mt;
332 if (dsize>GWEN_MEMORY_MAXBLOCK) {
333 fprintf(stderr,
"GWEN error: Memory block too big (%d>%d)\n",
334 dsize, GWEN_MEMORY_MAXBLOCK);
364 unsigned short bsize;
365 unsigned short rsize;
370 bsize=GWEN_MEMORY_READSIZE(p);
371 rsize=bsize & GWEN_MEMORY_MASK_LEN;
375 unsigned short nsize;
378 nsize=rsize-dsize-GWEN_MEMORY_SIZELEN;
379 np=p+GWEN_MEMORY_SIZELEN+dsize;
383 GWEN_MEMORY_WRITESIZE(np, (nsize & GWEN_MEMORY_MASK_LEN));
388 GWEN_MEMORY_WRITESIZE(p, (dsize |
389 GWEN_MEMORY_MASK_INUSE |
390 GWEN_MEMORY_MASK_MALLOCED));
393 return (
void *)GWEN_MEMORY_GETDATA(p);
401 #ifdef ENABLE_MY_SMALL_BLOCK_ALLOC 407 "GWEN error: allocating 0 bytes, maybe a program error\n");
411 #ifdef ENABLE_MY_SMALL_BLOCK_ALLOC 412 dsize=(wsize+GWEN_MEMORY_GRANULARITY-1) & ~(GWEN_MEMORY_GRANULARITY-1);
414 if (dsize<GWEN_MEMORY_MAXBLOCK) {
426 fprintf(stderr,
"GWEN info: Allocating %u bytes externally\n",
428 pc=(
unsigned char *)malloc(dsize+GWEN_MEMORY_SIZELEN);
430 GWEN_MEMORY_WRITESIZE(pc, GWEN_MEMORY_EXTERNAL);
431 p=GWEN_MEMORY_GETDATA(pc);
449 #ifdef ENABLE_MY_SMALL_BLOCK_ALLOC 452 unsigned short dsize;
453 unsigned short rsize;
459 #ifdef ENABLE_MY_SMALL_BLOCK_ALLOC 460 pc=GWEN_MEMORY_GETSTART(oldp);
461 dsize=GWEN_MEMORY_READSIZE(pc);
462 rsize=dsize & GWEN_MEMORY_MASK_LEN;
464 if (!(dsize & GWEN_MEMORY_MASK_MALLOCED)) {
465 fprintf(stderr,
"GWEN error: Block %p already free'd\n", oldp);
469 if (!(dsize & GWEN_MEMORY_MASK_INUSE)) {
470 fprintf(stderr,
"GWEN error: Block %p not in use\n", oldp);
477 memmove(p, oldp, rsize);
481 return realloc(oldp, nsize);
489 #ifdef ENABLE_MY_SMALL_BLOCK_ALLOC 492 unsigned short dsize;
494 pc=GWEN_MEMORY_GETSTART(p);
495 dsize=GWEN_MEMORY_READSIZE(pc);
497 if (!(dsize & GWEN_MEMORY_MASK_MALLOCED)) {
498 fprintf(stderr,
"GWEN error: Block %p already free'd\n", p);
502 if (!(dsize & GWEN_MEMORY_MASK_INUSE)) {
503 fprintf(stderr,
"GWEN error: Block %p not in use\n", p);
508 GWEN_MEMORY_WRITESIZE(pc,
510 ~GWEN_MEMORY_MASK_MALLOCED &
511 ~GWEN_MEMORY_MASK_INUSE));
514 GWEN_MEMORY_WRITESIZE(pc,
516 ~GWEN_MEMORY_MASK_MALLOCED));
519 if (dsize==GWEN_MEMORY_EXTERNAL) {
531 if (gwen_memory__released_since_collect>GWEN_MEMORY_COLLECT_AFTER) {
532 fprintf(stderr,
"GWEN info: collecting free blocks\n");
534 gwen_memory__released_since_collect=0;
548 #ifdef ENABLE_MY_SMALL_BLOCK_ALLOC 554 #ifdef ENABLE_MY_SMALL_BLOCK_ALLOC 559 memmove(p, s, dsize+1);
570 GWEN_MEMORY_TABLE *mt;
583 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)