Commit 3aedda98 authored by Damian Krolik's avatar Damian Krolik Committed by Christopher Friedt
Browse files

lib: os: add heap event listener



* add generic heap event listener module that can be used
  for notifying an application of heap-related events
* use the listener module in newlib libc hooks
* add a unit test

Signed-off-by: default avatarDamian Krolik <damian.krolik@nordicsemi.no>
parent 16571db0
Loading
Loading
Loading
Loading
+108 −0
Original line number Diff line number Diff line
/*
 * Copyright (c) 2021 Nordic Semiconductor ASA
 *
 * SPDX-License-Identifier: Apache-2.0
 */

#ifndef ZEPHYR_INCLUDE_SYS_HEAP_LISTENER_H
#define ZEPHYR_INCLUDE_SYS_HEAP_LISTENER_H

#include <stdint.h>
#include <sys/slist.h>

#ifdef __cplusplus
extern "C" {
#endif


struct heap_listener {
	/** Singly linked list node */
	sys_snode_t node;

	/**
	 * Identifier of the heap whose events are listened.
	 *
	 * It can be a heap pointer, if the heap is represented as an object,
	 * or 0 in the case of the global libc heap.
	 */
	uintptr_t heap_id;

	/** Function called when the listened heap is resized */
	void (*resize_cb)(void *old_heap_end, void *new_heap_end);
};

/**
 * @brief Register heap event listener
 *
 * Add the listener to the global list of heap listeners that can be notified by
 * different heap implementations upon certain events related to the heap usage.
 *
 * @param listener Pointer to the heap_listener object
 */
void heap_listener_register(struct heap_listener *listener);

/**
 * @brief Unregister heap event listener
 *
 * Remove the listener from the global list of heap listeners that can be
 * notified by different heap implementations upon certain events related to the
 * heap usage.
 *
 * @param listener Pointer to the heap_listener object
 */
void heap_listener_unregister(struct heap_listener *listener);

/**
 * @brief Notify listeners of heap resize event
 *
 * Notify registered heap event listeners with matching heap identifier that the
 * heap has been resized.
 *
 * @param heap_id Heap identifier
 * @param old_heap_end Address of the heap end before the change
 * @param new_heap_end Address of the heap end after the change
 */
void heap_listener_notify_resize(uintptr_t heap_id, void *old_heap_end, void *new_heap_end);

/**
 * @brief Construct heap identifier from heap pointer
 *
 * Construct a heap identifer from a pointer to the heap object, such as
 * sys_heap.
 *
 * @param heap_pointer Pointer to the heap object
 */
#define HEAP_ID_FROM_POINTER(heap_pointer) ((uintptr_t)heap_pointer)

/**
 * @brief Libc heap identifier
 *
 * Identifier of the global libc heap.
 */
#define HEAP_ID_LIBC ((uintptr_t)0)

/**
 * @brief Define heap event listener object
 *
 * Sample usage:
 * @code
 * void on_heap_resized(void *old_heap_end, void *new_heap_end)
 * {
 *   LOG_INF("Libc heap end moved from %p to %p", old_heap_end, new_heap_end);
 * }
 *
 * HEAP_LISTENER_DEFINE(my_listener, HEAP_ID_LIBC, on_heap_resized);
 * @endcode
 *
 * @param name		Name of the heap event listener object
 * @param _heap_id	Identifier of the heap to be listened
 * @param _resize_cb	Function to be called when the listened heap is resized
 */
#define HEAP_LISTENER_DEFINE(name, _heap_id, _resize_cb) \
	struct heap_listener name = { .heap_id = _heap_id, .resize_cb = _resize_cb }

#ifdef __cplusplus
}
#endif

#endif /* ZEPHYR_INCLUDE_SYS_HEAP_LISTENER_H */
+7 −0
Original line number Diff line number Diff line
@@ -110,6 +110,13 @@ config NEWLIB_LIBC_FLOAT_SCANF
	  Build with floating point scanf enabled. This will increase the size of
	  the image.

config NEWLIB_LIBC_HEAP_LISTENER
	bool "Notify heap listeners of newlib libc heap events"
	select HEAP_LISTENER
	help
	  Notify registered heap listeners upon certain events related to the newlib
	  libc heap usage, such as the heap resize.

endif # NEWLIB_LIBC

if MINIMAL_LIBC
+5 −0
Original line number Diff line number Diff line
@@ -13,6 +13,7 @@
#include <linker/linker-defs.h>
#include <sys/util.h>
#include <sys/errno_private.h>
#include <sys/heap_listener.h>
#include <sys/libc-hooks.h>
#include <syscall_handler.h>
#include <app_memory/app_memdomain.h>
@@ -291,6 +292,10 @@ void *_sbrk(intptr_t count)
	if ((heap_sz + count) < MAX_HEAP_SIZE) {
		heap_sz += count;
		ret = ptr;

#ifdef CONFIG_NEWLIB_LIBC_HEAP_LISTENER
		heap_listener_notify_resize(HEAP_ID_LIBC, ptr, (char *)ptr + count);
#endif
	} else {
		ret = (void *)-1;
	}
+2 −0
Original line number Diff line number Diff line
@@ -45,6 +45,8 @@ zephyr_sources_ifdef(CONFIG_REBOOT reboot.c)

zephyr_sources_ifdef(CONFIG_SHARED_MULTI_HEAP shared_multi_heap.c)

zephyr_sources_ifdef(CONFIG_HEAP_LISTENER heap_listener.c)

zephyr_library_include_directories(
  ${ZEPHYR_BASE}/kernel/include
  ${ZEPHYR_BASE}/arch/${ARCH}/include
+6 −0
Original line number Diff line number Diff line
@@ -51,6 +51,12 @@ config SYS_HEAP_RUNTIME_STATS
	help
	  Gather system heap runtime statistics.

config HEAP_LISTENER
	bool "Enable heap listener"
	help
	  Enable API for registering and notifying listeners of certain
	  events related to a heap usage, such as the heap resize.

choice
	prompt "Supported heap sizes"
	depends on !64BIT
Loading