From c790e2eb6da10c141cfb34642ea5e140a47432b1 Mon Sep 17 00:00:00 2001 From: Marian Buschsieweke Date: Thu, 10 Dec 2020 09:43:55 +0100 Subject: [PATCH] sys/malloc_thread_safety: use mutex Disabling IRQs during malloc() provides mutually exclusive access and even is safe from IRQ context, but is suboptimal for real time scenarios. Instead, the implementation is changed to use a mutex to provide mutually exclusive access. As a result, calls to malloc() and free() from IRQ context no longer is possible. But this this is a really horrible idea to begin with, the impact should be minimal and the improved real time properties of the system should make it a good trade-off. An assert() is added to allow easy detection of regressions and, hence, aid users to fix their code. --- sys/malloc_thread_safe/malloc_wrappers.c | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/sys/malloc_thread_safe/malloc_wrappers.c b/sys/malloc_thread_safe/malloc_wrappers.c index be81c82066..138dae65a2 100644 --- a/sys/malloc_thread_safe/malloc_wrappers.c +++ b/sys/malloc_thread_safe/malloc_wrappers.c @@ -14,41 +14,49 @@ * @author Gunar Schorcht */ +#include "assert.h" #include "irq.h" +#include "mutex.h" extern void *__real_malloc(size_t size); extern void __real_free(void *ptr); extern void *__real_calloc(size_t nmemb, size_t size); extern void *__real_realloc(void *ptr, size_t size); +static mutex_t _lock; + void *__wrap_malloc(size_t size) { - unsigned state = irq_disable(); + assert(!irq_is_in()); + mutex_lock(&_lock); void *ptr = __real_malloc(size); - irq_restore(state); + mutex_unlock(&_lock); return ptr; } void __wrap_free(void *ptr) { - unsigned state = irq_disable(); + assert(!irq_is_in()); + mutex_lock(&_lock); __real_free(ptr); - irq_restore(state); + mutex_unlock(&_lock); } void *__wrap_calloc(size_t nmemb, size_t size) { - unsigned state = irq_disable(); + assert(!irq_is_in()); + mutex_lock(&_lock); void *ptr = __real_calloc(nmemb, size); - irq_restore(state); + mutex_unlock(&_lock); return ptr; } void *__wrap_realloc(void *ptr, size_t size) { - unsigned state = irq_disable(); + assert(!irq_is_in()); + mutex_lock(&_lock); void *new = __real_realloc(ptr, size); - irq_restore(state); + mutex_unlock(&_lock); return new; }