#include #include #include "FreeRTOS.h" #include "task.h" #if defined(HOST_PRINTF) #include #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; }