LCOV - code coverage report
Current view: top level - zephyr/sys - heap_listener.h Hit Total Coverage
Test: new.info Lines: 16 23 69.6 %
Date: 2024-12-21 18:13:37

          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 1.14