diff options
author | 3gg <3gg@shellblade.net> | 2024-02-13 17:51:51 -0800 |
---|---|---|
committer | 3gg <3gg@shellblade.net> | 2024-02-13 17:51:51 -0800 |
commit | e153be0be2fb8df6656292daab3fa59963c76737 (patch) | |
tree | 7cca3fc134553017cb3c259db1dca33c98556109 /mempool | |
parent | 84bdfa4a23f5b8daa7921541b007518bc634be0f (diff) |
Let memory allocators trap by default when attempting to allocate beyond capacity.
Diffstat (limited to 'mempool')
-rw-r--r-- | mempool/CMakeLists.txt | 3 | ||||
-rw-r--r-- | mempool/include/mempool.h | 9 | ||||
-rw-r--r-- | mempool/src/mempool.c | 11 | ||||
-rw-r--r-- | mempool/test/mempool_test.c | 1 |
4 files changed, 24 insertions, 0 deletions
diff --git a/mempool/CMakeLists.txt b/mempool/CMakeLists.txt index fe3e2a5..8c9dd30 100644 --- a/mempool/CMakeLists.txt +++ b/mempool/CMakeLists.txt | |||
@@ -10,6 +10,9 @@ add_library(mempool | |||
10 | target_include_directories(mempool PUBLIC | 10 | target_include_directories(mempool PUBLIC |
11 | include) | 11 | include) |
12 | 12 | ||
13 | target_link_libraries(mempool PRIVATE | ||
14 | cassert) | ||
15 | |||
13 | target_compile_options(mempool PRIVATE -Wall -Wextra) | 16 | target_compile_options(mempool PRIVATE -Wall -Wextra) |
14 | 17 | ||
15 | # Test | 18 | # Test |
diff --git a/mempool/include/mempool.h b/mempool/include/mempool.h index bd4d4dd..de9ea4f 100644 --- a/mempool/include/mempool.h +++ b/mempool/include/mempool.h | |||
@@ -65,6 +65,9 @@ | |||
65 | 65 | ||
66 | /// Allocate a new block. | 66 | /// Allocate a new block. |
67 | /// Return 0 if there is no memory left. | 67 | /// Return 0 if there is no memory left. |
68 | /// When there is no space left in the pool, allocation can either trap | ||
69 | /// (default) or gracefully return 0. Call mem_enable_traps() to toggle this | ||
70 | /// behaviour. | ||
68 | /// New blocks are conveniently zeroed out. | 71 | /// New blocks are conveniently zeroed out. |
69 | #define mempool_alloc(POOL) mempool_alloc_(&(POOL)->pool) | 72 | #define mempool_alloc(POOL) mempool_alloc_(&(POOL)->pool) |
70 | 73 | ||
@@ -86,6 +89,10 @@ | |||
86 | /// Return the total capacity of the mempool in bytes. | 89 | /// Return the total capacity of the mempool in bytes. |
87 | #define mempool_capacity(POOL) mempool_capacity_(&(POOL)->pool) | 90 | #define mempool_capacity(POOL) mempool_capacity_(&(POOL)->pool) |
88 | 91 | ||
92 | /// Set whether to trap when attempting to allocate beyond capacity. | ||
93 | #define mempool_enable_traps(POOL, enable) \ | ||
94 | mempool_enable_traps_(&(POOL)->pool, enable) | ||
95 | |||
89 | /// Iterate over the used blocks of the pool. | 96 | /// Iterate over the used blocks of the pool. |
90 | /// | 97 | /// |
91 | /// The caller can use 'i' as the index of the current block. | 98 | /// The caller can use 'i' as the index of the current block. |
@@ -129,6 +136,7 @@ typedef struct mempool { | |||
129 | size_t head; /// Points to the first block in the free list. | 136 | size_t head; /// Points to the first block in the free list. |
130 | size_t used; /// Points to the first block in the used list. | 137 | size_t used; /// Points to the first block in the used list. |
131 | bool dynamic; /// True if blocks and info are dynamically-allocated. | 138 | bool dynamic; /// True if blocks and info are dynamically-allocated. |
139 | bool trap; /// Whether to trap when allocating beyond capacity. | ||
132 | BlockInfo* block_info; | 140 | BlockInfo* block_info; |
133 | uint8_t* blocks; | 141 | uint8_t* blocks; |
134 | } mempool; | 142 | } mempool; |
@@ -154,3 +162,4 @@ void mempool_free_(mempool*, void** block_ptr); | |||
154 | void* mempool_get_block_(const mempool*, size_t block_index); | 162 | void* mempool_get_block_(const mempool*, size_t block_index); |
155 | size_t mempool_get_block_index_(const mempool*, const void* block); | 163 | size_t mempool_get_block_index_(const mempool*, const void* block); |
156 | size_t mempool_capacity_(const mempool*); | 164 | size_t mempool_capacity_(const mempool*); |
165 | void mempool_enable_traps_(mempool*, bool); | ||
diff --git a/mempool/src/mempool.c b/mempool/src/mempool.c index 1100dad..b09038b 100644 --- a/mempool/src/mempool.c +++ b/mempool/src/mempool.c | |||
@@ -1,5 +1,7 @@ | |||
1 | #include "mempool.h" | 1 | #include "mempool.h" |
2 | 2 | ||
3 | #include <cassert.h> | ||
4 | |||
3 | #include <stdlib.h> | 5 | #include <stdlib.h> |
4 | #include <string.h> | 6 | #include <string.h> |
5 | 7 | ||
@@ -24,6 +26,7 @@ bool mempool_make_( | |||
24 | pool->num_blocks = num_blocks; | 26 | pool->num_blocks = num_blocks; |
25 | pool->head = 0; | 27 | pool->head = 0; |
26 | pool->used = 0; | 28 | pool->used = 0; |
29 | pool->trap = true; | ||
27 | 30 | ||
28 | // Initialize blocks and block info. | 31 | // Initialize blocks and block info. |
29 | if (!block_info) { | 32 | if (!block_info) { |
@@ -74,6 +77,9 @@ void* mempool_alloc_(mempool* pool) { | |||
74 | 77 | ||
75 | BlockInfo* head = &pool->block_info[pool->head]; | 78 | BlockInfo* head = &pool->block_info[pool->head]; |
76 | if (head->used) { | 79 | if (head->used) { |
80 | if (pool->trap) { | ||
81 | FAIL("mempool allocation failed, increase the pool's capacity."); | ||
82 | } | ||
77 | return 0; // Pool is full. | 83 | return 0; // Pool is full. |
78 | } | 84 | } |
79 | 85 | ||
@@ -134,3 +140,8 @@ size_t mempool_capacity_(const mempool* pool) { | |||
134 | assert(pool); | 140 | assert(pool); |
135 | return pool->num_blocks * pool->block_size_bytes; | 141 | return pool->num_blocks * pool->block_size_bytes; |
136 | } | 142 | } |
143 | |||
144 | void mempool_enable_traps_(mempool* pool, bool enable) { | ||
145 | assert(pool); | ||
146 | pool->trap = enable; | ||
147 | } | ||
diff --git a/mempool/test/mempool_test.c b/mempool/test/mempool_test.c index d5ed1ea..6c48a2a 100644 --- a/mempool/test/mempool_test.c +++ b/mempool/test/mempool_test.c | |||
@@ -67,6 +67,7 @@ TEST_CASE(mempool_fill_then_free) { | |||
67 | TEST_CASE(mempool_allocate_beyond_max_size) { | 67 | TEST_CASE(mempool_allocate_beyond_max_size) { |
68 | test_pool pool; | 68 | test_pool pool; |
69 | mempool_make(&pool); | 69 | mempool_make(&pool); |
70 | mempool_enable_traps(&pool, false); | ||
70 | 71 | ||
71 | // Fully allocate the pool. | 72 | // Fully allocate the pool. |
72 | for (int i = 0; i < NUM_BLOCKS; ++i) { | 73 | for (int i = 0; i < NUM_BLOCKS; ++i) { |