ref: bb2060028e616df560628cf6f1e6e5d196d50833
dir: /sys/src/libbin/bin.c/
#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 */ uintptr pos; uintptr end; uintptr 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 - (uintptr)bin->body; b->pos = (uintptr)b->body; b->end = b->pos + size; return b; } void* binalloc(Bin **bin, ulong size, int zero) { Bin *b; uintptr 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; uintptr p; p = (uintptr)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 = (uintptr)last->body; free(last); } }