freertos: Refactor configASSERTs for scheduler suspension

This commit adds a common macro for the differing configASSERT() calls that
check if the scheduler is suspended outside a critical section. This macro
allows vanilla behavior to be restored for single core builds. Also added
comments explaining why xTaskGetSchedulerState() is called instead when
building for SMP.
This commit is contained in:
Darian Leung 2023-03-02 21:38:09 +08:00
parent afbdb0f3ef
commit 353b25410a

View File

@ -282,6 +282,27 @@
#define prvGetTCBFromHandle( pxHandle ) ( ( ( pxHandle ) == NULL ) ? ( TaskHandle_t ) pxCurrentTCB[ 0 ] : ( ( TaskHandle_t ) pxHandle ) )
#endif
/*
* There are various blocking tasks.c API that call configASSERT() to check if
* the API is being called while the scheduler is suspended. However, these
* asserts are done outside a critical section or interrupt disabled block.
* Directly checking uxSchedulerSuspended[ xPortGetCoreID() ] outside a critical
* section can lead to false positives in SMP. Thus for SMP, we call
* xTaskGetSchedulerState() instead.
*
* Take the following example of an unpinned Task A in SMP calling
* uxSchedulerSuspended[ xPortGetCoreID() ]:
* - Task A calls xPortGetCoreID() which is 0
* - Task A gets preempted by Task B, Task A switches to core 1
* - Task B on core 0 calls vTaskSuspendAll()
* - Task A checks uxSchedulerSuspended[ 0 ] leading to a false positive
*/
#if ( configNUM_CORES > 1 )
#define taskIS_SCHEDULER_SUSPENDED() ( xTaskGetSchedulerState() == taskSCHEDULER_SUSPENDED )
#else
#define taskIS_SCHEDULER_SUSPENDED() ( uxSchedulerSuspended[ 0 ] > 0 )
#endif /* configNUM_CORES > 1 */
/* The item value of the event list item is normally used to hold the priority
* of the task to which it belongs (coded to allow it to be held in reverse
* priority order). However, it is occasionally borrowed for other purposes. It
@ -1488,7 +1509,7 @@ static void prvAddNewTaskToReadyList( TCB_t * pxNewTCB )
if( taskIS_CURRENTLY_RUNNING_ON_CORE( pxTCB, xPortGetCoreID() ) )
{
configASSERT( xTaskGetSchedulerState() != taskSCHEDULER_SUSPENDED );
configASSERT( uxSchedulerSuspended[ xPortGetCoreID() ] == 0 );
portYIELD_WITHIN_API();
}
else
@ -1522,7 +1543,7 @@ static void prvAddNewTaskToReadyList( TCB_t * pxNewTCB )
configASSERT( pxPreviousWakeTime );
configASSERT( ( xTimeIncrement > 0U ) );
configASSERT( xTaskGetSchedulerState() != taskSCHEDULER_SUSPENDED );
configASSERT( !taskIS_SCHEDULER_SUSPENDED() );
prvENTER_CRITICAL_OR_SUSPEND_ALL( &xKernelLock );
{
@ -1608,7 +1629,7 @@ static void prvAddNewTaskToReadyList( TCB_t * pxNewTCB )
/* A delay time of zero just forces a reschedule. */
if( xTicksToDelay > ( TickType_t ) 0U )
{
configASSERT( xTaskGetSchedulerState() != taskSCHEDULER_SUSPENDED );
configASSERT( !taskIS_SCHEDULER_SUSPENDED() );
prvENTER_CRITICAL_OR_SUSPEND_ALL( &xKernelLock );
{
traceTASK_DELAY();
@ -2540,7 +2561,7 @@ BaseType_t xTaskResumeAll( void )
/* If uxSchedulerSuspended is zero then this function does not match a
* previous call to vTaskSuspendAll(). */
configASSERT( uxSchedulerSuspended[ xPortGetCoreID() ] );
configASSERT( taskIS_SCHEDULER_SUSPENDED() );
/* It is possible that an ISR caused a task to be removed from an event
* list while the scheduler was suspended. If this was the case then the
@ -2990,11 +3011,7 @@ BaseType_t xTaskCatchUpTicks( TickType_t xTicksToCatchUp )
/* Must not be called with the scheduler suspended as the implementation
* relies on xPendedTicks being wound down to 0 in xTaskResumeAll(). */
#ifdef ESP_PLATFORM
configASSERT( xTaskGetSchedulerState() != taskSCHEDULER_SUSPENDED );
#else
configASSERT( uxSchedulerSuspended == 0 );
#endif // ESP_PLATFORM
configASSERT( !taskIS_SCHEDULER_SUSPENDED() );
/* Use xPendedTicks to mimic xTicksToCatchUp number of ticks occurring when
* the scheduler is suspended so the ticks are executed in xTaskResumeAll(). */
@ -3974,7 +3991,7 @@ void vTaskRemoveFromUnorderedEventList( ListItem_t * pxEventListItem,
/* THIS FUNCTION MUST BE CALLED WITH THE SCHEDULER SUSPENDED. It is used by
* the event flags implementation. */
configASSERT( uxSchedulerSuspended != pdFALSE );
configASSERT( uxSchedulerSuspended[ 0 ] != pdFALSE );
#endif /* configNUM_CORES > 1 */
/* Store the new item value in the event list. */