diff --git a/components/freertos/Kconfig b/components/freertos/Kconfig index 8ec085e14..8063c266b 100644 --- a/components/freertos/Kconfig +++ b/components/freertos/Kconfig @@ -419,4 +419,11 @@ menu "FreeRTOS" abort the application. This option is also required for GDB backtraces and C++ exceptions to work correctly inside top-level task functions. + config FREERTOS_CHECK_MUTEX_GIVEN_BY_OWNER + bool "Check that mutex semaphore is given by owner task" + default y + help + If enabled, assert that when a mutex semaphore is given, the task giving the + semaphore is the task which is currently holding the mutex. + endmenu diff --git a/components/freertos/include/freertos/FreeRTOSConfig.h b/components/freertos/include/freertos/FreeRTOSConfig.h index 80185f9e0..cc6cdad90 100644 --- a/components/freertos/include/freertos/FreeRTOSConfig.h +++ b/components/freertos/include/freertos/FreeRTOSConfig.h @@ -314,5 +314,11 @@ extern void vPortCleanUpTCB ( void *pxTCB ); #endif /* def __ASSEMBLER__ */ #endif +#if CONFIG_FREERTOS_CHECK_MUTEX_GIVEN_BY_OWNER +#define configCHECK_MUTEX_GIVEN_BY_OWNER 1 +#else +#define configCHECK_MUTEX_GIVEN_BY_OWNER 0 +#endif + #endif /* FREERTOS_CONFIG_H */ diff --git a/components/freertos/queue.c b/components/freertos/queue.c index f6b63de5e..eccd1a016 100644 --- a/components/freertos/queue.c +++ b/components/freertos/queue.c @@ -724,6 +724,12 @@ Queue_t * const pxQueue = ( Queue_t * ) xQueue; configASSERT( !( ( xTaskGetSchedulerState() == taskSCHEDULER_SUSPENDED ) && ( xTicksToWait != 0 ) ) ); } #endif + #if ( configUSE_MUTEXES == 1 && configCHECK_MUTEX_GIVEN_BY_OWNER == 1) + { + configASSERT(pxQueue->uxQueueType != queueQUEUE_IS_MUTEX || pxQueue->pxMutexHolder == NULL || xTaskGetCurrentTaskHandle() == pxQueue->pxMutexHolder); + } + #endif + /* This function relaxes the coding standard somewhat to allow return diff --git a/components/freertos/test/test_freertos_mutex.c b/components/freertos/test/test_freertos_mutex.c new file mode 100644 index 000000000..51697984e --- /dev/null +++ b/components/freertos/test/test_freertos_mutex.c @@ -0,0 +1,21 @@ +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "freertos/semphr.h" +#include "unity.h" +#include "esp_ipc.h" +#include "test_utils.h" + +static void mutex_release_task(void* arg) +{ + SemaphoreHandle_t mutex = (SemaphoreHandle_t) arg; + xSemaphoreGive(mutex); + TEST_FAIL_MESSAGE("should not be reached"); +} + +TEST_CASE("mutex released not by owner causes an assert", "[freertos][reset=abort,SW_CPU_RESET]") +{ + SemaphoreHandle_t mutex = xSemaphoreCreateMutex(); + xSemaphoreTake(mutex, portMAX_DELAY); + xTaskCreate(&mutex_release_task, "mutex_release", 2048, mutex, UNITY_FREERTOS_PRIORITY + 1, NULL); + vTaskDelay(1); +}