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.
This commit is contained in:
Darian Leung 2024-05-14 22:32:25 +08:00
parent ea010f84ef
commit 0dc29caf4a
No known key found for this signature in database
GPG Key ID: 8AC9127B487AA4EF

View File

@ -2462,22 +2462,29 @@ void vTaskEndScheduler( void )
void vTaskSuspendAll( 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 * 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! - * post in the FreeRTOS support forum before reporting this as a bug! -
* https://goo.gl/wu4acr */ * 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 /* The scheduler is suspended if uxSchedulerSuspended is non-zero. An increment
* do not otherwise exhibit real time behaviour. */ * is used to allow calls to vTaskSuspendAll() to nest. */
portSOFTWARE_BARRIER(); ++uxSchedulerSuspended[ portGET_CORE_ID() ];
/* The scheduler is suspended if uxSchedulerSuspended is non-zero. An increment /* Enforces ordering for ports and optimised compilers that may otherwise place
* is used to allow calls to vTaskSuspendAll() to nest. */ * the above increment elsewhere. */
++uxSchedulerSuspended[ portGET_CORE_ID() ]; portMEMORY_BARRIER();
}
/* Enforces ordering for ports and optimised compilers that may otherwise place /* Release the previously taken kernel lock. */
* the above increment elsewhere. */ prvEXIT_CRITICAL_SMP_ONLY( &xKernelLock );
portMEMORY_BARRIER();
} }
/*----------------------------------------------------------*/ /*----------------------------------------------------------*/