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