feat: rebuild heap4 card around upstream FreeRTOS allocator
This commit is contained in:
@@ -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;
|
||||
}
|
||||
Reference in New Issue
Block a user