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 gr-peach-opencv-project-sd-card 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_MEM_TRACING_ENABLED 00050 static SingletonPtr<PlatformMutex> mem_trace_mutex; 00051 #endif 00052 #ifdef MBED_HEAP_STATS_ENABLED 00053 static SingletonPtr<PlatformMutex> malloc_stats_mutex; 00054 static mbed_stats_heap_t heap_stats = {0, 0, 0, 0, 0}; 00055 #endif 00056 00057 void mbed_stats_heap_get(mbed_stats_heap_t *stats) 00058 { 00059 #ifdef MBED_HEAP_STATS_ENABLED 00060 extern uint32_t mbed_heap_size; 00061 heap_stats.reserved_size = mbed_heap_size; 00062 00063 malloc_stats_mutex->lock(); 00064 memcpy(stats, &heap_stats, sizeof(mbed_stats_heap_t)); 00065 malloc_stats_mutex->unlock(); 00066 #else 00067 memset(stats, 0, sizeof(mbed_stats_heap_t)); 00068 #endif 00069 } 00070 00071 /******************************************************************************/ 00072 /* GCC memory allocation wrappers */ 00073 /******************************************************************************/ 00074 00075 #if defined(TOOLCHAIN_GCC) 00076 00077 #ifdef FEATURE_UVISOR 00078 #include "uvisor-lib/uvisor-lib.h" 00079 #endif/* FEATURE_UVISOR */ 00080 00081 extern "C" { 00082 void * __real__malloc_r(struct _reent * r, size_t size); 00083 void * __real__memalign_r(struct _reent * r, size_t alignment, size_t bytes); 00084 void * __real__realloc_r(struct _reent * r, void * ptr, size_t size); 00085 void __real__free_r(struct _reent * r, void * ptr); 00086 void* __real__calloc_r(struct _reent * r, size_t nmemb, size_t size); 00087 } 00088 00089 // TODO: memory tracing doesn't work with uVisor enabled. 00090 #if !defined(FEATURE_UVISOR) 00091 00092 extern "C" void * __wrap__malloc_r(struct _reent * r, size_t size) { 00093 void *ptr = NULL; 00094 #ifdef MBED_HEAP_STATS_ENABLED 00095 malloc_stats_mutex->lock(); 00096 alloc_info_t *alloc_info = (alloc_info_t*)__real__malloc_r(r, size + sizeof(alloc_info_t)); 00097 if (alloc_info != NULL) { 00098 alloc_info->size = size; 00099 ptr = (void*)(alloc_info + 1); 00100 heap_stats.current_size += size; 00101 heap_stats.total_size += size; 00102 heap_stats.alloc_cnt += 1; 00103 if (heap_stats.current_size > heap_stats.max_size) { 00104 heap_stats.max_size = heap_stats.current_size; 00105 } 00106 } else { 00107 heap_stats.alloc_fail_cnt += 1; 00108 } 00109 malloc_stats_mutex->unlock(); 00110 #else // #ifdef MBED_HEAP_STATS_ENABLED 00111 ptr = __real__malloc_r(r, size); 00112 #endif // #ifdef MBED_HEAP_STATS_ENABLED 00113 #ifdef MBED_MEM_TRACING_ENABLED 00114 mem_trace_mutex->lock(); 00115 mbed_mem_trace_malloc(ptr, size, MBED_CALLER_ADDR()); 00116 mem_trace_mutex->unlock(); 00117 #endif // #ifdef MBED_MEM_TRACING_ENABLED 00118 return ptr; 00119 } 00120 00121 extern "C" void * __wrap__realloc_r(struct _reent * r, void * ptr, size_t size) { 00122 void *new_ptr = NULL; 00123 #ifdef MBED_HEAP_STATS_ENABLED 00124 // Implement realloc_r with malloc and free. 00125 // The function realloc_r can't be used here directly since 00126 // it can call into __wrap__malloc_r (returns ptr + 4) or 00127 // resize memory directly (returns ptr + 0). 00128 00129 // Note - no lock needed since malloc and free are thread safe 00130 00131 // Get old size 00132 uint32_t old_size = 0; 00133 if (ptr != NULL) { 00134 alloc_info_t *alloc_info = ((alloc_info_t*)ptr) - 1; 00135 old_size = alloc_info->size; 00136 } 00137 00138 // Allocate space 00139 if (size != 0) { 00140 new_ptr = malloc(size); 00141 } 00142 00143 // If the new buffer has been allocated copy the data to it 00144 // and free the old buffer 00145 if (new_ptr != NULL) { 00146 uint32_t copy_size = (old_size < size) ? old_size : size; 00147 memcpy(new_ptr, (void*)ptr, copy_size); 00148 free(ptr); 00149 } 00150 #else // #ifdef MBED_HEAP_STATS_ENABLED 00151 new_ptr = __real__realloc_r(r, ptr, size); 00152 #endif // #ifdef MBED_HEAP_STATS_ENABLED 00153 #ifdef MBED_MEM_TRACING_ENABLED 00154 mem_trace_mutex->lock(); 00155 mbed_mem_trace_realloc(new_ptr, ptr, size, MBED_CALLER_ADDR()); 00156 mem_trace_mutex->unlock(); 00157 #endif // #ifdef MBED_MEM_TRACING_ENABLED 00158 return new_ptr; 00159 } 00160 00161 extern "C" void __wrap__free_r(struct _reent * r, void * ptr) { 00162 #ifdef MBED_HEAP_STATS_ENABLED 00163 malloc_stats_mutex->lock(); 00164 alloc_info_t *alloc_info = NULL; 00165 if (ptr != NULL) { 00166 alloc_info = ((alloc_info_t*)ptr) - 1; 00167 heap_stats.current_size -= alloc_info->size; 00168 heap_stats.alloc_cnt -= 1; 00169 } 00170 __real__free_r(r, (void*)alloc_info); 00171 malloc_stats_mutex->unlock(); 00172 #else // #ifdef MBED_HEAP_STATS_ENABLED 00173 __real__free_r(r, ptr); 00174 #endif // #ifdef MBED_HEAP_STATS_ENABLED 00175 #ifdef MBED_MEM_TRACING_ENABLED 00176 mem_trace_mutex->lock(); 00177 mbed_mem_trace_free(ptr, MBED_CALLER_ADDR()); 00178 mem_trace_mutex->unlock(); 00179 #endif // #ifdef MBED_MEM_TRACING_ENABLED 00180 } 00181 00182 extern "C" void * __wrap__calloc_r(struct _reent * r, size_t nmemb, size_t size) { 00183 void *ptr = NULL; 00184 #ifdef MBED_HEAP_STATS_ENABLED 00185 // Note - no lock needed since malloc is thread safe 00186 00187 ptr = malloc(nmemb * size); 00188 if (ptr != NULL) { 00189 memset(ptr, 0, nmemb * size); 00190 } 00191 #else // #ifdef MBED_HEAP_STATS_ENABLED 00192 ptr = __real__calloc_r(r, nmemb, size); 00193 #endif // #ifdef MBED_HEAP_STATS_ENABLED 00194 #ifdef MBED_MEM_TRACING_ENABLED 00195 mem_trace_mutex->lock(); 00196 mbed_mem_trace_calloc(ptr, nmemb, size, MBED_CALLER_ADDR()); 00197 mem_trace_mutex->unlock(); 00198 #endif // #ifdef MBED_MEM_TRACING_ENABLED 00199 return ptr; 00200 } 00201 00202 extern "C" void * __wrap__memalign_r(struct _reent * r, size_t alignment, size_t bytes) { 00203 return __real__memalign_r(r, alignment, bytes); 00204 } 00205 00206 #endif // if !defined(FEATURE_UVISOR) 00207 00208 00209 /******************************************************************************/ 00210 /* ARMCC memory allocation wrappers */ 00211 /******************************************************************************/ 00212 00213 #elif defined(TOOLCHAIN_ARM) // #if defined(TOOLCHAIN_GCC) 00214 00215 /* Enable hooking of memory function only if tracing is also enabled */ 00216 #if defined(MBED_MEM_TRACING_ENABLED) || defined(MBED_HEAP_STATS_ENABLED) 00217 00218 extern "C" { 00219 void *$Super$$malloc(size_t size); 00220 void *$Super$$realloc(void *ptr, size_t size); 00221 void *$Super$$calloc(size_t nmemb, size_t size); 00222 void $Super$$free(void *ptr); 00223 } 00224 00225 extern "C" void* $Sub$$malloc(size_t size) { 00226 void *ptr = NULL; 00227 #ifdef MBED_HEAP_STATS_ENABLED 00228 malloc_stats_mutex->lock(); 00229 alloc_info_t *alloc_info = (alloc_info_t*)$Super$$malloc(size + sizeof(alloc_info_t)); 00230 if (alloc_info != NULL) { 00231 alloc_info->size = size; 00232 ptr = (void*)(alloc_info + 1); 00233 heap_stats.current_size += size; 00234 heap_stats.total_size += size; 00235 heap_stats.alloc_cnt += 1; 00236 if (heap_stats.current_size > heap_stats.max_size) { 00237 heap_stats.max_size = heap_stats.current_size; 00238 } 00239 } else { 00240 heap_stats.alloc_fail_cnt += 1; 00241 } 00242 malloc_stats_mutex->unlock(); 00243 #else // #ifdef MBED_HEAP_STATS_ENABLED 00244 ptr = $Super$$malloc(size); 00245 #endif // #ifdef MBED_HEAP_STATS_ENABLED 00246 #ifdef MBED_MEM_TRACING_ENABLED 00247 mem_trace_mutex->lock(); 00248 mbed_mem_trace_malloc(ptr, size, MBED_CALLER_ADDR()); 00249 mem_trace_mutex->unlock(); 00250 #endif // #ifdef MBED_MEM_TRACING_ENABLED 00251 return ptr; 00252 } 00253 00254 extern "C" void* $Sub$$realloc(void *ptr, size_t size) { 00255 void *new_ptr = NULL; 00256 #ifdef MBED_HEAP_STATS_ENABLED 00257 // Note - no lock needed since malloc and free are thread safe 00258 00259 // Get old size 00260 uint32_t old_size = 0; 00261 if (ptr != NULL) { 00262 alloc_info_t *alloc_info = ((alloc_info_t*)ptr) - 1; 00263 old_size = alloc_info->size; 00264 } 00265 00266 // Allocate space 00267 if (size != 0) { 00268 new_ptr = malloc(size); 00269 } 00270 00271 // If the new buffer has been allocated copy the data to it 00272 // and free the old buffer 00273 if (new_ptr != NULL) { 00274 uint32_t copy_size = (old_size < size) ? old_size : size; 00275 memcpy(new_ptr, (void*)ptr, copy_size); 00276 free(ptr); 00277 } 00278 #else // #ifdef MBED_HEAP_STATS_ENABLED 00279 new_ptr = $Super$$realloc(ptr, size); 00280 #endif // #ifdef MBED_HEAP_STATS_ENABLED 00281 #ifdef MBED_MEM_TRACING_ENABLED 00282 mem_trace_mutex->lock(); 00283 mbed_mem_trace_realloc(new_ptr, ptr, size, MBED_CALLER_ADDR()); 00284 mem_trace_mutex->unlock(); 00285 #endif // #ifdef MBED_MEM_TRACING_ENABLED 00286 return new_ptr; 00287 } 00288 00289 extern "C" void *$Sub$$calloc(size_t nmemb, size_t size) { 00290 void *ptr = NULL; 00291 #ifdef MBED_HEAP_STATS_ENABLED 00292 // Note - no lock needed since malloc is thread safe 00293 ptr = malloc(nmemb * size); 00294 if (ptr != NULL) { 00295 memset(ptr, 0, nmemb * size); 00296 } 00297 #else // #ifdef MBED_HEAP_STATS_ENABLED 00298 ptr = $Super$$calloc(nmemb, size); 00299 #endif // #ifdef MBED_HEAP_STATS_ENABLED 00300 #ifdef MBED_MEM_TRACING_ENABLED 00301 mem_trace_mutex->lock(); 00302 mbed_mem_trace_calloc(ptr, nmemb, size, MBED_CALLER_ADDR()); 00303 mem_trace_mutex->unlock(); 00304 #endif // #ifdef MBED_MEM_TRACING_ENABLED 00305 return ptr; 00306 } 00307 00308 extern "C" void $Sub$$free(void *ptr) { 00309 #ifdef MBED_HEAP_STATS_ENABLED 00310 malloc_stats_mutex->lock(); 00311 alloc_info_t *alloc_info = NULL; 00312 if (ptr != NULL) { 00313 alloc_info = ((alloc_info_t*)ptr) - 1; 00314 heap_stats.current_size -= alloc_info->size; 00315 heap_stats.alloc_cnt -= 1; 00316 } 00317 $Super$$free((void*)alloc_info); 00318 malloc_stats_mutex->unlock(); 00319 #else // #ifdef MBED_HEAP_STATS_ENABLED 00320 $Super$$free(ptr); 00321 #endif // #ifdef MBED_HEAP_STATS_ENABLED 00322 #ifdef MBED_MEM_TRACING_ENABLED 00323 mem_trace_mutex->lock(); 00324 mbed_mem_trace_free(ptr, MBED_CALLER_ADDR()); 00325 mem_trace_mutex->unlock(); 00326 #endif // #ifdef MBED_MEM_TRACING_ENABLED 00327 } 00328 00329 #endif // #if defined(MBED_MEM_TRACING_ENABLED) || defined(MBED_HEAP_STATS_ENABLED) 00330 00331 /******************************************************************************/ 00332 /* Allocation wrappers for other toolchains are not supported yet */ 00333 /******************************************************************************/ 00334 00335 #else // #if defined(TOOLCHAIN_GCC) 00336 00337 #ifdef MBED_MEM_TRACING_ENABLED 00338 #warning Memory tracing is not supported with the current toolchain. 00339 #endif 00340 00341 #ifdef MBED_HEAP_STATS_ENABLED 00342 #warning Heap statistics are not supported with the current toolchain. 00343 #endif 00344 00345 #endif // #if defined(TOOLCHAIN_GCC) 00346 00347
Generated on Tue Jul 12 2022 14:47:25 by
