#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); | |
} | |
} |