feat(freertos): Add SMP kernel changes to FreeRTOS v10.5.1

This commit adds the key kernel changes to the v10.5.1 kernel to support
dual-core SMP. These changes are temporarily documented in the `idf_changes.md`
document. This commit...

- Added changes to kernel data structures to support multiple cores
- Changes to scheduling algorithm support SMP scheduling.
- Changes to each FreeRTOS function to support multiple cores and SMP
scheduling algorithm.
This commit is contained in:
Darian Leung
2023-09-15 00:35:31 +08:00
parent ae80ad7ac7
commit db64e51e53
11 changed files with 1670 additions and 717 deletions

View File

@@ -405,48 +405,7 @@ _Static_assert( offsetof( StaticTask_t, pxDummy8 ) == offsetof( TCB_t, pxEndOfSt
/* ------------------------------------------------- Task Utilities ------------------------------------------------- */
#if ( INCLUDE_xTaskGetIdleTaskHandle == 1 )
TaskHandle_t xTaskGetIdleTaskHandleForCPU( BaseType_t xCoreID )
{
configASSERT( xCoreID >= 0 && xCoreID < configNUM_CORES );
configASSERT( ( xIdleTaskHandle[ xCoreID ] != NULL ) );
return ( TaskHandle_t ) xIdleTaskHandle[ xCoreID ];
}
#endif /* INCLUDE_xTaskGetIdleTaskHandle */
/*----------------------------------------------------------*/
#if ( ( INCLUDE_xTaskGetCurrentTaskHandle == 1 ) || ( configUSE_MUTEXES == 1 ) )
TaskHandle_t xTaskGetCurrentTaskHandleForCPU( BaseType_t xCoreID )
{
TaskHandle_t xReturn;
#if CONFIG_FREERTOS_SMP
{
xReturn = xTaskGetCurrentTaskHandleCPU( xCoreID );
}
#else /* CONFIG_FREERTOS_SMP */
{
if( xCoreID < configNUM_CORES )
{
xReturn = pxCurrentTCB[ xCoreID ];
}
else
{
xReturn = NULL;
}
}
#endif /* CONFIG_FREERTOS_SMP */
return xReturn;
}
#endif /* ( ( INCLUDE_xTaskGetCurrentTaskHandle == 1 ) || ( configUSE_MUTEXES == 1 ) ) */
/*----------------------------------------------------------*/
BaseType_t xTaskGetAffinity( TaskHandle_t xTask )
BaseType_t xTaskGetCoreID( TaskHandle_t xTask )
{
BaseType_t xReturn;
@@ -472,11 +431,10 @@ BaseType_t xTaskGetAffinity( TaskHandle_t xTask )
#else /* CONFIG_FREERTOS_SMP */
TCB_t * pxTCB;
/* Todo: Remove xCoreID for single core builds (IDF-7894) */
pxTCB = prvGetTCBFromHandle( xTask );
/* Simply read the xCoreID member of the TCB */
taskENTER_CRITICAL( &xKernelLock );
xReturn = pxTCB->xCoreID;
taskEXIT_CRITICAL_ISR( &xKernelLock );
#endif /* CONFIG_FREERTOS_SMP */
}
#else /* configNUM_CORES > 1 */
@@ -490,6 +448,140 @@ BaseType_t xTaskGetAffinity( TaskHandle_t xTask )
}
/*----------------------------------------------------------*/
#if ( INCLUDE_xTaskGetIdleTaskHandle == 1 )
TaskHandle_t xTaskGetIdleTaskHandleForCore( BaseType_t xCoreID )
{
#if CONFIG_FREERTOS_USE_KERNEL_10_5_1
{
/* If xTaskGetIdleTaskHandle() is called before the scheduler has been
* started, then xIdleTaskHandle will be NULL. */
configASSERT( ( xCoreID < configNUMBER_OF_CORES ) && ( xCoreID != tskNO_AFFINITY ) );
configASSERT( ( xIdleTaskHandle[ xCoreID ] != NULL ) );
return xIdleTaskHandle[ xCoreID ];
}
#else /* CONFIG_FREERTOS_USE_KERNEL_10_5_1 */
{
configASSERT( xCoreID >= 0 && xCoreID < configNUM_CORES );
configASSERT( ( xIdleTaskHandle[ xCoreID ] != NULL ) );
return ( TaskHandle_t ) xIdleTaskHandle[ xCoreID ];
}
#endif /* CONFIG_FREERTOS_USE_KERNEL_10_5_1 */
}
#endif /* INCLUDE_xTaskGetIdleTaskHandle */
/*----------------------------------------------------------*/
#if ( ( INCLUDE_xTaskGetCurrentTaskHandle == 1 ) || ( configUSE_MUTEXES == 1 ) )
TaskHandle_t xTaskGetCurrentTaskHandleForCore( BaseType_t xCoreID )
{
TaskHandle_t xReturn;
#if CONFIG_FREERTOS_USE_KERNEL_10_5_1
{
configASSERT( xCoreID < configNUMBER_OF_CORES );
configASSERT( xCoreID != tskNO_AFFINITY );
/* 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 this is not called from an interrupt and the current
* TCB will always be the same for any individual execution thread. */
taskENTER_CRITICAL_SMP_ONLY();
{
xReturn = pxCurrentTCBs[ xCoreID ];
}
/* Release the previously taken kernel lock. */
taskEXIT_CRITICAL_SMP_ONLY();
}
#else /* CONFIG_FREERTOS_USE_KERNEL_10_5_1 */
{
#if CONFIG_FREERTOS_SMP
{
xReturn = xTaskGetCurrentTaskHandleCPU( xCoreID );
}
#else /* CONFIG_FREERTOS_SMP */
{
if( xCoreID < configNUM_CORES )
{
xReturn = pxCurrentTCB[ xCoreID ];
}
else
{
xReturn = NULL;
}
}
#endif /* CONFIG_FREERTOS_SMP */
}
#endif /* CONFIG_FREERTOS_USE_KERNEL_10_5_1 */
return xReturn;
}
#endif /* ( ( INCLUDE_xTaskGetCurrentTaskHandle == 1 ) || ( configUSE_MUTEXES == 1 ) ) */
/*----------------------------------------------------------*/
#if ( CONFIG_FREERTOS_USE_KERNEL_10_5_1 && ( configGENERATE_RUN_TIME_STATS == 1 ) && ( INCLUDE_xTaskGetIdleTaskHandle == 1 ) )
configRUN_TIME_COUNTER_TYPE ulTaskGetIdleRunTimeCounterForCore( BaseType_t xCoreID )
{
uint32_t ulRunTimeCounter;
configASSERT( xCoreID < configNUMBER_OF_CORES );
configASSERT( xCoreID != tskNO_AFFINITY );
/* For SMP, we need to take the kernel lock here as we are about to
* access kernel data structures. */
taskENTER_CRITICAL_SMP_ONLY();
{
ulRunTimeCounter = xIdleTaskHandle[ xCoreID ]->ulRunTimeCounter;
}
/* Release the previously taken kernel lock. */
taskEXIT_CRITICAL_SMP_ONLY();
return ulRunTimeCounter;
}
#endif /* ( CONFIG_FREERTOS_USE_KERNEL_10_5_1 && ( configGENERATE_RUN_TIME_STATS == 1 ) && ( INCLUDE_xTaskGetIdleTaskHandle == 1 ) ) */
/*----------------------------------------------------------*/
#if ( CONFIG_FREERTOS_USE_KERNEL_10_5_1 && ( configGENERATE_RUN_TIME_STATS == 1 ) && ( INCLUDE_xTaskGetIdleTaskHandle == 1 ) )
configRUN_TIME_COUNTER_TYPE ulTaskGetIdleRunTimePercentForCore( BaseType_t xCoreID )
{
configRUN_TIME_COUNTER_TYPE ulTotalTime, ulReturn;
configASSERT( xCoreID < configNUMBER_OF_CORES );
configASSERT( xCoreID != tskNO_AFFINITY );
ulTotalTime = portGET_RUN_TIME_COUNTER_VALUE();
/* For percentage calculations. */
ulTotalTime /= ( configRUN_TIME_COUNTER_TYPE ) 100;
/* Avoid divide by zero errors. */
if( ulTotalTime > ( configRUN_TIME_COUNTER_TYPE ) 0 )
{
/* For SMP, we need to take the kernel lock here as we are about
* to access kernel data structures. */
taskENTER_CRITICAL_SMP_ONLY();
{
ulReturn = xIdleTaskHandle[ xCoreID ]->ulRunTimeCounter / ulTotalTime;
}
/* Release the previously taken kernel lock. */
taskEXIT_CRITICAL_SMP_ONLY();
}
else
{
ulReturn = 0;
}
return ulReturn;
}
#endif /* ( CONFIG_FREERTOS_USE_KERNEL_10_5_1 && ( configGENERATE_RUN_TIME_STATS == 1 ) && ( INCLUDE_xTaskGetIdleTaskHandle == 1 ) ) */
/*-----------------------------------------------------------*/
uint8_t * pxTaskGetStackStart( TaskHandle_t xTask )
{
TCB_t * pxTCB;

View File

@@ -31,6 +31,7 @@
#endif
/* *INDENT-ON* */
/* -------------------------------------------------- Task Creation ------------------------------------------------- */
#if ( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
@@ -108,6 +109,35 @@
/* ------------------------------------------------- Task Utilities ------------------------------------------------- */
/**
* @brief Get the current core ID of a particular task
*
* Helper function to get the core ID of a particular task. If the task is
* pinned to a particular core, the core ID is returned. If the task is not
* pinned to a particular core, tskNO_AFFINITY is returned.
*
* If CONFIG_FREERTOS_UNICORE is enabled, this function simply returns 0.
*
* [refactor-todo] See if this needs to be deprecated (IDF-8145)(IDF-8164)
*
* @note If CONFIG_FREERTOS_SMP is enabled, please call vTaskCoreAffinityGet()
* instead.
* @note In IDF FreerTOS when configNUMBER_OF_CORES == 1, this function will
* always return 0,
* @param xTask The task to query
* @return The task's core ID or tskNO_AFFINITY
*/
BaseType_t xTaskGetCoreID( TaskHandle_t xTask );
/** @cond */
/* Todo: Deprecate this API in favor of xTaskGetIdleTaskHandleForCore (IDF-8163) */
static inline __attribute__( ( always_inline ) )
BaseType_t xTaskGetAffinity( TaskHandle_t xTask )
{
return xTaskGetCoreID( xTask );
}
/** @endcond */
/**
* @brief Get the handle of idle task for the given core.
*
@@ -118,7 +148,16 @@
* @param xCoreID The core to query
* @return Handle of the idle task for the queried core
*/
TaskHandle_t xTaskGetIdleTaskHandleForCPU( BaseType_t xCoreID );
TaskHandle_t xTaskGetIdleTaskHandleForCore( BaseType_t xCoreID );
/** @cond */
/* Todo: Deprecate this API in favor of xTaskGetIdleTaskHandleForCore (IDF-8163) */
static inline __attribute__( ( always_inline ) )
TaskHandle_t xTaskGetIdleTaskHandleForCPU( BaseType_t xCoreID )
{
return xTaskGetIdleTaskHandleForCore( xCoreID );
}
/** @endcond */
/**
* @brief Get the handle of the task currently running on a certain core
@@ -134,25 +173,42 @@ TaskHandle_t xTaskGetIdleTaskHandleForCPU( BaseType_t xCoreID );
* @param xCoreID The core to query
* @return Handle of the current task running on the queried core
*/
TaskHandle_t xTaskGetCurrentTaskHandleForCPU( BaseType_t xCoreID );
TaskHandle_t xTaskGetCurrentTaskHandleForCore( BaseType_t xCoreID );
/** @cond */
/* Todo: Deprecate this API in favor of xTaskGetCurrentTaskHandleForCore (IDF-8163) */
static inline __attribute__( ( always_inline ) )
TaskHandle_t xTaskGetCurrentTaskHandleForCPU( BaseType_t xCoreID )
{
return xTaskGetCurrentTaskHandleForCore( xCoreID );
}
/** @endcond */
#if CONFIG_FREERTOS_USE_KERNEL_10_5_1
/**
* @brief Get the current core affinity of a particular task
* @brief Get the total execution of a particular core's idle task
*
* Helper function to get the core affinity of a particular task. If the task is
* pinned to a particular core, the core ID is returned. If the task is not
* pinned to a particular core, tskNO_AFFINITY is returned.
* This function is equivalent to ulTaskGetIdleRunTimeCounter() but queries the
* idle task of a particular core.
*
* If CONFIG_FREERTOS_UNICORE is enabled, this function simply returns 0.
*
* [refactor-todo] See if this needs to be deprecated (IDF-8145)(IDF-8164)
*
* @note If CONFIG_FREERTOS_SMP is enabled, please call vTaskCoreAffinityGet()
* instead.
* @param xTask The task to query
* @return The tasks coreID or tskNO_AFFINITY
* @param xCoreID Core ID of the idle task to query
* @return The total run time of the idle task
*/
BaseType_t xTaskGetAffinity( TaskHandle_t xTask );
configRUN_TIME_COUNTER_TYPE ulTaskGetIdleRunTimeCounterForCore( BaseType_t xCoreID );
/**
* @brief Get the percentage run time of a particular core's idle task
*
* This function is equivalent to ulTaskGetIdleRunTimePercent() but queries the
* idle task of a particular core.
*
* @param xCoreID Core ID of the idle task to query
* @return The percentage run time of the idle task
*/
configRUN_TIME_COUNTER_TYPE ulTaskGetIdleRunTimePercentForCore( BaseType_t xCoreID );
#endif /* CONFIG_FREERTOS_USE_KERNEL_10_5_1 */
/**
* Returns the start of the stack associated with xTask.