mirror of
https://github.com/espressif/esp-idf.git
synced 2025-08-06 06:04:33 +02:00
freertos: Synchronize tasks.c functions (major changes) to v10.4.3
This commit synchronizes multiple functions that contain major differences with upstream v10.4.3. Multi-core modifications are then reapplied to the function. Vanilla code uses "pxTCB == pxCurrentTCB" to check whether a task is currently running. This commit adds the following macros instead. - taskIS_CURRENTLY_RUNNING() - taskIS_CURRENTLY_RUNNING_ON_CORE() The following functions have been updated to use those macros instead. - eTaskGetState() - vTaskPrioritySet() - vTaskResume() The following functions have been synchronized with upstream v10.4.3. Multi-core modifications are then reapplied. - vTaskSuspend() - vTaskDelete() - prvGetExpectedIdleTime()
This commit is contained in:
@@ -259,6 +259,15 @@ extern void esp_vApplicationIdleHook(void);
|
|||||||
#define taskCAN_RUN_ON_CORE( xCore, xCoreID ) ( pdTRUE )
|
#define taskCAN_RUN_ON_CORE( xCore, xCoreID ) ( pdTRUE )
|
||||||
#endif /* configNUM_CORES > 1 */
|
#endif /* configNUM_CORES > 1 */
|
||||||
|
|
||||||
|
/* Check if a task is a currently running task. */
|
||||||
|
#if ( configNUM_CORES > 1 )
|
||||||
|
#define taskIS_CURRENTLY_RUNNING( pxTCB ) ( ( ( pxTCB ) == pxCurrentTCB[ 0 ] ) || ( ( pxTCB ) == pxCurrentTCB[ 1 ] ) )
|
||||||
|
#define taskIS_CURRENTLY_RUNNING_ON_CORE( pxTCB, xCoreID ) ( ( pxTCB ) == pxCurrentTCB[ ( xCoreID ) ] )
|
||||||
|
#else
|
||||||
|
#define taskIS_CURRENTLY_RUNNING( pxTCB ) ( ( pxTCB ) == pxCurrentTCB[ 0 ] )
|
||||||
|
#define taskIS_CURRENTLY_RUNNING_ON_CORE( pxTCB, xCoreID ) taskIS_CURRENTLY_RUNNING( ( pxTCB ) )
|
||||||
|
#endif /* configNUM_CORES > 1 */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Several functions take a TaskHandle_t parameter that can optionally be NULL,
|
* Several functions take a TaskHandle_t parameter that can optionally be NULL,
|
||||||
* where NULL is used to indicate that the handle of the currently executing
|
* where NULL is used to indicate that the handle of the currently executing
|
||||||
@@ -1363,14 +1372,17 @@ static void prvAddNewTaskToReadyList( TCB_t * pxNewTCB )
|
|||||||
void vTaskDelete( TaskHandle_t xTaskToDelete )
|
void vTaskDelete( TaskHandle_t xTaskToDelete )
|
||||||
{
|
{
|
||||||
TCB_t * pxTCB;
|
TCB_t * pxTCB;
|
||||||
TCB_t * curTCB;
|
BaseType_t xFreeNow;
|
||||||
BaseType_t core;
|
|
||||||
BaseType_t xFreeNow = 0;
|
|
||||||
|
|
||||||
taskENTER_CRITICAL( &xKernelLock );
|
taskENTER_CRITICAL( &xKernelLock );
|
||||||
{
|
{
|
||||||
core = xPortGetCoreID();
|
BaseType_t xCurCoreID;
|
||||||
curTCB = pxCurrentTCB[core];
|
#if ( configNUM_CORES > 1 )
|
||||||
|
xCurCoreID = xPortGetCoreID();
|
||||||
|
#else
|
||||||
|
xCurCoreID = 0;
|
||||||
|
( void ) xCurCoreID;
|
||||||
|
#endif
|
||||||
|
|
||||||
/* If null is passed in here then it is the calling task that is
|
/* If null is passed in here then it is the calling task that is
|
||||||
* being deleted. */
|
* being deleted. */
|
||||||
@@ -1402,12 +1414,19 @@ static void prvAddNewTaskToReadyList( TCB_t * pxNewTCB )
|
|||||||
* not return. */
|
* not return. */
|
||||||
uxTaskNumber++;
|
uxTaskNumber++;
|
||||||
|
|
||||||
if( pxTCB == curTCB ||
|
/*
|
||||||
/* in SMP, we also can't immediately delete the task active on the other core */
|
* We cannot immediately a task that is
|
||||||
(configNUM_CORES > 1 && pxTCB == pxCurrentTCB[ !core ]) ||
|
* - Currently running on either core
|
||||||
/* ... and we can't delete a non-running task pinned to the other core, as
|
* - If the task is not currently running but is pinned to the other (due to FPU cleanup)
|
||||||
FPU cleanup has to happen on the same core */
|
* Todo: Allow deletion of tasks pinned to other core (IDF-5803)
|
||||||
(configNUM_CORES > 1 && pxTCB->xCoreID == (!core)) )
|
*/
|
||||||
|
#if ( configNUM_CORES > 1 )
|
||||||
|
xFreeNow = ( taskIS_CURRENTLY_RUNNING( pxTCB ) || ( pxTCB->xCoreID == !xCurCoreID ) ) ? pdFALSE : pdTRUE;
|
||||||
|
#else
|
||||||
|
xFreeNow = ( taskIS_CURRENTLY_RUNNING( pxTCB ) ) ? pdFALSE : pdTRUE;
|
||||||
|
#endif /* configNUM_CORES > 1 */
|
||||||
|
|
||||||
|
if( xFreeNow == pdFALSE )
|
||||||
{
|
{
|
||||||
/* A task is deleting itself. This cannot complete within the
|
/* A task is deleting itself. This cannot complete within the
|
||||||
* task itself, as a context switch to another task is required.
|
* task itself, as a context switch to another task is required.
|
||||||
@@ -1421,43 +1440,47 @@ static void prvAddNewTaskToReadyList( TCB_t * pxNewTCB )
|
|||||||
* check the xTasksWaitingTermination list. */
|
* check the xTasksWaitingTermination list. */
|
||||||
++uxDeletedTasksWaitingCleanUp;
|
++uxDeletedTasksWaitingCleanUp;
|
||||||
|
|
||||||
|
/* Call the delete hook before portPRE_TASK_DELETE_HOOK() as
|
||||||
|
* portPRE_TASK_DELETE_HOOK() does not return in the Win32 port. */
|
||||||
|
traceTASK_DELETE( pxTCB );
|
||||||
|
|
||||||
/* The pre-delete hook is primarily for the Windows simulator,
|
/* The pre-delete hook is primarily for the Windows simulator,
|
||||||
* in which Windows specific clean up operations are performed,
|
* in which Windows specific clean up operations are performed,
|
||||||
* after which it is not possible to yield away from this task -
|
* after which it is not possible to yield away from this task -
|
||||||
* hence xYieldPending is used to latch that a context switch is
|
* hence xYieldPending is used to latch that a context switch is
|
||||||
* required. */
|
* required. */
|
||||||
portPRE_TASK_DELETE_HOOK( pxTCB, &xYieldPending[core] );
|
portPRE_TASK_DELETE_HOOK( pxTCB, &xYieldPending[ xCurCoreID ] );
|
||||||
|
|
||||||
if (configNUM_CORES > 1 && pxTCB == pxCurrentTCB[ !core ])
|
#if ( configNUM_CORES > 1 )
|
||||||
{
|
if( taskIS_CURRENTLY_RUNNING_ON_CORE( pxTCB, !xCurCoreID ) )
|
||||||
/* SMP case of deleting a task running on a different core. Same issue
|
{
|
||||||
as a task deleting itself, but we need to send a yield to this task now
|
/* SMP case of deleting a task running on a different core. Same issue
|
||||||
before we release xKernelLock.
|
as a task deleting itself, but we need to send a yield to this task now
|
||||||
|
before we release xKernelLock.
|
||||||
|
|
||||||
Specifically there is a case where the other core may already be spinning on
|
Specifically there is a case where the other core may already be spinning on
|
||||||
xKernelLock waiting to go into a blocked state. A check is added in
|
xKernelLock waiting to go into a blocked state. A check is added in
|
||||||
prvAddCurrentTaskToDelayedList() to prevent it from removing itself from
|
prvAddCurrentTaskToDelayedList() to prevent it from removing itself from
|
||||||
xTasksWaitingTermination list in this case (instead it will immediately
|
xTasksWaitingTermination list in this case (instead it will immediately
|
||||||
release xKernelLock again and be yielded before the FreeRTOS function
|
release xKernelLock again and be yielded before the FreeRTOS function
|
||||||
returns.) */
|
returns.) */
|
||||||
vPortYieldOtherCore( !core );
|
vPortYieldOtherCore( !xCurCoreID );
|
||||||
}
|
}
|
||||||
|
#endif /* configNUM_CORES > 1 */
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
--uxCurrentNumberOfTasks;
|
--uxCurrentNumberOfTasks;
|
||||||
xFreeNow = pdTRUE;
|
traceTASK_DELETE( pxTCB );
|
||||||
|
|
||||||
/* Reset the next expected unblock time in case it referred to
|
/* Reset the next expected unblock time in case it referred to
|
||||||
* the task that has just been deleted. */
|
* the task that has just been deleted. */
|
||||||
prvResetNextTaskUnblockTime();
|
prvResetNextTaskUnblockTime();
|
||||||
}
|
}
|
||||||
|
|
||||||
traceTASK_DELETE( pxTCB );
|
|
||||||
}
|
}
|
||||||
taskEXIT_CRITICAL( &xKernelLock );
|
taskEXIT_CRITICAL( &xKernelLock );
|
||||||
|
|
||||||
if(xFreeNow == pdTRUE) {
|
if( xFreeNow == pdTRUE ) {
|
||||||
#if ( configNUM_THREAD_LOCAL_STORAGE_POINTERS > 0 ) && ( configTHREAD_LOCAL_STORAGE_DELETE_CALLBACKS )
|
#if ( configNUM_THREAD_LOCAL_STORAGE_POINTERS > 0 ) && ( configTHREAD_LOCAL_STORAGE_DELETE_CALLBACKS )
|
||||||
prvDeleteTLS( pxTCB );
|
prvDeleteTLS( pxTCB );
|
||||||
#endif
|
#endif
|
||||||
@@ -1469,7 +1492,8 @@ static void prvAddNewTaskToReadyList( TCB_t * pxNewTCB )
|
|||||||
* been deleted. */
|
* been deleted. */
|
||||||
if( xSchedulerRunning != pdFALSE )
|
if( xSchedulerRunning != pdFALSE )
|
||||||
{
|
{
|
||||||
if( pxTCB == curTCB )
|
taskENTER_CRITICAL( &xKernelLock );
|
||||||
|
if( taskIS_CURRENTLY_RUNNING_ON_CORE( pxTCB, xPortGetCoreID() ) )
|
||||||
{
|
{
|
||||||
configASSERT( xTaskGetSchedulerState() != taskSCHEDULER_SUSPENDED );
|
configASSERT( xTaskGetSchedulerState() != taskSCHEDULER_SUSPENDED );
|
||||||
portYIELD_WITHIN_API();
|
portYIELD_WITHIN_API();
|
||||||
@@ -1478,6 +1502,7 @@ static void prvAddNewTaskToReadyList( TCB_t * pxNewTCB )
|
|||||||
{
|
{
|
||||||
mtCOVERAGE_TEST_MARKER();
|
mtCOVERAGE_TEST_MARKER();
|
||||||
}
|
}
|
||||||
|
taskEXIT_CRITICAL( &xKernelLock );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1649,18 +1674,11 @@ static void prvAddNewTaskToReadyList( TCB_t * pxNewTCB )
|
|||||||
configASSERT( pxTCB );
|
configASSERT( pxTCB );
|
||||||
|
|
||||||
taskENTER_CRITICAL( &xKernelLock ); //Need critical section incase either core context switches in between
|
taskENTER_CRITICAL( &xKernelLock ); //Need critical section incase either core context switches in between
|
||||||
if( pxTCB == pxCurrentTCB[xPortGetCoreID()])
|
if( taskIS_CURRENTLY_RUNNING( pxTCB ) )
|
||||||
{
|
{
|
||||||
/* The task calling this function is querying its own state. */
|
/* The task calling this function is querying its own state. */
|
||||||
eReturn = eRunning;
|
eReturn = eRunning;
|
||||||
}
|
}
|
||||||
#if (configNUM_CORES > 1)
|
|
||||||
else if (pxTCB == pxCurrentTCB[!xPortGetCoreID()])
|
|
||||||
{
|
|
||||||
/* The task calling this function is querying its own state. */
|
|
||||||
eReturn = eRunning;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
pxStateList = listLIST_ITEM_CONTAINER( &( pxTCB->xStateListItem ) );
|
pxStateList = listLIST_ITEM_CONTAINER( &( pxTCB->xStateListItem ) );
|
||||||
@@ -1847,7 +1865,7 @@ static void prvAddNewTaskToReadyList( TCB_t * pxNewTCB )
|
|||||||
* priority than the calling task. */
|
* priority than the calling task. */
|
||||||
if( uxNewPriority > uxCurrentBasePriority )
|
if( uxNewPriority > uxCurrentBasePriority )
|
||||||
{
|
{
|
||||||
if( pxTCB != pxCurrentTCB[ xPortGetCoreID() ] )
|
if( !taskIS_CURRENTLY_RUNNING( pxTCB ) )
|
||||||
{
|
{
|
||||||
/* 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
|
||||||
@@ -1868,13 +1886,22 @@ static void prvAddNewTaskToReadyList( TCB_t * pxNewTCB )
|
|||||||
* priority task able to run so no yield is required. */
|
* priority task able to run so no yield is required. */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if( pxTCB == pxCurrentTCB[ xPortGetCoreID() ] )
|
else if( taskIS_CURRENTLY_RUNNING_ON_CORE( pxTCB, 0 ) )
|
||||||
{
|
{
|
||||||
/* Setting the priority of the running task down means
|
/* Setting the priority of the running task down means
|
||||||
* there may now be another task of higher priority that
|
* there may now be another task of higher priority that
|
||||||
* is ready to execute. */
|
* is ready to execute. */
|
||||||
xYieldRequired = pdTRUE;
|
xYieldRequired = pdTRUE;
|
||||||
}
|
}
|
||||||
|
#if ( configNUM_CORES > 1 )
|
||||||
|
else if( taskIS_CURRENTLY_RUNNING_ON_CORE( pxTCB, 1 ) )
|
||||||
|
{
|
||||||
|
/* Setting the priority of the running task on the other
|
||||||
|
* core down means there may now be another task of
|
||||||
|
* higher priority that is ready to execute. */
|
||||||
|
vPortYieldOtherCore( 1 );
|
||||||
|
}
|
||||||
|
#endif /* configNUM_CORES > 1 */
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* Setting the priority of any other task down does not
|
/* Setting the priority of any other task down does not
|
||||||
@@ -1973,7 +2000,6 @@ static void prvAddNewTaskToReadyList( TCB_t * pxNewTCB )
|
|||||||
void vTaskSuspend( TaskHandle_t xTaskToSuspend )
|
void vTaskSuspend( TaskHandle_t xTaskToSuspend )
|
||||||
{
|
{
|
||||||
TCB_t * pxTCB;
|
TCB_t * pxTCB;
|
||||||
TCB_t * curTCB;
|
|
||||||
|
|
||||||
taskENTER_CRITICAL( &xKernelLock );
|
taskENTER_CRITICAL( &xKernelLock );
|
||||||
{
|
{
|
||||||
@@ -2005,7 +2031,6 @@ static void prvAddNewTaskToReadyList( TCB_t * pxNewTCB )
|
|||||||
}
|
}
|
||||||
|
|
||||||
vListInsertEnd( &xSuspendedTaskList, &( pxTCB->xStateListItem ) );
|
vListInsertEnd( &xSuspendedTaskList, &( pxTCB->xStateListItem ) );
|
||||||
curTCB = pxCurrentTCB[ xPortGetCoreID() ];
|
|
||||||
|
|
||||||
#if ( configUSE_TASK_NOTIFICATIONS == 1 )
|
#if ( configUSE_TASK_NOTIFICATIONS == 1 )
|
||||||
{
|
{
|
||||||
@@ -2022,76 +2047,70 @@ static void prvAddNewTaskToReadyList( TCB_t * pxNewTCB )
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif /* if ( configUSE_TASK_NOTIFICATIONS == 1 ) */
|
#endif /* if ( configUSE_TASK_NOTIFICATIONS == 1 ) */
|
||||||
}
|
|
||||||
taskEXIT_CRITICAL( &xKernelLock );
|
|
||||||
|
|
||||||
if( xSchedulerRunning != pdFALSE )
|
|
||||||
{
|
|
||||||
/* Reset the next expected unblock time in case it referred to the
|
|
||||||
* task that is now in the Suspended state. */
|
|
||||||
taskENTER_CRITICAL( &xKernelLock );
|
|
||||||
{
|
|
||||||
prvResetNextTaskUnblockTime();
|
|
||||||
}
|
|
||||||
taskEXIT_CRITICAL( &xKernelLock );
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
mtCOVERAGE_TEST_MARKER();
|
|
||||||
}
|
|
||||||
|
|
||||||
if( pxTCB == curTCB )
|
|
||||||
{
|
|
||||||
if( xSchedulerRunning != pdFALSE )
|
if( xSchedulerRunning != pdFALSE )
|
||||||
{
|
{
|
||||||
/* The current task has just been suspended. */
|
/* Reset the next expected unblock time in case it referred to the
|
||||||
taskENTER_CRITICAL( &xKernelLock );
|
|
||||||
BaseType_t suspended = uxSchedulerSuspended[xPortGetCoreID()];
|
|
||||||
taskEXIT_CRITICAL( &xKernelLock );
|
|
||||||
|
|
||||||
configASSERT( suspended == 0 );
|
|
||||||
(void)suspended;
|
|
||||||
portYIELD_WITHIN_API();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* The scheduler is not running, but the task that was pointed
|
|
||||||
* to by pxCurrentTCB has just been suspended and pxCurrentTCB
|
|
||||||
* must be adjusted to point to a different task. */
|
|
||||||
if( listCURRENT_LIST_LENGTH( &xSuspendedTaskList ) == uxCurrentNumberOfTasks ) /*lint !e931 Right has no side effect, just volatile. */
|
|
||||||
{
|
|
||||||
/* No other tasks are ready, so set pxCurrentTCB back to
|
|
||||||
* NULL so when the next task is created pxCurrentTCB will
|
|
||||||
* be set to point to it no matter what its relative priority
|
|
||||||
* is. */
|
|
||||||
taskENTER_CRITICAL( &xKernelLock );
|
|
||||||
pxCurrentTCB[ xPortGetCoreID() ] = NULL;
|
|
||||||
taskEXIT_CRITICAL( &xKernelLock );
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
vTaskSwitchContext();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if( xSchedulerRunning != pdFALSE )
|
|
||||||
{
|
|
||||||
/* A task other than the currently running task was suspended,
|
|
||||||
* reset the next expected unblock time in case it referred to the
|
|
||||||
* task that is now in the Suspended state. */
|
* task that is now in the Suspended state. */
|
||||||
taskENTER_CRITICAL( &xKernelLock );
|
prvResetNextTaskUnblockTime();
|
||||||
{
|
|
||||||
prvResetNextTaskUnblockTime();
|
|
||||||
}
|
|
||||||
taskEXIT_CRITICAL( &xKernelLock );
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
mtCOVERAGE_TEST_MARKER();
|
mtCOVERAGE_TEST_MARKER();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if( taskIS_CURRENTLY_RUNNING_ON_CORE( pxTCB, xPortGetCoreID() ) )
|
||||||
|
{
|
||||||
|
if( xSchedulerRunning != pdFALSE )
|
||||||
|
{
|
||||||
|
/* The current task has just been suspended. */
|
||||||
|
configASSERT( uxSchedulerSuspended[ xPortGetCoreID() ] == 0 );
|
||||||
|
portYIELD_WITHIN_API();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* The scheduler is not running, but the task that was pointed
|
||||||
|
* to by pxCurrentTCB has just been suspended and pxCurrentTCB
|
||||||
|
* must be adjusted to point to a different task. */
|
||||||
|
if( listCURRENT_LIST_LENGTH( &xSuspendedTaskList ) == uxCurrentNumberOfTasks ) /*lint !e931 Right has no side effect, just volatile. */
|
||||||
|
{
|
||||||
|
/* No other tasks are ready, so set pxCurrentTCB back to
|
||||||
|
* NULL so when the next task is created pxCurrentTCB will
|
||||||
|
* be set to point to it no matter what its relative priority
|
||||||
|
* is. */
|
||||||
|
pxCurrentTCB[ xPortGetCoreID() ] = NULL;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
vTaskSwitchContext();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#if ( configNUM_CORES > 1 )
|
||||||
|
else if( taskIS_CURRENTLY_RUNNING_ON_CORE( pxTCB, !xPortGetCoreID() ) )
|
||||||
|
{
|
||||||
|
/* The other core's current task has just been suspended */
|
||||||
|
if( xSchedulerRunning != pdFALSE )
|
||||||
|
{
|
||||||
|
vPortYieldOtherCore( !xPortGetCoreID() );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* The scheduler is not running, but the task that was pointed
|
||||||
|
* to by pxCurrentTCB[ otherCore ] has just been suspended.
|
||||||
|
* We simply set the pxCurrentTCB[ otherCore ] to NULL for now.
|
||||||
|
* Todo: Update vTaskSwitchContext() to be runnable on
|
||||||
|
* behalf of the other core. */
|
||||||
|
pxCurrentTCB[ !xPortGetCoreID() ] = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif /* configNUM_CORES > 1 */
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mtCOVERAGE_TEST_MARKER();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
taskEXIT_CRITICAL( &xKernelLock );
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* INCLUDE_vTaskSuspend */
|
#endif /* INCLUDE_vTaskSuspend */
|
||||||
@@ -2157,7 +2176,7 @@ static void prvAddNewTaskToReadyList( TCB_t * pxNewTCB )
|
|||||||
{
|
{
|
||||||
/* The parameter cannot be NULL as it is impossible to resume the
|
/* The parameter cannot be NULL as it is impossible to resume the
|
||||||
* currently executing task. */
|
* currently executing task. */
|
||||||
if( ( pxTCB != pxCurrentTCB[xPortGetCoreID()] ) && ( pxTCB != NULL ) )
|
if( !taskIS_CURRENTLY_RUNNING( pxTCB ) && ( pxTCB != NULL ) )
|
||||||
{
|
{
|
||||||
if( prvTaskIsTaskSuspended( pxTCB ) != pdFALSE )
|
if( prvTaskIsTaskSuspended( pxTCB ) != pdFALSE )
|
||||||
{
|
{
|
||||||
@@ -2457,47 +2476,45 @@ void vTaskSuspendAll( void )
|
|||||||
|
|
||||||
#if ( configUSE_TICKLESS_IDLE != 0 )
|
#if ( configUSE_TICKLESS_IDLE != 0 )
|
||||||
|
|
||||||
#if ( configNUM_CORES > 1 )
|
|
||||||
|
|
||||||
static BaseType_t xHaveReadyTasks( void )
|
|
||||||
{
|
|
||||||
for (int i = tskIDLE_PRIORITY + 1; i < configMAX_PRIORITIES; ++i)
|
|
||||||
{
|
|
||||||
if( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ i ] ) ) > 0 )
|
|
||||||
{
|
|
||||||
return pdTRUE;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
mtCOVERAGE_TEST_MARKER();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return pdFALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // configNUM_CORES > 1
|
|
||||||
|
|
||||||
static TickType_t prvGetExpectedIdleTime( void )
|
static TickType_t prvGetExpectedIdleTime( void )
|
||||||
{
|
{
|
||||||
TickType_t xReturn;
|
TickType_t xReturn;
|
||||||
|
UBaseType_t uxHigherPriorityReadyTasks = pdFALSE;
|
||||||
|
|
||||||
|
/* We need a critical section here as we are about to access kernel data structures */
|
||||||
taskENTER_CRITICAL( &xKernelLock );
|
taskENTER_CRITICAL( &xKernelLock );
|
||||||
|
|
||||||
|
/* uxHigherPriorityReadyTasks takes care of the case where
|
||||||
|
* configUSE_PREEMPTION is 0, so there may be tasks above the idle priority
|
||||||
|
* task that are in the Ready state, even though the idle task is
|
||||||
|
* running. */
|
||||||
|
#if ( configUSE_PORT_OPTIMISED_TASK_SELECTION == 0 )
|
||||||
|
{
|
||||||
|
if( uxTopReadyPriority > tskIDLE_PRIORITY )
|
||||||
|
{
|
||||||
|
uxHigherPriorityReadyTasks = pdTRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
{
|
||||||
|
const UBaseType_t uxLeastSignificantBit = ( UBaseType_t ) 0x01;
|
||||||
|
|
||||||
|
/* When port optimised task selection is used the uxTopReadyPriority
|
||||||
|
* variable is used as a bit map. If bits other than the least
|
||||||
|
* significant bit are set then there are tasks that have a priority
|
||||||
|
* above the idle priority that are in the Ready state. This takes
|
||||||
|
* care of the case where the co-operative scheduler is in use. */
|
||||||
|
if( uxTopReadyPriority > uxLeastSignificantBit )
|
||||||
|
{
|
||||||
|
uxHigherPriorityReadyTasks = pdTRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif /* if ( configUSE_PORT_OPTIMISED_TASK_SELECTION == 0 ) */
|
||||||
|
|
||||||
if( pxCurrentTCB[ xPortGetCoreID() ]->uxPriority > tskIDLE_PRIORITY )
|
if( pxCurrentTCB[ xPortGetCoreID() ]->uxPriority > tskIDLE_PRIORITY )
|
||||||
{
|
{
|
||||||
xReturn = 0;
|
xReturn = 0;
|
||||||
}
|
}
|
||||||
#if configNUM_CORES > 1
|
|
||||||
/* This function is called from Idle task; in single core case this
|
|
||||||
* means that no higher priority tasks are ready to run, and we can
|
|
||||||
* enter sleep. In SMP case, there might be ready tasks waiting for
|
|
||||||
* the other CPU, so need to check all ready lists.
|
|
||||||
*/
|
|
||||||
else if( xHaveReadyTasks() )
|
|
||||||
{
|
|
||||||
xReturn = 0;
|
|
||||||
}
|
|
||||||
#endif // configNUM_CORES > 1
|
|
||||||
else if( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ tskIDLE_PRIORITY ] ) ) > configNUM_CORES )
|
else if( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ tskIDLE_PRIORITY ] ) ) > configNUM_CORES )
|
||||||
{
|
{
|
||||||
/* There are other idle priority tasks in the ready state. If
|
/* There are other idle priority tasks in the ready state. If
|
||||||
@@ -2505,10 +2522,18 @@ void vTaskSuspendAll( void )
|
|||||||
* processed. */
|
* processed. */
|
||||||
xReturn = 0;
|
xReturn = 0;
|
||||||
}
|
}
|
||||||
|
else if( uxHigherPriorityReadyTasks != pdFALSE )
|
||||||
|
{
|
||||||
|
/* There are tasks in the Ready state that have a priority above the
|
||||||
|
* idle priority. This path can only be reached if
|
||||||
|
* configUSE_PREEMPTION is 0. */
|
||||||
|
xReturn = 0;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
xReturn = xNextTaskUnblockTime - xTickCount;
|
xReturn = xNextTaskUnblockTime - xTickCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
taskEXIT_CRITICAL( &xKernelLock );
|
taskEXIT_CRITICAL( &xKernelLock );
|
||||||
|
|
||||||
return xReturn;
|
return xReturn;
|
||||||
|
Reference in New Issue
Block a user