#include <stdlib.h>
#include "list.h"
#include "error.h"
#include "bin.h"
#include "mem.h"
#define MEM_PRE 4096
static align_t local_store[MEM_PRE / MEM_ALIGN];
#define space ((char *)local_store)
static unsigned int avail = MEM_PRE;
static int bomb_gc = 0;
static list_t gc = 0;
void inline *mem_alloc(int bytes)
{
int (*fn)(void *);
register char *x;
int tries = 0;
list_t lp;
/* could overflow if MEM_ALIGN is too large */
bytes = MEM_ALIGN + bytes - (bytes & (MEM_ALIGN - 1));
if (bytes <= avail) {
avail -= bytes;
return space + avail;
}
/* Clib */
retry_l:x = malloc(bytes);
if (!x) {
if (bomb_gc && tries > 9) {
/* try at most 10 times... if bomb_gc is set, bad things
* are going to happen anyway...
*/
errno = ENOMEM;
return x;
}
/* try gc handlers */
for (lp = gc; lp; lp = lp->next) {
x = lp->str;
fn = (int (*)(void *))(((char *)lp->str)+sizeof(char *));
if (fn(x)) {
tries++;
goto retry_l;
}
}
errno = ENOMEM;
}
return x;
}
void mem_free(void *x)
{
/* this assumes a flat address space */
if (((char *)x) >= space && ((char *)x) <= space + MEM_PRE)
return;
free(x);
}
void mem_register_gc(void *x, int (*fn)(void *x))
{
bin_t c;
if (!fn) return;
bomb_gc = 1;
bin_init(c);
bin_copy(c, (char *)&x, sizeof(char *));
bin_cat(c, (char *)&fn, sizeof(char *));
list_push(&gc, caddr(c));
bomb_gc = 0;
}
syntax highlighted by Code2HTML, v. 0.9.1