1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
| /* A memory pool implementation for fixed-size blocks
It uses Simple Segregated Storage, see e.g:
http://www.boost.org/doc/libs/1_55_0/libs/pool/doc/html/boost_pool/pool/pooling.html
*/
typedef struct _Pool Pool;
struct _Pool {
Pool * next; // next pool
};
typedef struct {
char * first, * lastb; // first and last free blocks
size_t size; // block size
size_t poolsize; // pool size
Pool * pool, * last; // first and last pools
} Mempool;
typedef struct {
char * next;
} FreeBlock;
Mempool * mempool_new (size_t poolsize, size_t size)
{
// check for 64 bytes alignment
assert (poolsize % 8 == 0);
assert (size >= sizeof(FreeBlock));
// to get the effective pool size, we cap this amount to 2^20 = 1MB
// i.e. something comparable to the size of a L2 cache
poolsize = min(1 << 20, poolsize + sizeof(Pool));
Mempool * m = qcalloc (1, Mempool);
m->poolsize = poolsize;
m->size = size;
return m;
}
void mempool_destroy (Mempool * m)
{
Pool * p = m->pool;
while (p) {
Pool * next = p->next;
free (p);
p = next;
}
free (m);
}
void * mempool_alloc (Mempool * m)
{
if (!m->first) {
// allocate new pool
Pool * p = (Pool *) malloc (m->poolsize);
p->next = NULL;
if (m->last)
m->last->next = p;
else
m->pool = p;
m->last = p;
m->first = m->lastb = ((char *)m->last) + sizeof(Pool);
FreeBlock * b = (FreeBlock *) m->first;
b->next = NULL;
}
void * ret = m->first;
FreeBlock * b = (FreeBlock *) ret;
char * next = b->next;
if (!next) {
m->lastb += m->size;
next = m->lastb;
if (next + m->size > ((char *) m->last) + m->poolsize)
next = NULL;
else {
FreeBlock * b = (FreeBlock *) next;
b->next = NULL;
}
}
m->first = next;
@if TRASH
double * v = (double *) ret;
for (int i = 0; i < m->size/sizeof(double); i++)
v[i] = undefined;
@endif
return ret;
}
void * mempool_alloc0 (Mempool * m)
{
void * ret = mempool_alloc (m);
memset (ret, 0, m->size);
return ret;
}
void mempool_free (Mempool * m, void * p)
{
@if TRASH
double * v = (double *) p;
for (int i = 0; i < m->size/sizeof(double); i++)
v[i] = undefined;
@endif
FreeBlock * b = (FreeBlock *) p;
b->next = m->first;
m->first = (char *) p;
}
|