diff --git a/platform/mbed_alloc_wrappers.cpp b/platform/mbed_alloc_wrappers.cpp index 9431811472..accfe26b5d 100644 --- a/platform/mbed_alloc_wrappers.cpp +++ b/platform/mbed_alloc_wrappers.cpp @@ -46,9 +46,6 @@ typedef struct { uint32_t pad; } alloc_info_t; -#ifdef MBED_MEM_TRACING_ENABLED -static SingletonPtr mem_trace_mutex; -#endif #ifdef MBED_HEAP_STATS_ENABLED static SingletonPtr malloc_stats_mutex; static mbed_stats_heap_t heap_stats = {0, 0, 0, 0, 0}; @@ -91,6 +88,9 @@ extern "C" { extern "C" void * __wrap__malloc_r(struct _reent * r, size_t size) { void *ptr = NULL; +#ifdef MBED_MEM_TRACING_ENABLED + mbed_mem_trace_lock(); +#endif #ifdef MBED_HEAP_STATS_ENABLED malloc_stats_mutex->lock(); alloc_info_t *alloc_info = (alloc_info_t*)__real__malloc_r(r, size + sizeof(alloc_info_t)); @@ -111,15 +111,17 @@ extern "C" void * __wrap__malloc_r(struct _reent * r, size_t size) { ptr = __real__malloc_r(r, size); #endif // #ifdef MBED_HEAP_STATS_ENABLED #ifdef MBED_MEM_TRACING_ENABLED - mem_trace_mutex->lock(); mbed_mem_trace_malloc(ptr, size, MBED_CALLER_ADDR()); - mem_trace_mutex->unlock(); + mbed_mem_trace_unlock(); #endif // #ifdef MBED_MEM_TRACING_ENABLED return ptr; } extern "C" void * __wrap__realloc_r(struct _reent * r, void * ptr, size_t size) { void *new_ptr = NULL; +#ifdef MBED_MEM_TRACING_ENABLED + mbed_mem_trace_lock(); +#endif #ifdef MBED_HEAP_STATS_ENABLED // Implement realloc_r with malloc and free. // The function realloc_r can't be used here directly since @@ -151,14 +153,16 @@ extern "C" void * __wrap__realloc_r(struct _reent * r, void * ptr, size_t size) new_ptr = __real__realloc_r(r, ptr, size); #endif // #ifdef MBED_HEAP_STATS_ENABLED #ifdef MBED_MEM_TRACING_ENABLED - mem_trace_mutex->lock(); mbed_mem_trace_realloc(new_ptr, ptr, size, MBED_CALLER_ADDR()); - mem_trace_mutex->unlock(); + mbed_mem_trace_unlock(); #endif // #ifdef MBED_MEM_TRACING_ENABLED return new_ptr; } extern "C" void __wrap__free_r(struct _reent * r, void * ptr) { +#ifdef MBED_MEM_TRACING_ENABLED + mbed_mem_trace_lock(); +#endif #ifdef MBED_HEAP_STATS_ENABLED malloc_stats_mutex->lock(); alloc_info_t *alloc_info = NULL; @@ -173,14 +177,16 @@ extern "C" void __wrap__free_r(struct _reent * r, void * ptr) { __real__free_r(r, ptr); #endif // #ifdef MBED_HEAP_STATS_ENABLED #ifdef MBED_MEM_TRACING_ENABLED - mem_trace_mutex->lock(); mbed_mem_trace_free(ptr, MBED_CALLER_ADDR()); - mem_trace_mutex->unlock(); + mbed_mem_trace_unlock(); #endif // #ifdef MBED_MEM_TRACING_ENABLED } extern "C" void * __wrap__calloc_r(struct _reent * r, size_t nmemb, size_t size) { void *ptr = NULL; +#ifdef MBED_MEM_TRACING_ENABLED + mbed_mem_trace_lock(); +#endif #ifdef MBED_HEAP_STATS_ENABLED // Note - no lock needed since malloc is thread safe @@ -192,9 +198,8 @@ extern "C" void * __wrap__calloc_r(struct _reent * r, size_t nmemb, size_t size) ptr = __real__calloc_r(r, nmemb, size); #endif // #ifdef MBED_HEAP_STATS_ENABLED #ifdef MBED_MEM_TRACING_ENABLED - mem_trace_mutex->lock(); mbed_mem_trace_calloc(ptr, nmemb, size, MBED_CALLER_ADDR()); - mem_trace_mutex->unlock(); + mbed_mem_trace_unlock(); #endif // #ifdef MBED_MEM_TRACING_ENABLED return ptr; } @@ -244,6 +249,9 @@ extern "C" { extern "C" void* SUB_MALLOC(size_t size) { void *ptr = NULL; +#ifdef MBED_MEM_TRACING_ENABLED + mbed_mem_trace_lock(); +#endif #ifdef MBED_HEAP_STATS_ENABLED malloc_stats_mutex->lock(); alloc_info_t *alloc_info = (alloc_info_t*)SUPER_MALLOC(size + sizeof(alloc_info_t)); @@ -264,15 +272,17 @@ extern "C" void* SUB_MALLOC(size_t size) { ptr = SUPER_MALLOC(size); #endif // #ifdef MBED_HEAP_STATS_ENABLED #ifdef MBED_MEM_TRACING_ENABLED - mem_trace_mutex->lock(); mbed_mem_trace_malloc(ptr, size, MBED_CALLER_ADDR()); - mem_trace_mutex->unlock(); + mbed_mem_trace_unlock(); #endif // #ifdef MBED_MEM_TRACING_ENABLED return ptr; } extern "C" void* SUB_REALLOC(void *ptr, size_t size) { void *new_ptr = NULL; +#ifdef MBED_MEM_TRACING_ENABLED + mbed_mem_trace_lock(); +#endif #ifdef MBED_HEAP_STATS_ENABLED // Note - no lock needed since malloc and free are thread safe @@ -299,15 +309,17 @@ extern "C" void* SUB_REALLOC(void *ptr, size_t size) { new_ptr = SUPER_REALLOC(ptr, size); #endif // #ifdef MBED_HEAP_STATS_ENABLED #ifdef MBED_MEM_TRACING_ENABLED - mem_trace_mutex->lock(); mbed_mem_trace_realloc(new_ptr, ptr, size, MBED_CALLER_ADDR()); - mem_trace_mutex->unlock(); + mbed_mem_trace_unlock(); #endif // #ifdef MBED_MEM_TRACING_ENABLED return new_ptr; } extern "C" void *SUB_CALLOC(size_t nmemb, size_t size) { void *ptr = NULL; +#ifdef MBED_MEM_TRACING_ENABLED + mbed_mem_trace_lock(); +#endif #ifdef MBED_HEAP_STATS_ENABLED // Note - no lock needed since malloc is thread safe ptr = malloc(nmemb * size); @@ -318,14 +330,16 @@ extern "C" void *SUB_CALLOC(size_t nmemb, size_t size) { ptr = SUPER_CALLOC(nmemb, size); #endif // #ifdef MBED_HEAP_STATS_ENABLED #ifdef MBED_MEM_TRACING_ENABLED - mem_trace_mutex->lock(); mbed_mem_trace_calloc(ptr, nmemb, size, MBED_CALLER_ADDR()); - mem_trace_mutex->unlock(); + mbed_mem_trace_unlock(); #endif // #ifdef MBED_MEM_TRACING_ENABLED return ptr; } extern "C" void SUB_FREE(void *ptr) { +#ifdef MBED_MEM_TRACING_ENABLED + mbed_mem_trace_lock(); +#endif #ifdef MBED_HEAP_STATS_ENABLED malloc_stats_mutex->lock(); alloc_info_t *alloc_info = NULL; @@ -340,9 +354,8 @@ extern "C" void SUB_FREE(void *ptr) { SUPER_FREE(ptr); #endif // #ifdef MBED_HEAP_STATS_ENABLED #ifdef MBED_MEM_TRACING_ENABLED - mem_trace_mutex->lock(); mbed_mem_trace_free(ptr, MBED_CALLER_ADDR()); - mem_trace_mutex->unlock(); + mbed_mem_trace_unlock(); #endif // #ifdef MBED_MEM_TRACING_ENABLED } diff --git a/platform/mbed_mem_trace.c b/platform/mbed_mem_trace.cpp similarity index 84% rename from platform/mbed_mem_trace.c rename to platform/mbed_mem_trace.cpp index ee00760a8c..17326f78e5 100644 --- a/platform/mbed_mem_trace.c +++ b/platform/mbed_mem_trace.cpp @@ -19,6 +19,8 @@ #include #include "platform/mbed_mem_trace.h" #include "platform/mbed_critical.h" +#include "platform/SingletonPtr.h" +#include "platform/PlatformMutex.h" /****************************************************************************** * Internal variables, functions and helpers @@ -26,10 +28,14 @@ /* The callback function that will be called after a traced memory operations finishes. */ static mbed_mem_trace_cb_t mem_trace_cb; -/* 'trave_level' guards "trace inside trace" situations (for example, the implementation +/* 'trace_lock_count' guards "trace inside trace" situations (for example, the implementation * of realloc() might call malloc() internally, and since malloc() is also traced, this could * result in two calls to the callback function instead of one. */ -static uint8_t trace_level; +static uint8_t trace_lock_count; +static SingletonPtr mem_trace_mutex; + +#define TRACE_FIRST_LOCK() (trace_lock_count < 2) + /****************************************************************************** * Public interface @@ -39,42 +45,50 @@ void mbed_mem_trace_set_callback(mbed_mem_trace_cb_t cb) { mem_trace_cb = cb; } +void mbed_mem_trace_lock() +{ + mem_trace_mutex->lock(); + trace_lock_count++; +} + +void mbed_mem_trace_unlock() +{ + trace_lock_count--; + mem_trace_mutex->unlock(); +} + void *mbed_mem_trace_malloc(void *res, size_t size, void *caller) { if (mem_trace_cb) { - if (core_util_atomic_incr_u8(&trace_level, 1) == 1) { + if (TRACE_FIRST_LOCK()) { mem_trace_cb(MBED_MEM_TRACE_MALLOC, res, caller, size); } - core_util_atomic_decr_u8(&trace_level, 1); } return res; } void *mbed_mem_trace_realloc(void *res, void *ptr, size_t size, void *caller) { if (mem_trace_cb) { - if (core_util_atomic_incr_u8(&trace_level, 1) == 1) { + if (TRACE_FIRST_LOCK()) { mem_trace_cb(MBED_MEM_TRACE_REALLOC, res, caller, ptr, size); } - core_util_atomic_decr_u8(&trace_level, 1); } return res; } void *mbed_mem_trace_calloc(void *res, size_t num, size_t size, void *caller) { if (mem_trace_cb) { - if (core_util_atomic_incr_u8(&trace_level, 1) == 1) { + if (TRACE_FIRST_LOCK()) { mem_trace_cb(MBED_MEM_TRACE_CALLOC, res, caller, num, size); } - core_util_atomic_decr_u8(&trace_level, 1); } return res; } void mbed_mem_trace_free(void *ptr, void *caller) { if (mem_trace_cb) { - if (core_util_atomic_incr_u8(&trace_level, 1) == 1) { + if (TRACE_FIRST_LOCK()) { mem_trace_cb(MBED_MEM_TRACE_FREE, NULL, caller, ptr); } - core_util_atomic_decr_u8(&trace_level, 1); } } diff --git a/platform/mbed_mem_trace.h b/platform/mbed_mem_trace.h index 59da721e2f..6b604a08a7 100644 --- a/platform/mbed_mem_trace.h +++ b/platform/mbed_mem_trace.h @@ -72,6 +72,17 @@ typedef void (*mbed_mem_trace_cb_t)(uint8_t op, void *res, void* caller, ...); */ void mbed_mem_trace_set_callback(mbed_mem_trace_cb_t cb); +/** + * Trace lock. + * @note Locking prevent recursive tracing of malloc/free inside relloc/calloc + */ +void mbed_mem_trace_lock(); + +/** + * Trace unlock. + */ +void mbed_mem_trace_unlock(); + /** * Trace a call to 'malloc'. * @param res the result of running 'malloc'.