Preliminary main mbed library for nexpaq development
Diff: hal/common/mbed_mem_trace.c
- Revision:
- 0:6c56fb4bc5f0
diff -r 000000000000 -r 6c56fb4bc5f0 hal/common/mbed_mem_trace.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hal/common/mbed_mem_trace.c Fri Nov 04 20:27:58 2016 +0000 @@ -0,0 +1,115 @@ +/* mbed Microcontroller Library + * Copyright (c) 2006-2016 ARM Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <stdlib.h> +#include <stdarg.h> +#include <stdio.h> +#include "mbed_mem_trace.h" +#include "critical.h" + +/****************************************************************************** + * Internal variables, functions and helpers + *****************************************************************************/ + +/* 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 + * 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; + +/****************************************************************************** + * Public interface + *****************************************************************************/ + +void mbed_mem_trace_set_callback(mbed_mem_trace_cb_t cb) { + mem_trace_cb = cb; +} + +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) { + 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) { + 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) { + 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) { + mem_trace_cb(MBED_MEM_TRACE_FREE, NULL, caller, ptr); + } + core_util_atomic_decr_u8(&trace_level, 1); + } +} + +void mbed_mem_trace_default_callback(uint8_t op, void *res, void *caller, ...) { + va_list va; + size_t temp_s1, temp_s2; + void *temp_ptr; + + va_start(va, caller); + switch(op) { + case MBED_MEM_TRACE_MALLOC: + temp_s1 = va_arg(va, size_t); + printf(MBED_MEM_DEFAULT_TRACER_PREFIX "m:%p;%p-%u\n", res, caller, temp_s1); + break; + + case MBED_MEM_TRACE_REALLOC: + temp_ptr = va_arg(va, void*); + temp_s1 = va_arg(va, size_t); + printf(MBED_MEM_DEFAULT_TRACER_PREFIX "r:%p;%p-%p;%u\n", res, caller, temp_ptr, temp_s1); + break; + + case MBED_MEM_TRACE_CALLOC: + temp_s1 = va_arg(va, size_t); + temp_s2 = va_arg(va, size_t); + printf(MBED_MEM_DEFAULT_TRACER_PREFIX "c:%p;%p-%u;%u\n", res, caller, temp_s1, temp_s2); + break; + + case MBED_MEM_TRACE_FREE: + temp_ptr = va_arg(va, void*); + printf(MBED_MEM_DEFAULT_TRACER_PREFIX "f:%p;%p-%p\n", res, caller, temp_ptr); + break; + + default: + printf("?\n"); + } + va_end(va); +} +