refactor(freertos/idf): Refactor yield and affinity macros

This commit refactors the following macros so that calling them no longer
requires referencing pxTCB->xCoreID.

- taskIS_YIELD_REQUIRED()
- taskIS_YIELD_REQUIRED_USING_PRIORITY()
- taskIS_AFFINITY_COMPATIBLE()
This commit is contained in:
Darian Leung 2023-11-16 19:18:17 +08:00
parent c9f1d3e8be
commit 63fee6c23a

View File

@ -130,27 +130,29 @@
/* Macros to check if an unblocked task causes a yield on the current core. /* Macros to check if an unblocked task causes a yield on the current core.
* - pxTCB is the TCB of the task to check * - pxTCB is the TCB of the task to check
* - xCurCoreID is the current core's ID
* - xYieldEqualPriority indicates whether a yield should occur if the unblocked
* task's priority is equal to the priority of the task currently running on the
* current core.
* - uxTaskPriority is the task's priority * - uxTaskPriority is the task's priority
* - xTaskCoreID is the task's core affinity */ * - xYieldEqualPriority if the task having equal priority as the currently
* executing task should cause a yield.
*
* In single-core, this macro simply checks the unblocked task has a high enough
* priority to preempt the current task, and returns pdTRUE if so.
*
* In SMP, this macro checks if the unblocked task can preempt either core:
* - If a yield is required on the current core, this macro return pdTRUE
* - if a yield is required on the other core, this macro will internally
* trigger it.
*/
#if ( configNUMBER_OF_CORES > 1 ) #if ( configNUMBER_OF_CORES > 1 )
#define taskIS_YIELD_REQUIRED( pxTCB, xCurCoreID, xYieldEqualPriority ) prvIsYieldUsingPrioritySMP( ( pxTCB )->uxPriority, ( pxTCB )->xCoreID, xCurCoreID, xYieldEqualPriority ) #define taskIS_YIELD_REQUIRED( pxTCB, xYieldEqualPriority ) prvIsYieldRequiredSMP( ( pxTCB ), ( pxTCB )->uxPriority, xYieldEqualPriority )
#define taskIS_YIELD_REQUIRED_USING_PRIORITY( uxTaskPriority, xTaskCoreID, xCurCoreID, xYieldEqualPriority ) prvIsYieldUsingPrioritySMP( uxTaskPriority, xTaskCoreID, xCurCoreID, xYieldEqualPriority ) #define taskIS_YIELD_REQUIRED_USING_PRIORITY( pxTCB, uxTaskPriority, xYieldEqualPriority ) prvIsYieldRequiredSMP( ( pxTCB ), uxTaskPriority, xYieldEqualPriority )
#else #else
#define taskIS_YIELD_REQUIRED( pxTCB, xCurCoreID, xYieldEqualPriority ) \ #define taskIS_YIELD_REQUIRED( pxTCB, xYieldEqualPriority ) \
( { \ ( { \
/* xCurCoreID is unused */ \
( void ) xCurCoreID; \
( ( ( pxTCB )->uxPriority + ( ( xYieldEqualPriority == pdTRUE ) ? 1 : 0 ) ) > pxCurrentTCBs[ 0 ]->uxPriority ) ? pdTRUE : pdFALSE; \ ( ( ( pxTCB )->uxPriority + ( ( xYieldEqualPriority == pdTRUE ) ? 1 : 0 ) ) > pxCurrentTCBs[ 0 ]->uxPriority ) ? pdTRUE : pdFALSE; \
} ) } )
#define taskIS_YIELD_REQUIRED_USING_PRIORITY( uxTaskPriority, xTaskCoreID, xCurCoreID, xYieldEqualPriority ) \ #define taskIS_YIELD_REQUIRED_USING_PRIORITY( pxTCB, uxTaskPriority, xYieldEqualPriority ) \
( { \ ( { \
/* xTaskCoreID and xCurCoreID are unused */ \ ( void ) pxTCB; \
( void ) xTaskCoreID; \
( void ) xCurCoreID; \
( ( uxTaskPriority + ( ( xYieldEqualPriority == pdTRUE ) ? 1 : 0 ) ) >= pxCurrentTCBs[ 0 ]->uxPriority ) ? pdTRUE : pdFALSE; \ ( ( uxTaskPriority + ( ( xYieldEqualPriority == pdTRUE ) ? 1 : 0 ) ) >= pxCurrentTCBs[ 0 ]->uxPriority ) ? pdTRUE : pdFALSE; \
} ) } )
#endif /* configNUMBER_OF_CORES > 1 */ #endif /* configNUMBER_OF_CORES > 1 */
@ -158,18 +160,19 @@
/* Macros to check if a task has a compatible affinity with a particular core. /* Macros to check if a task has a compatible affinity with a particular core.
* - xCore is the target core * - xCore is the target core
* - xCoreID is the affinity of the task to check * - pxTCB is the task to check
* *
* This macro will always return true on single core as the concept of core * This macro will always return true on single core as the concept of core
* affinity doesn't exist. */ * affinity doesn't exist. */
#if ( configNUMBER_OF_CORES > 1 ) #if ( configNUMBER_OF_CORES > 1 )
#define taskIS_AFFINITY_COMPATIBLE( xCore, xCoreID ) ( ( ( ( xCoreID ) == xCore ) || ( ( xCoreID ) == tskNO_AFFINITY ) ) ? pdTRUE : pdFALSE ) #define taskIS_AFFINITY_COMPATIBLE( xCore, pxTCB ) ( ( ( ( pxTCB )->xCoreID == xCore ) || ( ( pxTCB )->xCoreID == tskNO_AFFINITY ) ) ? pdTRUE : pdFALSE )
#else #else
#define taskIS_AFFINITY_COMPATIBLE( xCore, xCoreID ) \ #define taskIS_AFFINITY_COMPATIBLE( xCore, pxTCB ) \
( { \ ( { \
/* xCoreID is unused */ \ /* xCore and pxTCB are unused */ \
( void ) xCoreID; \ ( void ) xCore; \
pdTRUE; \ ( void ) pxTCB; \
pdTRUE; \
} ) } )
#endif /* configNUMBER_OF_CORES > 1 */ #endif /* configNUMBER_OF_CORES > 1 */
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -568,10 +571,9 @@ static BaseType_t prvCreateIdleTasks( void );
*/ */
#if ( configNUMBER_OF_CORES > 1 ) #if ( configNUMBER_OF_CORES > 1 )
static BaseType_t prvIsYieldUsingPrioritySMP( UBaseType_t uxTaskPriority, static BaseType_t prvIsYieldRequiredSMP( TCB_t * pxTCB,
BaseType_t xTaskCoreID, UBaseType_t uxTaskPriority,
BaseType_t xCurCoreID, BaseType_t xYieldEqualPriority ) PRIVILEGED_FUNCTION;
BaseType_t xYieldEqualPriority ) PRIVILEGED_FUNCTION;
#endif /* configNUMBER_OF_CORES > 1 */ #endif /* configNUMBER_OF_CORES > 1 */
@ -765,13 +767,15 @@ static void prvAddNewTaskToReadyList( TCB_t * pxNewTCB ) PRIVILEGED_FUNCTION;
#if ( configNUMBER_OF_CORES > 1 ) #if ( configNUMBER_OF_CORES > 1 )
static BaseType_t prvIsYieldUsingPrioritySMP( UBaseType_t uxTaskPriority, static BaseType_t prvIsYieldRequiredSMP( TCB_t * pxTCB,
BaseType_t xTaskCoreID, UBaseType_t uxTaskPriority,
BaseType_t xCurCoreID, BaseType_t xYieldEqualPriority )
BaseType_t xYieldEqualPriority )
{ {
configASSERT( uxTaskPriority < configMAX_PRIORITIES ); configASSERT( uxTaskPriority < configMAX_PRIORITIES );
/* Save core ID as we can no longer be preempted. */
const BaseType_t xCurCoreID = portGET_CORE_ID();
if( xYieldEqualPriority == pdTRUE ) if( xYieldEqualPriority == pdTRUE )
{ {
/* Increment the task priority to achieve the same affect as /* Increment the task priority to achieve the same affect as
@ -786,7 +790,7 @@ static void prvAddNewTaskToReadyList( TCB_t * pxNewTCB ) PRIVILEGED_FUNCTION;
* priority than the current core, and the core has not suspended * priority than the current core, and the core has not suspended
* scheduling, then yield the current core. * scheduling, then yield the current core.
* Todo: Make fair scheduling a configurable option (IDF-5772). */ * Todo: Make fair scheduling a configurable option (IDF-5772). */
if( ( taskIS_AFFINITY_COMPATIBLE( xCurCoreID, xTaskCoreID ) == pdTRUE ) && if( ( taskIS_AFFINITY_COMPATIBLE( xCurCoreID, pxTCB ) == pdTRUE ) &&
( uxTaskPriority > pxCurrentTCBs[ xCurCoreID ]->uxPriority ) && ( uxTaskPriority > pxCurrentTCBs[ xCurCoreID ]->uxPriority ) &&
( uxSchedulerSuspended[ xCurCoreID ] == ( UBaseType_t ) 0U ) ) ( uxSchedulerSuspended[ xCurCoreID ] == ( UBaseType_t ) 0U ) )
{ {
@ -797,7 +801,7 @@ static void prvAddNewTaskToReadyList( TCB_t * pxNewTCB ) PRIVILEGED_FUNCTION;
/* If the target task can run on the other core, and has a higher /* If the target task can run on the other core, and has a higher
* priority then the other core, and the other core has not suspended * priority then the other core, and the other core has not suspended
* scheduling, then yield the other core */ * scheduling, then yield the other core */
else if( ( taskIS_AFFINITY_COMPATIBLE( !xCurCoreID, xTaskCoreID ) == pdTRUE ) && else if( ( taskIS_AFFINITY_COMPATIBLE( !xCurCoreID, pxTCB ) == pdTRUE ) &&
( uxTaskPriority > pxCurrentTCBs[ !xCurCoreID ]->uxPriority ) && ( uxTaskPriority > pxCurrentTCBs[ !xCurCoreID ]->uxPriority ) &&
( uxSchedulerSuspended[ !xCurCoreID ] == ( UBaseType_t ) 0U ) ) ( uxSchedulerSuspended[ !xCurCoreID ] == ( UBaseType_t ) 0U ) )
{ {
@ -1194,7 +1198,7 @@ static void prvAddNewTaskToReadyList( TCB_t * pxNewTCB )
mtCOVERAGE_TEST_MARKER(); mtCOVERAGE_TEST_MARKER();
} }
if( ( pxCurrentTCBs[ 0 ] == NULL ) && ( taskIS_AFFINITY_COMPATIBLE( 0, pxNewTCB->xCoreID ) == pdTRUE ) ) if( ( pxCurrentTCBs[ 0 ] == NULL ) && ( taskIS_AFFINITY_COMPATIBLE( 0, pxNewTCB ) == pdTRUE ) )
{ {
/* On core 0, there are no other tasks, or all the other tasks /* On core 0, there are no other tasks, or all the other tasks
* are in the suspended state - make this the current task. */ * are in the suspended state - make this the current task. */
@ -1202,7 +1206,7 @@ static void prvAddNewTaskToReadyList( TCB_t * pxNewTCB )
} }
#if ( configNUMBER_OF_CORES > 1 ) #if ( configNUMBER_OF_CORES > 1 )
else if( ( pxCurrentTCBs[ 1 ] == NULL ) && ( taskIS_AFFINITY_COMPATIBLE( 1, pxNewTCB->xCoreID ) == pdTRUE ) ) else if( ( pxCurrentTCBs[ 1 ] == NULL ) && ( taskIS_AFFINITY_COMPATIBLE( 1, pxNewTCB ) == pdTRUE ) )
{ {
/* On core 1, there are no other tasks, or all the other tasks /* On core 1, there are no other tasks, or all the other tasks
* are in the suspended state - make this the current task. */ * are in the suspended state - make this the current task. */
@ -1217,7 +1221,7 @@ static void prvAddNewTaskToReadyList( TCB_t * pxNewTCB )
if( xSchedulerRunning == pdFALSE ) if( xSchedulerRunning == pdFALSE )
{ {
if( ( pxCurrentTCBs[ 0 ] != NULL ) && if( ( pxCurrentTCBs[ 0 ] != NULL ) &&
( taskIS_AFFINITY_COMPATIBLE( 0, pxNewTCB->xCoreID ) == pdTRUE ) && ( taskIS_AFFINITY_COMPATIBLE( 0, pxNewTCB ) == pdTRUE ) &&
( pxCurrentTCBs[ 0 ]->uxPriority <= pxNewTCB->uxPriority ) ) ( pxCurrentTCBs[ 0 ]->uxPriority <= pxNewTCB->uxPriority ) )
{ {
pxCurrentTCBs[ 0 ] = pxNewTCB; pxCurrentTCBs[ 0 ] = pxNewTCB;
@ -1225,7 +1229,7 @@ static void prvAddNewTaskToReadyList( TCB_t * pxNewTCB )
#if ( configNUMBER_OF_CORES > 1 ) #if ( configNUMBER_OF_CORES > 1 )
else if( ( pxCurrentTCBs[ 1 ] != NULL ) && else if( ( pxCurrentTCBs[ 1 ] != NULL ) &&
( taskIS_AFFINITY_COMPATIBLE( 1, pxNewTCB->xCoreID ) == pdTRUE ) && ( taskIS_AFFINITY_COMPATIBLE( 1, pxNewTCB ) == pdTRUE ) &&
( pxCurrentTCBs[ 1 ]->uxPriority <= pxNewTCB->uxPriority ) ) ( pxCurrentTCBs[ 1 ]->uxPriority <= pxNewTCB->uxPriority ) )
{ {
pxCurrentTCBs[ 1 ] = pxNewTCB; pxCurrentTCBs[ 1 ] = pxNewTCB;
@ -1260,7 +1264,7 @@ static void prvAddNewTaskToReadyList( TCB_t * pxNewTCB )
{ {
/* If the created task is of a higher priority than the current task /* If the created task is of a higher priority than the current task
* then it should run now. */ * then it should run now. */
if( taskIS_YIELD_REQUIRED( pxNewTCB, portGET_CORE_ID(), pdTRUE ) == pdTRUE ) if( taskIS_YIELD_REQUIRED( pxNewTCB, pdTRUE ) == pdTRUE )
{ {
taskYIELD_IF_USING_PREEMPTION(); taskYIELD_IF_USING_PREEMPTION();
} }
@ -1777,7 +1781,7 @@ static void prvAddNewTaskToReadyList( TCB_t * pxNewTCB )
/* The priority of a task other than the currently /* The priority of a task other than the currently
* running task is being raised. Is the priority being * running task is being raised. Is the priority being
* raised above that of the running task? */ * raised above that of the running task? */
if( taskIS_YIELD_REQUIRED_USING_PRIORITY( uxNewPriority, pxTCB->xCoreID, portGET_CORE_ID(), pdTRUE ) == pdTRUE ) if( taskIS_YIELD_REQUIRED_USING_PRIORITY( pxTCB, uxNewPriority, pdTRUE ) == pdTRUE )
{ {
xYieldRequired = pdTRUE; xYieldRequired = pdTRUE;
} }
@ -2106,7 +2110,7 @@ static void prvAddNewTaskToReadyList( TCB_t * pxNewTCB )
prvAddTaskToReadyList( pxTCB ); prvAddTaskToReadyList( pxTCB );
/* A higher priority task may have just been resumed. */ /* A higher priority task may have just been resumed. */
if( taskIS_YIELD_REQUIRED( pxTCB, portGET_CORE_ID(), pdTRUE ) == pdTRUE ) if( taskIS_YIELD_REQUIRED( pxTCB, pdTRUE ) == pdTRUE )
{ {
/* This yield may not cause the task just resumed to run, /* This yield may not cause the task just resumed to run,
* but will leave the lists in the correct state for the * but will leave the lists in the correct state for the
@ -2177,7 +2181,7 @@ static void prvAddNewTaskToReadyList( TCB_t * pxNewTCB )
{ {
/* Ready lists can be accessed so move the task from the /* Ready lists can be accessed so move the task from the
* suspended list to the ready list directly. */ * suspended list to the ready list directly. */
if( taskIS_YIELD_REQUIRED( pxTCB, xCurCoreID, pdTRUE ) == pdTRUE ) if( taskIS_YIELD_REQUIRED( pxTCB, pdTRUE ) == pdTRUE )
{ {
xYieldRequired = pdTRUE; xYieldRequired = pdTRUE;
@ -2575,7 +2579,7 @@ BaseType_t xTaskResumeAll( void )
/* If the moved task has a priority higher than or equal to /* If the moved task has a priority higher than or equal to
* the current task then a yield must be performed. */ * the current task then a yield must be performed. */
if( taskIS_YIELD_REQUIRED( pxTCB, xCurCoreID, pdTRUE ) == pdTRUE ) if( taskIS_YIELD_REQUIRED( pxTCB, pdTRUE ) == pdTRUE )
{ {
xYieldPending[ xCurCoreID ] = pdTRUE; xYieldPending[ xCurCoreID ] = pdTRUE;
} }
@ -3137,7 +3141,7 @@ BaseType_t xTaskCatchUpTicks( TickType_t xTicksToCatchUp )
/* Preemption is on, but a context switch should only be /* Preemption is on, but a context switch should only be
* performed if the unblocked task has a priority that is * performed if the unblocked task has a priority that is
* higher than the currently executing task. */ * higher than the currently executing task. */
if( taskIS_YIELD_REQUIRED( pxTCB, xCurCoreID, pdFALSE ) == pdTRUE ) if( taskIS_YIELD_REQUIRED( pxTCB, pdFALSE ) == pdTRUE )
{ {
/* Pend the yield to be performed when the scheduler /* Pend the yield to be performed when the scheduler
* is unsuspended. */ * is unsuspended. */
@ -3279,7 +3283,7 @@ BaseType_t xTaskIncrementTick( void )
* 0, we only need to context switch if the unblocked * 0, we only need to context switch if the unblocked
* task can run on core 0 and has a higher priority * task can run on core 0 and has a higher priority
* than the current task. */ * than the current task. */
if( ( taskIS_AFFINITY_COMPATIBLE( 0, pxTCB->xCoreID ) == pdTRUE ) && ( pxTCB->uxPriority > pxCurrentTCBs[ 0 ]->uxPriority ) ) if( ( taskIS_AFFINITY_COMPATIBLE( 0, pxTCB ) == pdTRUE ) && ( pxTCB->uxPriority > pxCurrentTCBs[ 0 ]->uxPriority ) )
{ {
xSwitchRequired = pdTRUE; xSwitchRequired = pdTRUE;
} }
@ -3542,7 +3546,7 @@ BaseType_t xTaskIncrementTick( void )
} }
/* Check if the current task has a compatible affinity */ /* Check if the current task has a compatible affinity */
if( taskIS_AFFINITY_COMPATIBLE( xCurCoreID, pxTCBCur->xCoreID ) == pdFALSE ) if( taskIS_AFFINITY_COMPATIBLE( xCurCoreID, pxTCBCur ) == pdFALSE )
{ {
goto get_next_task; goto get_next_task;
} }
@ -3858,7 +3862,7 @@ void vTaskPlaceOnUnorderedEventList( List_t * pxEventList,
listINSERT_END( &( xPendingReadyList[ uxPendCore ] ), &( pxUnblockedTCB->xEventListItem ) ); listINSERT_END( &( xPendingReadyList[ uxPendCore ] ), &( pxUnblockedTCB->xEventListItem ) );
} }
if( taskIS_YIELD_REQUIRED( pxUnblockedTCB, xCurCoreID, pdFALSE ) == pdTRUE ) if( taskIS_YIELD_REQUIRED( pxUnblockedTCB, pdFALSE ) == pdTRUE )
{ {
/* The unblocked task requires a the current core to yield */ /* The unblocked task requires a the current core to yield */
xReturn = pdTRUE; xReturn = pdTRUE;
@ -4043,7 +4047,7 @@ void vTaskRemoveFromUnorderedEventList( ListItem_t * pxEventListItem,
listREMOVE_ITEM( &( pxUnblockedTCB->xStateListItem ) ); listREMOVE_ITEM( &( pxUnblockedTCB->xStateListItem ) );
prvAddTaskToReadyList( pxUnblockedTCB ); prvAddTaskToReadyList( pxUnblockedTCB );
if( taskIS_YIELD_REQUIRED( pxUnblockedTCB, xCurCoreID, pdFALSE ) == pdTRUE ) if( taskIS_YIELD_REQUIRED( pxUnblockedTCB, pdFALSE ) == pdTRUE )
{ {
/* The unblocked task has a priority above that of the calling task, so /* The unblocked task has a priority above that of the calling task, so
* a context switch is required. This function is called with the * a context switch is required. This function is called with the
@ -5883,7 +5887,7 @@ TickType_t uxTaskResetEventItemValue( void )
} }
#endif #endif
if( taskIS_YIELD_REQUIRED( pxTCB, portGET_CORE_ID(), pdFALSE ) == pdTRUE ) if( taskIS_YIELD_REQUIRED( pxTCB, pdFALSE ) == pdTRUE )
{ {
/* The notified task has a priority above the currently /* The notified task has a priority above the currently
* executing task so a yield is required. */ * executing task so a yield is required. */
@ -6021,7 +6025,7 @@ TickType_t uxTaskResetEventItemValue( void )
listINSERT_END( &( xPendingReadyList[ xCurCoreID ] ), &( pxTCB->xEventListItem ) ); listINSERT_END( &( xPendingReadyList[ xCurCoreID ] ), &( pxTCB->xEventListItem ) );
} }
if( taskIS_YIELD_REQUIRED( pxTCB, xCurCoreID, pdFALSE ) == pdTRUE ) if( taskIS_YIELD_REQUIRED( pxTCB, pdFALSE ) == pdTRUE )
{ {
/* The notified task has a priority above the currently /* The notified task has a priority above the currently
* executing task so a yield is required. */ * executing task so a yield is required. */
@ -6115,7 +6119,7 @@ TickType_t uxTaskResetEventItemValue( void )
listINSERT_END( &( xPendingReadyList[ xCurCoreID ] ), &( pxTCB->xEventListItem ) ); listINSERT_END( &( xPendingReadyList[ xCurCoreID ] ), &( pxTCB->xEventListItem ) );
} }
if( taskIS_YIELD_REQUIRED( pxTCB, xCurCoreID, pdFALSE ) == pdTRUE ) if( taskIS_YIELD_REQUIRED( pxTCB, pdFALSE ) == pdTRUE )
{ {
/* The notified task has a priority above the currently /* The notified task has a priority above the currently
* executing task so a yield is required. */ * executing task so a yield is required. */