xref: /plan9/sys/src/libbin/bin.c (revision 74f16c8187aab477889167f2422d0597b1b7d0ff)
180ee5cbfSDavid du Colombier #include <u.h>
280ee5cbfSDavid du Colombier #include <libc.h>
380ee5cbfSDavid du Colombier #include <bin.h>
480ee5cbfSDavid du Colombier 
580ee5cbfSDavid du Colombier enum
680ee5cbfSDavid du Colombier {
76b6b9ac8SDavid du Colombier 	StructAlign = sizeof(union {vlong vl; double d; ulong p; void *v;
86b6b9ac8SDavid du Colombier 				struct{vlong v;}vs; struct{double d;}ds; struct{ulong p;}ss; struct{void *v;}xs;})
980ee5cbfSDavid du Colombier };
1080ee5cbfSDavid du Colombier 
1180ee5cbfSDavid du Colombier enum
1280ee5cbfSDavid du Colombier {
1380ee5cbfSDavid du Colombier 	BinSize	= 8*1024
1480ee5cbfSDavid du Colombier };
1580ee5cbfSDavid du Colombier 
1680ee5cbfSDavid du Colombier struct Bin
1780ee5cbfSDavid du Colombier {
1880ee5cbfSDavid du Colombier 	Bin	*next;
1980ee5cbfSDavid du Colombier 	ulong	total;			/* total bytes allocated in can->next */
20*74f16c81SDavid du Colombier 	uintptr	pos;
21*74f16c81SDavid du Colombier 	uintptr	end;
22*74f16c81SDavid du Colombier 	uintptr	v;			/* last value allocated */
2380ee5cbfSDavid du Colombier 	uchar	body[BinSize];
2480ee5cbfSDavid du Colombier };
2580ee5cbfSDavid du Colombier 
2680ee5cbfSDavid du Colombier /*
2780ee5cbfSDavid du Colombier  * allocator which allows an entire set to be freed at one time
2880ee5cbfSDavid du Colombier  */
2980ee5cbfSDavid du Colombier static Bin*
mkbin(Bin * bin,ulong size)3080ee5cbfSDavid du Colombier mkbin(Bin *bin, ulong size)
3180ee5cbfSDavid du Colombier {
3280ee5cbfSDavid du Colombier 	Bin *b;
3380ee5cbfSDavid du Colombier 
3480ee5cbfSDavid du Colombier 	size = ((size << 1) + (BinSize - 1)) & ~(BinSize - 1);
3580ee5cbfSDavid du Colombier 	b = malloc(sizeof(Bin) + size - BinSize);
3680ee5cbfSDavid du Colombier 	if(b == nil)
3780ee5cbfSDavid du Colombier 		return nil;
3880ee5cbfSDavid du Colombier 	b->next = bin;
3980ee5cbfSDavid du Colombier 	b->total = 0;
4080ee5cbfSDavid du Colombier 	if(bin != nil)
41*74f16c81SDavid du Colombier 		b->total = bin->total + bin->pos - (uintptr)bin->body;
42*74f16c81SDavid du Colombier 	b->pos = (uintptr)b->body;
4380ee5cbfSDavid du Colombier 	b->end = b->pos + size;
4480ee5cbfSDavid du Colombier 	return b;
4580ee5cbfSDavid du Colombier }
4680ee5cbfSDavid du Colombier 
4780ee5cbfSDavid du Colombier void*
binalloc(Bin ** bin,ulong size,int zero)4880ee5cbfSDavid du Colombier binalloc(Bin **bin, ulong size, int zero)
4980ee5cbfSDavid du Colombier {
5080ee5cbfSDavid du Colombier 	Bin *b;
51*74f16c81SDavid du Colombier 	uintptr p;
5280ee5cbfSDavid du Colombier 
5380ee5cbfSDavid du Colombier 	if(size == 0)
5480ee5cbfSDavid du Colombier 		size = 1;
5580ee5cbfSDavid du Colombier 	b = *bin;
5680ee5cbfSDavid du Colombier 	if(b == nil){
5780ee5cbfSDavid du Colombier 		b = mkbin(nil, size);
5880ee5cbfSDavid du Colombier 		if(b == nil)
5980ee5cbfSDavid du Colombier 			return nil;
6080ee5cbfSDavid du Colombier 		*bin = b;
6180ee5cbfSDavid du Colombier 	}
6280ee5cbfSDavid du Colombier 	p = b->pos;
6380ee5cbfSDavid du Colombier 	p = (p + (StructAlign - 1)) & ~(StructAlign - 1);
6480ee5cbfSDavid du Colombier 	if(p + size > b->end){
6580ee5cbfSDavid du Colombier 		b = mkbin(b, size);
6680ee5cbfSDavid du Colombier 		if(b == nil)
6780ee5cbfSDavid du Colombier 			return nil;
6880ee5cbfSDavid du Colombier 		*bin = b;
6980ee5cbfSDavid du Colombier 		p = b->pos;
7080ee5cbfSDavid du Colombier 	}
7180ee5cbfSDavid du Colombier 	b->pos = p + size;
7280ee5cbfSDavid du Colombier 	b->v = p;
7380ee5cbfSDavid du Colombier 	if(zero)
7480ee5cbfSDavid du Colombier 		memset((void*)p, 0, size);
7580ee5cbfSDavid du Colombier 	return (void*)p;
7680ee5cbfSDavid du Colombier }
7780ee5cbfSDavid du Colombier 
7880ee5cbfSDavid du Colombier void*
bingrow(Bin ** bin,void * op,ulong osize,ulong size,int zero)7980ee5cbfSDavid du Colombier bingrow(Bin **bin, void *op, ulong osize, ulong size, int zero)
8080ee5cbfSDavid du Colombier {
8180ee5cbfSDavid du Colombier 	Bin *b;
8280ee5cbfSDavid du Colombier 	void *np;
83*74f16c81SDavid du Colombier 	uintptr p;
8480ee5cbfSDavid du Colombier 
85*74f16c81SDavid du Colombier 	p = (uintptr)op;
8680ee5cbfSDavid du Colombier 	b = *bin;
8780ee5cbfSDavid du Colombier 	if(b != nil && p == b->v && p + size <= b->end){
8880ee5cbfSDavid du Colombier 		b->pos = p + size;
8980ee5cbfSDavid du Colombier 		if(zero)
9080ee5cbfSDavid du Colombier 			memset((char*)p + osize, 0, size - osize);
9180ee5cbfSDavid du Colombier 		return op;
9280ee5cbfSDavid du Colombier 	}
9380ee5cbfSDavid du Colombier 	np = binalloc(bin, size, zero);
9480ee5cbfSDavid du Colombier 	if(np == nil)
9580ee5cbfSDavid du Colombier 		return nil;
9680ee5cbfSDavid du Colombier 	memmove(np, op, osize);
9780ee5cbfSDavid du Colombier 	return np;
9880ee5cbfSDavid du Colombier }
9980ee5cbfSDavid du Colombier 
10080ee5cbfSDavid du Colombier void
binfree(Bin ** bin)10180ee5cbfSDavid du Colombier binfree(Bin **bin)
10280ee5cbfSDavid du Colombier {
10380ee5cbfSDavid du Colombier 	Bin *last;
10480ee5cbfSDavid du Colombier 
10580ee5cbfSDavid du Colombier 	while(*bin != nil){
10680ee5cbfSDavid du Colombier 		last = *bin;
10780ee5cbfSDavid du Colombier 		*bin = (*bin)->next;
108*74f16c81SDavid du Colombier 		last->pos = (uintptr)last->body;
10980ee5cbfSDavid du Colombier 		free(last);
11080ee5cbfSDavid du Colombier 	}
11180ee5cbfSDavid du Colombier }
112