From 7c38b262fbc01246f111086175d25517511308e3 Mon Sep 17 00:00:00 2001 From: Darian Leung Date: Tue, 14 May 2024 22:32:25 +0800 Subject: [PATCH] fix(freertos/idf): Add missing critical sections to vTaskSuspendAll() vTaskSuspendAll() requires critical sections when building for SMP. Otherwise, it is possible for a task to switch cores in between getting the core ID and before incremented uxSchedulerSuspended. --- components/freertos/FreeRTOS-Kernel/tasks.c | 29 +++++++++++++-------- 1 file changed, 18 insertions(+), 11 deletions(-) diff --git a/components/freertos/FreeRTOS-Kernel/tasks.c b/components/freertos/FreeRTOS-Kernel/tasks.c index 011699ed88..df7835de70 100644 --- a/components/freertos/FreeRTOS-Kernel/tasks.c +++ b/components/freertos/FreeRTOS-Kernel/tasks.c @@ -2462,22 +2462,29 @@ void vTaskEndScheduler( void ) void vTaskSuspendAll( void ) { - /* A critical section is not required as the variable is of type + /* For SMP, we need to take the kernel lock here as we are about to access + * kernel data structures. + * + * For single-core, a critical section is not required as the variable is of type * BaseType_t. Please read Richard Barry's reply in the following link to a * post in the FreeRTOS support forum before reporting this as a bug! - * https://goo.gl/wu4acr */ + prvENTER_CRITICAL_SMP_ONLY( &xKernelLock ); + { + /* portSOFTWARE_BARRIER() is only implemented for emulated/simulated ports that + * do not otherwise exhibit real time behaviour. */ + portSOFTWARE_BARRIER(); - /* portSOFTWARE_BARRIER() is only implemented for emulated/simulated ports that - * do not otherwise exhibit real time behaviour. */ - portSOFTWARE_BARRIER(); + /* The scheduler is suspended if uxSchedulerSuspended is non-zero. An increment + * is used to allow calls to vTaskSuspendAll() to nest. */ + ++uxSchedulerSuspended[ portGET_CORE_ID() ]; - /* The scheduler is suspended if uxSchedulerSuspended is non-zero. An increment - * is used to allow calls to vTaskSuspendAll() to nest. */ - ++uxSchedulerSuspended[ portGET_CORE_ID() ]; - - /* Enforces ordering for ports and optimised compilers that may otherwise place - * the above increment elsewhere. */ - portMEMORY_BARRIER(); + /* Enforces ordering for ports and optimised compilers that may otherwise place + * the above increment elsewhere. */ + portMEMORY_BARRIER(); + } + /* Release the previously taken kernel lock. */ + prvEXIT_CRITICAL_SMP_ONLY( &xKernelLock ); } /*----------------------------------------------------------*/