2 * Memory Pool implementation logic.
8 #define BLOCK_GROWTH_SIZE 1024*1024 - sizeof(struct mp_block);
11 * Allocate a new mp_block and insert it after the block specified in
12 * `insert_after`. If `insert_after` is NULL, then insert block at the
13 * head of the linked list.
15 static struct mp_block
*mem_pool_alloc_block(struct mem_pool
*pool
,
17 struct mp_block
*insert_after
)
21 pool
->pool_alloc
+= sizeof(struct mp_block
) + block_alloc
;
22 p
= xmalloc(st_add(sizeof(struct mp_block
), block_alloc
));
24 p
->next_free
= (char *)p
->space
;
25 p
->end
= p
->next_free
+ block_alloc
;
28 p
->next_block
= insert_after
->next_block
;
29 insert_after
->next_block
= p
;
31 p
->next_block
= pool
->mp_block
;
38 void mem_pool_init(struct mem_pool
*pool
, size_t initial_size
)
40 memset(pool
, 0, sizeof(*pool
));
41 pool
->block_alloc
= BLOCK_GROWTH_SIZE
;
44 mem_pool_alloc_block(pool
, initial_size
, NULL
);
47 void mem_pool_discard(struct mem_pool
*pool
, int invalidate_memory
)
49 struct mp_block
*block
, *block_to_free
;
51 block
= pool
->mp_block
;
54 block_to_free
= block
;
55 block
= block
->next_block
;
57 if (invalidate_memory
)
58 memset(block_to_free
->space
, 0xDD, ((char *)block_to_free
->end
) - ((char *)block_to_free
->space
));
63 pool
->mp_block
= NULL
;
67 void *mem_pool_alloc(struct mem_pool
*pool
, size_t len
)
69 struct mp_block
*p
= NULL
;
72 /* round up to a 'uintmax_t' alignment */
73 if (len
& (sizeof(uintmax_t) - 1))
74 len
+= sizeof(uintmax_t) - (len
& (sizeof(uintmax_t) - 1));
77 pool
->mp_block
->end
- pool
->mp_block
->next_free
>= len
)
81 if (len
>= (pool
->block_alloc
/ 2))
82 return mem_pool_alloc_block(pool
, len
, pool
->mp_block
);
84 p
= mem_pool_alloc_block(pool
, pool
->block_alloc
, NULL
);
92 void *mem_pool_calloc(struct mem_pool
*pool
, size_t count
, size_t size
)
94 size_t len
= st_mult(count
, size
);
95 void *r
= mem_pool_alloc(pool
, len
);
100 char *mem_pool_strdup(struct mem_pool
*pool
, const char *str
)
102 size_t len
= strlen(str
) + 1;
103 char *ret
= mem_pool_alloc(pool
, len
);
105 return memcpy(ret
, str
, len
);
108 char *mem_pool_strndup(struct mem_pool
*pool
, const char *str
, size_t len
)
110 char *p
= memchr(str
, '\0', len
);
111 size_t actual_len
= (p
? p
- str
: len
);
112 char *ret
= mem_pool_alloc(pool
, actual_len
+1);
114 ret
[actual_len
] = '\0';
115 return memcpy(ret
, str
, actual_len
);
118 int mem_pool_contains(struct mem_pool
*pool
, void *mem
)
122 /* Check if memory is allocated in a block */
123 for (p
= pool
->mp_block
; p
; p
= p
->next_block
)
124 if ((mem
>= ((void *)p
->space
)) &&
125 (mem
< ((void *)p
->end
)))
131 void mem_pool_combine(struct mem_pool
*dst
, struct mem_pool
*src
)
135 /* Append the blocks from src to dst */
136 if (dst
->mp_block
&& src
->mp_block
) {
138 * src and dst have blocks, append
139 * blocks from src to dst.
142 while (p
->next_block
)
145 p
->next_block
= src
->mp_block
;
146 } else if (src
->mp_block
) {
148 * src has blocks, dst is empty.
150 dst
->mp_block
= src
->mp_block
;
152 /* src is empty, nothing to do. */
155 dst
->pool_alloc
+= src
->pool_alloc
;
157 src
->mp_block
= NULL
;