Quake-III-Arena

Quake III Arena GPL Source Release
Log | Files | Refs

alloc.c (1866B)


      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 
     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 
     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 
     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 
     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 
     84 void *newarray(unsigned long m, unsigned long n, unsigned a) {
     85 	return allocate(m*n, a);
     86 }
     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