Files
lab-rv32i-freertos-heap4/src/tasks/task03_freertos_heap4.c
T

230 lines
6.3 KiB
C

#include <stddef.h>
#include <stdint.h>
#include "FreeRTOS.h"
#include "task.h"
#if defined(HOST_PRINTF)
#include <stdio.h>
#endif
uint8_t ucHeap[configTOTAL_HEAP_SIZE] __attribute__((aligned(portBYTE_ALIGNMENT)));
HeapStats_t g_initial_stats;
HeapStats_t g_after_a_stats;
HeapStats_t g_after_b_stats;
HeapStats_t g_after_allocations_stats;
HeapStats_t g_after_free_a_stats;
HeapStats_t g_fragmented_stats;
HeapStats_t g_final_stats;
volatile size_t g_initial_free;
volatile size_t g_after_a_free;
volatile size_t g_after_b_free;
volatile size_t g_after_allocations;
volatile size_t g_after_free_a;
volatile size_t g_fragmented_free;
volatile size_t g_final_free;
volatile size_t g_minimum_ever_free;
volatile size_t g_a_consumed;
volatile size_t g_b_consumed;
volatile size_t g_c_consumed;
void * volatile g_probe;
void * volatile g_a;
void * volatile g_b;
void * volatile g_c;
void * volatile g_too_large;
volatile int g_a_aligned;
volatile int g_b_aligned;
volatile int g_c_aligned;
volatile int g_allocations_aligned;
volatile int g_oom_is_null;
volatile int g_malloc_failed_hooks;
volatile int g_assert_failures;
volatile int g_rv32_layout_expected;
volatile int g_task03_pass;
void vApplicationMallocFailedHook(void)
{
g_malloc_failed_hooks++;
}
void heap4_lab_assert(const char *file, int line)
{
(void)file;
(void)line;
g_assert_failures++;
}
#if defined(HEAP4_HOST_ADAPTER)
void vTaskSuspendAll(void)
{
}
BaseType_t xTaskResumeAll(void)
{
return 0;
}
#endif
__attribute__((noinline)) void heap4_reset_checkpoint(void)
{
#if defined(__GNUC__)
__asm__ volatile("" ::: "memory");
#endif
}
__attribute__((noinline)) void heap4_alloc_a_checkpoint(void)
{
#if defined(__GNUC__)
__asm__ volatile("" ::: "memory");
#endif
}
__attribute__((noinline)) void heap4_alloc_b_checkpoint(void)
{
#if defined(__GNUC__)
__asm__ volatile("" ::: "memory");
#endif
}
__attribute__((noinline)) void heap4_alloc_c_checkpoint(void)
{
#if defined(__GNUC__)
__asm__ volatile("" ::: "memory");
#endif
}
__attribute__((noinline)) void heap4_free_a_checkpoint(void)
{
#if defined(__GNUC__)
__asm__ volatile("" ::: "memory");
#endif
}
__attribute__((noinline)) void heap4_fragmented_checkpoint(void)
{
#if defined(__GNUC__)
__asm__ volatile("" ::: "memory");
#endif
}
__attribute__((noinline)) void heap4_coalesced_checkpoint(void)
{
#if defined(__GNUC__)
__asm__ volatile("" ::: "memory");
#endif
}
__attribute__((noinline)) void task03_debug_checkpoint(void)
{
#if defined(__GNUC__)
__asm__ volatile("" ::: "memory");
#endif
}
int main(void)
{
vPortHeapResetState();
g_probe = pvPortMalloc(1U);
if (g_probe != NULL)
{
vPortFree(g_probe);
}
g_initial_free = xPortGetFreeHeapSize();
vPortGetHeapStats(&g_initial_stats);
heap4_reset_checkpoint();
g_a = pvPortMalloc(24U);
g_after_a_free = xPortGetFreeHeapSize();
g_a_consumed = g_initial_free - g_after_a_free;
g_a_aligned =
g_a != NULL && ((uintptr_t)g_a % portBYTE_ALIGNMENT) == 0U;
vPortGetHeapStats(&g_after_a_stats);
heap4_alloc_a_checkpoint();
g_b = pvPortMalloc(40U);
g_after_b_free = xPortGetFreeHeapSize();
g_b_consumed = g_after_a_free - g_after_b_free;
g_b_aligned =
g_b != NULL && ((uintptr_t)g_b % portBYTE_ALIGNMENT) == 0U;
vPortGetHeapStats(&g_after_b_stats);
heap4_alloc_b_checkpoint();
g_c = pvPortMalloc(16U);
g_after_allocations = xPortGetFreeHeapSize();
g_c_consumed = g_after_b_free - g_after_allocations;
g_c_aligned =
g_c != NULL && ((uintptr_t)g_c % portBYTE_ALIGNMENT) == 0U;
g_allocations_aligned =
g_a_aligned && g_b_aligned && g_c_aligned;
vPortGetHeapStats(&g_after_allocations_stats);
heap4_alloc_c_checkpoint();
vPortFree(g_a);
g_after_free_a = xPortGetFreeHeapSize();
vPortGetHeapStats(&g_after_free_a_stats);
heap4_free_a_checkpoint();
vPortFree(g_c);
g_fragmented_free = xPortGetFreeHeapSize();
vPortGetHeapStats(&g_fragmented_stats);
heap4_fragmented_checkpoint();
vPortFree(g_b);
g_final_free = xPortGetFreeHeapSize();
g_minimum_ever_free = xPortGetMinimumEverFreeHeapSize();
vPortGetHeapStats(&g_final_stats);
heap4_coalesced_checkpoint();
g_too_large = pvPortMalloc(configTOTAL_HEAP_SIZE * 2U);
g_oom_is_null = g_too_large == NULL;
#if defined(__riscv) && (__riscv_xlen == 32)
g_rv32_layout_expected =
portBYTE_ALIGNMENT == 16U &&
g_initial_free == 4080U &&
g_after_a_free == 4032U && g_a_consumed == 48U &&
g_after_b_free == 3968U && g_b_consumed == 64U &&
g_after_allocations == 3936U && g_c_consumed == 32U &&
g_after_free_a == 3984U &&
g_fragmented_free == 4016U &&
g_final_free == 4080U;
#else
g_rv32_layout_expected = 1;
#endif
g_task03_pass =
g_probe != NULL && g_allocations_aligned &&
g_rv32_layout_expected &&
g_initial_stats.xNumberOfFreeBlocks == 1U &&
g_after_a_free < g_initial_free &&
g_after_b_free < g_after_a_free &&
g_initial_free > g_after_allocations &&
g_after_free_a > g_after_allocations &&
g_fragmented_free > g_after_free_a &&
g_final_free == g_initial_free &&
g_minimum_ever_free <= g_after_allocations &&
g_after_free_a_stats.xNumberOfFreeBlocks == 2U &&
g_fragmented_stats.xNumberOfFreeBlocks == 2U &&
g_fragmented_stats.xAvailableHeapSpaceInBytes >
g_fragmented_stats.xSizeOfLargestFreeBlockInBytes &&
g_final_stats.xNumberOfFreeBlocks == 1U &&
g_final_stats.xSizeOfLargestFreeBlockInBytes == g_initial_free &&
g_oom_is_null && g_malloc_failed_hooks == 1 &&
g_assert_failures == 0;
task03_debug_checkpoint();
#if defined(HOST_PRINTF)
printf("initial=%zu after_a=%zu after_b=%zu after_c=%zu "
"free_a=%zu fragmented=%zu final=%zu min=%zu "
"consumed=%zu/%zu/%zu aligned=%d oom=%d hooks=%d "
"asserts=%d pass=%d\n",
g_initial_free, g_after_a_free, g_after_b_free,
g_after_allocations, g_after_free_a, g_fragmented_free,
g_final_free, g_minimum_ever_free,
g_a_consumed, g_b_consumed, g_c_consumed,
g_allocations_aligned, g_oom_is_null,
g_malloc_failed_hooks, g_assert_failures, g_task03_pass);
#endif
return g_task03_pass ? 0 : 1;
}