Skip to content
This repository was archived by the owner on Jan 15, 2021. It is now read-only.

Commit 45825fd

Browse files
author
Bogdan Marinescu
committed
Enable memory tracing
This commit enables tracing of dynamic memory operations (alloc/free/realloc) using the existing logging support in ualloc. Note that this support is preliminary, check the code for more details. In particular, "prevent_tracing" will have to go away eventually, but for now we need it. Tracing must be enabled via "yotta config": { "debug": { "options": { "memory-trace": true } } }
1 parent 5bfe6c8 commit 45825fd

File tree

1 file changed

+77
-19
lines changed

1 file changed

+77
-19
lines changed

source/ualloc.c

Lines changed: 77 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -27,12 +27,44 @@ extern int printf(const char *, ...);
2727

2828
extern void * volatile mbed_sbrk_ptr;
2929

30-
// Set debug level to 0 until non-allocating printf is available
31-
const UAllocDebug_t ualloc_debug_level = UALLOC_DEBUG_NONE;//(DEBUG?UALLOC_DEBUG_MAX:UALLOC_DEBUG_NONE);
30+
/*****************************************************************************************
31+
UALLOC_DEBUG_LOG is effectively reserved for tracing memory allocations
32+
Tracing must be enabled via "yotta config":
33+
{
34+
"debug": {
35+
"options": {
36+
"memory-trace": true
37+
}
38+
}
39+
}
40+
[TODO]: ualloc_debug_level probably needs better control with "yotta config"
41+
*****************************************************************************************/
42+
#ifdef YOTTA_CFG_DEBUG_OPTIONS_MEMORY_TRACE
43+
const UAllocDebug_t ualloc_debug_level = UALLOC_DEBUG_LOG;
44+
#else
45+
const UAllocDebug_t ualloc_debug_level = UALLOC_DEBUG_NONE;
46+
#endif
3247

3348
// Debug characters
3449
const char ua_chars[] = "NFEWIL";
3550

