11#include "exceptions.h"
13#include "os_helpers.h"
23#define PAYLOAD_ALIGNEMENT 4
25#define PAYLOAD_DATA_ALIGNEMENT 8
27#define ALLOC_CHUNK_HEADER_SIZE 4
29#define FREE_CHUNK_HEADER_SIZE 8
31#define HEAP_HEADER_SIZE \
32 ((sizeof(heap_t) + PAYLOAD_DATA_ALIGNEMENT - 1) & ~(PAYLOAD_DATA_ALIGNEMENT - 1))
35#define NB_LINEAR_SEGMENTS 5
48#define NB_MAX_SEGMENTS 10
50#define NB_SUB_SEGMENTS 4
53#define GET_PTR(_heap, index) ((header_t *) (((uint8_t *) _heap) + ((index) << 3)))
54#define GET_IDX(_heap, _ptr) ((((uint8_t *) (_ptr)) - ((uint8_t *) _heap)) >> 3)
55#define GET_PREV(_heap, _ptr) ((header_t *) (((uint8_t *) _heap) + ((_ptr)->fprev << 3)))
56#define GET_NEXT(_heap, _ptr) ((header_t *) (((uint8_t *) _heap) + ((_ptr)->fnext << 3)))
91static inline int seglist_index(
heap_t *heap,
size_t size)
97 sub_segment = (size >> (seg - 1)) & 0x3;
110static inline int seglist_index_up(
heap_t *heap,
size_t size)
114 size_t sub_segment_size;
117 sub_segment_size = (1 << (seg - 1));
120 size += sub_segment_size - 1;
121 size &= ~(sub_segment_size - 1);
124 sub_segment = (size >> (seg - 1)) & 0x3;
142 if (*first_free == elem) {
143 *first_free = elem_ptr->
fnext;
146 GET_PTR(heap, *first_free)->fprev = 0;
151 if (elem_ptr->
fprev) {
155 if (elem_ptr->
fnext) {
163 int seg_index = seglist_index(heap, header->
size);
169 if (first_idx ==
GET_IDX(heap, header)) {
173 header->
fnext = first_idx;
177 if (first_idx != 0) {
186static inline void ensure_chunk_valid(
heap_t *heap,
header_t *header)
192 PRINTF(
"invalid size: header->size = %d!\n", header->
size);
193 THROW(EXCEPTION_CORRUPT);
200 PRINTF(
"corrupted prev_chunk\n");
201 THROW(EXCEPTION_CORRUPT);
205 PRINTF(
"corrupted prev_chunk\n");
206 THROW(EXCEPTION_CORRUPT);
215 ensure_chunk_valid(heap, neighbour);
221 heap, &heap->
free_segments[seglist_index(heap, neighbour->
size)], neighbour_idx);
224 if (header < neighbour) {
226 if ((
void *) next < heap->
end) {
229 header->
size += neighbour->size;
231 memset(neighbour, 0,
sizeof(*neighbour));
236 if ((
void *) next < heap->
end) {
239 neighbour->size += header->size;
241 memset(header, 0,
sizeof(*header));
249static bool parse_callback(
void *data,
uint8_t *addr,
bool allocated,
size_t size)
293 heap->
end = ((
uint8_t *) heap_start) + heap_size;
306 list_push(heap, first_free);
346 seg = seglist_index_up(heap, nb_bytes);
354 if (chunk_idx != 0) {
358 ensure_chunk_valid(heap, header);
360 if (nb_bytes > header->
size) {
372 new_free->
size = header->
size - nb_bytes;
377 if ((
void *) next < heap->end) {
380 list_push(heap, new_free);
382 header->
size = nb_bytes;
413 ensure_chunk_valid(heap, header);
421 header = coalesce(heap, header, (
header_t *) (block + header->
size));
429 list_push(heap, header);
443#ifdef DEBUG_FREE_SEGMENTS
444 for (
size_t i = 0; i < heap->
nb_segs; i++) {
455 while (header != NULL) {
458 if (callback(data, block, header->
allocated, header->
size)) {
#define GET_NEXT(_heap, _ptr)
#define GET_PTR(_heap, index)
#define ALLOC_CHUNK_HEADER_SIZE
#define PAYLOAD_ALIGNEMENT
mem_ctx_t mem_init(void *heap_start, size_t heap_size)
initializes the heap for this allocator
#define NB_LINEAR_SEGMENTS
void * mem_alloc(mem_ctx_t ctx, size_t nb_bytes)
allocates a buffer of the given size, if possible
#define FREE_CHUNK_HEADER_SIZE
void mem_free(mem_ctx_t ctx, void *ptr)
frees the given buffer
void mem_stat(mem_ctx_t *ctx, mem_stat_t *stat)
function used to get statistics (nb chunks, nb allocated chunks, total size) about the heap
void mem_parse(mem_ctx_t ctx, mem_parse_callback_t callback, void *data)
parse the heap
#define GET_PREV(_heap, _ptr)
#define GET_IDX(_heap, _ptr)
Dynamic memory allocation API.
void * mem_ctx_t
type shared externally
bool(* mem_parse_callback_t)(void *data, uint8_t *addr, bool allocated, size_t size)
function called for each chunk found in the heap.
void * end
end of headp buffer, for consistency check
size_t nb_segs
actual number of used segments
uint16_t free_segments[NB_MAX_SEGMENTS *NB_SUB_SEGMENTS]
this structure, filled by mem_stat
size_t allocated_size
nb bytes allocated in the heap (including headers)
size_t total_size
total size of the heap (including allocator internal data)
uint32_t nb_allocated
number of allocated chunks
uint32_t nb_chunks
total number of chunks