| #include <u.h> | 
 | #include <libc.h> | 
 | #include <bin.h> | 
 |  | 
 | enum | 
 | { | 
 | 	StructAlign = sizeof(union {vlong vl; double d; ulong p; void *v; | 
 | 				struct{vlong v;}vs; struct{double d;}ds; struct{ulong p;}ss; struct{void *v;}xs;}) | 
 | }; | 
 |  | 
 | enum | 
 | { | 
 | 	BinSize	= 8*1024 | 
 | }; | 
 |  | 
 | struct Bin | 
 | { | 
 | 	Bin	*next; | 
 | 	ulong	total;			/* total bytes allocated in can->next */ | 
 | 	ulong	pos; | 
 | 	ulong	end; | 
 | 	ulong	v;			/* last value allocated */ | 
 | 	uchar	body[BinSize]; | 
 | }; | 
 |  | 
 | /* | 
 |  * allocator which allows an entire set to be freed at one time | 
 |  */ | 
 | static Bin* | 
 | mkbin(Bin *bin, ulong size) | 
 | { | 
 | 	Bin *b; | 
 |  | 
 | 	size = ((size << 1) + (BinSize - 1)) & ~(BinSize - 1); | 
 | 	b = malloc(sizeof(Bin) + size - BinSize); | 
 | 	if(b == nil) | 
 | 		return nil; | 
 | 	b->next = bin; | 
 | 	b->total = 0; | 
 | 	if(bin != nil) | 
 | 		b->total = bin->total + bin->pos - (ulong)bin->body; | 
 | 	b->pos = (ulong)b->body; | 
 | 	b->end = b->pos + size; | 
 | 	return b; | 
 | } | 
 |  | 
 | void* | 
 | binalloc(Bin **bin, ulong size, int zero) | 
 | { | 
 | 	Bin *b; | 
 | 	ulong p; | 
 |  | 
 | 	if(size == 0) | 
 | 		size = 1; | 
 | 	b = *bin; | 
 | 	if(b == nil){ | 
 | 		b = mkbin(nil, size); | 
 | 		if(b == nil) | 
 | 			return nil; | 
 | 		*bin = b; | 
 | 	} | 
 | 	p = b->pos; | 
 | 	p = (p + (StructAlign - 1)) & ~(StructAlign - 1); | 
 | 	if(p + size > b->end){ | 
 | 		b = mkbin(b, size); | 
 | 		if(b == nil) | 
 | 			return nil; | 
 | 		*bin = b; | 
 | 		p = b->pos; | 
 | 	} | 
 | 	b->pos = p + size; | 
 | 	b->v = p; | 
 | 	if(zero) | 
 | 		memset((void*)p, 0, size); | 
 | 	return (void*)p; | 
 | } | 
 |  | 
 | void* | 
 | bingrow(Bin **bin, void *op, ulong osize, ulong size, int zero) | 
 | { | 
 | 	Bin *b; | 
 | 	void *np; | 
 | 	ulong p; | 
 |  | 
 | 	p = (ulong)op; | 
 | 	b = *bin; | 
 | 	if(b != nil && p == b->v && p + size <= b->end){ | 
 | 		b->pos = p + size; | 
 | 		if(zero) | 
 | 			memset((char*)p + osize, 0, size - osize); | 
 | 		return op; | 
 | 	} | 
 | 	np = binalloc(bin, size, zero); | 
 | 	if(np == nil) | 
 | 		return nil; | 
 | 	memmove(np, op, osize); | 
 | 	return np; | 
 | } | 
 |  | 
 | void | 
 | binfree(Bin **bin) | 
 | { | 
 | 	Bin *last; | 
 |  | 
 | 	while(*bin != nil){ | 
 | 		last = *bin; | 
 | 		*bin = (*bin)->next; | 
 | 		last->pos = (ulong)last->body; | 
 | 		free(last); | 
 | 	} | 
 | } |