xmempool 1.0
A Simple Memory Pool Implementation
Loading...
Searching...
No Matches
xmempool.c
Go to the documentation of this file.
1
17#include "xmempool.h"
18#include <stdio.h>
19#include <stdlib.h>
20#include <string.h>
21
22#ifndef _WIN32
23#include <unistd.h>
24#endif
25
26typedef struct xmem_pool_block {
27 char* start;
28 uint32_t block_size;
32
46
47#define MIN_ALLOC_BLOCK_NODE_COUNT (1024)
48#define MAX_ALLOC_BLOCK_NODE_COUNT (1024 << 2)
49#define MIN_ALLOC_LENGTH (1024)
50#define MAX_ALLOC_LENGTH (1024 << 2)
55static int _xmem_page_size = 0;
56static uint32_t _block_size = sizeof(xmem_pool_block);
57
58uint32_t size_count_with_4(uint32_t size) {
59 if (size % 4 == 0) {
60 return size;
61 } else {
62 return size + (4 - size % 4);
63 }
64}
65
74static inline void _alloc_block_nodes() {
79 }
80
81#ifdef _WIN32
82 char* start = (char*)malloc(size_count);
83#else
84 char* start;
85 posix_memalign((void**)&start, _xmem_page_size, size_count);
86#endif
87 char* block_ptr = start;
88 char* end = start + size_count;
89
90 // Check if memory allocation was successful
91 if (!block_ptr) return;
92
93 for (; block_ptr < end; block_ptr += _block_size) {
94 xmem_pool_block* block = (xmem_pool_block*)block_ptr;
95 block->is_block_start = (block_ptr == start);
96 block->start = 0;
97
98 // Link the current block to the previous one, except for the first block
99 if (block_ptr != start) {
100 ((xmem_pool_block*)(block_ptr - _block_size))->next = block;
101 }
102
103 block->block_size = 0;
104 }
105 ((xmem_pool_block*)(end - _block_size))->next = 0;
106
107 // Add newly allocated blocks to the free list
109 // Append new blocks to the existing free list
111 } else {
112 // Initialize the free list with the new blocks
114 }
115
117}
118
128 xmem_pool_block* should_return;
129
130 // If no more block node, generate a new block node list
131 if (!_free_block_ptr) {
133 }
134
135 // If still no more block node, return NULL to indicate error
136 if (!_free_block_ptr) return (xmem_pool_block*)0;
137
138 should_return = _free_block_ptr;
140
141 // If should_return is the last one, set the tail to NULL
142 if (should_return == _free_block_ptr_end) {
144 }
145
146 return should_return;
147}
148
149static inline void _recover_block_node(xmem_pool_block* node) {
150 node->block_size = 0;
151 node->next = NULL;
152 node->start = NULL;
153
156 _free_block_ptr_end = node;
157 } else {
159 }
160}
161
162static inline int _xmem_count_free_blocks(xmem_pool* pool) {
163 xmem_pool_block* block;
164 int count;
165
166 if (!pool->free_blocks) return 0;
167 block = pool->free_blocks;
168 count = 1;
169
170 while (block != pool->free_blocks_tail) {
171 count++;
172 block = block->next;
173 }
174
175 return count;
176}
177
190 static uint32_t _pool_size = sizeof(xmem_pool);
191 xmem_pool* pool = (xmem_pool*)malloc(_pool_size);
192 uint32_t size_count = block_count * block_size;
193 uint32_t alloc_size = size_count_with_4(size_count);
194 char* space;
195
196#ifndef _WIN32
197 if (_xmem_page_size < alloc_size) {
198 posix_memalign((void**)&space, _xmem_page_size, alloc_size);
199 } else {
200#endif
201 space = (char*)malloc(size_count);
202#ifndef _WIN32
203 }
204#endif
205 xmem_pool_block* start_block = 0;
206 xmem_pool_block* end_block = 0;
207
208 // Allocate memory for the pool structure
209 if (!pool) return (char*)0;
210 if (!space) {
211 free(pool);
212 return (char*)0;
213 }
214
215 // Initialize pool properties
216 pool->start = space;
217 pool->end = space + (block_count * block_size);
218
219 pool->block_size = block_size;
220 pool->block_count = block_count;
221 pool->next = 0;
222
223 pool->next_alloc_length = block_count << 1;
226 }
227
228 // Initialize free blocks
229 for (; space < pool->end; space += block_size) {
231 if (!start_block) {
232 start_block = wrapper;
233 }
234
235 // Handle allocation failure
236 if (!wrapper) {
237 free(pool);
238 free(space);
239 while (start_block) {
240 xmem_pool_block* next = start_block->next;
241 _recover_block_node(start_block);
242 start_block = next;
243 }
244 return 0;
245 }
246
247 wrapper->block_size = block_size;
248 wrapper->start = space;
249 wrapper->next = 0;
250
251 // Link blocks in the free list
252 if (end_block) {
253 end_block->next = wrapper;
254 }
255 end_block = wrapper;
256 }
257
258 pool->free_blocks = start_block;
259 pool->free_blocks_tail = end_block;
260
261 return (char*)pool;
262}
263
265 xmem_pool* pool = (xmem_pool*)_pool;
266 int pool_id = 0;
267
268 if (!_pool) return;
269
270 while (pool) {
271 printf("----- POOL OF SIZE [%.4d] -----\n", pool->block_size);
272 printf(" + id: %d\n", pool_id++);
273 printf(" + count: %d\n", pool->block_count);
274
275#pragma GCC diagnostic push
276#pragma GCC diagnostic ignored "-Wpointer-to-int-cast"
277 printf(" + spaces: [0x%.8X, 0x%.8X)\n",
278 (unsigned int)pool->start,
279 (unsigned int)pool->end);
280#pragma GCC diagnostic pop
281
282 if (pool_id == 1) {
283 printf(" + free blocks: %d\n", _xmem_count_free_blocks(pool));
284 } else {
285 printf(" + free blocks: -\n");
286 }
287
288 pool = pool->next;
289 }
290}
291
293#ifndef _WIN32
294 // Initialize page size for non-Windows systems
295 if (_xmem_page_size == 0) {
296 _xmem_page_size = getpagesize();
297 }
298#endif
299
300#ifdef XMEM_DBG
301 // Debug mode: create pool and print creation message
303 printf("A new pool of [%d] is created!", block_size);
304 return pool;
305#endif
306
307 // Normal mode: create pool with minimum allocation length
309}
310
312 xmem_pool* pool = (xmem_pool*)handle;
313 xmem_pool* next_pool;
314
315 if (!handle) return;
316
317 // Iterate through all pools in the chain
318 while (pool) {
319 // Free the memory space allocated for blocks
320 free(pool->start);
321
322 // For the first pool, recover all free block nodes
323 if (pool == (xmem_pool*)handle) {
324 xmem_pool_block* block = pool->free_blocks;
325 xmem_pool_block* next_block;
326
327 while (block) {
328 next_block = block->next;
329 _recover_block_node(block);
330 block = next_block;
331 }
332 }
333
334 // Move to the next pool
335 next_pool = pool->next;
336 free(pool);
337 pool = next_pool;
338 }
339}
340
342 static uint32_t pool_element_size = sizeof(xmem_pool);
343 xmem_pool* pool = (xmem_pool*)handle;
344 xmem_pool temp_pool;
345 xmem_pool_block* block;
346 char* space;
347
348 // If no more free blocks, create a new pool
349 if (!pool->free_blocks) {
350 xmem_pool* new_pool =
352
353 if (!new_pool) {
354 return 0;
355 }
356
357 // Swap the new pool with the current one
358 memcpy(&temp_pool, pool, pool_element_size);
359 memcpy(pool, new_pool, pool_element_size);
360 memcpy(new_pool, &temp_pool, pool_element_size);
361
362 pool->next = new_pool;
363 }
364
365 // Allocate the first free block
366 block = pool->free_blocks;
367 pool->free_blocks = block->next;
368 space = block->start;
369
370 if (!pool->free_blocks) pool->free_blocks_tail = 0;
371
372 // Initialize allocated space and recover the block node
373 memset(space, 0, block->block_size);
374 _recover_block_node(block);
375
376 return space;
377}
378
379int xmem_free(xmem_pool_handle handle, char* pointer) {
380 xmem_pool* pool = (xmem_pool*)handle;
381
382 // Get a new block node
384 if (!block) {
385 return 0;
386 }
387
388 // Initialize the new block and add it to the free list
389 block->block_size = pool->block_size;
390 block->start = pointer;
391 block->next = 0;
392
393 if (!pool->free_blocks && !pool->free_blocks_tail) {
394 pool->free_blocks = pool->free_blocks_tail = block;
395 return 1;
396 }
397
398 pool->free_blocks_tail->next = block;
399 pool->free_blocks_tail = block;
400
401 return 1;
402}
403
404void xmem_init() {
405 // Placeholder for potential initialization code
406}
407
411 xmem_pool_block* end = 0;
412
413 // Reorganize the free block list
414 while (blk != 0) {
415 if (blk->is_block_start) {
416 if (end) {
417 end->next = blk;
418 } else {
419 start = blk;
420 }
421 end = blk;
422 }
423 blk = blk->next;
424 }
425 if (end) end->next = 0;
426
427 // Free all allocated block nodes
428 blk = start;
429 while (blk != 0) {
430 end = blk->next; // Temporary variable for the next block
431 free(blk);
432 blk = end;
433 }
434
435 // Reset global pointers
437}
xmempool - A Simple Memory Pool Implementation
Definition xmempool.c:26
struct xmem_pool_block * next
Definition xmempool.c:29
uint32_t block_size
Definition xmempool.c:28
uint32_t is_block_start
Definition xmempool.c:30
char * start
Definition xmempool.c:37
struct xmem_pool * next
Definition xmempool.c:42
xmem_pool_block * free_blocks_tail
Definition xmempool.c:41
uint32_t block_count
Definition xmempool.c:35
uint32_t block_size
Definition xmempool.c:34
xmem_pool_block * free_blocks
Definition xmempool.c:40
char * end
Definition xmempool.c:38
uint32_t next_alloc_length
Definition xmempool.c:44
uint32_t size_count_with_4(uint32_t size)
Definition xmempool.c:58
static uint32_t _xmem_pool_next_alloc_block_node_count
Definition xmempool.c:51
void xmem_clean_up()
Clean up global resources used by xmempool.
Definition xmempool.c:408
void xmem_print_info(xmem_pool_handle _pool)
Print information about the memory pool.
Definition xmempool.c:264
static void _alloc_block_nodes()
Allocate memory for new block nodes.
Definition xmempool.c:74
void xmem_init()
Definition xmempool.c:404
static int _xmem_page_size
Definition xmempool.c:55
#define MIN_ALLOC_LENGTH
Definition xmempool.c:49
static void _recover_block_node(xmem_pool_block *node)
Definition xmempool.c:149
char * xmem_alloc(xmem_pool_handle handle)
Allocate a block from the memory pool.
Definition xmempool.c:341
static int _xmem_count_free_blocks(xmem_pool *pool)
Definition xmempool.c:162
#define MAX_ALLOC_LENGTH
Definition xmempool.c:50
static xmem_pool_block * _free_block_ptr
Definition xmempool.c:53
static uint32_t _block_size
Definition xmempool.c:56
#define MAX_ALLOC_BLOCK_NODE_COUNT
Definition xmempool.c:48
int xmem_free(xmem_pool_handle handle, char *pointer)
Free a block back to the memory pool.
Definition xmempool.c:379
void xmem_destroy_pool(xmem_pool_handle handle)
Destroy a memory pool and free all associated resources.
Definition xmempool.c:311
#define MIN_ALLOC_BLOCK_NODE_COUNT
Definition xmempool.c:47
static xmem_pool_block * _get_next_block_node()
Get the next available block node.
Definition xmempool.c:127
xmem_pool_handle _create_pool(uint32_t block_size, uint32_t block_count)
Create a new memory pool.
Definition xmempool.c:189
static xmem_pool_block * _free_block_ptr_end
Definition xmempool.c:54
xmem_pool_handle xmem_create_pool(unsigned int block_size)
Definition xmempool.c:292
Memory pool management APIs.
char * xmem_pool_handle
Handle type for memory pools.
Definition xmempool.h:49