Subversion Repositories planix.SVN

Rev

Rev 2 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 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
	uintptr	pos;
21
	uintptr	end;
22
	uintptr	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 - (uintptr)bin->body;
42
	b->pos = (uintptr)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
	uintptr 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
	uintptr p;
84
 
85
	p = (uintptr)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 = (uintptr)last->body;
109
		free(last);
110
	}
111
}