diff options
Diffstat (limited to 'src/tools/lcc/src/alloc.c')
-rw-r--r-- | src/tools/lcc/src/alloc.c | 94 |
1 files changed, 94 insertions, 0 deletions
diff --git a/src/tools/lcc/src/alloc.c b/src/tools/lcc/src/alloc.c new file mode 100644 index 00000000..e0566dfd --- /dev/null +++ b/src/tools/lcc/src/alloc.c @@ -0,0 +1,94 @@ +#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 |