1 /*
2 * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #include <stdbool.h>
8 #include <stdlib.h>
9 #include <string.h>
10 #include <zephyr/kernel.h>
11 #include <zephyr/sys/math_extras.h>
12 #include <esp_attr.h>
13 #include <esp_heap_caps.h>
14
15 #if (CONFIG_ESP_HEAP_MEM_POOL_REGION_1_SIZE > 0)
16 char __aligned(sizeof(void *)) __NOINIT_ATTR dram0_seg_1_heap[CONFIG_ESP_HEAP_MEM_POOL_REGION_1_SIZE];
17 STRUCT_SECTION_ITERABLE(k_heap, _internal_heap_1) = {
18 .heap = {
19 .init_mem = dram0_seg_1_heap,
20 .init_bytes = CONFIG_ESP_HEAP_MEM_POOL_REGION_1_SIZE,
21 }
22 };
23 #endif /* CONFIG_ESP_HEAP_MEM_POOL_REGION_1_SIZE > 0 */
24
25 static esp_alloc_failed_hook_t alloc_failed_callback;
26
heap_caps_register_failed_alloc_callback(esp_alloc_failed_hook_t callback)27 esp_err_t heap_caps_register_failed_alloc_callback(esp_alloc_failed_hook_t callback)
28 {
29 if (callback == NULL) {
30 return ESP_ERR_INVALID_ARG;
31 }
32
33 alloc_failed_callback = callback;
34
35 return ESP_OK;
36 }
37
heap_caps_alloc_failed(size_t requested_size,uint32_t caps,const char * function_name)38 static void heap_caps_alloc_failed(size_t requested_size, uint32_t caps, const char *function_name)
39 {
40 if (alloc_failed_callback) {
41 alloc_failed_callback(requested_size, caps, function_name);
42 }
43
44 #ifdef CONFIG_HEAP_ABORT_WHEN_ALLOCATION_FAILS
45 esp_system_abort("Memory allocation failed");
46 #endif
47 }
48
49 /*
50 Routine to allocate a bit of memory with certain capabilities. caps is a bitfield of MALLOC_CAP_* bits.
51 */
heap_caps_malloc_base(size_t size,uint32_t caps)52 static void *heap_caps_malloc_base( size_t size, uint32_t caps)
53 {
54
55 void *ptr = k_malloc(size);
56
57 if (!ptr && size > 0) {
58 heap_caps_alloc_failed(size, caps, __func__);
59 }
60
61 return ptr;
62 }
63
heap_caps_malloc(size_t size,uint32_t caps)64 void *heap_caps_malloc( size_t size, uint32_t caps)
65 {
66 return heap_caps_malloc_base(size, caps);
67 }
68
heap_caps_malloc_extmem_enable(size_t limit)69 void heap_caps_malloc_extmem_enable(size_t limit)
70 {
71 (void)limit;
72 // Not implemented
73 }
74
heap_caps_malloc_default(size_t size)75 void *heap_caps_malloc_default( size_t size )
76 {
77 return heap_caps_malloc_base(size, MALLOC_CAP_DEFAULT);
78 }
79
heap_caps_malloc_prefer(size_t size,size_t num,...)80 void *heap_caps_malloc_prefer( size_t size, size_t num, ... )
81 {
82 return heap_caps_malloc(size, MALLOC_CAP_DEFAULT);
83 }
84
85
heap_caps_realloc_base(void * ptr,size_t size,uint32_t caps)86 static void *heap_caps_realloc_base( void *ptr, size_t size, uint32_t caps)
87 {
88 ptr = k_realloc(ptr, size);
89
90 if (ptr == NULL && size > 0) {
91 heap_caps_alloc_failed(size, caps, __func__);
92 }
93
94 return ptr;
95 }
96
heap_caps_realloc(void * ptr,size_t size,uint32_t caps)97 void *heap_caps_realloc( void *ptr, size_t size, uint32_t caps)
98 {
99 return heap_caps_realloc_base(ptr, size, caps);
100 }
101
heap_caps_realloc_default(void * ptr,size_t size)102 void *heap_caps_realloc_default( void *ptr, size_t size )
103 {
104 return heap_caps_realloc_base(ptr, size, MALLOC_CAP_DEFAULT);
105 }
106
heap_caps_realloc_prefer(void * ptr,size_t size,size_t num,...)107 void *heap_caps_realloc_prefer( void *ptr, size_t size, size_t num, ... )
108 {
109 return heap_caps_realloc_base(ptr, size, MALLOC_CAP_DEFAULT);
110 }
111
heap_caps_free(void * ptr)112 void heap_caps_free( void *ptr)
113 {
114 k_free(ptr);
115 }
116
heap_caps_calloc_base(size_t n,size_t size,uint32_t caps)117 static void *heap_caps_calloc_base( size_t n, size_t size, uint32_t caps)
118 {
119 size_t size_bytes;
120
121 if (__builtin_mul_overflow(n, size, &size_bytes)) {
122 return NULL;
123 }
124
125 return k_calloc(n, size);
126 }
127
heap_caps_calloc(size_t n,size_t size,uint32_t caps)128 void *heap_caps_calloc( size_t n, size_t size, uint32_t caps)
129 {
130 void *ptr = heap_caps_calloc_base(n, size, caps);
131
132 if (!ptr && size > 0) {
133 heap_caps_alloc_failed(size, caps, __func__);
134 }
135
136 return ptr;
137 }
138
139
heap_caps_calloc_prefer(size_t n,size_t size,size_t num,...)140 void *heap_caps_calloc_prefer( size_t n, size_t size, size_t num, ... )
141 {
142 return heap_caps_calloc_base(n, size, MALLOC_CAP_DEFAULT);
143 }
144
heap_caps_get_total_size(uint32_t caps)145 size_t heap_caps_get_total_size(uint32_t caps)
146 {
147 return K_HEAP_MEM_POOL_SIZE;
148 }
149
heap_caps_get_free_size(uint32_t caps)150 size_t heap_caps_get_free_size( uint32_t caps )
151 {
152 // Not implemented
153 return 0;
154 }
155
heap_caps_get_minimum_free_size(uint32_t caps)156 size_t heap_caps_get_minimum_free_size( uint32_t caps )
157 {
158 // Not implemented
159 return 0;
160 }
161
heap_caps_get_largest_free_block(uint32_t caps)162 size_t heap_caps_get_largest_free_block( uint32_t caps )
163 {
164 // Not implemented
165 return 0;
166 }
167
heap_caps_get_info(multi_heap_info_t * info,uint32_t caps)168 void heap_caps_get_info( multi_heap_info_t *info, uint32_t caps )
169 {
170 memset(info, 0, sizeof(multi_heap_info_t));
171 }
172
heap_caps_print_heap_info(uint32_t caps)173 void heap_caps_print_heap_info( uint32_t caps )
174 {
175 printf("No heap summary available when building for the zephyr target");
176 }
177
heap_caps_check_integrity(uint32_t caps,bool print_errors)178 bool heap_caps_check_integrity(uint32_t caps, bool print_errors)
179 {
180 return true;
181 }
182
heap_caps_check_integrity_all(bool print_errors)183 bool heap_caps_check_integrity_all(bool print_errors)
184 {
185 return heap_caps_check_integrity(MALLOC_CAP_INVALID, print_errors);
186 }
187
heap_caps_check_integrity_addr(intptr_t addr,bool print_errors)188 bool heap_caps_check_integrity_addr(intptr_t addr, bool print_errors)
189 {
190 return true;
191 }
192
heap_caps_dump(uint32_t caps)193 void heap_caps_dump(uint32_t caps)
194 {
195 // Not implemented
196
197 }
198
heap_caps_dump_all(void)199 void heap_caps_dump_all(void)
200 {
201 heap_caps_dump(MALLOC_CAP_INVALID);
202 }
203
heap_caps_get_allocated_size(void * ptr)204 size_t heap_caps_get_allocated_size( void *ptr )
205 {
206 return 0;
207 }
208
heap_caps_aligned_alloc(size_t alignment,size_t size,uint32_t caps)209 void *heap_caps_aligned_alloc(size_t alignment, size_t size, uint32_t caps)
210 {
211 void *ptr = k_aligned_alloc(alignment, size);
212
213 if (!ptr && size > 0) {
214 heap_caps_alloc_failed(size, caps, __func__);
215 }
216
217 return ptr;
218 }
219
heap_caps_aligned_free(void * ptr)220 void heap_caps_aligned_free(void *ptr)
221 {
222 heap_caps_free(ptr);
223 }
224
heap_caps_aligned_calloc(size_t alignment,size_t n,size_t size,uint32_t caps)225 void *heap_caps_aligned_calloc(size_t alignment, size_t n, size_t size, uint32_t caps)
226 {
227 size_t size_bytes;
228 if (__builtin_mul_overflow(n, size, &size_bytes)) {
229 return NULL;
230 }
231
232 void *ptr = heap_caps_aligned_alloc(alignment, size_bytes, caps);
233 if (ptr != NULL) {
234 memset(ptr, 0, size_bytes);
235 }
236
237 return ptr;
238 }
239