13e12c5d1SDavid du Colombier #include <stdlib.h>
23e12c5d1SDavid du Colombier #include <string.h>
3*306ddfb6SDavid du Colombier #include <inttypes.h>
43e12c5d1SDavid du Colombier
53e12c5d1SDavid du Colombier typedef unsigned int uint;
63e12c5d1SDavid du Colombier
73e12c5d1SDavid du Colombier enum
83e12c5d1SDavid du Colombier {
93e12c5d1SDavid du Colombier MAGIC = 0xbada110c,
103e12c5d1SDavid du Colombier MAX2SIZE = 32,
113e12c5d1SDavid du Colombier CUTOFF = 12,
123e12c5d1SDavid du Colombier };
133e12c5d1SDavid du Colombier
143e12c5d1SDavid du Colombier typedef struct Bucket Bucket;
153e12c5d1SDavid du Colombier struct Bucket
163e12c5d1SDavid du Colombier {
173e12c5d1SDavid du Colombier int size;
183e12c5d1SDavid du Colombier int magic;
193e12c5d1SDavid du Colombier Bucket *next;
20219b2ee8SDavid du Colombier int pad;
213e12c5d1SDavid du Colombier char data[1];
223e12c5d1SDavid du Colombier };
233e12c5d1SDavid du Colombier
243e12c5d1SDavid du Colombier typedef struct Arena Arena;
253e12c5d1SDavid du Colombier struct Arena
263e12c5d1SDavid du Colombier {
273e12c5d1SDavid du Colombier Bucket *btab[MAX2SIZE];
283e12c5d1SDavid du Colombier };
293e12c5d1SDavid du Colombier static Arena arena;
303e12c5d1SDavid du Colombier
313e12c5d1SDavid du Colombier #define datoff ((int)((Bucket*)0)->data)
323e12c5d1SDavid du Colombier #define nil ((void*)0)
333e12c5d1SDavid du Colombier
343e12c5d1SDavid du Colombier extern void *sbrk(unsigned long);
353e12c5d1SDavid du Colombier
363e12c5d1SDavid du Colombier void*
malloc(size_t size)373e12c5d1SDavid du Colombier malloc(size_t size)
383e12c5d1SDavid du Colombier {
393e12c5d1SDavid du Colombier uint next;
403e12c5d1SDavid du Colombier int pow, n;
413e12c5d1SDavid du Colombier Bucket *bp, *nbp;
423e12c5d1SDavid du Colombier
433e12c5d1SDavid du Colombier for(pow = 1; pow < MAX2SIZE; pow++) {
443e12c5d1SDavid du Colombier if(size <= (1<<pow))
453e12c5d1SDavid du Colombier goto good;
463e12c5d1SDavid du Colombier }
473e12c5d1SDavid du Colombier
483e12c5d1SDavid du Colombier return nil;
493e12c5d1SDavid du Colombier good:
503e12c5d1SDavid du Colombier /* Allocate off this list */
513e12c5d1SDavid du Colombier bp = arena.btab[pow];
523e12c5d1SDavid du Colombier if(bp) {
533e12c5d1SDavid du Colombier arena.btab[pow] = bp->next;
543e12c5d1SDavid du Colombier
553e12c5d1SDavid du Colombier if(bp->magic != 0)
563e12c5d1SDavid du Colombier abort();
573e12c5d1SDavid du Colombier
583e12c5d1SDavid du Colombier bp->magic = MAGIC;
593e12c5d1SDavid du Colombier return bp->data;
603e12c5d1SDavid du Colombier }
613e12c5d1SDavid du Colombier size = sizeof(Bucket)+(1<<pow);
62219b2ee8SDavid du Colombier size += 7;
63219b2ee8SDavid du Colombier size &= ~7;
643e12c5d1SDavid du Colombier
653e12c5d1SDavid du Colombier if(pow < CUTOFF) {
663e12c5d1SDavid du Colombier n = (CUTOFF-pow)+2;
673e12c5d1SDavid du Colombier bp = sbrk(size*n);
68*306ddfb6SDavid du Colombier if((intptr_t)bp == -1)
693e12c5d1SDavid du Colombier return nil;
703e12c5d1SDavid du Colombier
713e12c5d1SDavid du Colombier next = (uint)bp+size;
723e12c5d1SDavid du Colombier nbp = (Bucket*)next;
733e12c5d1SDavid du Colombier arena.btab[pow] = nbp;
743e12c5d1SDavid du Colombier for(n -= 2; n; n--) {
753e12c5d1SDavid du Colombier next = (uint)nbp+size;
763e12c5d1SDavid du Colombier nbp->next = (Bucket*)next;
773e12c5d1SDavid du Colombier nbp->size = pow;
783e12c5d1SDavid du Colombier nbp = nbp->next;
793e12c5d1SDavid du Colombier }
803e12c5d1SDavid du Colombier nbp->size = pow;
813e12c5d1SDavid du Colombier }
823e12c5d1SDavid du Colombier else {
833e12c5d1SDavid du Colombier bp = sbrk(size);
84*306ddfb6SDavid du Colombier if((intptr_t)bp == -1)
853e12c5d1SDavid du Colombier return nil;
863e12c5d1SDavid du Colombier }
873e12c5d1SDavid du Colombier
883e12c5d1SDavid du Colombier bp->size = pow;
893e12c5d1SDavid du Colombier bp->magic = MAGIC;
903e12c5d1SDavid du Colombier
913e12c5d1SDavid du Colombier return bp->data;
923e12c5d1SDavid du Colombier }
933e12c5d1SDavid du Colombier
943e12c5d1SDavid du Colombier void
free(void * ptr)953e12c5d1SDavid du Colombier free(void *ptr)
963e12c5d1SDavid du Colombier {
973e12c5d1SDavid du Colombier Bucket *bp, **l;
983e12c5d1SDavid du Colombier
993e12c5d1SDavid du Colombier if(ptr == nil)
1003e12c5d1SDavid du Colombier return;
1013e12c5d1SDavid du Colombier
1023e12c5d1SDavid du Colombier /* Find the start of the structure */
1033e12c5d1SDavid du Colombier bp = (Bucket*)((uint)ptr - datoff);
1043e12c5d1SDavid du Colombier
1053e12c5d1SDavid du Colombier if(bp->magic != MAGIC)
1063e12c5d1SDavid du Colombier abort();
1073e12c5d1SDavid du Colombier
1083e12c5d1SDavid du Colombier bp->magic = 0;
1093e12c5d1SDavid du Colombier l = &arena.btab[bp->size];
1103e12c5d1SDavid du Colombier bp->next = *l;
1113e12c5d1SDavid du Colombier *l = bp;
1123e12c5d1SDavid du Colombier }
1133e12c5d1SDavid du Colombier
1143e12c5d1SDavid du Colombier void*
realloc(void * ptr,size_t n)1153e12c5d1SDavid du Colombier realloc(void *ptr, size_t n)
1163e12c5d1SDavid du Colombier {
1173e12c5d1SDavid du Colombier void *new;
1183e12c5d1SDavid du Colombier uint osize;
1193e12c5d1SDavid du Colombier Bucket *bp;
1203e12c5d1SDavid du Colombier
1213e12c5d1SDavid du Colombier if(ptr == nil)
1223e12c5d1SDavid du Colombier return malloc(n);
1233e12c5d1SDavid du Colombier
1243e12c5d1SDavid du Colombier /* Find the start of the structure */
1253e12c5d1SDavid du Colombier bp = (Bucket*)((uint)ptr - datoff);
1263e12c5d1SDavid du Colombier
1273e12c5d1SDavid du Colombier if(bp->magic != MAGIC)
1283e12c5d1SDavid du Colombier abort();
1293e12c5d1SDavid du Colombier
1303e12c5d1SDavid du Colombier /* enough space in this bucket */
1313e12c5d1SDavid du Colombier osize = 1<<bp->size;
1323e12c5d1SDavid du Colombier if(osize >= n)
1333e12c5d1SDavid du Colombier return ptr;
1343e12c5d1SDavid du Colombier
1353e12c5d1SDavid du Colombier new = malloc(n);
1363e12c5d1SDavid du Colombier if(new == nil)
1373e12c5d1SDavid du Colombier return nil;
1383e12c5d1SDavid du Colombier
1393e12c5d1SDavid du Colombier memmove(new, ptr, osize);
1403e12c5d1SDavid du Colombier free(ptr);
1413e12c5d1SDavid du Colombier
1423e12c5d1SDavid du Colombier return new;
1433e12c5d1SDavid du Colombier }
144