plan9port

fork of plan9port with libvec, libstr and libsdb
Log | Files | Refs | README | LICENSE

bin.c (1811B)


      1 #include <u.h>
      2 #include <libc.h>
      3 #include <bin.h>
      4 
      5 enum
      6 {
      7 	StructAlign = sizeof(union {vlong vl; double d; ulong p; void *v;
      8 				struct{vlong v;}vs; struct{double d;}ds; struct{ulong p;}ss; struct{void *v;}xs;})
      9 };
     10 
     11 enum
     12 {
     13 	BinSize	= 8*1024
     14 };
     15 
     16 struct Bin
     17 {
     18 	Bin	*next;
     19 	ulong	total;			/* total bytes allocated in can->next */
     20 	ulong	pos;
     21 	ulong	end;
     22 	ulong	v;			/* last value allocated */
     23 	uchar	body[BinSize];
     24 };
     25 
     26 /*
     27  * allocator which allows an entire set to be freed at one time
     28  */
     29 static Bin*
     30 mkbin(Bin *bin, ulong size)
     31 {
     32 	Bin *b;
     33 
     34 	size = ((size << 1) + (BinSize - 1)) & ~(BinSize - 1);
     35 	b = malloc(sizeof(Bin) + size - BinSize);
     36 	if(b == nil)
     37 		return nil;
     38 	b->next = bin;
     39 	b->total = 0;
     40 	if(bin != nil)
     41 		b->total = bin->total + bin->pos - (ulong)bin->body;
     42 	b->pos = (ulong)b->body;
     43 	b->end = b->pos + size;
     44 	return b;
     45 }
     46 
     47 void*
     48 binalloc(Bin **bin, ulong size, int zero)
     49 {
     50 	Bin *b;
     51 	ulong p;
     52 
     53 	if(size == 0)
     54 		size = 1;
     55 	b = *bin;
     56 	if(b == nil){
     57 		b = mkbin(nil, size);
     58 		if(b == nil)
     59 			return nil;
     60 		*bin = b;
     61 	}
     62 	p = b->pos;
     63 	p = (p + (StructAlign - 1)) & ~(StructAlign - 1);
     64 	if(p + size > b->end){
     65 		b = mkbin(b, size);
     66 		if(b == nil)
     67 			return nil;
     68 		*bin = b;
     69 		p = b->pos;
     70 	}
     71 	b->pos = p + size;
     72 	b->v = p;
     73 	if(zero)
     74 		memset((void*)p, 0, size);
     75 	return (void*)p;
     76 }
     77 
     78 void*
     79 bingrow(Bin **bin, void *op, ulong osize, ulong size, int zero)
     80 {
     81 	Bin *b;
     82 	void *np;
     83 	ulong p;
     84 
     85 	p = (ulong)op;
     86 	b = *bin;
     87 	if(b != nil && p == b->v && p + size <= b->end){
     88 		b->pos = p + size;
     89 		if(zero)
     90 			memset((char*)p + osize, 0, size - osize);
     91 		return op;
     92 	}
     93 	np = binalloc(bin, size, zero);
     94 	if(np == nil)
     95 		return nil;
     96 	memmove(np, op, osize);
     97 	return np;
     98 }
     99 
    100 void
    101 binfree(Bin **bin)
    102 {
    103 	Bin *last;
    104 
    105 	while(*bin != nil){
    106 		last = *bin;
    107 		*bin = (*bin)->next;
    108 		last->pos = (ulong)last->body;
    109 		free(last);
    110 	}
    111 }