mbed-os5 only for TYBLE16

Dependents:   TYBLE16_simple_data_logger TYBLE16_MP3_Air

Committer:
kenjiArai
Date:
Tue Dec 31 06:02:27 2019 +0000
Revision:
1:9db0e321a9f4
updated based on mbed-os5.15.0

Who changed what in which revision?

UserRevisionLine numberNew contents of line
kenjiArai 1:9db0e321a9f4 1 /* mbed Microcontroller Library
kenjiArai 1:9db0e321a9f4 2 * Copyright (c) 2006-2016 ARM Limited
kenjiArai 1:9db0e321a9f4 3 * SPDX-License-Identifier: Apache-2.0
kenjiArai 1:9db0e321a9f4 4 *
kenjiArai 1:9db0e321a9f4 5 * Licensed under the Apache License, Version 2.0 (the "License");
kenjiArai 1:9db0e321a9f4 6 * you may not use this file except in compliance with the License.
kenjiArai 1:9db0e321a9f4 7 * You may obtain a copy of the License at
kenjiArai 1:9db0e321a9f4 8 *
kenjiArai 1:9db0e321a9f4 9 * http://www.apache.org/licenses/LICENSE-2.0
kenjiArai 1:9db0e321a9f4 10 *
kenjiArai 1:9db0e321a9f4 11 * Unless required by applicable law or agreed to in writing, software
kenjiArai 1:9db0e321a9f4 12 * distributed under the License is distributed on an "AS IS" BASIS,
kenjiArai 1:9db0e321a9f4 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
kenjiArai 1:9db0e321a9f4 14 * See the License for the specific language governing permissions and
kenjiArai 1:9db0e321a9f4 15 * limitations under the License.
kenjiArai 1:9db0e321a9f4 16 */
kenjiArai 1:9db0e321a9f4 17
kenjiArai 1:9db0e321a9f4 18 #include "platform/mbed_mem_trace.h"
kenjiArai 1:9db0e321a9f4 19 #include "platform/mbed_stats.h"
kenjiArai 1:9db0e321a9f4 20 #include "platform/mbed_toolchain.h"
kenjiArai 1:9db0e321a9f4 21 #include "platform/SingletonPtr.h"
kenjiArai 1:9db0e321a9f4 22 #include "platform/PlatformMutex.h"
kenjiArai 1:9db0e321a9f4 23 #include <stddef.h>
kenjiArai 1:9db0e321a9f4 24 #include <stdio.h>
kenjiArai 1:9db0e321a9f4 25 #include <string.h>
kenjiArai 1:9db0e321a9f4 26 #include <stdlib.h>
kenjiArai 1:9db0e321a9f4 27
kenjiArai 1:9db0e321a9f4 28 /* There are two memory tracers in mbed OS:
kenjiArai 1:9db0e321a9f4 29
kenjiArai 1:9db0e321a9f4 30 - the first can be used to detect the maximum heap usage at runtime. It is
kenjiArai 1:9db0e321a9f4 31 activated by setting the configuration option MBED_HEAP_STATS_ENABLED to true.
kenjiArai 1:9db0e321a9f4 32 - the second can be used to trace each memory call by automatically invoking
kenjiArai 1:9db0e321a9f4 33 a callback on each memory operation (see hal/api/mbed_mem_trace.h). It is
kenjiArai 1:9db0e321a9f4 34 activated by setting the configuration option MBED_MEM_TRACING_ENABLED to true.
kenjiArai 1:9db0e321a9f4 35
kenjiArai 1:9db0e321a9f4 36 Both tracers can be activated and deactivated in any combination. If both tracers
kenjiArai 1:9db0e321a9f4 37 are active, the second one (MBED_MEM_TRACING_ENABLED) will trace the first one's
kenjiArai 1:9db0e321a9f4 38 (MBED_HEAP_STATS_ENABLED) memory calls.*/
kenjiArai 1:9db0e321a9f4 39
kenjiArai 1:9db0e321a9f4 40 /******************************************************************************/
kenjiArai 1:9db0e321a9f4 41 /* Implementation of the runtime max heap usage checker */
kenjiArai 1:9db0e321a9f4 42 /******************************************************************************/
kenjiArai 1:9db0e321a9f4 43
kenjiArai 1:9db0e321a9f4 44 typedef struct {
kenjiArai 1:9db0e321a9f4 45 uint32_t size;
kenjiArai 1:9db0e321a9f4 46 uint32_t signature;
kenjiArai 1:9db0e321a9f4 47 } alloc_info_t;
kenjiArai 1:9db0e321a9f4 48
kenjiArai 1:9db0e321a9f4 49 #if MBED_HEAP_STATS_ENABLED
kenjiArai 1:9db0e321a9f4 50 #define MBED_HEAP_STATS_SIGNATURE (0xdeadbeef)
kenjiArai 1:9db0e321a9f4 51
kenjiArai 1:9db0e321a9f4 52 static SingletonPtr<PlatformMutex> malloc_stats_mutex;
kenjiArai 1:9db0e321a9f4 53 static mbed_stats_heap_t heap_stats = {0, 0, 0, 0, 0, 0, 0};
kenjiArai 1:9db0e321a9f4 54
kenjiArai 1:9db0e321a9f4 55 typedef struct {
kenjiArai 1:9db0e321a9f4 56 size_t size;
kenjiArai 1:9db0e321a9f4 57 } mbed_heap_overhead_t;
kenjiArai 1:9db0e321a9f4 58
kenjiArai 1:9db0e321a9f4 59 #define MALLOC_HEADER_SIZE (sizeof(mbed_heap_overhead_t))
kenjiArai 1:9db0e321a9f4 60 #define MALLOC_HEADER_PTR(p) (mbed_heap_overhead_t *)((char *)(p) - MALLOC_HEADER_SIZE)
kenjiArai 1:9db0e321a9f4 61 #define MALLOC_HEAP_TOTAL_SIZE(p) (((p)->size) & (~0x1))
kenjiArai 1:9db0e321a9f4 62 #endif
kenjiArai 1:9db0e321a9f4 63
kenjiArai 1:9db0e321a9f4 64 void mbed_stats_heap_get(mbed_stats_heap_t *stats)
kenjiArai 1:9db0e321a9f4 65 {
kenjiArai 1:9db0e321a9f4 66 #if MBED_HEAP_STATS_ENABLED
kenjiArai 1:9db0e321a9f4 67 extern uint32_t mbed_heap_size;
kenjiArai 1:9db0e321a9f4 68 heap_stats.reserved_size = mbed_heap_size;
kenjiArai 1:9db0e321a9f4 69
kenjiArai 1:9db0e321a9f4 70 malloc_stats_mutex->lock();
kenjiArai 1:9db0e321a9f4 71 memcpy(stats, &heap_stats, sizeof(mbed_stats_heap_t));
kenjiArai 1:9db0e321a9f4 72 malloc_stats_mutex->unlock();
kenjiArai 1:9db0e321a9f4 73 #else
kenjiArai 1:9db0e321a9f4 74 memset(stats, 0, sizeof(mbed_stats_heap_t));
kenjiArai 1:9db0e321a9f4 75 #endif
kenjiArai 1:9db0e321a9f4 76 }
kenjiArai 1:9db0e321a9f4 77
kenjiArai 1:9db0e321a9f4 78 /******************************************************************************/
kenjiArai 1:9db0e321a9f4 79 /* GCC memory allocation wrappers */
kenjiArai 1:9db0e321a9f4 80 /******************************************************************************/
kenjiArai 1:9db0e321a9f4 81
kenjiArai 1:9db0e321a9f4 82 #if defined(TOOLCHAIN_GCC)
kenjiArai 1:9db0e321a9f4 83
kenjiArai 1:9db0e321a9f4 84 extern "C" {
kenjiArai 1:9db0e321a9f4 85 void *__real__malloc_r(struct _reent *r, size_t size);
kenjiArai 1:9db0e321a9f4 86 void *__real__memalign_r(struct _reent *r, size_t alignment, size_t bytes);
kenjiArai 1:9db0e321a9f4 87 void *__real__realloc_r(struct _reent *r, void *ptr, size_t size);
kenjiArai 1:9db0e321a9f4 88 void __real__free_r(struct _reent *r, void *ptr);
kenjiArai 1:9db0e321a9f4 89 void *__real__calloc_r(struct _reent *r, size_t nmemb, size_t size);
kenjiArai 1:9db0e321a9f4 90 void *malloc_wrapper(struct _reent *r, size_t size, void *caller);
kenjiArai 1:9db0e321a9f4 91 void free_wrapper(struct _reent *r, void *ptr, void *caller);
kenjiArai 1:9db0e321a9f4 92 }
kenjiArai 1:9db0e321a9f4 93
kenjiArai 1:9db0e321a9f4 94
kenjiArai 1:9db0e321a9f4 95 extern "C" void *__wrap__malloc_r(struct _reent *r, size_t size)
kenjiArai 1:9db0e321a9f4 96 {
kenjiArai 1:9db0e321a9f4 97 return malloc_wrapper(r, size, MBED_CALLER_ADDR());
kenjiArai 1:9db0e321a9f4 98 }
kenjiArai 1:9db0e321a9f4 99
kenjiArai 1:9db0e321a9f4 100 extern "C" void *malloc_wrapper(struct _reent *r, size_t size, void *caller)
kenjiArai 1:9db0e321a9f4 101 {
kenjiArai 1:9db0e321a9f4 102 void *ptr = NULL;
kenjiArai 1:9db0e321a9f4 103 #if MBED_MEM_TRACING_ENABLED
kenjiArai 1:9db0e321a9f4 104 mbed_mem_trace_lock();
kenjiArai 1:9db0e321a9f4 105 #endif
kenjiArai 1:9db0e321a9f4 106 #if MBED_HEAP_STATS_ENABLED
kenjiArai 1:9db0e321a9f4 107 malloc_stats_mutex->lock();
kenjiArai 1:9db0e321a9f4 108 alloc_info_t *alloc_info = (alloc_info_t *)__real__malloc_r(r, size + sizeof(alloc_info_t));
kenjiArai 1:9db0e321a9f4 109 if (alloc_info != NULL) {
kenjiArai 1:9db0e321a9f4 110 alloc_info->size = size;
kenjiArai 1:9db0e321a9f4 111 alloc_info->signature = MBED_HEAP_STATS_SIGNATURE;
kenjiArai 1:9db0e321a9f4 112 ptr = (void *)(alloc_info + 1);
kenjiArai 1:9db0e321a9f4 113 heap_stats.current_size += size;
kenjiArai 1:9db0e321a9f4 114 heap_stats.total_size += size;
kenjiArai 1:9db0e321a9f4 115 heap_stats.alloc_cnt += 1;
kenjiArai 1:9db0e321a9f4 116 if (heap_stats.current_size > heap_stats.max_size) {
kenjiArai 1:9db0e321a9f4 117 heap_stats.max_size = heap_stats.current_size;
kenjiArai 1:9db0e321a9f4 118 }
kenjiArai 1:9db0e321a9f4 119 heap_stats.overhead_size += MALLOC_HEAP_TOTAL_SIZE(MALLOC_HEADER_PTR(alloc_info)) - size;
kenjiArai 1:9db0e321a9f4 120 } else {
kenjiArai 1:9db0e321a9f4 121 heap_stats.alloc_fail_cnt += 1;
kenjiArai 1:9db0e321a9f4 122 }
kenjiArai 1:9db0e321a9f4 123 malloc_stats_mutex->unlock();
kenjiArai 1:9db0e321a9f4 124 #else // #if MBED_HEAP_STATS_ENABLED
kenjiArai 1:9db0e321a9f4 125 ptr = __real__malloc_r(r, size);
kenjiArai 1:9db0e321a9f4 126 #endif // #if MBED_HEAP_STATS_ENABLED
kenjiArai 1:9db0e321a9f4 127 #if MBED_MEM_TRACING_ENABLED
kenjiArai 1:9db0e321a9f4 128 mbed_mem_trace_malloc(ptr, size, caller);
kenjiArai 1:9db0e321a9f4 129 mbed_mem_trace_unlock();
kenjiArai 1:9db0e321a9f4 130 #endif // #if MBED_MEM_TRACING_ENABLED
kenjiArai 1:9db0e321a9f4 131 return ptr;
kenjiArai 1:9db0e321a9f4 132 }
kenjiArai 1:9db0e321a9f4 133
kenjiArai 1:9db0e321a9f4 134 extern "C" void *__wrap__realloc_r(struct _reent *r, void *ptr, size_t size)
kenjiArai 1:9db0e321a9f4 135 {
kenjiArai 1:9db0e321a9f4 136 void *new_ptr = NULL;
kenjiArai 1:9db0e321a9f4 137 #if MBED_MEM_TRACING_ENABLED
kenjiArai 1:9db0e321a9f4 138 mbed_mem_trace_lock();
kenjiArai 1:9db0e321a9f4 139 #endif
kenjiArai 1:9db0e321a9f4 140 #if MBED_HEAP_STATS_ENABLED
kenjiArai 1:9db0e321a9f4 141 // Implement realloc_r with malloc and free.
kenjiArai 1:9db0e321a9f4 142 // The function realloc_r can't be used here directly since
kenjiArai 1:9db0e321a9f4 143 // it can call into __wrap__malloc_r (returns ptr + 4) or
kenjiArai 1:9db0e321a9f4 144 // resize memory directly (returns ptr + 0).
kenjiArai 1:9db0e321a9f4 145
kenjiArai 1:9db0e321a9f4 146 // Note - no lock needed since malloc and free are thread safe
kenjiArai 1:9db0e321a9f4 147
kenjiArai 1:9db0e321a9f4 148 // Get old size
kenjiArai 1:9db0e321a9f4 149 uint32_t old_size = 0;
kenjiArai 1:9db0e321a9f4 150 if (ptr != NULL) {
kenjiArai 1:9db0e321a9f4 151 alloc_info_t *alloc_info = ((alloc_info_t *)ptr) - 1;
kenjiArai 1:9db0e321a9f4 152 old_size = alloc_info->size;
kenjiArai 1:9db0e321a9f4 153 }
kenjiArai 1:9db0e321a9f4 154
kenjiArai 1:9db0e321a9f4 155 // Allocate space
kenjiArai 1:9db0e321a9f4 156 if (size != 0) {
kenjiArai 1:9db0e321a9f4 157 new_ptr = malloc(size);
kenjiArai 1:9db0e321a9f4 158 }
kenjiArai 1:9db0e321a9f4 159
kenjiArai 1:9db0e321a9f4 160 // If the new buffer has been allocated copy the data to it
kenjiArai 1:9db0e321a9f4 161 // and free the old buffer
kenjiArai 1:9db0e321a9f4 162 if (new_ptr != NULL) {
kenjiArai 1:9db0e321a9f4 163 uint32_t copy_size = (old_size < size) ? old_size : size;
kenjiArai 1:9db0e321a9f4 164 memcpy(new_ptr, (void *)ptr, copy_size);
kenjiArai 1:9db0e321a9f4 165 free(ptr);
kenjiArai 1:9db0e321a9f4 166 }
kenjiArai 1:9db0e321a9f4 167 #else // #if MBED_HEAP_STATS_ENABLED
kenjiArai 1:9db0e321a9f4 168 new_ptr = __real__realloc_r(r, ptr, size);
kenjiArai 1:9db0e321a9f4 169 #endif // #if MBED_HEAP_STATS_ENABLED
kenjiArai 1:9db0e321a9f4 170 #if MBED_MEM_TRACING_ENABLED
kenjiArai 1:9db0e321a9f4 171 mbed_mem_trace_realloc(new_ptr, ptr, size, MBED_CALLER_ADDR());
kenjiArai 1:9db0e321a9f4 172 mbed_mem_trace_unlock();
kenjiArai 1:9db0e321a9f4 173 #endif // #if MBED_MEM_TRACING_ENABLED
kenjiArai 1:9db0e321a9f4 174 return new_ptr;
kenjiArai 1:9db0e321a9f4 175 }
kenjiArai 1:9db0e321a9f4 176
kenjiArai 1:9db0e321a9f4 177 extern "C" void __wrap__free_r(struct _reent *r, void *ptr)
kenjiArai 1:9db0e321a9f4 178 {
kenjiArai 1:9db0e321a9f4 179 free_wrapper(r, ptr, MBED_CALLER_ADDR());
kenjiArai 1:9db0e321a9f4 180 }
kenjiArai 1:9db0e321a9f4 181
kenjiArai 1:9db0e321a9f4 182 extern "C" void free_wrapper(struct _reent *r, void *ptr, void *caller)
kenjiArai 1:9db0e321a9f4 183 {
kenjiArai 1:9db0e321a9f4 184 #if MBED_MEM_TRACING_ENABLED
kenjiArai 1:9db0e321a9f4 185 mbed_mem_trace_lock();
kenjiArai 1:9db0e321a9f4 186 #endif
kenjiArai 1:9db0e321a9f4 187 #if MBED_HEAP_STATS_ENABLED
kenjiArai 1:9db0e321a9f4 188 malloc_stats_mutex->lock();
kenjiArai 1:9db0e321a9f4 189 alloc_info_t *alloc_info = NULL;
kenjiArai 1:9db0e321a9f4 190 if (ptr != NULL) {
kenjiArai 1:9db0e321a9f4 191 alloc_info = ((alloc_info_t *)ptr) - 1;
kenjiArai 1:9db0e321a9f4 192 if (MBED_HEAP_STATS_SIGNATURE == alloc_info->signature) {
kenjiArai 1:9db0e321a9f4 193 size_t user_size = alloc_info->size;
kenjiArai 1:9db0e321a9f4 194 size_t alloc_size = MALLOC_HEAP_TOTAL_SIZE(MALLOC_HEADER_PTR(alloc_info));
kenjiArai 1:9db0e321a9f4 195 alloc_info->signature = 0x0;
kenjiArai 1:9db0e321a9f4 196 heap_stats.current_size -= user_size;
kenjiArai 1:9db0e321a9f4 197 heap_stats.alloc_cnt -= 1;
kenjiArai 1:9db0e321a9f4 198 heap_stats.overhead_size -= (alloc_size - user_size);
kenjiArai 1:9db0e321a9f4 199 __real__free_r(r, (void *)alloc_info);
kenjiArai 1:9db0e321a9f4 200 } else {
kenjiArai 1:9db0e321a9f4 201 __real__free_r(r, ptr);
kenjiArai 1:9db0e321a9f4 202 }
kenjiArai 1:9db0e321a9f4 203 }
kenjiArai 1:9db0e321a9f4 204
kenjiArai 1:9db0e321a9f4 205 malloc_stats_mutex->unlock();
kenjiArai 1:9db0e321a9f4 206 #else // #if MBED_HEAP_STATS_ENABLED
kenjiArai 1:9db0e321a9f4 207 __real__free_r(r, ptr);
kenjiArai 1:9db0e321a9f4 208 #endif // #if MBED_HEAP_STATS_ENABLED
kenjiArai 1:9db0e321a9f4 209 #if MBED_MEM_TRACING_ENABLED
kenjiArai 1:9db0e321a9f4 210 mbed_mem_trace_free(ptr, caller);
kenjiArai 1:9db0e321a9f4 211 mbed_mem_trace_unlock();
kenjiArai 1:9db0e321a9f4 212 #endif // #if MBED_MEM_TRACING_ENABLED
kenjiArai 1:9db0e321a9f4 213 }
kenjiArai 1:9db0e321a9f4 214
kenjiArai 1:9db0e321a9f4 215 extern "C" void *__wrap__calloc_r(struct _reent *r, size_t nmemb, size_t size)
kenjiArai 1:9db0e321a9f4 216 {
kenjiArai 1:9db0e321a9f4 217 void *ptr = NULL;
kenjiArai 1:9db0e321a9f4 218 #if MBED_MEM_TRACING_ENABLED
kenjiArai 1:9db0e321a9f4 219 mbed_mem_trace_lock();
kenjiArai 1:9db0e321a9f4 220 #endif
kenjiArai 1:9db0e321a9f4 221 #if MBED_HEAP_STATS_ENABLED
kenjiArai 1:9db0e321a9f4 222 // Note - no lock needed since malloc is thread safe
kenjiArai 1:9db0e321a9f4 223
kenjiArai 1:9db0e321a9f4 224 ptr = malloc(nmemb * size);
kenjiArai 1:9db0e321a9f4 225 if (ptr != NULL) {
kenjiArai 1:9db0e321a9f4 226 memset(ptr, 0, nmemb * size);
kenjiArai 1:9db0e321a9f4 227 }
kenjiArai 1:9db0e321a9f4 228 #else // #if MBED_HEAP_STATS_ENABLED
kenjiArai 1:9db0e321a9f4 229 ptr = __real__calloc_r(r, nmemb, size);
kenjiArai 1:9db0e321a9f4 230 #endif // #if MBED_HEAP_STATS_ENABLED
kenjiArai 1:9db0e321a9f4 231 #if MBED_MEM_TRACING_ENABLED
kenjiArai 1:9db0e321a9f4 232 mbed_mem_trace_calloc(ptr, nmemb, size, MBED_CALLER_ADDR());
kenjiArai 1:9db0e321a9f4 233 mbed_mem_trace_unlock();
kenjiArai 1:9db0e321a9f4 234 #endif // #if MBED_MEM_TRACING_ENABLED
kenjiArai 1:9db0e321a9f4 235 return ptr;
kenjiArai 1:9db0e321a9f4 236 }
kenjiArai 1:9db0e321a9f4 237
kenjiArai 1:9db0e321a9f4 238 extern "C" void *__wrap__memalign_r(struct _reent *r, size_t alignment, size_t bytes)
kenjiArai 1:9db0e321a9f4 239 {
kenjiArai 1:9db0e321a9f4 240 return __real__memalign_r(r, alignment, bytes);
kenjiArai 1:9db0e321a9f4 241 }
kenjiArai 1:9db0e321a9f4 242
kenjiArai 1:9db0e321a9f4 243
kenjiArai 1:9db0e321a9f4 244 /******************************************************************************/
kenjiArai 1:9db0e321a9f4 245 /* ARMCC / IAR memory allocation wrappers */
kenjiArai 1:9db0e321a9f4 246 /******************************************************************************/
kenjiArai 1:9db0e321a9f4 247
kenjiArai 1:9db0e321a9f4 248 #elif defined(TOOLCHAIN_ARM) || defined(__ICCARM__)
kenjiArai 1:9db0e321a9f4 249
kenjiArai 1:9db0e321a9f4 250 #if defined(TOOLCHAIN_ARM)
kenjiArai 1:9db0e321a9f4 251 #define SUPER_MALLOC $Super$$malloc
kenjiArai 1:9db0e321a9f4 252 #define SUB_MALLOC $Sub$$malloc
kenjiArai 1:9db0e321a9f4 253 #define SUPER_REALLOC $Super$$realloc
kenjiArai 1:9db0e321a9f4 254 #define SUB_REALLOC $Sub$$realloc
kenjiArai 1:9db0e321a9f4 255 #define SUPER_CALLOC $Super$$calloc
kenjiArai 1:9db0e321a9f4 256 #define SUB_CALLOC $Sub$$calloc
kenjiArai 1:9db0e321a9f4 257 #define SUPER_FREE $Super$$free
kenjiArai 1:9db0e321a9f4 258 #define SUB_FREE $Sub$$free
kenjiArai 1:9db0e321a9f4 259 #elif defined(__ICCARM__)
kenjiArai 1:9db0e321a9f4 260 #define SUPER_MALLOC $Super$$__iar_dlmalloc
kenjiArai 1:9db0e321a9f4 261 #define SUB_MALLOC $Sub$$__iar_dlmalloc
kenjiArai 1:9db0e321a9f4 262 #define SUPER_REALLOC $Super$$__iar_dlrealloc
kenjiArai 1:9db0e321a9f4 263 #define SUB_REALLOC $Sub$$__iar_dlrealloc
kenjiArai 1:9db0e321a9f4 264 #define SUPER_CALLOC $Super$$__iar_dlcalloc
kenjiArai 1:9db0e321a9f4 265 #define SUB_CALLOC $Sub$$__iar_dlcalloc
kenjiArai 1:9db0e321a9f4 266 #define SUPER_FREE $Super$$__iar_dlfree
kenjiArai 1:9db0e321a9f4 267 #define SUB_FREE $Sub$$__iar_dlfree
kenjiArai 1:9db0e321a9f4 268 #endif
kenjiArai 1:9db0e321a9f4 269
kenjiArai 1:9db0e321a9f4 270 /* Enable hooking of memory function only if tracing is also enabled */
kenjiArai 1:9db0e321a9f4 271 #if defined(MBED_MEM_TRACING_ENABLED) || defined(MBED_HEAP_STATS_ENABLED)
kenjiArai 1:9db0e321a9f4 272
kenjiArai 1:9db0e321a9f4 273 extern "C" {
kenjiArai 1:9db0e321a9f4 274 void *SUPER_MALLOC(size_t size);
kenjiArai 1:9db0e321a9f4 275 void *SUPER_REALLOC(void *ptr, size_t size);
kenjiArai 1:9db0e321a9f4 276 void *SUPER_CALLOC(size_t nmemb, size_t size);
kenjiArai 1:9db0e321a9f4 277 void SUPER_FREE(void *ptr);
kenjiArai 1:9db0e321a9f4 278 void *malloc_wrapper(size_t size, void *caller);
kenjiArai 1:9db0e321a9f4 279 void free_wrapper(void *ptr, void *caller);
kenjiArai 1:9db0e321a9f4 280 }
kenjiArai 1:9db0e321a9f4 281
kenjiArai 1:9db0e321a9f4 282 extern "C" void *SUB_MALLOC(size_t size)
kenjiArai 1:9db0e321a9f4 283 {
kenjiArai 1:9db0e321a9f4 284 return malloc_wrapper(size, MBED_CALLER_ADDR());
kenjiArai 1:9db0e321a9f4 285 }
kenjiArai 1:9db0e321a9f4 286
kenjiArai 1:9db0e321a9f4 287 extern "C" void *malloc_wrapper(size_t size, void *caller)
kenjiArai 1:9db0e321a9f4 288 {
kenjiArai 1:9db0e321a9f4 289 void *ptr = NULL;
kenjiArai 1:9db0e321a9f4 290 #if MBED_MEM_TRACING_ENABLED
kenjiArai 1:9db0e321a9f4 291 mbed_mem_trace_lock();
kenjiArai 1:9db0e321a9f4 292 #endif
kenjiArai 1:9db0e321a9f4 293 #if MBED_HEAP_STATS_ENABLED
kenjiArai 1:9db0e321a9f4 294 malloc_stats_mutex->lock();
kenjiArai 1:9db0e321a9f4 295 alloc_info_t *alloc_info = (alloc_info_t *)SUPER_MALLOC(size + sizeof(alloc_info_t));
kenjiArai 1:9db0e321a9f4 296 if (alloc_info != NULL) {
kenjiArai 1:9db0e321a9f4 297 alloc_info->size = size;
kenjiArai 1:9db0e321a9f4 298 alloc_info->signature = MBED_HEAP_STATS_SIGNATURE;
kenjiArai 1:9db0e321a9f4 299 ptr = (void *)(alloc_info + 1);
kenjiArai 1:9db0e321a9f4 300 heap_stats.current_size += size;
kenjiArai 1:9db0e321a9f4 301 heap_stats.total_size += size;
kenjiArai 1:9db0e321a9f4 302 heap_stats.alloc_cnt += 1;
kenjiArai 1:9db0e321a9f4 303 if (heap_stats.current_size > heap_stats.max_size) {
kenjiArai 1:9db0e321a9f4 304 heap_stats.max_size = heap_stats.current_size;
kenjiArai 1:9db0e321a9f4 305 }
kenjiArai 1:9db0e321a9f4 306 heap_stats.overhead_size += MALLOC_HEAP_TOTAL_SIZE(MALLOC_HEADER_PTR(alloc_info)) - size;
kenjiArai 1:9db0e321a9f4 307 } else {
kenjiArai 1:9db0e321a9f4 308 heap_stats.alloc_fail_cnt += 1;
kenjiArai 1:9db0e321a9f4 309 }
kenjiArai 1:9db0e321a9f4 310 malloc_stats_mutex->unlock();
kenjiArai 1:9db0e321a9f4 311 #else // #if MBED_HEAP_STATS_ENABLED
kenjiArai 1:9db0e321a9f4 312 ptr = SUPER_MALLOC(size);
kenjiArai 1:9db0e321a9f4 313 #endif // #if MBED_HEAP_STATS_ENABLED
kenjiArai 1:9db0e321a9f4 314 #if MBED_MEM_TRACING_ENABLED
kenjiArai 1:9db0e321a9f4 315 mbed_mem_trace_malloc(ptr, size, caller);
kenjiArai 1:9db0e321a9f4 316 mbed_mem_trace_unlock();
kenjiArai 1:9db0e321a9f4 317 #endif // #if MBED_MEM_TRACING_ENABLED
kenjiArai 1:9db0e321a9f4 318 return ptr;
kenjiArai 1:9db0e321a9f4 319 }
kenjiArai 1:9db0e321a9f4 320
kenjiArai 1:9db0e321a9f4 321
kenjiArai 1:9db0e321a9f4 322 extern "C" void *SUB_REALLOC(void *ptr, size_t size)
kenjiArai 1:9db0e321a9f4 323 {
kenjiArai 1:9db0e321a9f4 324 void *new_ptr = NULL;
kenjiArai 1:9db0e321a9f4 325 #if MBED_MEM_TRACING_ENABLED
kenjiArai 1:9db0e321a9f4 326 mbed_mem_trace_lock();
kenjiArai 1:9db0e321a9f4 327 #endif
kenjiArai 1:9db0e321a9f4 328 #if MBED_HEAP_STATS_ENABLED
kenjiArai 1:9db0e321a9f4 329 // Note - no lock needed since malloc and free are thread safe
kenjiArai 1:9db0e321a9f4 330
kenjiArai 1:9db0e321a9f4 331 // Get old size
kenjiArai 1:9db0e321a9f4 332 uint32_t old_size = 0;
kenjiArai 1:9db0e321a9f4 333 if (ptr != NULL) {
kenjiArai 1:9db0e321a9f4 334 alloc_info_t *alloc_info = ((alloc_info_t *)ptr) - 1;
kenjiArai 1:9db0e321a9f4 335 old_size = alloc_info->size;
kenjiArai 1:9db0e321a9f4 336 }
kenjiArai 1:9db0e321a9f4 337
kenjiArai 1:9db0e321a9f4 338 // Allocate space
kenjiArai 1:9db0e321a9f4 339 if (size != 0) {
kenjiArai 1:9db0e321a9f4 340 new_ptr = malloc(size);
kenjiArai 1:9db0e321a9f4 341 }
kenjiArai 1:9db0e321a9f4 342
kenjiArai 1:9db0e321a9f4 343 // If the new buffer has been allocated copy the data to it
kenjiArai 1:9db0e321a9f4 344 // and free the old buffer
kenjiArai 1:9db0e321a9f4 345 if ((new_ptr != NULL) && (ptr != NULL)) {
kenjiArai 1:9db0e321a9f4 346 uint32_t copy_size = (old_size < size) ? old_size : size;
kenjiArai 1:9db0e321a9f4 347 memcpy(new_ptr, (void *)ptr, copy_size);
kenjiArai 1:9db0e321a9f4 348 free(ptr);
kenjiArai 1:9db0e321a9f4 349 }
kenjiArai 1:9db0e321a9f4 350 #else // #if MBED_HEAP_STATS_ENABLED
kenjiArai 1:9db0e321a9f4 351 new_ptr = SUPER_REALLOC(ptr, size);
kenjiArai 1:9db0e321a9f4 352 #endif // #if MBED_HEAP_STATS_ENABLED
kenjiArai 1:9db0e321a9f4 353 #if MBED_MEM_TRACING_ENABLED
kenjiArai 1:9db0e321a9f4 354 mbed_mem_trace_realloc(new_ptr, ptr, size, MBED_CALLER_ADDR());
kenjiArai 1:9db0e321a9f4 355 mbed_mem_trace_unlock();
kenjiArai 1:9db0e321a9f4 356 #endif // #if MBED_MEM_TRACING_ENABLED
kenjiArai 1:9db0e321a9f4 357 return new_ptr;
kenjiArai 1:9db0e321a9f4 358 }
kenjiArai 1:9db0e321a9f4 359
kenjiArai 1:9db0e321a9f4 360 extern "C" void *SUB_CALLOC(size_t nmemb, size_t size)
kenjiArai 1:9db0e321a9f4 361 {
kenjiArai 1:9db0e321a9f4 362 void *ptr = NULL;
kenjiArai 1:9db0e321a9f4 363 #if MBED_MEM_TRACING_ENABLED
kenjiArai 1:9db0e321a9f4 364 mbed_mem_trace_lock();
kenjiArai 1:9db0e321a9f4 365 #endif
kenjiArai 1:9db0e321a9f4 366 #if MBED_HEAP_STATS_ENABLED
kenjiArai 1:9db0e321a9f4 367 // Note - no lock needed since malloc is thread safe
kenjiArai 1:9db0e321a9f4 368 ptr = malloc(nmemb * size);
kenjiArai 1:9db0e321a9f4 369 if (ptr != NULL) {
kenjiArai 1:9db0e321a9f4 370 memset(ptr, 0, nmemb * size);
kenjiArai 1:9db0e321a9f4 371 }
kenjiArai 1:9db0e321a9f4 372 #else // #if MBED_HEAP_STATS_ENABLED
kenjiArai 1:9db0e321a9f4 373 ptr = SUPER_CALLOC(nmemb, size);
kenjiArai 1:9db0e321a9f4 374 #endif // #if MBED_HEAP_STATS_ENABLED
kenjiArai 1:9db0e321a9f4 375 #if MBED_MEM_TRACING_ENABLED
kenjiArai 1:9db0e321a9f4 376 mbed_mem_trace_calloc(ptr, nmemb, size, MBED_CALLER_ADDR());
kenjiArai 1:9db0e321a9f4 377 mbed_mem_trace_unlock();
kenjiArai 1:9db0e321a9f4 378 #endif // #if MBED_MEM_TRACING_ENABLED
kenjiArai 1:9db0e321a9f4 379 return ptr;
kenjiArai 1:9db0e321a9f4 380 }
kenjiArai 1:9db0e321a9f4 381
kenjiArai 1:9db0e321a9f4 382 extern "C" void SUB_FREE(void *ptr)
kenjiArai 1:9db0e321a9f4 383 {
kenjiArai 1:9db0e321a9f4 384 free_wrapper(ptr, MBED_CALLER_ADDR());
kenjiArai 1:9db0e321a9f4 385 }
kenjiArai 1:9db0e321a9f4 386
kenjiArai 1:9db0e321a9f4 387 extern "C" void free_wrapper(void *ptr, void *caller)
kenjiArai 1:9db0e321a9f4 388 {
kenjiArai 1:9db0e321a9f4 389 #if MBED_MEM_TRACING_ENABLED
kenjiArai 1:9db0e321a9f4 390 mbed_mem_trace_lock();
kenjiArai 1:9db0e321a9f4 391 #endif
kenjiArai 1:9db0e321a9f4 392 #if MBED_HEAP_STATS_ENABLED
kenjiArai 1:9db0e321a9f4 393 malloc_stats_mutex->lock();
kenjiArai 1:9db0e321a9f4 394 alloc_info_t *alloc_info = NULL;
kenjiArai 1:9db0e321a9f4 395 if (ptr != NULL) {
kenjiArai 1:9db0e321a9f4 396 alloc_info = ((alloc_info_t *)ptr) - 1;
kenjiArai 1:9db0e321a9f4 397 if (MBED_HEAP_STATS_SIGNATURE == alloc_info->signature) {
kenjiArai 1:9db0e321a9f4 398 size_t user_size = alloc_info->size;
kenjiArai 1:9db0e321a9f4 399 size_t alloc_size = MALLOC_HEAP_TOTAL_SIZE(MALLOC_HEADER_PTR(alloc_info));
kenjiArai 1:9db0e321a9f4 400 alloc_info->signature = 0x0;
kenjiArai 1:9db0e321a9f4 401 heap_stats.current_size -= user_size;
kenjiArai 1:9db0e321a9f4 402 heap_stats.alloc_cnt -= 1;
kenjiArai 1:9db0e321a9f4 403 heap_stats.overhead_size -= (alloc_size - user_size);
kenjiArai 1:9db0e321a9f4 404 SUPER_FREE((void *)alloc_info);
kenjiArai 1:9db0e321a9f4 405 } else {
kenjiArai 1:9db0e321a9f4 406 SUPER_FREE(ptr);
kenjiArai 1:9db0e321a9f4 407 }
kenjiArai 1:9db0e321a9f4 408 }
kenjiArai 1:9db0e321a9f4 409
kenjiArai 1:9db0e321a9f4 410 malloc_stats_mutex->unlock();
kenjiArai 1:9db0e321a9f4 411 #else // #if MBED_HEAP_STATS_ENABLED
kenjiArai 1:9db0e321a9f4 412 SUPER_FREE(ptr);
kenjiArai 1:9db0e321a9f4 413 #endif // #if MBED_HEAP_STATS_ENABLED
kenjiArai 1:9db0e321a9f4 414 #if MBED_MEM_TRACING_ENABLED
kenjiArai 1:9db0e321a9f4 415 mbed_mem_trace_free(ptr, caller);
kenjiArai 1:9db0e321a9f4 416 mbed_mem_trace_unlock();
kenjiArai 1:9db0e321a9f4 417 #endif // #if MBED_MEM_TRACING_ENABLED
kenjiArai 1:9db0e321a9f4 418 }
kenjiArai 1:9db0e321a9f4 419
kenjiArai 1:9db0e321a9f4 420 #endif // #if defined(MBED_MEM_TRACING_ENABLED) || defined(MBED_HEAP_STATS_ENABLED)
kenjiArai 1:9db0e321a9f4 421
kenjiArai 1:9db0e321a9f4 422 /******************************************************************************/
kenjiArai 1:9db0e321a9f4 423 /* Allocation wrappers for other toolchains are not supported yet */
kenjiArai 1:9db0e321a9f4 424 /******************************************************************************/
kenjiArai 1:9db0e321a9f4 425
kenjiArai 1:9db0e321a9f4 426 #else
kenjiArai 1:9db0e321a9f4 427
kenjiArai 1:9db0e321a9f4 428 #if MBED_MEM_TRACING_ENABLED
kenjiArai 1:9db0e321a9f4 429 #error Memory tracing is not supported with the current toolchain.
kenjiArai 1:9db0e321a9f4 430 #endif
kenjiArai 1:9db0e321a9f4 431
kenjiArai 1:9db0e321a9f4 432 #if MBED_HEAP_STATS_ENABLED
kenjiArai 1:9db0e321a9f4 433 #error Heap statistics are not supported with the current toolchain.
kenjiArai 1:9db0e321a9f4 434 #endif
kenjiArai 1:9db0e321a9f4 435
kenjiArai 1:9db0e321a9f4 436 #endif // #if defined(TOOLCHAIN_GCC)