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