2005-08-26 04:48:05 +00:00
|
|
|
#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
|