230 lines
6.3 KiB
C
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;
|
|
}
|