@@ -27,12 +27,44 @@ extern int printf(const char *, ...);
2727
2828extern 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
3449const 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,9 @@ const char ua_chars[] = "NFEWIL";
5284 #define caller_addr () (NULL)
5385#endif
5486
55- void * mbed_ualloc (size_t bytes , UAllocTraits_t traits )
87+ static void * mbed_ualloc_internal (size_t bytes , UAllocTraits_t traits , void * caller )
5688{
5789 void * ptr = NULL ;
58- void * caller = (void * ) caller_addr ();
5990 if (UALLOC_TEST_TRAITS (traits .flags , UALLOC_TRAITS_NEVER_FREE )) {
6091 ptr = mbed_krbs (bytes );
6192 // krbs uses the same semantics as sbrk, so translate a -1 to NULL.
@@ -76,47 +107,79 @@ void * mbed_ualloc(size_t bytes, UAllocTraits_t traits)
76107
77108 if (ptr == NULL ) {
78109 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 );
81110 }
111+
82112 return ptr ;
83113}
84- void * mbed_urealloc (void * ptr , size_t bytes , UAllocTraits_t traits )
114+
115+ void * mbed_ualloc (size_t bytes , UAllocTraits_t traits )
116+ {
117+ void * caller = (void * )caller_addr ();
118+ void * p = mbed_ualloc_internal (bytes , traits , caller );
119+ if (!prevent_tracing ) {
120+ prevent_tracing = 1 ;
121+ ualloc_debug (UALLOC_DEBUG_LOG , "ua c:%p s:%u m:%p\n" , caller , (unsigned )bytes , p );
122+ prevent_tracing = 0 ;
123+ }
124+ return p ;
125+ }
126+
127+ static void * mbed_urealloc_internal (void * ptr , size_t bytes , UAllocTraits_t traits , void * caller )
85128{
86- void * caller = (void * ) caller_addr ();
87129 void * newptr = NULL ;
88130 if (ptr == NULL ) {
89131 return mbed_ualloc (bytes , traits );
90132 }
91133 if (traits .flags & ~UALLOC_TRAITS_BITMASK ) {
92134 // Traits not supported in urealloc yet
93- ualloc_debug (UALLOC_DEBUG_WARNING , "ua c:%p fail\n" , caller );
135+ ualloc_debug (UALLOC_DEBUG_ERROR , "ur c:%p fail\n" , caller );
94136 return NULL ;
95137 }
96138 uintptr_t ptr_tmp = (uintptr_t ) ptr ;
97139 if ((ptr_tmp < (uintptr_t ) mbed_sbrk_ptr ) &&
98140 (ptr_tmp >= (uintptr_t )& __mbed_sbrk_start )) {
99141 newptr = dlrealloc (ptr , bytes );
100142 } else {
101- ualloc_debug (UALLOC_DEBUG_LOG , "uf c:%p m:%p non-heap realloc\n" , caller , ptr );
143+ ualloc_debug (UALLOC_DEBUG_ERROR , "ur c:%p m:%p non-heap realloc\n" , caller , ptr );
102144 }
103145
104146 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 );
147+ ualloc_debug (UALLOC_DEBUG_WARNING , "ur c:%p p:%p fail\n" , caller , ptr );
108148 }
109149 return newptr ;
110150}
111- void mbed_ufree (void * ptr )
151+
152+ void * mbed_urealloc (void * ptr , size_t bytes , UAllocTraits_t traits )
153+ {
154+ void * caller = (void * )caller_addr ();
155+ void * p = mbed_urealloc_internal (ptr , bytes , traits , caller );
156+ if (!prevent_tracing ) {
157+ prevent_tracing = 1 ;
158+ ualloc_debug (UALLOC_DEBUG_LOG , "ur c:%p s:%u p:%p m:%p\n" , caller , (unsigned )bytes , ptr , p );
159+ prevent_tracing = 0 ;
160+ }
161+ return p ;
162+ }
163+
164+ static void mbed_ufree_internal (void * ptr , void * caller )
112165{
113- void * caller = (void * ) caller_addr ();
114- ualloc_debug (UALLOC_DEBUG_LOG , "uf c:%p m:%p\n" , caller , ptr );
115166 uintptr_t ptr_tmp = (uintptr_t ) ptr ;
116167 if ((ptr_tmp < (uintptr_t ) mbed_sbrk_ptr ) &&
117168 (ptr_tmp >= (uintptr_t )& __mbed_sbrk_start )) {
118169 dlfree (ptr );
119170 } else {
120- ualloc_debug (UALLOC_DEBUG_LOG , "uf c:%p m:%p non-heap free\n" , caller , ptr );
171+ ualloc_debug (UALLOC_DEBUG_WARNING , "uf c:%p m:%p non-heap free\n" , caller , ptr );
121172 }
122173}
174+
175+ void mbed_ufree (void * ptr )
176+ {
177+ void * caller = (void * )caller_addr ();
178+ mbed_ufree_internal (ptr , caller );
179+ if (!prevent_tracing ) {
180+ prevent_tracing = 1 ;
181+ ualloc_debug (UALLOC_DEBUG_LOG , "uf c:%p m:%p\n" , caller , ptr );
182+ prevent_tracing = 0 ;
183+ }
184+ }
185+
0 commit comments