1 #include <stdlib.h> 2 #include "list.h" 3 #include "error.h" 4 #include "bin.h" 5 #include "mem.h" 6 7 #define MEM_PRE 4096 8 static align_t local_store[MEM_PRE / MEM_ALIGN]; 9 #define space ((char *)local_store) 10 static unsigned int avail = MEM_PRE; 11 static int bomb_gc = 0; 12 static list_t gc = 0; 13 mem_alloc(int bytes)14void inline *mem_alloc(int bytes) 15 { 16 int (*fn)(void *); 17 register char *x; 18 int tries = 0; 19 list_t lp; 20 21 /* could overflow if MEM_ALIGN is too large */ 22 bytes = MEM_ALIGN + bytes - (bytes & (MEM_ALIGN - 1)); 23 if (bytes <= avail) { 24 avail -= bytes; 25 return space + avail; 26 } 27 28 /* Clib */ 29 retry_l:x = malloc(bytes); 30 if (!x) { 31 if (bomb_gc && tries > 9) { 32 /* try at most 10 times... if bomb_gc is set, bad things 33 * are going to happen anyway... 34 */ 35 errno = ENOMEM; 36 return x; 37 } 38 /* try gc handlers */ 39 for (lp = gc; lp; lp = lp->next) { 40 x = lp->str; 41 fn = (int (*)(void *))(((char *)lp->str)+sizeof(char *)); 42 if (fn(x)) { 43 tries++; 44 goto retry_l; 45 } 46 } 47 errno = ENOMEM; 48 } 49 return x; 50 } mem_free(void * x)51void mem_free(void *x) 52 { 53 /* this assumes a flat address space */ 54 if (((char *)x) >= space && ((char *)x) <= space + MEM_PRE) 55 return; 56 free(x); 57 } mem_register_gc(void * x,int (* fn)(void * x))58void mem_register_gc(void *x, int (*fn)(void *x)) 59 { 60 bin_t c; 61 62 if (!fn) return; 63 64 bomb_gc = 1; 65 bin_init(c); 66 bin_copy(c, (char *)&x, sizeof(char *)); 67 bin_cat(c, (char *)&fn, sizeof(char *)); 68 list_push(&gc, caddr(c)); 69 bomb_gc = 0; 70 } 71 72