freertos: Updated vTaskRemoveFromUnorderedEventList() to consider scheduler state before adding task to ready list

vTaskRemoveFromUnorderedEventList() runs under the assumption that the
scheduler is suspended during the call. However, for IDF FreeRTOS, this
is not true. When dual-core system is active, this API call is made in
a critical section but without suspending the scheduler. This commit
updates the vTaskRemoveFromUnorderedEventList() function to now consider
the scheduler state on either cores before adding a task to the ready list.
This commit is contained in:
Sudeep Mohanty
2023-04-05 14:54:31 +02:00
parent 66c999fcf8
commit abe5311a22

View File

@@ -4064,25 +4064,49 @@ void vTaskRemoveFromUnorderedEventList( ListItem_t * pxEventListItem,
configASSERT( pxUnblockedTCB ); configASSERT( pxUnblockedTCB );
( void ) uxListRemove( pxEventListItem ); ( void ) uxListRemove( pxEventListItem );
#if ( configUSE_TICKLESS_IDLE != 0 ) /* Add the task to the ready list if a core with compatible affinity
{ * has NOT suspended its scheduler. This occurs when:
/* If a task is blocked on a kernel object then xNextTaskUnblockTime * - The task is pinned, and the pinned core's scheduler is running
* might be set to the blocked task's time out time. If the task is * - The task is unpinned, and at least one of the core's scheduler is running */
* unblocked for a reason other than a timeout xNextTaskUnblockTime is if( taskCAN_BE_SCHEDULED( pxUnblockedTCB ) )
* normally left unchanged, because it is automatically reset to a new {
* value when the tick count equals xNextTaskUnblockTime. However if ( void ) uxListRemove( &( pxUnblockedTCB->xStateListItem ) );
* tickless idling is used it might be more important to enter sleep mode prvAddTaskToReadyList( pxUnblockedTCB );
* at the earliest possible time - so reset xNextTaskUnblockTime here to
* ensure it is updated at the earliest possible time. */
prvResetNextTaskUnblockTime();
}
#endif
/* Remove the task from the delayed list and add it to the ready list. The #if ( configUSE_TICKLESS_IDLE != 0 )
* scheduler is suspended so interrupts will not be accessing the ready {
* lists. */ /* If a task is blocked on a kernel object then xNextTaskUnblockTime
( void ) uxListRemove( &( pxUnblockedTCB->xStateListItem ) ); * might be set to the blocked task's time out time. If the task is
prvAddTaskToReadyList( pxUnblockedTCB ); * unblocked for a reason other than a timeout xNextTaskUnblockTime is
* normally left unchanged, because it is automatically reset to a new
* value when the tick count equals xNextTaskUnblockTime. However if
* tickless idling is used it might be more important to enter sleep mode
* at the earliest possible time - so reset xNextTaskUnblockTime here to
* ensure it is updated at the earliest possible time. */
prvResetNextTaskUnblockTime();
}
#endif
}
else
{
/* We arrive here due to one of the following possibilities:
* - The task is pinned to core X and core X has suspended its scheduler
* - The task is unpinned and both cores have suspend their schedulers
* Therefore, we add the task to one of the pending lists:
* - If the task is pinned to core X, add it to core X's pending list
* - If the task is unpinned, add it to the current core's pending list */
BaseType_t xPendingListCore;
#if ( configNUM_CORES > 1 )
xPendingListCore = ( ( pxUnblockedTCB->xCoreID == tskNO_AFFINITY ) ? xCurCoreID : pxUnblockedTCB->xCoreID );
#else
xPendingListCore = 0;
#endif /* configNUM_CORES > 1 */
configASSERT( uxSchedulerSuspended[ xPendingListCore ] != ( UBaseType_t ) 0U );
/* The delayed and ready lists cannot be accessed, so hold this task
* pending until the scheduler is resumed. */
vListInsertEnd( &( xPendingReadyList[ xPendingListCore ] ), &( pxUnblockedTCB->xEventListItem ) );
}
if( prvCheckForYield( pxUnblockedTCB, xCurCoreID, pdFALSE ) ) if( prvCheckForYield( pxUnblockedTCB, xCurCoreID, pdFALSE ) )
{ {