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)14 void 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)51 void 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))58 void 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