Add FreeRTOS heap4 intro card
This commit is contained in:
@@ -0,0 +1,61 @@
|
||||
#ifndef HEAP4_COMMON_H
|
||||
#define HEAP4_COMMON_H
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef HOST_PRINTF
|
||||
#include <stdio.h>
|
||||
#define TRACE_PRINTF(...) printf(__VA_ARGS__)
|
||||
#else
|
||||
#define TRACE_PRINTF(...) ((void)0)
|
||||
#endif
|
||||
|
||||
#define HEAP4_ARRAY_LEN(a) ((int)(sizeof(a) / sizeof((a)[0])))
|
||||
#define HEAP4_ALIGNMENT ((size_t)8)
|
||||
#define HEAP4_ALIGNMENT_MASK (HEAP4_ALIGNMENT - 1U)
|
||||
#define HEAP4_ALLOCATED_BIT ((size_t)1U << (sizeof(size_t) * 8U - 1U))
|
||||
|
||||
typedef struct HeapBlock {
|
||||
struct HeapBlock *next;
|
||||
size_t size;
|
||||
} HeapBlock;
|
||||
|
||||
static inline size_t heap4_align_up(size_t value)
|
||||
{
|
||||
if ((value & HEAP4_ALIGNMENT_MASK) != 0U)
|
||||
value += HEAP4_ALIGNMENT - (value & HEAP4_ALIGNMENT_MASK);
|
||||
return value;
|
||||
}
|
||||
|
||||
static inline uintptr_t heap4_align_address(uintptr_t address)
|
||||
{
|
||||
uintptr_t mask;
|
||||
|
||||
mask = (uintptr_t)HEAP4_ALIGNMENT_MASK;
|
||||
if ((address & mask) != 0U)
|
||||
address += (uintptr_t)HEAP4_ALIGNMENT - (address & mask);
|
||||
return address;
|
||||
}
|
||||
|
||||
static inline size_t heap4_clear_allocated(size_t size)
|
||||
{
|
||||
return size & ~HEAP4_ALLOCATED_BIT;
|
||||
}
|
||||
|
||||
static inline size_t heap4_mark_allocated(size_t size)
|
||||
{
|
||||
return size | HEAP4_ALLOCATED_BIT;
|
||||
}
|
||||
|
||||
static inline int heap4_is_allocated(size_t size)
|
||||
{
|
||||
return (size & HEAP4_ALLOCATED_BIT) != 0U;
|
||||
}
|
||||
|
||||
static inline int heap4_blocks_touch(HeapBlock *left, HeapBlock *right)
|
||||
{
|
||||
return (uint8_t *)left + heap4_clear_allocated(left->size) == (uint8_t *)right;
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,29 @@
|
||||
#include "heap4_common.h"
|
||||
|
||||
volatile size_t g_header_size;
|
||||
volatile size_t g_aligned_header_size;
|
||||
volatile size_t g_allocated_bit_set;
|
||||
volatile size_t g_user_bytes;
|
||||
volatile size_t g_total_block_bytes;
|
||||
|
||||
int main(void)
|
||||
{
|
||||
HeapBlock block;
|
||||
size_t requested;
|
||||
|
||||
requested = 13U;
|
||||
block.next = 0;
|
||||
block.size = heap4_mark_allocated(heap4_align_up(requested + sizeof(HeapBlock)));
|
||||
|
||||
g_header_size = sizeof(HeapBlock);
|
||||
g_aligned_header_size = heap4_align_up(sizeof(HeapBlock));
|
||||
g_allocated_bit_set = heap4_is_allocated(block.size);
|
||||
g_total_block_bytes = heap4_clear_allocated(block.size);
|
||||
g_user_bytes = g_total_block_bytes - sizeof(HeapBlock);
|
||||
|
||||
TRACE_PRINTF("header=%u aligned=%u allocated=%u total=%u user=%u\n",
|
||||
(unsigned)g_header_size, (unsigned)g_aligned_header_size,
|
||||
(unsigned)g_allocated_bit_set, (unsigned)g_total_block_bytes,
|
||||
(unsigned)g_user_bytes);
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
#include "heap4_common.h"
|
||||
|
||||
volatile size_t g_free_total;
|
||||
volatile size_t g_largest_free;
|
||||
volatile int g_node_count;
|
||||
|
||||
static size_t list_total(HeapBlock *start)
|
||||
{
|
||||
HeapBlock *block;
|
||||
size_t total;
|
||||
|
||||
total = 0U;
|
||||
for (block = start->next; block != 0; block = block->next)
|
||||
total += block->size;
|
||||
return total;
|
||||
}
|
||||
|
||||
static size_t list_largest(HeapBlock *start)
|
||||
{
|
||||
HeapBlock *block;
|
||||
size_t largest;
|
||||
|
||||
largest = 0U;
|
||||
for (block = start->next; block != 0; block = block->next)
|
||||
if (block->size > largest)
|
||||
largest = block->size;
|
||||
return largest;
|
||||
}
|
||||
|
||||
static int list_count(HeapBlock *start)
|
||||
{
|
||||
HeapBlock *block;
|
||||
int count;
|
||||
|
||||
count = 0;
|
||||
for (block = start->next; block != 0; block = block->next)
|
||||
count++;
|
||||
return count;
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
HeapBlock start;
|
||||
HeapBlock a;
|
||||
HeapBlock b;
|
||||
HeapBlock c;
|
||||
|
||||
start.next = &a;
|
||||
start.size = 0U;
|
||||
a.next = &b;
|
||||
a.size = 32U;
|
||||
b.next = &c;
|
||||
b.size = 80U;
|
||||
c.next = 0;
|
||||
c.size = 24U;
|
||||
|
||||
g_free_total = list_total(&start);
|
||||
g_largest_free = list_largest(&start);
|
||||
g_node_count = list_count(&start);
|
||||
|
||||
TRACE_PRINTF("free=%u largest=%u count=%d\n",
|
||||
(unsigned)g_free_total, (unsigned)g_largest_free, g_node_count);
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
#include "heap4_common.h"
|
||||
|
||||
#define HEAP_BYTES 160U
|
||||
|
||||
static uint8_t heap_area[HEAP_BYTES + HEAP4_ALIGNMENT];
|
||||
static HeapBlock start;
|
||||
static HeapBlock *end_marker;
|
||||
|
||||
volatile size_t g_initial_free_size;
|
||||
volatile uintptr_t g_aligned_offset;
|
||||
volatile int g_end_is_last;
|
||||
|
||||
static void heap_init(void)
|
||||
{
|
||||
uintptr_t raw;
|
||||
uintptr_t aligned;
|
||||
size_t available;
|
||||
HeapBlock *first;
|
||||
|
||||
raw = (uintptr_t)&heap_area[0];
|
||||
aligned = heap4_align_address(raw);
|
||||
available = HEAP_BYTES - (size_t)(aligned - raw);
|
||||
available &= ~HEAP4_ALIGNMENT_MASK;
|
||||
|
||||
first = (HeapBlock *)aligned;
|
||||
end_marker = (HeapBlock *)(aligned + available - sizeof(HeapBlock));
|
||||
end_marker->next = 0;
|
||||
end_marker->size = 0U;
|
||||
|
||||
first->next = end_marker;
|
||||
first->size = (uint8_t *)end_marker - (uint8_t *)first;
|
||||
|
||||
start.next = first;
|
||||
start.size = 0U;
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
heap_init();
|
||||
|
||||
g_aligned_offset = (uintptr_t)start.next - (uintptr_t)&heap_area[0];
|
||||
g_initial_free_size = start.next->size;
|
||||
g_end_is_last = (start.next->next == end_marker) && (end_marker->next == 0);
|
||||
|
||||
TRACE_PRINTF("offset=%u free=%u end_last=%d\n",
|
||||
(unsigned)g_aligned_offset, (unsigned)g_initial_free_size,
|
||||
g_end_is_last);
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
#include "heap4_common.h"
|
||||
|
||||
volatile size_t g_request_1;
|
||||
volatile size_t g_request_9;
|
||||
volatile size_t g_request_17;
|
||||
volatile uintptr_t g_address_delta;
|
||||
|
||||
int main(void)
|
||||
{
|
||||
uint8_t bytes[32];
|
||||
uintptr_t raw;
|
||||
uintptr_t aligned;
|
||||
|
||||
g_request_1 = heap4_align_up(1U + sizeof(HeapBlock));
|
||||
g_request_9 = heap4_align_up(9U + sizeof(HeapBlock));
|
||||
g_request_17 = heap4_align_up(17U + sizeof(HeapBlock));
|
||||
|
||||
raw = (uintptr_t)&bytes[1];
|
||||
aligned = heap4_align_address(raw);
|
||||
g_address_delta = aligned - raw;
|
||||
|
||||
TRACE_PRINTF("r1=%u r9=%u r17=%u delta=%u\n",
|
||||
(unsigned)g_request_1, (unsigned)g_request_9,
|
||||
(unsigned)g_request_17, (unsigned)g_address_delta);
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
#include "heap4_common.h"
|
||||
|
||||
#define HEAP_BYTES 128U
|
||||
|
||||
static uint8_t heap_area[HEAP_BYTES + HEAP4_ALIGNMENT];
|
||||
static HeapBlock start;
|
||||
static HeapBlock *end_marker;
|
||||
|
||||
volatile size_t g_allocated_size;
|
||||
volatile size_t g_remaining_free;
|
||||
volatile int g_allocation_ok;
|
||||
|
||||
static void heap_init_one_block(void)
|
||||
{
|
||||
uintptr_t raw;
|
||||
uintptr_t aligned;
|
||||
HeapBlock *first;
|
||||
|
||||
raw = (uintptr_t)&heap_area[0];
|
||||
aligned = heap4_align_address(raw);
|
||||
first = (HeapBlock *)aligned;
|
||||
end_marker = (HeapBlock *)(aligned + 120U);
|
||||
|
||||
end_marker->next = 0;
|
||||
end_marker->size = 0U;
|
||||
first->next = end_marker;
|
||||
first->size = (uint8_t *)end_marker - (uint8_t *)first;
|
||||
start.next = first;
|
||||
start.size = 0U;
|
||||
}
|
||||
|
||||
static void *heap_malloc_whole_block(size_t wanted)
|
||||
{
|
||||
HeapBlock *previous;
|
||||
HeapBlock *block;
|
||||
size_t total;
|
||||
|
||||
total = heap4_align_up(wanted + sizeof(HeapBlock));
|
||||
previous = &start;
|
||||
block = start.next;
|
||||
|
||||
while (block != end_marker) {
|
||||
if (block->size >= total) {
|
||||
previous->next = block->next;
|
||||
block->next = 0;
|
||||
block->size = heap4_mark_allocated(block->size);
|
||||
return (uint8_t *)block + sizeof(HeapBlock);
|
||||
}
|
||||
previous = block;
|
||||
block = block->next;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
void *p;
|
||||
HeapBlock *allocated;
|
||||
|
||||
heap_init_one_block();
|
||||
p = heap_malloc_whole_block(24U);
|
||||
allocated = (HeapBlock *)((uint8_t *)p - sizeof(HeapBlock));
|
||||
|
||||
g_allocation_ok = p != 0;
|
||||
g_allocated_size = heap4_clear_allocated(allocated->size);
|
||||
g_remaining_free = start.next->size;
|
||||
|
||||
TRACE_PRINTF("ok=%d allocated=%u remaining=%u\n",
|
||||
g_allocation_ok, (unsigned)g_allocated_size,
|
||||
(unsigned)g_remaining_free);
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,93 @@
|
||||
#include "heap4_common.h"
|
||||
|
||||
#define HEAP_BYTES 192U
|
||||
#define MIN_SPLIT_SIZE ((size_t)(sizeof(HeapBlock) * 2U))
|
||||
|
||||
static uint8_t heap_area[HEAP_BYTES + HEAP4_ALIGNMENT];
|
||||
static HeapBlock start;
|
||||
static HeapBlock *end_marker;
|
||||
|
||||
volatile size_t g_allocated_size;
|
||||
volatile size_t g_split_free_size;
|
||||
volatile int g_free_nodes;
|
||||
|
||||
static void heap_init_one_block(void)
|
||||
{
|
||||
uintptr_t aligned;
|
||||
HeapBlock *first;
|
||||
|
||||
aligned = heap4_align_address((uintptr_t)&heap_area[0]);
|
||||
first = (HeapBlock *)aligned;
|
||||
end_marker = (HeapBlock *)(aligned + 176U);
|
||||
end_marker->next = 0;
|
||||
end_marker->size = 0U;
|
||||
first->next = end_marker;
|
||||
first->size = (uint8_t *)end_marker - (uint8_t *)first;
|
||||
start.next = first;
|
||||
start.size = 0U;
|
||||
}
|
||||
|
||||
static void *heap_malloc_split(size_t wanted)
|
||||
{
|
||||
HeapBlock *previous;
|
||||
HeapBlock *block;
|
||||
HeapBlock *remainder;
|
||||
size_t total;
|
||||
size_t original;
|
||||
|
||||
total = heap4_align_up(wanted + sizeof(HeapBlock));
|
||||
previous = &start;
|
||||
block = start.next;
|
||||
|
||||
while (block != end_marker) {
|
||||
if (block->size >= total) {
|
||||
original = block->size;
|
||||
if (original - total > MIN_SPLIT_SIZE) {
|
||||
remainder = (HeapBlock *)((uint8_t *)block + total);
|
||||
remainder->size = original - total;
|
||||
remainder->next = block->next;
|
||||
previous->next = remainder;
|
||||
block->size = total;
|
||||
} else {
|
||||
previous->next = block->next;
|
||||
}
|
||||
block->next = 0;
|
||||
block->size = heap4_mark_allocated(block->size);
|
||||
return (uint8_t *)block + sizeof(HeapBlock);
|
||||
}
|
||||
previous = block;
|
||||
block = block->next;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int count_free_nodes(void)
|
||||
{
|
||||
HeapBlock *block;
|
||||
int count;
|
||||
|
||||
count = 0;
|
||||
for (block = start.next; block != end_marker; block = block->next)
|
||||
count++;
|
||||
return count;
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
void *p;
|
||||
HeapBlock *allocated;
|
||||
|
||||
heap_init_one_block();
|
||||
p = heap_malloc_split(32U);
|
||||
allocated = (HeapBlock *)((uint8_t *)p - sizeof(HeapBlock));
|
||||
|
||||
g_allocated_size = heap4_clear_allocated(allocated->size);
|
||||
g_split_free_size = start.next->size;
|
||||
g_free_nodes = count_free_nodes();
|
||||
|
||||
TRACE_PRINTF("allocated=%u split=%u nodes=%d\n",
|
||||
(unsigned)g_allocated_size, (unsigned)g_split_free_size,
|
||||
g_free_nodes);
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,88 @@
|
||||
#include "heap4_common.h"
|
||||
|
||||
static uint8_t heap_area[192];
|
||||
static HeapBlock start;
|
||||
static HeapBlock *end_marker;
|
||||
|
||||
volatile int g_order_ok;
|
||||
volatile int g_free_count;
|
||||
volatile size_t g_total_free;
|
||||
|
||||
static void insert_block(HeapBlock *block)
|
||||
{
|
||||
HeapBlock *iterator;
|
||||
|
||||
for (iterator = &start; iterator->next < block; iterator = iterator->next)
|
||||
;
|
||||
|
||||
block->next = iterator->next;
|
||||
iterator->next = block;
|
||||
}
|
||||
|
||||
static void heap_free_model(void *p)
|
||||
{
|
||||
HeapBlock *block;
|
||||
|
||||
if (p == 0)
|
||||
return;
|
||||
|
||||
block = (HeapBlock *)((uint8_t *)p - sizeof(HeapBlock));
|
||||
block->size = heap4_clear_allocated(block->size);
|
||||
insert_block(block);
|
||||
}
|
||||
|
||||
static int count_free(void)
|
||||
{
|
||||
HeapBlock *block;
|
||||
int count;
|
||||
|
||||
count = 0;
|
||||
for (block = start.next; block != end_marker; block = block->next)
|
||||
count++;
|
||||
return count;
|
||||
}
|
||||
|
||||
static size_t total_free(void)
|
||||
{
|
||||
HeapBlock *block;
|
||||
size_t total;
|
||||
|
||||
total = 0U;
|
||||
for (block = start.next; block != end_marker; block = block->next)
|
||||
total += block->size;
|
||||
return total;
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
HeapBlock *a;
|
||||
HeapBlock *b;
|
||||
HeapBlock *c;
|
||||
void *payload;
|
||||
|
||||
a = (HeapBlock *)&heap_area[0];
|
||||
b = (HeapBlock *)&heap_area[64];
|
||||
c = (HeapBlock *)&heap_area[128];
|
||||
end_marker = (HeapBlock *)&heap_area[176];
|
||||
|
||||
start.next = a;
|
||||
a->next = c;
|
||||
c->next = end_marker;
|
||||
end_marker->next = 0;
|
||||
|
||||
a->size = 40U;
|
||||
b->size = heap4_mark_allocated(32U);
|
||||
c->size = 48U;
|
||||
end_marker->size = 0U;
|
||||
|
||||
payload = (uint8_t *)b + sizeof(HeapBlock);
|
||||
heap_free_model(payload);
|
||||
|
||||
g_order_ok = start.next == a && a->next == b && b->next == c && c->next == end_marker;
|
||||
g_free_count = count_free();
|
||||
g_total_free = total_free();
|
||||
|
||||
TRACE_PRINTF("order=%d count=%d total=%u\n",
|
||||
g_order_ok, g_free_count, (unsigned)g_total_free);
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
#include "heap4_common.h"
|
||||
|
||||
static uint8_t heap_area[192];
|
||||
static HeapBlock start;
|
||||
static HeapBlock *end_marker;
|
||||
|
||||
volatile int g_free_count;
|
||||
volatile size_t g_merged_size;
|
||||
volatile int g_merged_with_right;
|
||||
|
||||
static void insert_block_merge(HeapBlock *block)
|
||||
{
|
||||
HeapBlock *iterator;
|
||||
uint8_t *block_end;
|
||||
|
||||
for (iterator = &start; iterator->next < block; iterator = iterator->next)
|
||||
;
|
||||
|
||||
block_end = (uint8_t *)block + block->size;
|
||||
if (block_end == (uint8_t *)iterator->next) {
|
||||
block->size += iterator->next->size;
|
||||
block->next = iterator->next->next;
|
||||
} else {
|
||||
block->next = iterator->next;
|
||||
}
|
||||
|
||||
if (iterator != &start && heap4_blocks_touch(iterator, block)) {
|
||||
iterator->size += block->size;
|
||||
iterator->next = block->next;
|
||||
} else {
|
||||
iterator->next = block;
|
||||
}
|
||||
}
|
||||
|
||||
static int count_free(void)
|
||||
{
|
||||
HeapBlock *block;
|
||||
int count;
|
||||
|
||||
count = 0;
|
||||
for (block = start.next; block != end_marker; block = block->next)
|
||||
count++;
|
||||
return count;
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
HeapBlock *left;
|
||||
HeapBlock *middle;
|
||||
HeapBlock *right;
|
||||
|
||||
left = (HeapBlock *)&heap_area[0];
|
||||
middle = (HeapBlock *)&heap_area[48];
|
||||
right = (HeapBlock *)&heap_area[96];
|
||||
end_marker = (HeapBlock *)&heap_area[160];
|
||||
|
||||
start.next = left;
|
||||
left->next = right;
|
||||
right->next = end_marker;
|
||||
end_marker->next = 0;
|
||||
|
||||
left->size = 48U;
|
||||
middle->size = 48U;
|
||||
right->size = 64U;
|
||||
end_marker->size = 0U;
|
||||
|
||||
insert_block_merge(middle);
|
||||
|
||||
g_free_count = count_free();
|
||||
g_merged_size = start.next->size;
|
||||
g_merged_with_right = start.next->next == end_marker;
|
||||
|
||||
TRACE_PRINTF("count=%d size=%u merged_right=%d\n",
|
||||
g_free_count, (unsigned)g_merged_size, g_merged_with_right);
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
#include "heap4_common.h"
|
||||
|
||||
#ifndef CONFIG_TOTAL_HEAP_SIZE
|
||||
#define CONFIG_TOTAL_HEAP_SIZE 256U
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_SUPPORT_DYNAMIC_ALLOCATION
|
||||
#define CONFIG_SUPPORT_DYNAMIC_ALLOCATION 1
|
||||
#endif
|
||||
|
||||
#define CONFIG_ADJUSTED_HEAP_SIZE (CONFIG_TOTAL_HEAP_SIZE - HEAP4_ALIGNMENT)
|
||||
|
||||
volatile size_t g_total_heap;
|
||||
volatile size_t g_adjusted_heap;
|
||||
volatile int g_dynamic_enabled;
|
||||
volatile int g_trace_is_host_only;
|
||||
|
||||
int main(void)
|
||||
{
|
||||
g_total_heap = CONFIG_TOTAL_HEAP_SIZE;
|
||||
g_adjusted_heap = CONFIG_ADJUSTED_HEAP_SIZE;
|
||||
g_dynamic_enabled = CONFIG_SUPPORT_DYNAMIC_ALLOCATION;
|
||||
|
||||
#ifdef HOST_PRINTF
|
||||
g_trace_is_host_only = 1;
|
||||
#else
|
||||
g_trace_is_host_only = 0;
|
||||
#endif
|
||||
|
||||
TRACE_PRINTF("heap=%u adjusted=%u dynamic=%d host_trace=%d\n",
|
||||
(unsigned)g_total_heap, (unsigned)g_adjusted_heap,
|
||||
g_dynamic_enabled, g_trace_is_host_only);
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,175 @@
|
||||
#include "heap4_common.h"
|
||||
|
||||
#define HEAP_BYTES 256U
|
||||
#define MIN_SPLIT_SIZE ((size_t)(sizeof(HeapBlock) * 2U))
|
||||
|
||||
static uint8_t heap_area[HEAP_BYTES + HEAP4_ALIGNMENT];
|
||||
static HeapBlock start;
|
||||
static HeapBlock *end_marker;
|
||||
|
||||
volatile int g_allocations_ok;
|
||||
volatile int g_final_free_nodes;
|
||||
volatile size_t g_final_free_total;
|
||||
volatile size_t g_minimum_ever_free;
|
||||
|
||||
static size_t free_bytes_remaining;
|
||||
static size_t minimum_ever_free;
|
||||
|
||||
static size_t list_total(void)
|
||||
{
|
||||
HeapBlock *block;
|
||||
size_t total;
|
||||
|
||||
total = 0U;
|
||||
for (block = start.next; block != end_marker; block = block->next)
|
||||
total += block->size;
|
||||
return total;
|
||||
}
|
||||
|
||||
static int list_count(void)
|
||||
{
|
||||
HeapBlock *block;
|
||||
int count;
|
||||
|
||||
count = 0;
|
||||
for (block = start.next; block != end_marker; block = block->next)
|
||||
count++;
|
||||
return count;
|
||||
}
|
||||
|
||||
static void insert_block_merge(HeapBlock *block)
|
||||
{
|
||||
HeapBlock *iterator;
|
||||
uint8_t *block_end;
|
||||
|
||||
for (iterator = &start; iterator->next < block; iterator = iterator->next)
|
||||
;
|
||||
|
||||
block_end = (uint8_t *)block + block->size;
|
||||
if (block_end == (uint8_t *)iterator->next) {
|
||||
block->size += iterator->next->size;
|
||||
block->next = iterator->next->next;
|
||||
} else {
|
||||
block->next = iterator->next;
|
||||
}
|
||||
|
||||
if (iterator != &start && heap4_blocks_touch(iterator, block)) {
|
||||
iterator->size += block->size;
|
||||
iterator->next = block->next;
|
||||
} else {
|
||||
iterator->next = block;
|
||||
}
|
||||
}
|
||||
|
||||
static void heap_init(void)
|
||||
{
|
||||
uintptr_t raw;
|
||||
uintptr_t aligned;
|
||||
size_t available;
|
||||
HeapBlock *first;
|
||||
|
||||
raw = (uintptr_t)&heap_area[0];
|
||||
aligned = heap4_align_address(raw);
|
||||
available = HEAP_BYTES - (size_t)(aligned - raw);
|
||||
available &= ~HEAP4_ALIGNMENT_MASK;
|
||||
|
||||
first = (HeapBlock *)aligned;
|
||||
end_marker = (HeapBlock *)(aligned + available - sizeof(HeapBlock));
|
||||
end_marker->next = 0;
|
||||
end_marker->size = 0U;
|
||||
|
||||
first->next = end_marker;
|
||||
first->size = (uint8_t *)end_marker - (uint8_t *)first;
|
||||
start.next = first;
|
||||
start.size = 0U;
|
||||
|
||||
free_bytes_remaining = first->size;
|
||||
minimum_ever_free = free_bytes_remaining;
|
||||
}
|
||||
|
||||
static void *heap_malloc_model(size_t wanted)
|
||||
{
|
||||
HeapBlock *previous;
|
||||
HeapBlock *block;
|
||||
HeapBlock *remainder;
|
||||
size_t total;
|
||||
size_t original;
|
||||
|
||||
if (wanted == 0U)
|
||||
return 0;
|
||||
|
||||
total = heap4_align_up(wanted + sizeof(HeapBlock));
|
||||
previous = &start;
|
||||
block = start.next;
|
||||
|
||||
while (block != end_marker) {
|
||||
if (block->size >= total) {
|
||||
original = block->size;
|
||||
if (original - total > MIN_SPLIT_SIZE) {
|
||||
remainder = (HeapBlock *)((uint8_t *)block + total);
|
||||
remainder->size = original - total;
|
||||
remainder->next = block->next;
|
||||
previous->next = remainder;
|
||||
block->size = total;
|
||||
} else {
|
||||
previous->next = block->next;
|
||||
total = original;
|
||||
}
|
||||
|
||||
block->next = 0;
|
||||
block->size = heap4_mark_allocated(block->size);
|
||||
free_bytes_remaining -= total;
|
||||
if (free_bytes_remaining < minimum_ever_free)
|
||||
minimum_ever_free = free_bytes_remaining;
|
||||
return (uint8_t *)block + sizeof(HeapBlock);
|
||||
}
|
||||
previous = block;
|
||||
block = block->next;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void heap_free_model(void *p)
|
||||
{
|
||||
HeapBlock *block;
|
||||
size_t size;
|
||||
|
||||
if (p == 0)
|
||||
return;
|
||||
|
||||
block = (HeapBlock *)((uint8_t *)p - sizeof(HeapBlock));
|
||||
if (!heap4_is_allocated(block->size))
|
||||
return;
|
||||
|
||||
size = heap4_clear_allocated(block->size);
|
||||
block->size = size;
|
||||
free_bytes_remaining += size;
|
||||
insert_block_merge(block);
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
void *a;
|
||||
void *b;
|
||||
void *c;
|
||||
|
||||
heap_init();
|
||||
|
||||
a = heap_malloc_model(24U);
|
||||
b = heap_malloc_model(40U);
|
||||
heap_free_model(a);
|
||||
c = heap_malloc_model(16U);
|
||||
heap_free_model(b);
|
||||
heap_free_model(c);
|
||||
|
||||
g_allocations_ok = a != 0 && b != 0 && c != 0;
|
||||
g_final_free_nodes = list_count();
|
||||
g_final_free_total = list_total();
|
||||
g_minimum_ever_free = minimum_ever_free;
|
||||
|
||||
TRACE_PRINTF("ok=%d nodes=%d free=%u min=%u\n",
|
||||
g_allocations_ok, g_final_free_nodes,
|
||||
(unsigned)g_final_free_total, (unsigned)g_minimum_ever_free);
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user