1 /* Copyright (c) 2021 Intel Corporation 2 * SPDX-License-Identifier: Apache-2.0 3 */ 4 5 #ifndef ZEPHYR_INCLUDE_SYS_MULTI_HEAP_H_ 6 #define ZEPHYR_INCLUDE_SYS_MULTI_HEAP_H_ 7 8 #include <zephyr/types.h> 9 10 #define MAX_MULTI_HEAPS 8 11 12 /** 13 * @defgroup multi_heap_wrapper Multi-Heap Wrapper 14 * @ingroup heaps 15 * @{ 16 */ 17 18 /** 19 * @brief Multi-heap allocator 20 * 21 * A sys_multi_heap represents a single allocator made from multiple, 22 * separately managed pools of memory that must be accessed via a 23 * unified API. They can be discontiguous, and in many cases will be 24 * expected to have different capabilities (for example: latency, 25 * cacheability, cpu affinity, etc...) 26 * 27 * Allocation from the multiheap provides an opaque "configuration" 28 * value to specify requirements and heuristics to assist the choice 29 * in backend, which is then provided to a user-specified "choice" 30 * function whose job it is to select a heap based on information in 31 * the config specifier and runtime state (heap full state, etc...) 32 */ 33 struct sys_multi_heap; 34 35 /** 36 * @brief Multi-heap choice function 37 * 38 * This is a user-provided functions whose responsibility is selecting 39 * a specific sys_heap backend based on the opaque cfg value, which is 40 * specified by the user as an argument to sys_multi_heap_alloc(), and 41 * performing the allocation on behalf of the caller. The callback is 42 * free to choose any registered heap backend to perform the 43 * allocation, and may choose to pad the user-provided values as 44 * needed, and to use an aligned allocation where required by the 45 * specified configuration. 46 * 47 * NULL may be returned, which will cause the 48 * allocation to fail and a NULL reported to the calling code. 49 * 50 * @param mheap Multi-heap structure. 51 * @param cfg An opaque user-provided value. It may be interpreted in 52 * any way by the application 53 * @param align Alignment of requested memory (or zero for no alignment) 54 * @param size The user-specified allocation size in bytes 55 * @return A pointer to the allocated memory 56 */ 57 typedef void *(*sys_multi_heap_fn_t)(struct sys_multi_heap *mheap, void *cfg, 58 size_t align, size_t size); 59 60 61 struct sys_multi_heap_rec { 62 struct sys_heap *heap; 63 void *user_data; 64 }; 65 66 struct sys_multi_heap { 67 unsigned int nheaps; 68 sys_multi_heap_fn_t choice; 69 struct sys_multi_heap_rec heaps[MAX_MULTI_HEAPS]; 70 }; 71 72 /** 73 * @brief Initialize multi-heap 74 * 75 * Initialize a sys_multi_heap struct with the specified choice 76 * function. Note that individual heaps must be added later with 77 * sys_multi_heap_add_heap so that the heap bounds can be tracked by 78 * the multi heap code. 79 * 80 * @note In general a multiheap is likely to be instantiated 81 * semi-statically from system configuration (for example, via 82 * linker-provided bounds on available memory in different regions, or 83 * from devicetree definitions of hardware-provided addressable 84 * memory, etc...). The general expectation is that a soc- or 85 * board-level platform device will be initialized at system boot from 86 * these upstream configuration sources and not that an application 87 * will assemble a multi-heap on its own. 88 * 89 * @param heap A sys_multi_heap to initialize 90 * @param choice_fn A sys_multi_heap_fn_t callback used to select 91 * heaps at allocation time 92 */ 93 void sys_multi_heap_init(struct sys_multi_heap *heap, 94 sys_multi_heap_fn_t choice_fn); 95 96 /** 97 * @brief Add sys_heap to multi heap 98 * 99 * This adds a known sys_heap backend to an existing multi heap, 100 * allowing the multi heap internals to track the bounds of the heap 101 * and determine which heap (if any) from which a freed block was 102 * allocated. 103 * 104 * @param mheap A sys_multi_heap to which to add a heap 105 * @param heap The heap to add 106 * @param user_data pointer to any data for the heap 107 */ 108 void sys_multi_heap_add_heap(struct sys_multi_heap *mheap, struct sys_heap *heap, void *user_data); 109 110 /** 111 * @brief Allocate memory from multi heap 112 * 113 * Just as for sys_heap_alloc(), allocates a block of memory of the 114 * specified size in bytes. Takes an opaque configuration pointer 115 * passed to the multi heap choice function, which is used by 116 * integration code to choose a heap backend. 117 * 118 * @param mheap Multi heap pointer 119 * @param cfg Opaque configuration parameter, as for sys_multi_heap_fn_t 120 * @param bytes Requested size of the allocation, in bytes 121 * @return A valid pointer to heap memory, or NULL if no memory is available 122 */ 123 void *sys_multi_heap_alloc(struct sys_multi_heap *mheap, void *cfg, size_t bytes); 124 125 /** 126 * @brief Allocate aligned memory from multi heap 127 * 128 * Just as for sys_multi_heap_alloc(), allocates a block of memory of 129 * the specified size in bytes. Takes an additional parameter 130 * specifying a power of two alignment, in bytes. 131 * 132 * @param mheap Multi heap pointer 133 * @param cfg Opaque configuration parameter, as for sys_multi_heap_fn_t 134 * @param align Power of two alignment for the returned pointer, in bytes 135 * @param bytes Requested size of the allocation, in bytes 136 * @return A valid pointer to heap memory, or NULL if no memory is available 137 */ 138 void *sys_multi_heap_aligned_alloc(struct sys_multi_heap *mheap, 139 void *cfg, size_t align, size_t bytes); 140 141 /** 142 * @brief Get a specific heap for provided address 143 * 144 * Finds a single system heap (with user_data) 145 * controlling the provided pointer 146 * 147 * @param mheap Multi heap pointer 148 * @param addr address to be found, must be a pointer to a block allocated by sys_multi_heap_alloc 149 * @return 0 multi_heap_rec pointer to a structure to be filled with return data 150 * or NULL if the heap has not been found 151 */ 152 const struct sys_multi_heap_rec *sys_multi_heap_get_heap(const struct sys_multi_heap *mheap, 153 void *addr); 154 155 /** 156 * @brief Free memory allocated from multi heap 157 * 158 * Returns the specified block, which must be the return value of a 159 * previously successful sys_multi_heap_alloc() or 160 * sys_multi_heap_aligned_alloc() call, to the heap backend from which 161 * it was allocated. 162 * 163 * Accepts NULL as a block parameter, which is specified to have no 164 * effect. 165 * 166 * @param mheap Multi heap pointer 167 * @param block Block to free, must be a pointer to a block allocated by sys_multi_heap_alloc 168 */ 169 void sys_multi_heap_free(struct sys_multi_heap *mheap, void *block); 170 171 /** 172 * @} 173 */ 174 175 #endif /* ZEPHYR_INCLUDE_SYS_MULTI_HEAP_H_ */ 176