From a1736e6341b97761404181ab781f67d7f677fdce Mon Sep 17 00:00:00 2001 From: Bartek Szatkowski Date: Mon, 10 Jul 2017 16:30:59 +0100 Subject: [PATCH] Boot: Provide dynamic mutexes for ARM toolchain ARM toolchain requires variable number of dynamic mutexes. We use combination of RTX mutex pool and heap allocation to achieve that. --- rtos/mbed_boot.c | 43 +++++++++++++++++++++++++++++ rtos/rtx5/TARGET_CORTEX_M/rtx_lib.c | 8 +++--- rtos/rtx5/mbed_rtx_conf.h | 1 + 3 files changed, 48 insertions(+), 4 deletions(-) diff --git a/rtos/mbed_boot.c b/rtos/mbed_boot.c index 93029898fb..7be1badf2b 100644 --- a/rtos/mbed_boot.c +++ b/rtos/mbed_boot.c @@ -160,6 +160,8 @@ * */ +#include + #include "cmsis.h" #include "mbed_rtx.h" #include "mbed_rtos_storage.h" @@ -413,6 +415,47 @@ void __rt_entry (void) { mbed_start_main(); } +typedef void *mutex; + +/* ARM toolchain requires dynamically created mutexes to enforce thread safety. There's + up to 8 static mutexes, protecting atexit, signalinit, stdin, stdout, stderr, stream_list, + fp_trap_init and the heap. Additionally for each call to fopen one extra mutex will be + created. + mbed OS provides a RTX pool for 8 mutexes, to satisfy the static requirements. All + additional mutexes will be allocated on the heap. We can't use the heap allocation for + all the required mutexes, as the heap operations also require a mutex. We don't need to + worry about freeing the allocated memory as library mutexes are only freed when the + application finishes executing. + */ +int _mutex_initialize(mutex *m) +{ + osMutexAttr_t attr; + memset(&attr, 0, sizeof(attr)); + attr.name = "ARM toolchain mutex"; + attr.attr_bits = osMutexRecursive | osMutexPrioInherit | osMutexRobust; + + *m = osMutexNew(&attr); + if (*m != NULL) { + return 1; + } + + /* Mutex pool exhausted, try using HEAP */ + attr.cb_size = sizeof(mbed_rtos_storage_mutex_t); + attr.cb_mem = (void*)malloc(attr.cb_size); + if (attr.cb_mem == NULL) { + osRtxErrorNotify(osRtxErrorClibSpace, m); + return 0; + } + + *m = osMutexNew(&attr); + if (*m == NULL) { + osRtxErrorNotify(osRtxErrorClibMutex, m); + return 0; + } + + return 1; +} + #endif /* ARMC */ #elif defined (__GNUC__) /******************** GCC ********************/ diff --git a/rtos/rtx5/TARGET_CORTEX_M/rtx_lib.c b/rtos/rtx5/TARGET_CORTEX_M/rtx_lib.c index 1020f7adab..4a157e9c8b 100644 --- a/rtos/rtx5/TARGET_CORTEX_M/rtx_lib.c +++ b/rtos/rtx5/TARGET_CORTEX_M/rtx_lib.c @@ -597,7 +597,7 @@ typedef void *mutex; // Initialize mutex __USED int _mutex_initialize(mutex *m); -int _mutex_initialize(mutex *m) { +__WEAK int _mutex_initialize(mutex *m) { *m = osMutexNew(NULL); if (*m == NULL) { osRtxErrorNotify(osRtxErrorClibMutex, m); @@ -609,7 +609,7 @@ int _mutex_initialize(mutex *m) { // Acquire mutex __USED void _mutex_acquire(mutex *m); -void _mutex_acquire(mutex *m) { +__WEAK void _mutex_acquire(mutex *m) { if (os_kernel_is_active()) { osMutexAcquire(*m, osWaitForever); } @@ -618,7 +618,7 @@ void _mutex_acquire(mutex *m) { // Release mutex __USED void _mutex_release(mutex *m); -void _mutex_release(mutex *m) { +__WEAK void _mutex_release(mutex *m) { if (os_kernel_is_active()) { osMutexRelease(*m); } @@ -627,7 +627,7 @@ void _mutex_release(mutex *m) { // Free mutex __USED void _mutex_free(mutex *m); -void _mutex_free(mutex *m) { +__WEAK void _mutex_free(mutex *m) { osMutexDelete(*m); } diff --git a/rtos/rtx5/mbed_rtx_conf.h b/rtos/rtx5/mbed_rtx_conf.h index c41a8df5e0..b4fe1d4f22 100644 --- a/rtos/rtx5/mbed_rtx_conf.h +++ b/rtos/rtx5/mbed_rtx_conf.h @@ -39,6 +39,7 @@ #define OS_DYNAMIC_MEM_SIZE 0 #if defined(__CC_ARM) +/* ARM toolchain uses up to 8 static mutexes, any further mutexes will be allocated on the heap. */ #define OS_MUTEX_OBJ_MEM 1 #define OS_MUTEX_NUM 8 #endif