Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Fork of OmniWheels by
mbed_alloc_wrappers.cpp
00001 /* mbed Microcontroller Library 00002 * Copyright (c) 2006-2016 ARM Limited 00003 * 00004 * Licensed under the Apache License, Version 2.0 (the "License"); 00005 * you may not use this file except in compliance with the License. 00006 * You may obtain a copy of the License at 00007 * 00008 * http://www.apache.org/licenses/LICENSE-2.0 00009 * 00010 * Unless required by applicable law or agreed to in writing, software 00011 * distributed under the License is distributed on an "AS IS" BASIS, 00012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00013 * See the License for the specific language governing permissions and 00014 * limitations under the License. 00015 */ 00016 00017 #include "platform/mbed_mem_trace.h" 00018 #include "platform/mbed_stats.h" 00019 #include "platform/mbed_toolchain.h" 00020 #include "platform/SingletonPtr.h" 00021 #include "platform/PlatformMutex.h" 00022 #include <stddef.h> 00023 #include <stdio.h> 00024 #include <string.h> 00025 #include <stdlib.h> 00026 00027 /* There are two memory tracers in mbed OS: 00028 00029 - the first can be used to detect the maximum heap usage at runtime. It is 00030 activated by defining the MBED_HEAP_STATS_ENABLED macro. 00031 - the second can be used to trace each memory call by automatically invoking 00032 a callback on each memory operation (see hal/api/mbed_mem_trace.h). It is 00033 activated by defining the MBED_MEM_TRACING_ENABLED macro. 00034 00035 Both tracers can be activated and deactivated in any combination. If both tracers 00036 are active, the second one (MBED_MEM_TRACING_ENABLED) will trace the first one's 00037 (MBED_HEAP_STATS_ENABLED) memory calls.*/ 00038 00039 /******************************************************************************/ 00040 /* Implementation of the runtime max heap usage checker */ 00041 /******************************************************************************/ 00042 00043 /* Size must be a multiple of 8 to keep alignment */ 00044 typedef struct { 00045 uint32_t size; 00046 uint32_t pad; 00047 } alloc_info_t; 00048 00049 #ifdef MBED_HEAP_STATS_ENABLED 00050 static SingletonPtr<PlatformMutex> malloc_stats_mutex; 00051 static mbed_stats_heap_t heap_stats = {0, 0, 0, 0, 0}; 00052 #endif 00053 00054 void mbed_stats_heap_get(mbed_stats_heap_t *stats) 00055 { 00056 #ifdef MBED_HEAP_STATS_ENABLED 00057 extern uint32_t mbed_heap_size; 00058 heap_stats.reserved_size = mbed_heap_size; 00059 00060 malloc_stats_mutex->lock(); 00061 memcpy(stats, &heap_stats, sizeof(mbed_stats_heap_t)); 00062 malloc_stats_mutex->unlock(); 00063 #else 00064 memset(stats, 0, sizeof(mbed_stats_heap_t)); 00065 #endif 00066 } 00067 00068 /******************************************************************************/ 00069 /* GCC memory allocation wrappers */ 00070 /******************************************************************************/ 00071 00072 #if defined(TOOLCHAIN_GCC) 00073 00074 #ifdef FEATURE_UVISOR 00075 #include "uvisor-lib/uvisor-lib.h" 00076 #endif/* FEATURE_UVISOR */ 00077 00078 extern "C" { 00079 void * __real__malloc_r(struct _reent * r, size_t size); 00080 void * __real__memalign_r(struct _reent * r, size_t alignment, size_t bytes); 00081 void * __real__realloc_r(struct _reent * r, void * ptr, size_t size); 00082 void __real__free_r(struct _reent * r, void * ptr); 00083 void* __real__calloc_r(struct _reent * r, size_t nmemb, size_t size); 00084 void* malloc_wrapper(struct _reent * r, size_t size, void * caller); 00085 void free_wrapper(struct _reent * r, void * ptr, void* caller); 00086 } 00087 00088 // TODO: memory tracing doesn't work with uVisor enabled. 00089 #if !defined(FEATURE_UVISOR) 00090 00091 extern "C" void * __wrap__malloc_r(struct _reent * r, size_t size) { 00092 return malloc_wrapper(r, size, MBED_CALLER_ADDR()); 00093 } 00094 00095 extern "C" void * malloc_wrapper(struct _reent * r, size_t size, void * caller) { 00096 void *ptr = NULL; 00097 #ifdef MBED_MEM_TRACING_ENABLED 00098 mbed_mem_trace_lock(); 00099 #endif 00100 #ifdef MBED_HEAP_STATS_ENABLED 00101 malloc_stats_mutex->lock(); 00102 alloc_info_t *alloc_info = (alloc_info_t*)__real__malloc_r(r, size + sizeof(alloc_info_t)); 00103 if (alloc_info != NULL) { 00104 alloc_info->size = size; 00105 ptr = (void*)(alloc_info + 1); 00106 heap_stats.current_size += size; 00107 heap_stats.total_size += size; 00108 heap_stats.alloc_cnt += 1; 00109 if (heap_stats.current_size > heap_stats.max_size) { 00110 heap_stats.max_size = heap_stats.current_size; 00111 } 00112 } else { 00113 heap_stats.alloc_fail_cnt += 1; 00114 } 00115 malloc_stats_mutex->unlock(); 00116 #else // #ifdef MBED_HEAP_STATS_ENABLED 00117 ptr = __real__malloc_r(r, size); 00118 #endif // #ifdef MBED_HEAP_STATS_ENABLED 00119 #ifdef MBED_MEM_TRACING_ENABLED 00120 mbed_mem_trace_malloc(ptr, size, caller); 00121 mbed_mem_trace_unlock(); 00122 #endif // #ifdef MBED_MEM_TRACING_ENABLED 00123 return ptr; 00124 } 00125 00126 extern "C" void * __wrap__realloc_r(struct _reent * r, void * ptr, size_t size) { 00127 void *new_ptr = NULL; 00128 #ifdef MBED_MEM_TRACING_ENABLED 00129 mbed_mem_trace_lock(); 00130 #endif 00131 #ifdef MBED_HEAP_STATS_ENABLED 00132 // Implement realloc_r with malloc and free. 00133 // The function realloc_r can't be used here directly since 00134 // it can call into __wrap__malloc_r (returns ptr + 4) or 00135 // resize memory directly (returns ptr + 0). 00136 00137 // Note - no lock needed since malloc and free are thread safe 00138 00139 // Get old size 00140 uint32_t old_size = 0; 00141 if (ptr != NULL) { 00142 alloc_info_t *alloc_info = ((alloc_info_t*)ptr) - 1; 00143 old_size = alloc_info->size; 00144 } 00145 00146 // Allocate space 00147 if (size != 0) { 00148 new_ptr = malloc(size); 00149 } 00150 00151 // If the new buffer has been allocated copy the data to it 00152 // and free the old buffer 00153 if (new_ptr != NULL) { 00154 uint32_t copy_size = (old_size < size) ? old_size : size; 00155 memcpy(new_ptr, (void*)ptr, copy_size); 00156 free(ptr); 00157 } 00158 #else // #ifdef MBED_HEAP_STATS_ENABLED 00159 new_ptr = __real__realloc_r(r, ptr, size); 00160 #endif // #ifdef MBED_HEAP_STATS_ENABLED 00161 #ifdef MBED_MEM_TRACING_ENABLED 00162 mbed_mem_trace_realloc(new_ptr, ptr, size, MBED_CALLER_ADDR()); 00163 mbed_mem_trace_unlock(); 00164 #endif // #ifdef MBED_MEM_TRACING_ENABLED 00165 return new_ptr; 00166 } 00167 00168 extern "C" void __wrap__free_r(struct _reent * r, void * ptr) { 00169 free_wrapper(r, ptr, MBED_CALLER_ADDR()); 00170 } 00171 00172 extern "C" void free_wrapper(struct _reent * r, void * ptr, void * caller) { 00173 #ifdef MBED_MEM_TRACING_ENABLED 00174 mbed_mem_trace_lock(); 00175 #endif 00176 #ifdef MBED_HEAP_STATS_ENABLED 00177 malloc_stats_mutex->lock(); 00178 alloc_info_t *alloc_info = NULL; 00179 if (ptr != NULL) { 00180 alloc_info = ((alloc_info_t*)ptr) - 1; 00181 heap_stats.current_size -= alloc_info->size; 00182 heap_stats.alloc_cnt -= 1; 00183 } 00184 __real__free_r(r, (void*)alloc_info); 00185 malloc_stats_mutex->unlock(); 00186 #else // #ifdef MBED_HEAP_STATS_ENABLED 00187 __real__free_r(r, ptr); 00188 #endif // #ifdef MBED_HEAP_STATS_ENABLED 00189 #ifdef MBED_MEM_TRACING_ENABLED 00190 mbed_mem_trace_free(ptr, caller); 00191 mbed_mem_trace_unlock(); 00192 #endif // #ifdef MBED_MEM_TRACING_ENABLED 00193 } 00194 00195 extern "C" void * __wrap__calloc_r(struct _reent * r, size_t nmemb, size_t size) { 00196 void *ptr = NULL; 00197 #ifdef MBED_MEM_TRACING_ENABLED 00198 mbed_mem_trace_lock(); 00199 #endif 00200 #ifdef MBED_HEAP_STATS_ENABLED 00201 // Note - no lock needed since malloc is thread safe 00202 00203 ptr = malloc(nmemb * size); 00204 if (ptr != NULL) { 00205 memset(ptr, 0, nmemb * size); 00206 } 00207 #else // #ifdef MBED_HEAP_STATS_ENABLED 00208 ptr = __real__calloc_r(r, nmemb, size); 00209 #endif // #ifdef MBED_HEAP_STATS_ENABLED 00210 #ifdef MBED_MEM_TRACING_ENABLED 00211 mbed_mem_trace_calloc(ptr, nmemb, size, MBED_CALLER_ADDR()); 00212 mbed_mem_trace_unlock(); 00213 #endif // #ifdef MBED_MEM_TRACING_ENABLED 00214 return ptr; 00215 } 00216 00217 extern "C" void * __wrap__memalign_r(struct _reent * r, size_t alignment, size_t bytes) { 00218 return __real__memalign_r(r, alignment, bytes); 00219 } 00220 00221 #endif // if !defined(FEATURE_UVISOR) 00222 00223 00224 /******************************************************************************/ 00225 /* ARMCC / IAR memory allocation wrappers */ 00226 /******************************************************************************/ 00227 00228 #elif defined(TOOLCHAIN_ARM) || defined(__ICCARM__) 00229 00230 #if defined(TOOLCHAIN_ARM) 00231 #define SUPER_MALLOC $Super$$malloc 00232 #define SUB_MALLOC $Sub$$malloc 00233 #define SUPER_REALLOC $Super$$realloc 00234 #define SUB_REALLOC $Sub$$realloc 00235 #define SUPER_CALLOC $Super$$calloc 00236 #define SUB_CALLOC $Sub$$calloc 00237 #define SUPER_FREE $Super$$free 00238 #define SUB_FREE $Sub$$free 00239 #elif defined(__ICCARM__) 00240 #define SUPER_MALLOC $Super$$__iar_dlmalloc 00241 #define SUB_MALLOC $Sub$$__iar_dlmalloc 00242 #define SUPER_REALLOC $Super$$__iar_dlrealloc 00243 #define SUB_REALLOC $Sub$$__iar_dlrealloc 00244 #define SUPER_CALLOC $Super$$__iar_dlcalloc 00245 #define SUB_CALLOC $Sub$$__iar_dlcalloc 00246 #define SUPER_FREE $Super$$__iar_dlfree 00247 #define SUB_FREE $Sub$$__iar_dlfree 00248 #endif 00249 00250 /* Enable hooking of memory function only if tracing is also enabled */ 00251 #if defined(MBED_MEM_TRACING_ENABLED) || defined(MBED_HEAP_STATS_ENABLED) 00252 00253 extern "C" { 00254 void *SUPER_MALLOC(size_t size); 00255 void *SUPER_REALLOC(void *ptr, size_t size); 00256 void *SUPER_CALLOC(size_t nmemb, size_t size); 00257 void SUPER_FREE(void *ptr); 00258 void *malloc_wrapper(size_t size, void* caller); 00259 void free_wrapper(void *ptr, void* caller); 00260 } 00261 00262 00263 extern "C" void* SUB_MALLOC(size_t size) { 00264 return malloc_wrapper(size, MBED_CALLER_ADDR()); 00265 } 00266 00267 extern "C" void* malloc_wrapper(size_t size, void* caller) { 00268 void *ptr = NULL; 00269 #ifdef MBED_MEM_TRACING_ENABLED 00270 mbed_mem_trace_lock(); 00271 #endif 00272 #ifdef MBED_HEAP_STATS_ENABLED 00273 malloc_stats_mutex->lock(); 00274 alloc_info_t *alloc_info = (alloc_info_t*)SUPER_MALLOC(size + sizeof(alloc_info_t)); 00275 if (alloc_info != NULL) { 00276 alloc_info->size = size; 00277 ptr = (void*)(alloc_info + 1); 00278 heap_stats.current_size += size; 00279 heap_stats.total_size += size; 00280 heap_stats.alloc_cnt += 1; 00281 if (heap_stats.current_size > heap_stats.max_size) { 00282 heap_stats.max_size = heap_stats.current_size; 00283 } 00284 } else { 00285 heap_stats.alloc_fail_cnt += 1; 00286 } 00287 malloc_stats_mutex->unlock(); 00288 #else // #ifdef MBED_HEAP_STATS_ENABLED 00289 ptr = SUPER_MALLOC(size); 00290 #endif // #ifdef MBED_HEAP_STATS_ENABLED 00291 #ifdef MBED_MEM_TRACING_ENABLED 00292 mbed_mem_trace_malloc(ptr, size, caller); 00293 mbed_mem_trace_unlock(); 00294 #endif // #ifdef MBED_MEM_TRACING_ENABLED 00295 return ptr; 00296 } 00297 00298 00299 extern "C" void* SUB_REALLOC(void *ptr, size_t size) { 00300 void *new_ptr = NULL; 00301 #ifdef MBED_MEM_TRACING_ENABLED 00302 mbed_mem_trace_lock(); 00303 #endif 00304 #ifdef MBED_HEAP_STATS_ENABLED 00305 // Note - no lock needed since malloc and free are thread safe 00306 00307 // Get old size 00308 uint32_t old_size = 0; 00309 if (ptr != NULL) { 00310 alloc_info_t *alloc_info = ((alloc_info_t*)ptr) - 1; 00311 old_size = alloc_info->size; 00312 } 00313 00314 // Allocate space 00315 if (size != 0) { 00316 new_ptr = malloc(size); 00317 } 00318 00319 // If the new buffer has been allocated copy the data to it 00320 // and free the old buffer 00321 if (new_ptr != NULL) { 00322 uint32_t copy_size = (old_size < size) ? old_size : size; 00323 memcpy(new_ptr, (void*)ptr, copy_size); 00324 free(ptr); 00325 } 00326 #else // #ifdef MBED_HEAP_STATS_ENABLED 00327 new_ptr = SUPER_REALLOC(ptr, size); 00328 #endif // #ifdef MBED_HEAP_STATS_ENABLED 00329 #ifdef MBED_MEM_TRACING_ENABLED 00330 mbed_mem_trace_realloc(new_ptr, ptr, size, MBED_CALLER_ADDR()); 00331 mbed_mem_trace_unlock(); 00332 #endif // #ifdef MBED_MEM_TRACING_ENABLED 00333 return new_ptr; 00334 } 00335 00336 extern "C" void *SUB_CALLOC(size_t nmemb, size_t size) { 00337 void *ptr = NULL; 00338 #ifdef MBED_MEM_TRACING_ENABLED 00339 mbed_mem_trace_lock(); 00340 #endif 00341 #ifdef MBED_HEAP_STATS_ENABLED 00342 // Note - no lock needed since malloc is thread safe 00343 ptr = malloc(nmemb * size); 00344 if (ptr != NULL) { 00345 memset(ptr, 0, nmemb * size); 00346 } 00347 #else // #ifdef MBED_HEAP_STATS_ENABLED 00348 ptr = SUPER_CALLOC(nmemb, size); 00349 #endif // #ifdef MBED_HEAP_STATS_ENABLED 00350 #ifdef MBED_MEM_TRACING_ENABLED 00351 mbed_mem_trace_calloc(ptr, nmemb, size, MBED_CALLER_ADDR()); 00352 mbed_mem_trace_unlock(); 00353 #endif // #ifdef MBED_MEM_TRACING_ENABLED 00354 return ptr; 00355 } 00356 00357 extern "C" void SUB_FREE(void *ptr) { 00358 free_wrapper(ptr, MBED_CALLER_ADDR()); 00359 } 00360 00361 extern "C" void free_wrapper(void *ptr, void* caller) { 00362 #ifdef MBED_MEM_TRACING_ENABLED 00363 mbed_mem_trace_lock(); 00364 #endif 00365 #ifdef MBED_HEAP_STATS_ENABLED 00366 malloc_stats_mutex->lock(); 00367 alloc_info_t *alloc_info = NULL; 00368 if (ptr != NULL) { 00369 alloc_info = ((alloc_info_t*)ptr) - 1; 00370 heap_stats.current_size -= alloc_info->size; 00371 heap_stats.alloc_cnt -= 1; 00372 } 00373 SUPER_FREE((void*)alloc_info); 00374 malloc_stats_mutex->unlock(); 00375 #else // #ifdef MBED_HEAP_STATS_ENABLED 00376 SUPER_FREE(ptr); 00377 #endif // #ifdef MBED_HEAP_STATS_ENABLED 00378 #ifdef MBED_MEM_TRACING_ENABLED 00379 mbed_mem_trace_free(ptr, caller); 00380 mbed_mem_trace_unlock(); 00381 #endif // #ifdef MBED_MEM_TRACING_ENABLED 00382 } 00383 00384 #endif // #if defined(MBED_MEM_TRACING_ENABLED) || defined(MBED_HEAP_STATS_ENABLED) 00385 00386 /******************************************************************************/ 00387 /* Allocation wrappers for other toolchains are not supported yet */ 00388 /******************************************************************************/ 00389 00390 #else 00391 00392 #ifdef MBED_MEM_TRACING_ENABLED 00393 #error Memory tracing is not supported with the current toolchain. 00394 #endif 00395 00396 #ifdef MBED_HEAP_STATS_ENABLED 00397 #error Heap statistics are not supported with the current toolchain. 00398 #endif 00399 00400 #endif // #if defined(TOOLCHAIN_GCC)
Generated on Fri Jul 22 2022 04:53:56 by
