@@ -24,6 +24,39 @@ extern void REAL_FUNC(free)(void *mem);
24
24
25
25
extern char __StackLimit ; /* Set by linker. */
26
26
27
+ #if !PICO_USE_MALLOC_MUTEX
28
+ #define MALLOC_ENTER (outer ) ((void)0);
29
+ #define MALLOC_EXIT (outer ) ((void)0);
30
+ #elif !__PICOLIBC__
31
+ #define MALLOC_ENTER (outer ) mutex_enter_blocking(&malloc_mutex);
32
+ #define MALLOC_EXIT (outer ) mutex_exit(&malloc_mutex);
33
+ #else
34
+ static uint8_t mutex_exception_level_plus_one [NUM_CORES ];
35
+ // PICOLIBC implementations of calloc and realloc may call malloc and free,
36
+ // so we need to cope with re-entrant calls. We don't want to use a recursive
37
+ // mutex as that won't catch usage within an ISR; instead we record the exception
38
+ // nesting as of acquiring the mutex
39
+ #define MALLOC_ENTER (outer ) \
40
+ uint exception = __get_current_exception(); \
41
+ uint core_num = get_core_num(); \
42
+ /* we skip the locking on outer == false if we are in the same irq nesting */ \
43
+ /* note: the `+ 1` is to distinguish no malloc nesting vs no-exception/irq level */ \
44
+ bool do_lock = outer || exception + 1 != mutex_exception_level_plus_one [core_num ]; \
45
+ if (do_lock ) { \
46
+ mutex_enter_blocking (& malloc_mutex ); \
47
+ if (outer ) mutex_exception_level_plus_one [core_num ] = (uint8_t )(exception + 1 ); \
48
+ }
49
+
50
+ #define MALLOC_EXIT (outer ) \
51
+ if (outer) { \
52
+ mutex_exception_level_plus_one[core_num] = 0; \
53
+ } \
54
+ if (do_lock) { \
55
+ mutex_exit(&malloc_mutex); \
56
+ }
57
+
58
+ #endif
59
+
27
60
static inline void check_alloc (__unused void * mem , __unused uint size ) {
28
61
#if PICO_MALLOC_PANIC
29
62
if (!mem || (((char * )mem ) + size ) > & __StackLimit ) {
@@ -33,13 +66,9 @@ static inline void check_alloc(__unused void *mem, __unused uint size) {
33
66
}
34
67
35
68
void * WRAPPER_FUNC (malloc )(size_t size ) {
36
- #if PICO_USE_MALLOC_MUTEX
37
- mutex_enter_blocking (& malloc_mutex );
38
- #endif
69
+ MALLOC_ENTER (false )
39
70
void * rc = REAL_FUNC (malloc )(size );
40
- #if PICO_USE_MALLOC_MUTEX
41
- mutex_exit (& malloc_mutex );
42
- #endif
71
+ MALLOC_EXIT (false )
43
72
#if PICO_DEBUG_MALLOC
44
73
if (!rc ) {
45
74
printf ("malloc %d failed to allocate memory\n" , (uint ) size );
@@ -52,13 +81,9 @@ void *WRAPPER_FUNC(malloc)(size_t size) {
52
81
}
53
82
54
83
void * WRAPPER_FUNC (calloc )(size_t count , size_t size ) {
55
- #if PICO_USE_MALLOC_MUTEX
56
- mutex_enter_blocking (& malloc_mutex );
57
- #endif
84
+ MALLOC_ENTER (true )
58
85
void * rc = REAL_FUNC (calloc )(count , size );
59
- #if PICO_USE_MALLOC_MUTEX
60
- mutex_exit (& malloc_mutex );
61
- #endif
86
+ MALLOC_EXIT (true )
62
87
#if PICO_DEBUG_MALLOC
63
88
if (!rc ) {
64
89
printf ("calloc %d failed to allocate memory\n" , (uint ) (count * size ));
@@ -71,13 +96,9 @@ void *WRAPPER_FUNC(calloc)(size_t count, size_t size) {
71
96
}
72
97
73
98
void * WRAPPER_FUNC (realloc )(void * mem , size_t size ) {
74
- #if PICO_USE_MALLOC_MUTEX
75
- mutex_enter_blocking (& malloc_mutex );
76
- #endif
99
+ MALLOC_ENTER (true )
77
100
void * rc = REAL_FUNC (realloc )(mem , size );
78
- #if PICO_USE_MALLOC_MUTEX
79
- mutex_exit (& malloc_mutex );
80
- #endif
101
+ MALLOC_EXIT (true )
81
102
#if PICO_DEBUG_MALLOC
82
103
if (!rc ) {
83
104
printf ("realloc %d failed to allocate memory\n" , (uint ) size );
@@ -90,11 +111,7 @@ void *WRAPPER_FUNC(realloc)(void *mem, size_t size) {
90
111
}
91
112
92
113
void WRAPPER_FUNC (free )(void * mem ) {
93
- #if PICO_USE_MALLOC_MUTEX
94
- mutex_enter_blocking (& malloc_mutex );
95
- #endif
114
+ MALLOC_ENTER (false )
96
115
REAL_FUNC (free )(mem );
97
- #if PICO_USE_MALLOC_MUTEX
98
- mutex_exit (& malloc_mutex );
99
- #endif
116
+ MALLOC_EXIT (false )
100
117
}
0 commit comments