xref: /plan9/sys/src/libc/port/malloc.c (revision 3e12c5d1bb89fc02707907988834ef147769ddaf)
1*3e12c5d1SDavid du Colombier #include <u.h>
2*3e12c5d1SDavid du Colombier #include <libc.h>
3*3e12c5d1SDavid du Colombier 
4*3e12c5d1SDavid du Colombier enum
5*3e12c5d1SDavid du Colombier {
6*3e12c5d1SDavid du Colombier 	MAGIC		= 0xbada110c,
7*3e12c5d1SDavid du Colombier 	MAX2SIZE	= 32,
8*3e12c5d1SDavid du Colombier 	CUTOFF		= 12,
9*3e12c5d1SDavid du Colombier };
10*3e12c5d1SDavid du Colombier 
11*3e12c5d1SDavid du Colombier typedef struct Bucket Bucket;
12*3e12c5d1SDavid du Colombier struct Bucket
13*3e12c5d1SDavid du Colombier {
14*3e12c5d1SDavid du Colombier 	int	size;
15*3e12c5d1SDavid du Colombier 	int	magic;
16*3e12c5d1SDavid du Colombier 	Bucket	*next;
17*3e12c5d1SDavid du Colombier 	char	data[1];
18*3e12c5d1SDavid du Colombier };
19*3e12c5d1SDavid du Colombier 
20*3e12c5d1SDavid du Colombier typedef struct Arena Arena;
21*3e12c5d1SDavid du Colombier struct Arena
22*3e12c5d1SDavid du Colombier {
23*3e12c5d1SDavid du Colombier 	Bucket	*btab[MAX2SIZE];
24*3e12c5d1SDavid du Colombier };
25*3e12c5d1SDavid du Colombier static Arena arena;
26*3e12c5d1SDavid du Colombier 
27*3e12c5d1SDavid du Colombier #define datoff		((int)((Bucket*)0)->data)
28*3e12c5d1SDavid du Colombier #define nil		((void*)0)
29*3e12c5d1SDavid du Colombier 
30*3e12c5d1SDavid du Colombier void*
31*3e12c5d1SDavid du Colombier malloc(long size)
32*3e12c5d1SDavid du Colombier {
33*3e12c5d1SDavid du Colombier 	ulong next;
34*3e12c5d1SDavid du Colombier 	int pow, n;
35*3e12c5d1SDavid du Colombier 	Bucket *bp, *nbp;
36*3e12c5d1SDavid du Colombier 
37*3e12c5d1SDavid du Colombier 	for(pow = 1; pow < MAX2SIZE; pow++) {
38*3e12c5d1SDavid du Colombier 		if(size <= (1<<pow))
39*3e12c5d1SDavid du Colombier 			goto good;
40*3e12c5d1SDavid du Colombier 	}
41*3e12c5d1SDavid du Colombier 
42*3e12c5d1SDavid du Colombier 	return nil;
43*3e12c5d1SDavid du Colombier good:
44*3e12c5d1SDavid du Colombier 	/* Allocate off this list */
45*3e12c5d1SDavid du Colombier 	bp = arena.btab[pow];
46*3e12c5d1SDavid du Colombier 	if(bp) {
47*3e12c5d1SDavid du Colombier 		arena.btab[pow] = bp->next;
48*3e12c5d1SDavid du Colombier 
49*3e12c5d1SDavid du Colombier 		if(bp->magic != 0)
50*3e12c5d1SDavid du Colombier 			abort();
51*3e12c5d1SDavid du Colombier 
52*3e12c5d1SDavid du Colombier 		bp->magic = MAGIC;
53*3e12c5d1SDavid du Colombier 		return  bp->data;
54*3e12c5d1SDavid du Colombier 	}
55*3e12c5d1SDavid du Colombier 	size = sizeof(Bucket)+(1<<pow);
56*3e12c5d1SDavid du Colombier 	size += 3;
57*3e12c5d1SDavid du Colombier 	size &= ~3;
58*3e12c5d1SDavid du Colombier 
59*3e12c5d1SDavid du Colombier 	if(pow < CUTOFF) {
60*3e12c5d1SDavid du Colombier 		n = (CUTOFF-pow)+2;
61*3e12c5d1SDavid du Colombier 		bp = sbrk(size*n);
62*3e12c5d1SDavid du Colombier 		if((int)bp < 0)
63*3e12c5d1SDavid du Colombier 			return nil;
64*3e12c5d1SDavid du Colombier 
65*3e12c5d1SDavid du Colombier 		next = (ulong)bp+size;
66*3e12c5d1SDavid du Colombier 		nbp = (Bucket*)next;
67*3e12c5d1SDavid du Colombier 		arena.btab[pow] = nbp;
68*3e12c5d1SDavid du Colombier 		for(n -= 2; n; n--) {
69*3e12c5d1SDavid du Colombier 			next = (ulong)nbp+size;
70*3e12c5d1SDavid du Colombier 			nbp->next = (Bucket*)next;
71*3e12c5d1SDavid du Colombier 			nbp->size = pow;
72*3e12c5d1SDavid du Colombier 			nbp = nbp->next;
73*3e12c5d1SDavid du Colombier 		}
74*3e12c5d1SDavid du Colombier 		nbp->size = pow;
75*3e12c5d1SDavid du Colombier 	}
76*3e12c5d1SDavid du Colombier 	else {
77*3e12c5d1SDavid du Colombier 		bp = sbrk(size);
78*3e12c5d1SDavid du Colombier 		if((int)bp < 0)
79*3e12c5d1SDavid du Colombier 			return nil;
80*3e12c5d1SDavid du Colombier 	}
81*3e12c5d1SDavid du Colombier 
82*3e12c5d1SDavid du Colombier 	bp->size = pow;
83*3e12c5d1SDavid du Colombier 	bp->magic = MAGIC;
84*3e12c5d1SDavid du Colombier 
85*3e12c5d1SDavid du Colombier 	return bp->data;
86*3e12c5d1SDavid du Colombier }
87*3e12c5d1SDavid du Colombier 
88*3e12c5d1SDavid du Colombier void*
89*3e12c5d1SDavid du Colombier calloc(long n, long size)
90*3e12c5d1SDavid du Colombier {
91*3e12c5d1SDavid du Colombier 	void *p;
92*3e12c5d1SDavid du Colombier 
93*3e12c5d1SDavid du Colombier 	n *= size;
94*3e12c5d1SDavid du Colombier 	p = malloc(n);
95*3e12c5d1SDavid du Colombier 	if(p)
96*3e12c5d1SDavid du Colombier 		memset(p, 0, n);
97*3e12c5d1SDavid du Colombier 
98*3e12c5d1SDavid du Colombier 	return p;
99*3e12c5d1SDavid du Colombier }
100*3e12c5d1SDavid du Colombier 
101*3e12c5d1SDavid du Colombier void
102*3e12c5d1SDavid du Colombier free(void *ptr)
103*3e12c5d1SDavid du Colombier {
104*3e12c5d1SDavid du Colombier 	Bucket *bp, **l;
105*3e12c5d1SDavid du Colombier 
106*3e12c5d1SDavid du Colombier 	if(ptr == nil)
107*3e12c5d1SDavid du Colombier 		return;
108*3e12c5d1SDavid du Colombier 
109*3e12c5d1SDavid du Colombier 	/* Find the start of the structure */
110*3e12c5d1SDavid du Colombier 	bp = (Bucket*)((uint)ptr - datoff);
111*3e12c5d1SDavid du Colombier 
112*3e12c5d1SDavid du Colombier 	if(bp->magic != MAGIC)
113*3e12c5d1SDavid du Colombier 		abort();
114*3e12c5d1SDavid du Colombier 
115*3e12c5d1SDavid du Colombier 	bp->magic = 0;
116*3e12c5d1SDavid du Colombier 	l = &arena.btab[bp->size];
117*3e12c5d1SDavid du Colombier 	bp->next = *l;
118*3e12c5d1SDavid du Colombier 	*l = bp;
119*3e12c5d1SDavid du Colombier }
120*3e12c5d1SDavid du Colombier 
121*3e12c5d1SDavid du Colombier void*
122*3e12c5d1SDavid du Colombier realloc(void *ptr, long n)
123*3e12c5d1SDavid du Colombier {
124*3e12c5d1SDavid du Colombier 	void *new;
125*3e12c5d1SDavid du Colombier 	uint osize;
126*3e12c5d1SDavid du Colombier 	Bucket *bp;
127*3e12c5d1SDavid du Colombier 
128*3e12c5d1SDavid du Colombier 	if(ptr == nil)
129*3e12c5d1SDavid du Colombier 		return malloc(n);
130*3e12c5d1SDavid du Colombier 
131*3e12c5d1SDavid du Colombier 	/* Find the start of the structure */
132*3e12c5d1SDavid du Colombier 	bp = (Bucket*)((uint)ptr - datoff);
133*3e12c5d1SDavid du Colombier 
134*3e12c5d1SDavid du Colombier 	if(bp->magic != MAGIC)
135*3e12c5d1SDavid du Colombier 		abort();
136*3e12c5d1SDavid du Colombier 
137*3e12c5d1SDavid du Colombier 	/* enough space in this bucket */
138*3e12c5d1SDavid du Colombier 	osize = 1<<bp->size;
139*3e12c5d1SDavid du Colombier 	if(osize >= n)
140*3e12c5d1SDavid du Colombier 		return ptr;
141*3e12c5d1SDavid du Colombier 
142*3e12c5d1SDavid du Colombier 	new = malloc(n);
143*3e12c5d1SDavid du Colombier 	if(new == nil)
144*3e12c5d1SDavid du Colombier 		return nil;
145*3e12c5d1SDavid du Colombier 
146*3e12c5d1SDavid du Colombier 	memmove(new, ptr, osize);
147*3e12c5d1SDavid du Colombier 	free(ptr);
148*3e12c5d1SDavid du Colombier 
149*3e12c5d1SDavid du Colombier 	return new;
150*3e12c5d1SDavid du Colombier }
151