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