1 #include "c.h"
2 struct block {
3 	struct block *next;
4 	char *limit;
5 	char *avail;
6 };
7 union align {
8 	long l;
9 	char *p;
10 	double d;
11 	int (*f)(void);
12 };
13 union header {
14 	struct block b;
15 	union align a;
16 };
17 #ifdef PURIFY
18 union header *arena[3];
19 
allocate(unsigned long n,unsigned a)20 void *allocate(unsigned long n, unsigned a) {
21 	union header *new = malloc(sizeof *new + n);
22 
23 	assert(a < NELEMS(arena));
24 	if (new == NULL) {
25 		error("insufficient memory\n");
26 		exit(1);
27 	}
28 	new->b.next = (void *)arena[a];
29 	arena[a] = new;
30 	return new + 1;
31 }
32 
deallocate(unsigned a)33 void deallocate(unsigned a) {
34 	union header *p, *q;
35 
36 	assert(a < NELEMS(arena));
37 	for (p = arena[a]; p; p = q) {
38 		q = (void *)p->b.next;
39 		free(p);
40 	}
41 	arena[a] = NULL;
42 }
43 
newarray(unsigned long m,unsigned long n,unsigned a)44 void *newarray(unsigned long m, unsigned long n, unsigned a) {
45 	return allocate(m*n, a);
46 }
47 #else
48 static struct block
49 	 first[] = {  { NULL },  { NULL },  { NULL } },
50 	*arena[] = { &first[0], &first[1], &first[2] };
51 static struct block *freeblocks;
52 
allocate(unsigned long n,unsigned a)53 void *allocate(unsigned long n, unsigned a) {
54 	struct block *ap;
55 
56 	assert(a < NELEMS(arena));
57 	assert(n > 0);
58 	ap = arena[a];
59 	n = roundup(n, sizeof (union align));
60 	while (n > ap->limit - ap->avail) {
61 		if ((ap->next = freeblocks) != NULL) {
62 			freeblocks = freeblocks->next;
63 			ap = ap->next;
64 		} else
65 			{
66 				unsigned m = sizeof (union header) + n + roundup(10*1024, sizeof (union align));
67 				ap->next = malloc(m);
68 				ap = ap->next;
69 				if (ap == NULL) {
70 					error("insufficient memory\n");
71 					exit(1);
72 				}
73 				ap->limit = (char *)ap + m;
74 			}
75 		ap->avail = (char *)((union header *)ap + 1);
76 		ap->next = NULL;
77 		arena[a] = ap;
78 
79 	}
80 	ap->avail += n;
81 	return ap->avail - n;
82 }
83 
newarray(unsigned long m,unsigned long n,unsigned a)84 void *newarray(unsigned long m, unsigned long n, unsigned a) {
85 	return allocate(m*n, a);
86 }
deallocate(unsigned a)87 void deallocate(unsigned a) {
88 	assert(a < NELEMS(arena));
89 	arena[a]->next = freeblocks;
90 	freeblocks = first[a].next;
91 	first[a].next = NULL;
92 	arena[a] = &first[a];
93 }
94 #endif
95