| #include "c.h" |
| struct block { |
| struct block *next; |
| char *limit; |
| char *avail; |
| }; |
| union align { |
| long l; |
| char *p; |
| double d; |
| int (*f)(void); |
| }; |
| union header { |
| struct block b; |
| union align a; |
| }; |
| #ifdef PURIFY |
| union header *arena[3]; |
| |
| void *allocate(unsigned long n, unsigned a) { |
| union header *new = malloc(sizeof *new + n); |
| |
| assert(a < NELEMS(arena)); |
| if (new == NULL) { |
| error("insufficient memory\n"); |
| exit(1); |
| } |
| new->b.next = (void *)arena[a]; |
| arena[a] = new; |
| return new + 1; |
| } |
| |
| void deallocate(unsigned a) { |
| union header *p, *q; |
| |
| assert(a < NELEMS(arena)); |
| for (p = arena[a]; p; p = q) { |
| q = (void *)p->b.next; |
| free(p); |
| } |
| arena[a] = NULL; |
| } |
| |
| void *newarray(unsigned long m, unsigned long n, unsigned a) { |
| return allocate(m*n, a); |
| } |
| #else |
| static struct block |
| first[] = { { NULL }, { NULL }, { NULL } }, |
| *arena[] = { &first[0], &first[1], &first[2] }; |
| static struct block *freeblocks; |
| |
| void *allocate(unsigned long n, unsigned a) { |
| struct block *ap; |
| |
| assert(a < NELEMS(arena)); |
| assert(n > 0); |
| ap = arena[a]; |
| n = roundup(n, sizeof (union align)); |
| while (n > ap->limit - ap->avail) { |
| if ((ap->next = freeblocks) != NULL) { |
| freeblocks = freeblocks->next; |
| ap = ap->next; |
| } else |
| { |
| unsigned m = sizeof (union header) + n + roundup(10*1024, sizeof (union align)); |
| ap->next = malloc(m); |
| ap = ap->next; |
| if (ap == NULL) { |
| error("insufficient memory\n"); |
| exit(1); |
| } |
| ap->limit = (char *)ap + m; |
| } |
| ap->avail = (char *)((union header *)ap + 1); |
| ap->next = NULL; |
| arena[a] = ap; |
| |
| } |
| ap->avail += n; |
| return ap->avail - n; |
| } |
| |
| void *newarray(unsigned long m, unsigned long n, unsigned a) { |
| return allocate(m*n, a); |
| } |
| void deallocate(unsigned a) { |
| assert(a < NELEMS(arena)); |
| arena[a]->next = freeblocks; |
| freeblocks = first[a].next; |
| first[a].next = NULL; |
| arena[a] = &first[a]; |
| } |
| #endif |