00001 #include "c.h"
00002 struct block {
00003 struct block *next;
00004 char *limit;
00005 char *avail;
00006 };
00007 union align {
00008 long l;
00009 char *p;
00010 double d;
00011 int (*f)(void);
00012 };
00013 union header {
00014 struct block b;
00015 union align a;
00016 };
00017 #ifdef PURIFY
00018 union header *arena[3];
00019
00020 void *allocate(unsigned long n, unsigned a) {
00021 union header *new = malloc(sizeof *new + n);
00022
00023 assert(a < NELEMS(arena));
00024 if (new == NULL) {
00025 error("insufficient memory\n");
00026 exit(1);
00027 }
00028 new->b.next = (void *)arena[a];
00029 arena[a] = new;
00030 return new + 1;
00031 }
00032
00033 void deallocate(unsigned a) {
00034 union header *p, *q;
00035
00036 assert(a < NELEMS(arena));
00037 for (p = arena[a]; p; p = q) {
00038 q = (void *)p->b.next;
00039 free(p);
00040 }
00041 arena[a] = NULL;
00042 }
00043
00044 void *newarray(unsigned long m, unsigned long n, unsigned a) {
00045 return allocate(m*n, a);
00046 }
00047 #else
00048 static struct block
00049 first[] = { { NULL }, { NULL }, { NULL } },
00050 *arena[] = { &first[0], &first[1], &first[2] };
00051 static struct block *freeblocks;
00052
00053 void *allocate(unsigned long n, unsigned a) {
00054 struct block *ap;
00055
00056 assert(a < NELEMS(arena));
00057 assert(n > 0);
00058 ap = arena[a];
00059 n = roundup(n, sizeof (union align));
00060 while (n > ap->limit - ap->avail) {
00061 if ((ap->next = freeblocks) != NULL) {
00062 freeblocks = freeblocks->next;
00063 ap = ap->next;
00064 } else
00065 {
00066 unsigned m = sizeof (union header) + n + roundup(10*1024, sizeof (union align));
00067 ap->next = malloc(m);
00068 ap = ap->next;
00069 if (ap == NULL) {
00070 error("insufficient memory\n");
00071 exit(1);
00072 }
00073 ap->limit = (char *)ap + m;
00074 }
00075 ap->avail = (char *)((union header *)ap + 1);
00076 ap->next = NULL;
00077 arena[a] = ap;
00078
00079 }
00080 ap->avail += n;
00081 return ap->avail - n;
00082 }
00083
00084 void *newarray(unsigned long m, unsigned long n, unsigned a) {
00085 return allocate(m*n, a);
00086 }
00087 void deallocate(unsigned a) {
00088 assert(a < NELEMS(arena));
00089 arena[a]->next = freeblocks;
00090 freeblocks = first[a].next;
00091 first[a].next = NULL;
00092 arena[a] = &first[a];
00093 }
00094 #endif