blob: 4b8ec3bbdd24569c6cd9c0f89f5a3f4e7876db57 [file] [log] [blame]
/*
* Copyright (c) 2021 Nordic Semiconductor ASA.
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <zephyr/sys/heap_listener.h>
#include <zephyr/kernel.h>
#include <zephyr/ztest.h>
#include <malloc.h>
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
/*
* Function used by malloc() to obtain or free memory to the system.
* Returns the heap end before applying the change.
*/
extern void *sbrk(intptr_t count);
static uintptr_t current_heap_end(void)
{
return (uintptr_t)sbrk(0);
}
static ptrdiff_t heap_difference;
static void heap_resized(uintptr_t heap_id, void *old_heap_end, void *new_heap_end)
{
ARG_UNUSED(heap_id);
heap_difference += ((char *)new_heap_end - (char *)old_heap_end);
}
static HEAP_LISTENER_RESIZE_DEFINE(listener, HEAP_ID_LIBC, heap_resized);
void *ptr;
/**
* @brief Test that heap listener is notified when libc heap size changes.
*
* This test calls the malloc() and free() followed by malloc_trim() functions
* and verifies that the heap listener is notified of allocating or returning
* memory from the system.
*/
ZTEST(newlib_libc_heap_listener, test_alloc_and_trim)
{
uintptr_t saved_heap_end;
TC_PRINT("Allocating memory...\n");
heap_listener_register(&listener);
saved_heap_end = current_heap_end();
ptr = malloc(4096);
TC_PRINT("Total heap size change: %zi\n", heap_difference);
zassert_true(heap_difference > 0, "Heap increase not detected");
zassert_equal(current_heap_end() - saved_heap_end, heap_difference,
"Heap increase not detected");
TC_PRINT("Freeing memory...\n");
heap_difference = 0;
saved_heap_end = current_heap_end();
free(ptr);
malloc_trim(0);
/*
* malloc_trim() may not free any memory to the system if there is not enough to free.
* Therefore, do not require that heap_difference < 0.
*/
zassert_equal(current_heap_end() - saved_heap_end, heap_difference,
"Heap decrease not detected");
heap_listener_unregister(&listener);
}
ZTEST_SUITE(newlib_libc_heap_listener, NULL, NULL, NULL, NULL, NULL);