LCOV - code coverage report
Current view: top level - zephyr/sys - heap_listener.h Coverage Total Hit
Test: new.info Lines: 69.6 % 23 16
Test Date: 2025-09-05 20:47:19

            Line data    Source code
       1            0 : /*
       2              :  * Copyright (c) 2021 Nordic Semiconductor ASA
       3              :  *
       4              :  * SPDX-License-Identifier: Apache-2.0
       5              :  */
       6              : 
       7              : #ifndef ZEPHYR_INCLUDE_SYS_HEAP_LISTENER_H
       8              : #define ZEPHYR_INCLUDE_SYS_HEAP_LISTENER_H
       9              : 
      10              : #include <stdint.h>
      11              : #include <zephyr/toolchain.h>
      12              : #include <zephyr/sys/slist.h>
      13              : 
      14              : #ifdef __cplusplus
      15              : extern "C" {
      16              : #endif
      17              : 
      18              : #if defined(CONFIG_HEAP_LISTENER) || defined(__DOXYGEN__)
      19              : 
      20              : /**
      21              :  * @defgroup heap_listener_apis Heap Listener APIs
      22              :  * @ingroup heaps
      23              :  * @{
      24              :  */
      25              : 
      26            0 : enum heap_event_types {
      27              :         /*
      28              :          * Dummy event so an un-initialized but zero-ed listener node
      29              :          * will not trigger any callbacks.
      30              :          */
      31              :         HEAP_EVT_UNKNOWN = 0,
      32              : 
      33              :         HEAP_RESIZE,
      34              :         HEAP_ALLOC,
      35              :         HEAP_FREE,
      36              :         HEAP_REALLOC,
      37              : 
      38              :         HEAP_MAX_EVENTS
      39              : };
      40              : 
      41              : /**
      42              :  * @typedef heap_listener_resize_cb_t
      43              :  * @brief Callback used when heap is resized
      44              :  *
      45              :  * @note Minimal C library does not emit this event.
      46              :  *
      47              :  * @param heap_id Identifier of heap being resized
      48              :  * @param old_heap_end Pointer to end of heap before resize
      49              :  * @param new_heap_end Pointer to end of heap after resize
      50              :  */
      51            1 : typedef void (*heap_listener_resize_cb_t)(uintptr_t heap_id,
      52              :                                           void *old_heap_end,
      53              :                                           void *new_heap_end);
      54              : 
      55              : /**
      56              :  * @typedef heap_listener_alloc_cb_t
      57              :  * @brief Callback used when there is heap allocation
      58              :  *
      59              :  * @note Heaps managed by libraries outside of code in
      60              :  *       Zephyr main code repository may not emit this event.
      61              :  *
      62              :  * @note The number of bytes allocated may not match exactly
      63              :  *       to the request to the allocation function. Internal
      64              :  *       mechanism of the heap may allocate more than
      65              :  *       requested.
      66              :  *
      67              :  * @param heap_id Heap identifier
      68              :  * @param mem Pointer to the allocated memory
      69              :  * @param bytes Size of allocated memory
      70              :  */
      71            1 : typedef void (*heap_listener_alloc_cb_t)(uintptr_t heap_id,
      72              :                                          void *mem, size_t bytes);
      73              : 
      74              : /**
      75              :  * @typedef heap_listener_free_cb_t
      76              :  * @brief Callback used when memory is freed from heap
      77              :  *
      78              :  * @note Heaps managed by libraries outside of code in
      79              :  *       Zephyr main code repository may not emit this event.
      80              :  *
      81              :  * @note The number of bytes freed may not match exactly to
      82              :  *       the request to the allocation function. Internal
      83              :  *       mechanism of the heap dictates how memory is
      84              :  *       allocated or freed.
      85              :  *
      86              :  * @param heap_id Heap identifier
      87              :  * @param mem Pointer to the freed memory
      88              :  * @param bytes Size of freed memory
      89              :  */
      90            1 : typedef void (*heap_listener_free_cb_t)(uintptr_t heap_id,
      91              :                                         void *mem, size_t bytes);
      92              : 
      93            0 : struct heap_listener {
      94              :         /** Singly linked list node */
      95            1 :         sys_snode_t node;
      96              : 
      97              :         /**
      98              :          * Identifier of the heap whose events are listened.
      99              :          *
     100              :          * It can be a heap pointer, if the heap is represented as an object,
     101              :          * or 0 in the case of the global libc heap.
     102              :          */
     103            1 :         uintptr_t heap_id;
     104              : 
     105              :         /**
     106              :          * The heap event to be notified.
     107              :          */
     108            1 :         enum heap_event_types event;
     109              : 
     110              :         union {
     111            0 :                 heap_listener_alloc_cb_t alloc_cb;
     112            0 :                 heap_listener_free_cb_t free_cb;
     113            0 :                 heap_listener_resize_cb_t resize_cb;
     114            0 :         };
     115              : };
     116              : 
     117              : /**
     118              :  * @brief Register heap event listener
     119              :  *
     120              :  * Add the listener to the global list of heap listeners that can be notified by
     121              :  * different heap implementations upon certain events related to the heap usage.
     122              :  *
     123              :  * @param listener Pointer to the heap_listener object
     124              :  */
     125            1 : void heap_listener_register(struct heap_listener *listener);
     126              : 
     127              : /**
     128              :  * @brief Unregister heap event listener
     129              :  *
     130              :  * Remove the listener from the global list of heap listeners that can be
     131              :  * notified by different heap implementations upon certain events related to the
     132              :  * heap usage.
     133              :  *
     134              :  * @param listener Pointer to the heap_listener object
     135              :  */
     136            1 : void heap_listener_unregister(struct heap_listener *listener);
     137              : 
     138              : /**
     139              :  * @brief Notify listeners of heap allocation event
     140              :  *
     141              :  * Notify registered heap event listeners with matching heap identifier that an
     142              :  * allocation has been done on heap
     143              :  *
     144              :  * @param heap_id Heap identifier
     145              :  * @param mem Pointer to the allocated memory
     146              :  * @param bytes Size of allocated memory
     147              :  */
     148            1 : void heap_listener_notify_alloc(uintptr_t heap_id, void *mem, size_t bytes);
     149              : 
     150              : /**
     151              :  * @brief Notify listeners of heap free event
     152              :  *
     153              :  * Notify registered heap event listeners with matching heap identifier that
     154              :  * memory is freed on heap
     155              :  *
     156              :  * @param heap_id Heap identifier
     157              :  * @param mem Pointer to the freed memory
     158              :  * @param bytes Size of freed memory
     159              :  */
     160            1 : void heap_listener_notify_free(uintptr_t heap_id, void *mem, size_t bytes);
     161              : 
     162              : /**
     163              :  * @brief Notify listeners of heap resize event
     164              :  *
     165              :  * Notify registered heap event listeners with matching heap identifier that the
     166              :  * heap has been resized.
     167              :  *
     168              :  * @param heap_id Heap identifier
     169              :  * @param old_heap_end Address of the heap end before the change
     170              :  * @param new_heap_end Address of the heap end after the change
     171              :  */
     172            1 : void heap_listener_notify_resize(uintptr_t heap_id, void *old_heap_end, void *new_heap_end);
     173              : 
     174              : /**
     175              :  * @brief Construct heap identifier from heap pointer
     176              :  *
     177              :  * Construct a heap identifier from a pointer to the heap object, such as
     178              :  * sys_heap.
     179              :  *
     180              :  * @param heap_pointer Pointer to the heap object
     181              :  */
     182            1 : #define HEAP_ID_FROM_POINTER(heap_pointer) ((uintptr_t)heap_pointer)
     183              : 
     184              : /**
     185              :  * @brief Libc heap identifier
     186              :  *
     187              :  * Identifier of the global libc heap.
     188              :  */
     189            1 : #define HEAP_ID_LIBC ((uintptr_t)0)
     190              : 
     191              : /**
     192              :  * @brief Define heap event listener node for allocation event
     193              :  *
     194              :  * Sample usage:
     195              :  * @code
     196              :  * void on_heap_alloc(uintptr_t heap_id, void *mem, size_t bytes)
     197              :  * {
     198              :  *   LOG_INF("Memory allocated at %p, size %ld", mem, bytes);
     199              :  * }
     200              :  *
     201              :  * HEAP_LISTENER_ALLOC_DEFINE(my_listener, HEAP_ID_LIBC, on_heap_alloc);
     202              :  * @endcode
     203              :  *
     204              :  * @param name          Name of the heap event listener object
     205              :  * @param _heap_id      Identifier of the heap to be listened
     206              :  * @param _alloc_cb     Function to be called for allocation event
     207              :  */
     208            1 : #define HEAP_LISTENER_ALLOC_DEFINE(name, _heap_id, _alloc_cb) \
     209              :         struct heap_listener name = { \
     210              :                 .heap_id = _heap_id, \
     211              :                 .event = HEAP_ALLOC, \
     212              :                 { \
     213              :                         .alloc_cb = _alloc_cb \
     214              :                 }, \
     215              :         }
     216              : 
     217              : /**
     218              :  * @brief Define heap event listener node for free event
     219              :  *
     220              :  * Sample usage:
     221              :  * @code
     222              :  * void on_heap_free(uintptr_t heap_id, void *mem, size_t bytes)
     223              :  * {
     224              :  *   LOG_INF("Memory freed at %p, size %ld", mem, bytes);
     225              :  * }
     226              :  *
     227              :  * HEAP_LISTENER_FREE_DEFINE(my_listener, HEAP_ID_LIBC, on_heap_free);
     228              :  * @endcode
     229              :  *
     230              :  * @param name          Name of the heap event listener object
     231              :  * @param _heap_id      Identifier of the heap to be listened
     232              :  * @param _free_cb      Function to be called for free event
     233              :  */
     234            1 : #define HEAP_LISTENER_FREE_DEFINE(name, _heap_id, _free_cb) \
     235              :         struct heap_listener name = { \
     236              :                 .heap_id = _heap_id, \
     237              :                 .event = HEAP_FREE, \
     238              :                 { \
     239              :                         .free_cb = _free_cb \
     240              :                 }, \
     241              :         }
     242              : 
     243              : /**
     244              :  * @brief Define heap event listener node for resize event
     245              :  *
     246              :  * Sample usage:
     247              :  * @code
     248              :  * void on_heap_resized(uintptr_t heap_id, void *old_heap_end, void *new_heap_end)
     249              :  * {
     250              :  *   LOG_INF("Libc heap end moved from %p to %p", old_heap_end, new_heap_end);
     251              :  * }
     252              :  *
     253              :  * HEAP_LISTENER_RESIZE_DEFINE(my_listener, HEAP_ID_LIBC, on_heap_resized);
     254              :  * @endcode
     255              :  *
     256              :  * @param name          Name of the heap event listener object
     257              :  * @param _heap_id      Identifier of the heap to be listened
     258              :  * @param _resize_cb    Function to be called when the listened heap is resized
     259              :  */
     260            1 : #define HEAP_LISTENER_RESIZE_DEFINE(name, _heap_id, _resize_cb) \
     261              :         struct heap_listener name = { \
     262              :                 .heap_id = _heap_id, \
     263              :                 .event = HEAP_RESIZE, \
     264              :                 { \
     265              :                         .resize_cb = _resize_cb \
     266              :                 }, \
     267              :         }
     268              : 
     269              : /** @} */
     270              : 
     271              : #else /* CONFIG_HEAP_LISTENER */
     272              : 
     273              : #define HEAP_ID_FROM_POINTER(heap_pointer) ((uintptr_t)NULL)
     274              : 
     275              : static inline void heap_listener_notify_alloc(uintptr_t heap_id, void *mem, size_t bytes)
     276              : {
     277              :         ARG_UNUSED(heap_id);
     278              :         ARG_UNUSED(mem);
     279              :         ARG_UNUSED(bytes);
     280              : }
     281              : 
     282              : static inline void heap_listener_notify_free(uintptr_t heap_id, void *mem, size_t bytes)
     283              : {
     284              :         ARG_UNUSED(heap_id);
     285              :         ARG_UNUSED(mem);
     286              :         ARG_UNUSED(bytes);
     287              : }
     288              : 
     289              : static inline void heap_listener_notify_resize(uintptr_t heap_id, void *old_heap_end,
     290              :                                                void *new_heap_end)
     291              : {
     292              :         ARG_UNUSED(heap_id);
     293              :         ARG_UNUSED(old_heap_end);
     294              :         ARG_UNUSED(new_heap_end);
     295              : }
     296              : 
     297              : #endif /* CONFIG_HEAP_LISTENER */
     298              : 
     299              : #ifdef __cplusplus
     300              : }
     301              : #endif
     302              : 
     303              : #endif /* ZEPHYR_INCLUDE_SYS_HEAP_LISTENER_H */
        

Generated by: LCOV version 2.0-1