1 /*
2  * SPDX-FileCopyrightText: 2019-2021 Espressif Systems (Shanghai) CO LTD
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #pragma once
8 
9 #include <stdint.h>
10 #include <stdlib.h>
11 #include "multi_heap.h"
12 #include <sdkconfig.h>
13 #include "esp_err.h"
14 
15 #ifdef __cplusplus
16 extern "C" {
17 #endif
18 
19 /**
20  * @brief Flags to indicate the capabilities of the various memory systems
21  */
22 #define MALLOC_CAP_EXEC             (1<<0)  ///< Memory must be able to run executable code
23 #define MALLOC_CAP_32BIT            (1<<1)  ///< Memory must allow for aligned 32-bit data accesses
24 #define MALLOC_CAP_8BIT             (1<<2)  ///< Memory must allow for 8/16/...-bit data accesses
25 #define MALLOC_CAP_DMA              (1<<3)  ///< Memory must be able to accessed by DMA
26 #define MALLOC_CAP_PID2             (1<<4)  ///< Memory must be mapped to PID2 memory space (PIDs are not currently used)
27 #define MALLOC_CAP_PID3             (1<<5)  ///< Memory must be mapped to PID3 memory space (PIDs are not currently used)
28 #define MALLOC_CAP_PID4             (1<<6)  ///< Memory must be mapped to PID4 memory space (PIDs are not currently used)
29 #define MALLOC_CAP_PID5             (1<<7)  ///< Memory must be mapped to PID5 memory space (PIDs are not currently used)
30 #define MALLOC_CAP_PID6             (1<<8)  ///< Memory must be mapped to PID6 memory space (PIDs are not currently used)
31 #define MALLOC_CAP_PID7             (1<<9)  ///< Memory must be mapped to PID7 memory space (PIDs are not currently used)
32 #define MALLOC_CAP_SPIRAM           (1<<10) ///< Memory must be in SPI RAM
33 #define MALLOC_CAP_INTERNAL         (1<<11) ///< Memory must be internal; specifically it should not disappear when flash/spiram cache is switched off
34 #define MALLOC_CAP_DEFAULT          (1<<12) ///< Memory can be returned in a non-capability-specific memory allocation (e.g. malloc(), calloc()) call
35 #define MALLOC_CAP_IRAM_8BIT        (1<<13) ///< Memory must be in IRAM and allow unaligned access
36 #define MALLOC_CAP_RETENTION        (1<<14)
37 #define MALLOC_CAP_RTCRAM           (1<<15) ///< Memory must be in RTC fast memory
38 
39 #define MALLOC_CAP_INVALID          (1<<31) ///< Memory can't be used / list end marker
40 
41 /**
42  * @brief callback called when a allocation operation fails, if registered
43  * @param size in bytes of failed allocation
44  * @param caps capabillites requested of failed allocation
45  * @param function_name function which generated the failure
46  */
47 typedef void (*esp_alloc_failed_hook_t) (size_t size, uint32_t caps, const char * function_name);
48 
49 /**
50  * @brief registers a callback function to be invoked if a memory allocation operation fails
51  * @param callback caller defined callback to be invoked
52  * @return ESP_OK if callback was registered.
53  */
54 esp_err_t heap_caps_register_failed_alloc_callback(esp_alloc_failed_hook_t callback);
55 
56 /**
57  * @brief Allocate a chunk of memory which has the given capabilities
58  *
59  * Equivalent semantics to libc malloc(), for capability-aware memory.
60  *
61  * In IDF, ``malloc(p)`` is equivalent to ``heap_caps_malloc(p, MALLOC_CAP_8BIT)``.
62  *
63  * @param size Size, in bytes, of the amount of memory to allocate
64  * @param caps        Bitwise OR of MALLOC_CAP_* flags indicating the type
65  *                    of memory to be returned
66  *
67  * @return A pointer to the memory allocated on success, NULL on failure
68  */
69 void *heap_caps_malloc(size_t size, uint32_t caps);
70 
71 
72 /**
73  * @brief Free memory previously allocated via heap_caps_malloc() or heap_caps_realloc().
74  *
75  * Equivalent semantics to libc free(), for capability-aware memory.
76  *
77  *  In IDF, ``free(p)`` is equivalent to ``heap_caps_free(p)``.
78  *
79  * @param ptr Pointer to memory previously returned from heap_caps_malloc() or heap_caps_realloc(). Can be NULL.
80  */
81 void heap_caps_free( void *ptr);
82 
83 /**
84  * @brief Reallocate memory previously allocated via heap_caps_malloc() or heap_caps_realloc().
85  *
86  * Equivalent semantics to libc realloc(), for capability-aware memory.
87  *
88  * In IDF, ``realloc(p, s)`` is equivalent to ``heap_caps_realloc(p, s, MALLOC_CAP_8BIT)``.
89  *
90  * 'caps' parameter can be different to the capabilities that any original 'ptr' was allocated with. In this way,
91  * realloc can be used to "move" a buffer if necessary to ensure it meets a new set of capabilities.
92  *
93  * @param ptr Pointer to previously allocated memory, or NULL for a new allocation.
94  * @param size Size of the new buffer requested, or 0 to free the buffer.
95  * @param caps        Bitwise OR of MALLOC_CAP_* flags indicating the type
96  *                    of memory desired for the new allocation.
97  *
98  * @return Pointer to a new buffer of size 'size' with capabilities 'caps', or NULL if allocation failed.
99  */
100 void *heap_caps_realloc( void *ptr, size_t size, uint32_t caps);
101 
102 /**
103  * @brief Allocate a aligned chunk of memory which has the given capabilities
104  *
105  * Equivalent semantics to libc aligned_alloc(), for capability-aware memory.
106  * @param alignment  How the pointer received needs to be aligned
107  *                   must be a power of two
108  * @param size Size, in bytes, of the amount of memory to allocate
109  * @param caps        Bitwise OR of MALLOC_CAP_* flags indicating the type
110  *                    of memory to be returned
111  *
112  * @return A pointer to the memory allocated on success, NULL on failure
113  *
114  *
115  */
116 void *heap_caps_aligned_alloc(size_t alignment, size_t size, uint32_t caps);
117 
118 /**
119  * @brief Used to deallocate memory previously allocated with heap_caps_aligned_alloc
120  *
121  * @param ptr Pointer to the memory allocated
122  * @note This function is deprecated, plase consider using heap_caps_free() instead
123  */
124 void __attribute__((deprecated))  heap_caps_aligned_free(void *ptr);
125 
126 /**
127  * @brief Allocate a aligned chunk of memory which has the given capabilities. The initialized value in the memory is set to zero.
128  *
129  * @param alignment  How the pointer received needs to be aligned
130  *                   must be a power of two
131  * @param n    Number of continuing chunks of memory to allocate
132  * @param size Size, in bytes, of a chunk of memory to allocate
133  * @param caps        Bitwise OR of MALLOC_CAP_* flags indicating the type
134  *                    of memory to be returned
135  *
136  * @return A pointer to the memory allocated on success, NULL on failure
137  *
138  */
139 void *heap_caps_aligned_calloc(size_t alignment, size_t n, size_t size, uint32_t caps);
140 
141 
142 /**
143  * @brief Allocate a chunk of memory which has the given capabilities. The initialized value in the memory is set to zero.
144  *
145  * Equivalent semantics to libc calloc(), for capability-aware memory.
146  *
147  * In IDF, ``calloc(p)`` is equivalent to ``heap_caps_calloc(p, MALLOC_CAP_8BIT)``.
148  *
149  * @param n    Number of continuing chunks of memory to allocate
150  * @param size Size, in bytes, of a chunk of memory to allocate
151  * @param caps        Bitwise OR of MALLOC_CAP_* flags indicating the type
152  *                    of memory to be returned
153  *
154  * @return A pointer to the memory allocated on success, NULL on failure
155  */
156 void *heap_caps_calloc(size_t n, size_t size, uint32_t caps);
157 
158 /**
159  * @brief Get the total size of all the regions that have the given capabilities
160  *
161  * This function takes all regions capable of having the given capabilities allocated in them
162  * and adds up the total space they have.
163  *
164  * @param caps        Bitwise OR of MALLOC_CAP_* flags indicating the type
165  *                    of memory
166  *
167  * @return total size in bytes
168  */
169 
170 size_t heap_caps_get_total_size(uint32_t caps);
171 
172 /**
173  * @brief Get the total free size of all the regions that have the given capabilities
174  *
175  * This function takes all regions capable of having the given capabilities allocated in them
176  * and adds up the free space they have.
177  *
178  * Note that because of heap fragmentation it is probably not possible to allocate a single block of memory
179  * of this size. Use heap_caps_get_largest_free_block() for this purpose.
180 
181  * @param caps        Bitwise OR of MALLOC_CAP_* flags indicating the type
182  *                    of memory
183  *
184  * @return Amount of free bytes in the regions
185  */
186 size_t heap_caps_get_free_size( uint32_t caps );
187 
188 
189 /**
190  * @brief Get the total minimum free memory of all regions with the given capabilities
191  *
192  * This adds all the low water marks of the regions capable of delivering the memory
193  * with the given capabilities.
194  *
195  * Note the result may be less than the global all-time minimum available heap of this kind, as "low water marks" are
196  * tracked per-region. Individual regions' heaps may have reached their "low water marks" at different points in time. However
197  * this result still gives a "worst case" indication for all-time minimum free heap.
198  *
199  * @param caps        Bitwise OR of MALLOC_CAP_* flags indicating the type
200  *                    of memory
201  *
202  * @return Amount of free bytes in the regions
203  */
204 size_t heap_caps_get_minimum_free_size( uint32_t caps );
205 
206 /**
207  * @brief Get the largest free block of memory able to be allocated with the given capabilities.
208  *
209  * Returns the largest value of ``s`` for which ``heap_caps_malloc(s, caps)`` will succeed.
210  *
211  * @param caps        Bitwise OR of MALLOC_CAP_* flags indicating the type
212  *                    of memory
213  *
214  * @return Size of largest free block in bytes.
215  */
216 size_t heap_caps_get_largest_free_block( uint32_t caps );
217 
218 
219 /**
220  * @brief Get heap info for all regions with the given capabilities.
221  *
222  * Calls multi_heap_info() on all heaps which share the given capabilities.  The information returned is an aggregate
223  * across all matching heaps.  The meanings of fields are the same as defined for multi_heap_info_t, except that
224  * ``minimum_free_bytes`` has the same caveats described in heap_caps_get_minimum_free_size().
225  *
226  * @param info        Pointer to a structure which will be filled with relevant
227  *                    heap metadata.
228  * @param caps        Bitwise OR of MALLOC_CAP_* flags indicating the type
229  *                    of memory
230  *
231  */
232 void heap_caps_get_info( multi_heap_info_t *info, uint32_t caps );
233 
234 
235 /**
236  * @brief Print a summary of all memory with the given capabilities.
237  *
238  * Calls multi_heap_info on all heaps which share the given capabilities, and
239  * prints a two-line summary for each, then a total summary.
240  *
241  * @param caps        Bitwise OR of MALLOC_CAP_* flags indicating the type
242  *                    of memory
243  *
244  */
245 void heap_caps_print_heap_info( uint32_t caps );
246 
247 /**
248  * @brief Check integrity of all heap memory in the system.
249  *
250  * Calls multi_heap_check on all heaps. Optionally print errors if heaps are corrupt.
251  *
252  * Calling this function is equivalent to calling heap_caps_check_integrity
253  * with the caps argument set to MALLOC_CAP_INVALID.
254  *
255  * @param print_errors Print specific errors if heap corruption is found.
256  *
257  * @return True if all heaps are valid, False if at least one heap is corrupt.
258  */
259 bool heap_caps_check_integrity_all(bool print_errors);
260 
261 /**
262  * @brief Check integrity of all heaps with the given capabilities.
263  *
264  * Calls multi_heap_check on all heaps which share the given capabilities. Optionally
265  * print errors if the heaps are corrupt.
266  *
267  * See also heap_caps_check_integrity_all to check all heap memory
268  * in the system and heap_caps_check_integrity_addr to check memory
269  * around a single address.
270  *
271  * @param caps        Bitwise OR of MALLOC_CAP_* flags indicating the type
272  *                    of memory
273  * @param print_errors Print specific errors if heap corruption is found.
274  *
275  * @return True if all heaps are valid, False if at least one heap is corrupt.
276  */
277 bool heap_caps_check_integrity(uint32_t caps, bool print_errors);
278 
279 /**
280  * @brief Check integrity of heap memory around a given address.
281  *
282  * This function can be used to check the integrity of a single region of heap memory,
283  * which contains the given address.
284  *
285  * This can be useful if debugging heap integrity for corruption at a known address,
286  * as it has a lower overhead than checking all heap regions. Note that if the corrupt
287  * address moves around between runs (due to timing or other factors) then this approach
288  * won't work and you should call heap_caps_check_integrity or
289  * heap_caps_check_integrity_all instead.
290  *
291  * @note The entire heap region around the address is checked, not only the adjacent
292  * heap blocks.
293  *
294  * @param addr Address in memory. Check for corruption in region containing this address.
295  * @param print_errors Print specific errors if heap corruption is found.
296  *
297  * @return True if the heap containing the specified address is valid,
298  * False if at least one heap is corrupt or the address doesn't belong to a heap region.
299  */
300 bool heap_caps_check_integrity_addr(intptr_t addr, bool print_errors);
301 
302 /**
303  * @brief Enable malloc() in external memory and set limit below which
304  *        malloc() attempts are placed in internal memory.
305  *
306  * When external memory is in use, the allocation strategy is to initially try to
307  * satisfy smaller allocation requests with internal memory and larger requests
308  * with external memory. This sets the limit between the two, as well as generally
309  * enabling allocation in external memory.
310  *
311  * @param limit       Limit, in bytes.
312  */
313 void heap_caps_malloc_extmem_enable(size_t limit);
314 
315 /**
316  * @brief Allocate a chunk of memory as preference in decreasing order.
317  *
318  * @attention The variable parameters are bitwise OR of MALLOC_CAP_* flags indicating the type of memory.
319  *            This API prefers to allocate memory with the first parameter. If failed, allocate memory with
320  *            the next parameter. It will try in this order until allocating a chunk of memory successfully
321  *            or fail to allocate memories with any of the parameters.
322  *
323  * @param size Size, in bytes, of the amount of memory to allocate
324  * @param num Number of variable paramters
325  *
326  * @return A pointer to the memory allocated on success, NULL on failure
327  */
328 void *heap_caps_malloc_prefer( size_t size, size_t num, ... );
329 
330 /**
331  * @brief Allocate a chunk of memory as preference in decreasing order.
332  *
333  * @param ptr Pointer to previously allocated memory, or NULL for a new allocation.
334  * @param size Size of the new buffer requested, or 0 to free the buffer.
335  * @param num Number of variable paramters
336  *
337  * @return Pointer to a new buffer of size 'size', or NULL if allocation failed.
338  */
339 void *heap_caps_realloc_prefer( void *ptr, size_t size, size_t num, ... );
340 
341 /**
342  * @brief Allocate a chunk of memory as preference in decreasing order.
343  *
344  * @param n    Number of continuing chunks of memory to allocate
345  * @param size Size, in bytes, of a chunk of memory to allocate
346  * @param num  Number of variable paramters
347  *
348  * @return A pointer to the memory allocated on success, NULL on failure
349  */
350 void *heap_caps_calloc_prefer( size_t n, size_t size, size_t num, ... );
351 
352 /**
353  * @brief Dump the full structure of all heaps with matching capabilities.
354  *
355  * Prints a large amount of output to serial (because of locking limitations,
356  * the output bypasses stdout/stderr). For each (variable sized) block
357  * in each matching heap, the following output is printed on a single line:
358  *
359  * - Block address (the data buffer returned by malloc is 4 bytes after this
360  *   if heap debugging is set to Basic, or 8 bytes otherwise).
361  * - Data size (the data size may be larger than the size requested by malloc,
362  *   either due to heap fragmentation or because of heap debugging level).
363  * - Address of next block in the heap.
364  * - If the block is free, the address of the next free block is also printed.
365  *
366  * @param caps        Bitwise OR of MALLOC_CAP_* flags indicating the type
367  *                    of memory
368  */
369 void heap_caps_dump(uint32_t caps);
370 
371 /**
372  * @brief Dump the full structure of all heaps.
373  *
374  * Covers all registered heaps. Prints a large amount of output to serial.
375  *
376  * Output is the same as for heap_caps_dump.
377  *
378  */
379 void heap_caps_dump_all(void);
380 
381 /**
382  * @brief Return the size that a particular pointer was allocated with.
383  *
384  * @param ptr Pointer to currently allocated heap memory. Must be a pointer value previously
385  * returned by heap_caps_malloc,malloc,calloc, etc. and not yet freed.
386  *
387  * @note The app will crash with an assertion failure if the pointer is not valid.
388  *
389  * @return Size of the memory allocated at this block.
390  *
391  */
392 size_t heap_caps_get_allocated_size( void *ptr );
393 
394 #ifdef __cplusplus
395 }
396 #endif
397