diff --git a/.github/lexicon.txt b/.github/lexicon.txt index cd16258f3..04b3d5d76 100644 --- a/.github/lexicon.txt +++ b/.github/lexicon.txt @@ -2400,7 +2400,8 @@ uxbitstoset uxbitstowait uxbitstowaitfor uxcontrolbits -uxcoreexclude +uxcoreaffinitymask +uxcoreaffinityinheritancemask uxcriticalnesting uxcurrenteventbits uxcurrentnumberoftasks diff --git a/include/FreeRTOS.h b/include/FreeRTOS.h index b51940b92..9eefd0d8a 100644 --- a/include/FreeRTOS.h +++ b/include/FreeRTOS.h @@ -240,8 +240,8 @@ #define configUSE_TASK_PREEMPTION_DISABLE 0 #endif -#ifndef configUSE_CORE_EXCLUSION - #define configUSE_CORE_EXCLUSION 0 +#ifndef configUSE_CORE_AFFINITY + #define configUSE_CORE_AFFINITY 0 #endif #ifndef configUSE_ALTERNATIVE_API @@ -948,7 +948,7 @@ #error configUSE_MUTEXES must be set to 1 to use recursive mutexes #endif -#if( ( configRUN_MULTIPLE_PRIORITIES == 0 ) && ( configUSE_CORE_EXCLUSION != 0 ) ) +#if( ( configRUN_MULTIPLE_PRIORITIES == 0 ) && ( configUSE_CORE_AFFINITY != 0 ) ) #error configRUN_MULTIPLE_PRIORITIES must be set to 1 to use core exclusion #endif @@ -1209,7 +1209,7 @@ typedef struct xSTATIC_TCB #if ( configUSE_TASK_PREEMPTION_DISABLE == 1 ) BaseType_t xDummy24; #endif - #if ( configUSE_CORE_EXCLUSION == 1 ) + #if ( configUSE_CORE_AFFINITY == 1 && configNUM_CORES > 1 ) UBaseType_t uxDummy25; #endif #if ( ( portSTACK_GROWTH > 0 ) || ( configRECORD_STACK_HIGH_ADDRESS == 1 ) ) diff --git a/include/task.h b/include/task.h index 87085b2c8..16339cc2a 100644 --- a/include/task.h +++ b/include/task.h @@ -170,6 +170,14 @@ typedef enum */ #define tskIDLE_PRIORITY ( ( UBaseType_t ) 0U ) +/** + * Defines affinity to all available cores. + * + */ +#define tskNO_AFFINITY ( ( UBaseType_t ) -1U ) + + + /** * task. h * @@ -1235,8 +1243,10 @@ void vTaskResume( TaskHandle_t xTaskToResume ) PRIVILEGED_FUNCTION; */ BaseType_t xTaskResumeFromISR( TaskHandle_t xTaskToResume ) PRIVILEGED_FUNCTION; -void vTaskCoreExclusionSet( const TaskHandle_t xTask, UBaseType_t uxCoreExclude ); -UBaseType_t vTaskCoreExclusionGet( const TaskHandle_t xTask ); +#if ( configUSE_CORE_AFFINITY == 1) +void vTaskCoreAffinitySet( const TaskHandle_t xTask, UBaseType_t uxCoreAffinityMask ); +UBaseType_t vTaskCoreAffinityGet( const TaskHandle_t xTask ); +#endif void vTaskPreemptionDisable( const TaskHandle_t xTask ); void vTaskPreemptionEnable( const TaskHandle_t xTask ); diff --git a/tasks.c b/tasks.c index 13e2535d0..dee586634 100644 --- a/tasks.c +++ b/tasks.c @@ -254,8 +254,8 @@ typedef struct tskTaskControlBlock /* The old naming convention is used to BaseType_t xPreemptionDisable; /*< Used to prevent the task from being preempted */ #endif - #if ( configUSE_CORE_EXCLUSION == 1 ) - UBaseType_t uxCoreExclude; /*< Used to exclude the task from certain cores */ + #if ( configUSE_CORE_AFFINITY == 1 && configNUM_CORES > 1 ) + UBaseType_t uxCoreAffinityMask; /*< Used to link the task to certain cores. UBaseType_t must have >= the same number of bits as SMP confNUM_CORES */ #endif #if ( ( portSTACK_GROWTH > 0 ) || ( configRECORD_STACK_HIGH_ADDRESS == 1 ) ) @@ -289,7 +289,6 @@ typedef struct tskTaskControlBlock /* The old naming convention is used to #endif #if ( configUSE_NEWLIB_REENTRANT == 1 ) - /* Allocate a Newlib reent structure that is specific to this task. * Note Newlib support has been included by popular demand, but is not * used by the FreeRTOS maintainers themselves. FreeRTOS is not @@ -760,8 +759,10 @@ static void prvYieldForTask( TCB_t * pxTCB, { if( xTaskPriority <= xLowestPriority ) { - #if ( configUSE_CORE_EXCLUSION == 1 ) - if( ( pxTCB->uxCoreExclude & ( 1 << x ) ) == 0 ) + #if ( configNUM_CORES > 1 ) + #if ( configUSE_CORE_AFFINITY == 1 ) + if( ( pxTCB->uxCoreAffinityMask & ( 1 << x ) ) != 0 ) + #endif #endif { #if ( configUSE_TASK_PREEMPTION_DISABLE == 1 ) @@ -824,7 +825,7 @@ static void prvYieldForTask( TCB_t * pxTCB, BaseType_t xTaskScheduled = pdFALSE; BaseType_t xDecrementTopPriority = pdTRUE; - #if ( configUSE_CORE_EXCLUSION == 1 ) + #if ( configUSE_CORE_AFFINITY == 1 ) TCB_t * pxPreviousTCB = NULL; #endif #if ( ( configRUN_MULTIPLE_PRIORITIES == 0 ) && ( configNUM_CORES > 1 ) ) @@ -892,13 +893,15 @@ static void prvYieldForTask( TCB_t * pxTCB, if( pxTCB->xTaskRunState == taskTASK_NOT_RUNNING ) { - #if ( configUSE_CORE_EXCLUSION == 1 ) - if( ( pxTCB->uxCoreExclude & ( 1 << xCoreID ) ) == 0 ) + #if ( configNUM_CORES > 1 ) + #if ( configUSE_CORE_AFFINITY == 1 ) + if( ( pxTCB->uxCoreAffinityMask & ( 1 << xCoreID ) ) != 0 ) + #endif #endif { /* If the task is not being executed by any core swap it in */ pxCurrentTCBs[ xCoreID ]->xTaskRunState = taskTASK_NOT_RUNNING; - #if ( configUSE_CORE_EXCLUSION == 1 ) + #if ( configUSE_CORE_AFFINITY == 1 ) pxPreviousTCB = pxCurrentTCBs[ xCoreID ]; #endif pxTCB->xTaskRunState = ( TaskRunning_t ) xCoreID; @@ -909,8 +912,10 @@ static void prvYieldForTask( TCB_t * pxTCB, else if( pxTCB == pxCurrentTCBs[ xCoreID ] ) { configASSERT( ( pxTCB->xTaskRunState == xCoreID ) || ( pxTCB->xTaskRunState == taskTASK_YIELDING ) ); - #if ( configUSE_CORE_EXCLUSION == 1 ) - if( ( pxTCB->uxCoreExclude & ( 1 << xCoreID ) ) == 0 ) + #if ( configNUM_CORES > 1 ) + #if ( configUSE_CORE_AFFINITY == 1 ) + if( ( pxTCB->uxCoreAffinityMask & ( 1 << xCoreID ) ) != 0 ) + #endif #endif { /* The task is already running on this core, mark it as scheduled */ @@ -974,12 +979,13 @@ static void prvYieldForTask( TCB_t * pxTCB, } #endif /* if ( ( configRUN_MULTIPLE_PRIORITIES == 0 ) && ( configNUM_CORES > 1 ) ) */ - #if ( configUSE_CORE_EXCLUSION == 1 ) + #if ( configNUM_CORES > 1 ) + #if ( configUSE_CORE_AFFINITY == 1 ) if( ( pxPreviousTCB != NULL ) && ( listIS_CONTAINED_WITHIN( &( pxReadyTasksLists[ pxPreviousTCB->uxPriority ] ), &( pxPreviousTCB->xStateListItem ) ) != pdFALSE ) ) { - /* A ready task was just bumped off this core. Look at the cores it is not excluded + /* A ready task was just bumped off this core. Look at the cores it can run from * from to see if it is able to run on any of them */ - UBaseType_t uxCoreMap = ~( pxPreviousTCB->uxCoreExclude ); + UBaseType_t uxCoreMap = pxPreviousTCB->uxCoreAffinityMask; BaseType_t xLowestPriority = pxPreviousTCB->uxPriority - pxPreviousTCB->xIsIdle; BaseType_t xLowestPriorityCore = -1; @@ -990,12 +996,12 @@ static void prvYieldForTask( TCB_t * pxTCB, * on with the cores that the new task is excluded from. It is possible that the * new task was only placed onto this core because it is excluded from another. * Check to see if the previous task could run on one of those cores. */ - uxCoreMap &= pxCurrentTCBs[ xCoreID ]->uxCoreExclude; + uxCoreMap &= ~( pxCurrentTCBs[ xCoreID ]->uxCoreAffinityMask ); } else { /* The ready task that was removed from this core is excluded from it. - * See if we can schedule it on any of the cores where it is not excluded from. */ + * @todo See if we can schedule it on any of the cores where it is not excluded from. */ } uxCoreMap &= ( ( 1 << configNUM_CORES ) - 1 ); @@ -1027,7 +1033,8 @@ static void prvYieldForTask( TCB_t * pxTCB, prvYieldCore( xLowestPriorityCore ); } } - #endif /* if ( configUSE_CORE_EXCLUSION == 1 ) */ + #endif /* if ( configUSE_CORE_AFFINITY == 1 ) */ + #endif /* if ( configNUM_CORES > 1 ) */ return pdTRUE; } @@ -1047,8 +1054,6 @@ static void prvYieldForTask( TCB_t * pxTCB, #endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */ /*-----------------------------------------------------------*/ - - #if ( configSUPPORT_STATIC_ALLOCATION == 1 ) TaskHandle_t xTaskCreateStatic( TaskFunction_t pxTaskCode, @@ -1481,10 +1486,12 @@ static void prvInitialiseNewTask( TaskFunction_t pxTaskCode, } #endif - #if ( configUSE_CORE_EXCLUSION == 1 ) + #if ( configNUM_CORES > 1 ) + #if ( configUSE_CORE_AFFINITY == 1 ) { - pxNewTCB->uxCoreExclude = 0; + pxNewTCB->uxCoreAffinityMask = tskNO_AFFINITY; } + #endif #endif #if ( configUSE_TASK_PREEMPTION_DISABLE == 1 ) { @@ -1552,8 +1559,9 @@ static void prvInitialiseNewTask( TaskFunction_t pxTaskCode, { pxNewTCB->xIsIdle = pdTRUE; } - #if(configNUM_CORES > 1) - else if(pxTaskCode == prvMinimalIdleTask) + + #if ( configNUM_CORES > 1 ) + else if( pxTaskCode == prvMinimalIdleTask ) { pxNewTCB->xIsIdle = pdTRUE; } @@ -1608,11 +1616,6 @@ static void prvAddNewTaskToReadyList( TCB_t * pxNewTCB ) if( pxCurrentTCBs[ xCoreID ] == NULL ) { pxNewTCB->xTaskRunState = xCoreID; - #if ( configUSE_CORE_EXCLUSION == 1 ) - { - pxNewTCB->uxCoreExclude = ~( 1 << xCoreID ); - } - #endif pxCurrentTCBs[ xCoreID ] = pxNewTCB; break; } @@ -1702,7 +1705,6 @@ static void prvAddNewTaskToReadyList( TCB_t * pxNewTCB ) * no longer running. */ if( xTaskRunningOnCore != taskTASK_NOT_RUNNING ) { - /* A running task is being deleted. This cannot complete within the * task itself, as a context switch to another task is required. * Place the task in the termination list. The idle task will @@ -1744,7 +1746,6 @@ static void prvAddNewTaskToReadyList( TCB_t * pxNewTCB ) xCoreID = portGET_CORE_ID(); - if( xTaskRunningOnCore == xCoreID ) { configASSERT( uxSchedulerSuspended == 0 ); @@ -1948,7 +1949,7 @@ static void prvAddNewTaskToReadyList( TCB_t * pxNewTCB ) } } } - #else /* if ( configUSE_TASK_NOTIFICATIONS == 1 ) */ + #else /* if ( configUSE_TASK_NOTIFICATIONS == 1 ) */ { eReturn = eSuspended; } @@ -2220,10 +2221,11 @@ static void prvAddNewTaskToReadyList( TCB_t * pxNewTCB ) #endif /* INCLUDE_vTaskPrioritySet */ /*-----------------------------------------------------------*/ -#if ( configUSE_CORE_EXCLUSION == 1 ) +#if ( configNUM_CORES > 1 ) + #if ( configUSE_CORE_AFFINITY == 1 ) - void vTaskCoreExclusionSet( const TaskHandle_t xTask, - UBaseType_t uxCoreExclude ) + void vTaskCoreAffinitySet( const TaskHandle_t xTask, + UBaseType_t uxCoreAffinityMask ) { TCB_t * pxTCB; BaseType_t xCoreID; @@ -2232,7 +2234,7 @@ static void prvAddNewTaskToReadyList( TCB_t * pxNewTCB ) { pxTCB = prvGetTCBFromHandle( xTask ); - pxTCB->uxCoreExclude = uxCoreExclude; + pxTCB->uxCoreAffinityMask = uxCoreAffinityMask; if( xSchedulerRunning != pdFALSE ) { @@ -2240,7 +2242,7 @@ static void prvAddNewTaskToReadyList( TCB_t * pxNewTCB ) { xCoreID = ( BaseType_t ) pxTCB->xTaskRunState; - if( ( uxCoreExclude & ( 1 << xCoreID ) ) != 0 ) + if( ( uxCoreAffinityMask & ( 1 << xCoreID ) ) != 0 ) { prvYieldCore( xCoreID ); } @@ -2250,27 +2252,31 @@ static void prvAddNewTaskToReadyList( TCB_t * pxNewTCB ) taskEXIT_CRITICAL(); } -#endif /* configUSE_CORE_EXCLUSION */ + #endif /* configUSE_CORE_AFFINITY */ +#endif /* if ( configNUM_CORES > 1 ) */ /*-----------------------------------------------------------*/ -#if ( configUSE_CORE_EXCLUSION == 1 ) +#if ( configNUM_CORES > 1 ) + #if ( configUSE_CORE_AFFINITY == 1 ) - UBaseType_t vTaskCoreExclusionGet( const TaskHandle_t xTask ) + UBaseType_t vTaskCoreAffinityGet( const TaskHandle_t xTask ) { TCB_t * pxTCB; - UBaseType_t uxCoreExclude; + UBaseType_t uxCoreAffinityMask; taskENTER_CRITICAL(); { pxTCB = prvGetTCBFromHandle( xTask ); - uxCoreExclude = pxTCB->uxCoreExclude; + uxCoreAffinityMask = pxTCB->uxCoreAffinityMask; } taskEXIT_CRITICAL(); - return uxCoreExclude; + return uxCoreAffinityMask; } -#endif /* configUSE_CORE_EXCLUSION */ + #endif /* configUSE_CORE_AFFINITY */ +#endif /* if ( configNUM_CORES > 1 ) */ + /*-----------------------------------------------------------*/ #if ( configUSE_TASK_PREEMPTION_DISABLE == 1 ) @@ -2451,8 +2457,7 @@ static void prvAddNewTaskToReadyList( TCB_t * pxNewTCB ) BaseType_t xReturn = pdFALSE; const TCB_t * const pxTCB = xTask; - /* Accesses xPendingReadyList so must be called from a critical - * section. */ + /* Accesses xPendingReadyList so must be called from a critical section. */ /* It does not make sense to check if the calling task is suspended. */ configASSERT( xTask ); @@ -2673,7 +2678,7 @@ static BaseType_t prvCreateIdleTasks( void ) #if ( configSUPPORT_STATIC_ALLOCATION == 1 ) { - if(xCoreID == 0) + if( xCoreID == 0 ) { StaticTask_t * pxIdleTaskTCBBuffer = NULL; StackType_t * pxIdleTaskStackBuffer = NULL; @@ -2690,21 +2695,22 @@ static BaseType_t prvCreateIdleTasks( void ) pxIdleTaskStackBuffer, pxIdleTaskTCBBuffer ); /*lint !e961 MISRA exception, justified as it is not a redundant explicit cast to all supported compilers. */ } - #if( configNUM_CORES > 1) + #if ( configNUM_CORES > 1 ) else { - static StaticTask_t xIdleTCBBuffers[configNUM_CORES-1]; - static StackType_t xIdleTaskStackBuffers[configMINIMAL_STACK_SIZE][configNUM_CORES-1]; + static StaticTask_t xIdleTCBBuffers[ configNUM_CORES - 1 ]; + static StackType_t xIdleTaskStackBuffers[ configNUM_CORES - 1 ][ configMINIMAL_STACK_SIZE ]; xIdleTaskHandle[ xCoreID ] = xTaskCreateStatic( prvMinimalIdleTask, cIdleName, configMINIMAL_STACK_SIZE, - ( void * ) NULL, /*lint !e961. The cast is not redundant for all compilers. */ - portPRIVILEGE_BIT, /* In effect ( tskIDLE_PRIORITY | portPRIVILEGE_BIT ), but tskIDLE_PRIORITY is zero. */ - xIdleTaskStackBuffers[xCoreID-1], - &xIdleTCBBuffers[xCoreID-1] ); /*lint !e961 MISRA exception, justified as it is not a redundant explicit cast to all supported compilers. */ + ( void * ) NULL, /*lint !e961. The cast is not redundant for all compilers. */ + portPRIVILEGE_BIT, /* In effect ( tskIDLE_PRIORITY | portPRIVILEGE_BIT ), but tskIDLE_PRIORITY is zero. */ + xIdleTaskStackBuffers[ xCoreID - 1 ], + &xIdleTCBBuffers[ xCoreID - 1 ] ); /*lint !e961 MISRA exception, justified as it is not a redundant explicit cast to all supported compilers. */ } - #endif + #endif /* if ( configNUM_CORES > 1 ) */ + if( xIdleTaskHandle[ xCoreID ] != NULL ) { xReturn = pdPASS; @@ -2714,9 +2720,9 @@ static BaseType_t prvCreateIdleTasks( void ) xReturn = pdFAIL; } } - #else /* if ( configSUPPORT_STATIC_ALLOCATION == 1 ) */ + #else /* if ( configSUPPORT_STATIC_ALLOCATION == 1 ) */ { - if(xCoreID == 0) + if( xCoreID == 0 ) { /* The Idle task is being created using dynamically allocated RAM. */ xReturn = xTaskCreate( prvIdleTask, @@ -2726,7 +2732,8 @@ static BaseType_t prvCreateIdleTasks( void ) portPRIVILEGE_BIT, /* In effect ( tskIDLE_PRIORITY | portPRIVILEGE_BIT ), but tskIDLE_PRIORITY is zero. */ &xIdleTaskHandle[ xCoreID ] ); /*lint !e961 MISRA exception, justified as it is not a redundant explicit cast to all supported compilers. */ } - #if( configNUM_CORES > 1 ) + + #if ( configNUM_CORES > 1 ) else { xReturn = xTaskCreate( prvMinimalIdleTask, @@ -4210,10 +4217,12 @@ void vTaskMissedYield( void ) * * @todo additional conditional compiles to remove this function. */ -#if (configNUM_CORES > 1) + +#if ( configNUM_CORES > 1 ) static portTASK_FUNCTION( prvMinimalIdleTask, pvParameters ) { - for(;;) + taskYIELD(); + for( ; ; ) { #if ( configUSE_PREEMPTION == 0 ) { @@ -4249,7 +4258,8 @@ static portTASK_FUNCTION( prvMinimalIdleTask, pvParameters ) #endif /* ( ( configUSE_PREEMPTION == 1 ) && ( configIDLE_SHOULD_YIELD == 1 ) ) */ } } -#endif +#endif /* if ( configNUM_CORES > 1 ) */ + /* * ----------------------------------------------------------- * The Idle task.