51+
/*****************************************************************************************
52+
The purpose of "prevent_tracing" below is twofold:
53+
54+
1. prevent infinite loops (mbed_ualloc_internal -> ualloc_debug -> printf ->
55+
mbed_ualloc_internal -> ualloc_debug -> printf...)
56+
2. prevent a possible scenario when an interrupt occurs while ualloc_debug
57+
is printing debug information and the interrupt also calls 'mbed_ualloc' or
58+
another memory operation that would result in ualloc_debug being called,
59+
which would in turn result in garbled output. By using "prevent_tracing",
60+
the output is kept consistent, but the memory operation invoked in the
61+
interrupt handler is not logged.
62+
63+
1 above can be prevented by using a logging function that doesn't allocate memory.
64+
2 above can be prevented by queueing log messages instead of logging them immediately.
65+
*****************************************************************************************/
66+
static volatile int prevent_tracing = 0;
67+
3668
#define ualloc_debug(ADBG_LEVEL, fmt, ...) do { \
3769
if (ADBG_LEVEL <= ualloc_debug_level && ADBG_LEVEL < UALLOC_DEBUG_MAX) { \
3870
printf("UAL:%c " fmt, ua_chars[ADBG_LEVEL], __VA_ARGS__); \
@@ -52,10 +84,8 @@ const char ua_chars[] = "NFEWIL";
5284
#define caller_addr() (NULL)
5385
#endif
5486

55-
void * mbed_ualloc(size_t bytes, UAllocTraits_t traits)
56-
{
87+
static void * mbed_ualloc_internal(size_t bytes, UAllocTraits_t traits, void *caller) {
5788
void * ptr = NULL;
58-
void * caller = (void*) caller_addr();
5989
if (UALLOC_TEST_TRAITS(traits.flags, UALLOC_TRAITS_NEVER_FREE)) {
6090
ptr = mbed_krbs(bytes);
6191
// krbs uses the same semantics as sbrk, so translate a -1 to NULL.
@@ -76,47 +106,75 @@ void * mbed_ualloc(size_t bytes, UAllocTraits_t traits)
76106

77107
if(ptr == NULL) {
78108
ualloc_debug(UALLOC_DEBUG_WARNING, "ua c:%p fail\n", caller);
79-
} else {
80-
ualloc_debug(UALLOC_DEBUG_LOG, "ua c:%p m:%p\n", caller, ptr);
81109
}
110+
82111
return ptr;
83112
}
84-
void * mbed_urealloc(void * ptr, size_t bytes, UAllocTraits_t traits)
85-
{
86-
void * caller = (void*) caller_addr();
113+
114+
void *mbed_ualloc(size_t bytes, UAllocTraits_t traits) {
115+
void *caller = (void*)caller_addr();
116+
void *p = mbed_ualloc_internal(bytes, traits, caller);
117+
if (!prevent_tracing) {
118+
prevent_tracing = 1;
119+
ualloc_debug(UALLOC_DEBUG_LOG, "ua c:%p s:%u m:%p\n", caller, (unsigned)bytes, p);
120+
prevent_tracing = 0;
121+
}
122+
return p;
123+
}
124+
125+
static void * mbed_urealloc_internal(void * ptr, size_t bytes, UAllocTraits_t traits, void *caller) {
87126
void *newptr = NULL;
88127
if (ptr == NULL) {
89128
return mbed_ualloc(bytes, traits);
90129
}
91130
if(traits.flags & ~UALLOC_TRAITS_BITMASK) {
92131
// Traits not supported in urealloc yet
93-
ualloc_debug(UALLOC_DEBUG_WARNING, "ua c:%p fail\n", caller);
132+
ualloc_debug(UALLOC_DEBUG_ERROR, "ua c:%p fail\n", caller);
94133
return NULL;
95134
}
96135
uintptr_t ptr_tmp = (uintptr_t) ptr;
97136
if ((ptr_tmp < (uintptr_t) mbed_sbrk_ptr) &&
98137
(ptr_tmp >= (uintptr_t)&__mbed_sbrk_start)) {
99138
newptr = dlrealloc(ptr, bytes);
100139
} else {
101-
ualloc_debug(UALLOC_DEBUG_LOG, "uf c:%p m:%p non-heap realloc\n", caller, ptr);
140+
ualloc_debug(UALLOC_DEBUG_ERROR, "uf c:%p m:%p non-heap realloc\n", caller, ptr);
102141
}
103142

104143
if(newptr == NULL) {
105-
ualloc_debug(UALLOC_DEBUG_WARNING, "ur c:%p m0:%p fail\n", caller, ptr);
106-
} else {
107-
ualloc_debug(UALLOC_DEBUG_LOG, "ur c:%p m0:%p m1:%p\n", caller, ptr, newptr);
144+
ualloc_debug(UALLOC_DEBUG_WARNING, "ur c:%p p:%p fail\n", caller, ptr);
108145
}
109146
return newptr;
110147
}
111-
void mbed_ufree(void * ptr)
148+
149+
void * mbed_urealloc(void * ptr, size_t bytes, UAllocTraits_t traits) {
150+
void *caller = (void*)caller_addr();
151+
void *p = mbed_urealloc_internal(ptr, bytes, traits, caller);
152+
if (!prevent_tracing) {
153+
prevent_tracing = 1;
154+
ualloc_debug(UALLOC_DEBUG_LOG, "ua c:%p s:%u p:%p m:%p\n", caller, (unsigned)bytes, ptr, p);
155+
prevent_tracing = 0;
156+
}
157+
return p;
158+
}
159+
160+
static void mbed_ufree_internal(void * ptr, void *caller)
112161
{
113-
void * caller = (void*) caller_addr();
114-
ualloc_debug(UALLOC_DEBUG_LOG, "uf c:%p m:%p\n", caller, ptr);
115162
uintptr_t ptr_tmp = (uintptr_t) ptr;
116163
if ((ptr_tmp < (uintptr_t) mbed_sbrk_ptr) &&
117164
(ptr_tmp >= (uintptr_t)&__mbed_sbrk_start)) {
118165
dlfree(ptr);
119166
} else {
120-
ualloc_debug(UALLOC_DEBUG_LOG, "uf c:%p m:%p non-heap free\n", caller, ptr);
167+
ualloc_debug(UALLOC_DEBUG_WARNING, "uf c:%p m:%p non-heap free\n", caller, ptr);
168+
}
169+
}
170+
171+
void mbed_ufree(void *ptr) {
172+
void *caller = (void*)caller_addr();
173+
mbed_ufree_internal(ptr, caller);
174+
if (!prevent_tracing) {
175+
prevent_tracing = 1;
176+
ualloc_debug(UALLOC_DEBUG_LOG, "uf c:%p m:%p\n", caller, ptr);
177+
prevent_tracing = 0;
121178
}
122179
}
180+

0 commit comments

Comments
 (0)