feat: rebuild heap4 card around upstream FreeRTOS allocator

This commit is contained in:
user
2026-07-14 23:24:56 +02:00
parent 032a06fdef
commit 2b17bb4ff9
41 changed files with 1462 additions and 2138 deletions
+136
View File
@@ -0,0 +1,136 @@
#include "heap4_model.h"
enum { BLOCK_BYTES = 48 };
typedef struct {
ModelBlock first;
uint8_t first_payload[BLOCK_BYTES - sizeof(ModelBlock)];
ModelBlock middle;
uint8_t middle_payload[BLOCK_BYTES - sizeof(ModelBlock)];
ModelBlock last;
uint8_t last_payload[BLOCK_BYTES - sizeof(ModelBlock)];
} CoalesceArena;
typedef union {
uint64_t force_alignment;
CoalesceArena blocks;
} AlignedCoalesceArena;
AlignedCoalesceArena g_coalesce_arena;
ModelBlock *g_free_head;
volatile size_t g_before_nodes;
volatile size_t g_before_total;
volatile size_t g_before_largest;
volatile size_t g_after_nodes;
volatile size_t g_after_total;
volatile size_t g_after_largest;
volatile int g_task02_pass;
static void insert_and_coalesce(ModelBlock *block)
{
ModelBlock *previous = NULL;
ModelBlock *current = g_free_head;
while (current != NULL && (uintptr_t)current < (uintptr_t)block)
{
previous = current;
current = current->next;
}
block->next = current;
if (current != NULL &&
(uint8_t *)block + block->size == (uint8_t *)current)
{
block->size += current->size;
block->next = current->next;
}
if (previous != NULL &&
(uint8_t *)previous + previous->size == (uint8_t *)block)
{
previous->size += block->size;
previous->next = block->next;
}
else if (previous != NULL)
{
previous->next = block;
}
else
{
g_free_head = block;
}
}
static void measure(size_t *nodes, size_t *total, size_t *largest)
{
ModelBlock *block;
*nodes = 0U;
*total = 0U;
*largest = 0U;
for (block = g_free_head; block != NULL; block = block->next)
{
(*nodes)++;
*total += block->size;
if (block->size > *largest)
{
*largest = block->size;
}
}
}
__attribute__((noinline)) void task02_fragmented_checkpoint(void)
{
#if defined(__GNUC__)
__asm__ volatile("" ::: "memory");
#endif
}
__attribute__((noinline)) void task02_debug_checkpoint(void)
{
#if defined(__GNUC__)
__asm__ volatile("" ::: "memory");
#endif
}
int main(void)
{
CoalesceArena *arena = &g_coalesce_arena.blocks;
size_t nodes;
size_t total;
size_t largest;
arena->first.size = BLOCK_BYTES;
arena->middle.size = BLOCK_BYTES;
arena->last.size = BLOCK_BYTES;
g_free_head = NULL;
insert_and_coalesce(&arena->first);
insert_and_coalesce(&arena->last);
measure(&nodes, &total, &largest);
g_before_nodes = nodes;
g_before_total = total;
g_before_largest = largest;
task02_fragmented_checkpoint();
insert_and_coalesce(&arena->middle);
measure(&nodes, &total, &largest);
g_after_nodes = nodes;
g_after_total = total;
g_after_largest = largest;
g_task02_pass =
g_before_nodes == 2U && g_before_total == 96U &&
g_before_largest == 48U && g_after_nodes == 1U &&
g_after_total == 144U && g_after_largest == 144U &&
g_free_head == &arena->first && g_free_head->next == NULL;
task02_debug_checkpoint();
#if defined(HOST_PRINTF)
printf("before_nodes=%zu before_total=%zu before_largest=%zu "
"after_nodes=%zu after_total=%zu after_largest=%zu pass=%d\n",
g_before_nodes, g_before_total, g_before_largest,
g_after_nodes, g_after_total, g_after_largest, g_task02_pass);
#endif
return g_task02_pass ? 0 : 1;
}