Line data Source code
1 0 : /* 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 0 : #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 1 : typedef void *(*sys_multi_heap_fn_t)(struct sys_multi_heap *mheap, void *cfg,
58 : size_t align, size_t size);
59 :
60 :
61 0 : struct sys_multi_heap_rec {
62 0 : struct sys_heap *heap;
63 0 : void *user_data;
64 : };
65 :
66 0 : struct sys_multi_heap {
67 0 : unsigned int nheaps;
68 0 : sys_multi_heap_fn_t choice;
69 0 : 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 1 : 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 1 : 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 1 : 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 1 : 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 1 : 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 1 : void sys_multi_heap_free(struct sys_multi_heap *mheap, void *block);
170 :
171 : /** @brief Expand the size of an existing allocation on the multi heap
172 : *
173 : * Returns a pointer to a new memory region with the same contents,
174 : * but a different allocated size. If the new allocation can be
175 : * expanded in place, the pointer returned will be identical.
176 : * Otherwise the data will be copies to a new block and the old one
177 : * will be freed as per sys_heap_free(). If the specified size is
178 : * smaller than the original, the block will be truncated in place and
179 : * the remaining memory returned to the heap. If the allocation of a
180 : * new block fails, then NULL will be returned and the old block will
181 : * not be freed or modified. If a new allocation is needed, the choice
182 : * for the heap used will be bases on the cfg parameter (same as in sys_multi_heap_aligned_alloc).
183 : *
184 : * @param mheap Multi heap pointer
185 : * @param cfg Opaque configuration parameter, as for sys_multi_heap_fn_t
186 : * @param ptr Original pointer returned from a previous allocation
187 : * @param align Alignment in bytes, must be a power of two
188 : * @param bytes Number of bytes requested for the new block
189 : * @return Pointer to memory the caller can now use, or NULL
190 : */
191 1 : void *sys_multi_heap_aligned_realloc(struct sys_multi_heap *mheap, void *cfg,
192 : void *ptr, size_t align, size_t bytes);
193 :
194 0 : #define sys_multi_heap_realloc(mheap, cfg, ptr, bytes) \
195 : sys_multi_heap_aligned_realloc(mheap, cfg, ptr, 0, bytes)
196 :
197 : /**
198 : * @}
199 : */
200 :
201 : #endif /* ZEPHYR_INCLUDE_SYS_MULTI_HEAP_H_ */
|