forked from espressif/esp-idf
fix(freertos): Fix vTaskRemoveFromUnorderedEventList()
This commit fixes and optimizes vTaskRemoveFromUnorderedEventList() in the following ways: - Fixed bug in single core builds where the unblocked task would be placed on xPendingReadyList. - If an ISR occurs while accessing xPendingReadyList, and the ISR also accesses the xPendingReadyList, xPendingReadyList would be corrupted. - In single core builds, this function is only called from event groups with the scheduler suspended. Thus the function should have exclusive access to pxReadyTasksLists instead of xPendingReadyList. - The function's single core logic has now been updated to match upstream behavior, by always placing the unblocked task on pxReadyTasksLists. - Optimized the function for single core builds by removing the taskCAN_BE_SCHEDULED() check. - In single core builds, given that the function is always called with the scheduler suspended - Thus, the taskCAN_BE_SCHEDULED (and the subsequent routine to place the unblocked task on the xPendingReadyList) is not necessary for single core builds. - The function now matches upstream behavior in single core builds. Closes https://github.com/espressif/esp-idf/issues/11883
This commit is contained in:
@@ -4077,15 +4077,6 @@ void vTaskRemoveFromUnorderedEventList( ListItem_t * pxEventListItem,
|
||||
configASSERT( pxUnblockedTCB );
|
||||
( void ) uxListRemove( pxEventListItem );
|
||||
|
||||
/* Add the task to the ready list if a core with compatible affinity
|
||||
* has NOT suspended its scheduler. This occurs when:
|
||||
* - The task is pinned, and the pinned core's scheduler is running
|
||||
* - The task is unpinned, and at least one of the core's scheduler is running */
|
||||
if( taskCAN_BE_SCHEDULED( pxUnblockedTCB ) )
|
||||
{
|
||||
( void ) uxListRemove( &( pxUnblockedTCB->xStateListItem ) );
|
||||
prvAddTaskToReadyList( pxUnblockedTCB );
|
||||
|
||||
#if ( configUSE_TICKLESS_IDLE != 0 )
|
||||
{
|
||||
/* If a task is blocked on a kernel object then xNextTaskUnblockTime
|
||||
@@ -4099,8 +4090,15 @@ void vTaskRemoveFromUnorderedEventList( ListItem_t * pxEventListItem,
|
||||
prvResetNextTaskUnblockTime();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
else
|
||||
|
||||
#if ( configNUM_CORES > 1 )
|
||||
|
||||
/* Add the task to the ready list if a core with compatible affinity
|
||||
* has NOT suspended its scheduler. This occurs when:
|
||||
* - The task is pinned, and the pinned core's scheduler is running
|
||||
* - The task is unpinned, and at least one of the core's scheduler is
|
||||
* running */
|
||||
if( !taskCAN_BE_SCHEDULED( pxUnblockedTCB ) )
|
||||
{
|
||||
/* We arrive here due to one of the following possibilities:
|
||||
* - The task is pinned to core X and core X has suspended its scheduler
|
||||
@@ -4108,18 +4106,26 @@ void vTaskRemoveFromUnorderedEventList( ListItem_t * pxEventListItem,
|
||||
* 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 */
|
||||
BaseType_t xPendingListCore = ( ( pxUnblockedTCB->xCoreID == tskNO_AFFINITY ) ? xCurCoreID : pxUnblockedTCB->xCoreID );
|
||||
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 ) );
|
||||
}
|
||||
else
|
||||
#else /* configNUM_CORES > 1 */
|
||||
|
||||
/* In single core, the caller of this function has already suspended the
|
||||
* scheduler, which means we have exclusive access to the ready list.
|
||||
* We add the unblocked task to the ready list directly. */
|
||||
#endif /* configNUM_CORES > 1 */
|
||||
{
|
||||
/* Remove the task from the delayed list and add it to the ready list. The
|
||||
* scheduler is suspended so interrupts will not be accessing the ready
|
||||
* lists. */
|
||||
( void ) uxListRemove( &( pxUnblockedTCB->xStateListItem ) );
|
||||
prvAddTaskToReadyList( pxUnblockedTCB );
|
||||
|
||||
if( prvCheckForYield( pxUnblockedTCB, xCurCoreID, pdFALSE ) )
|
||||
{
|
||||
@@ -4127,7 +4133,8 @@ void vTaskRemoveFromUnorderedEventList( ListItem_t * pxEventListItem,
|
||||
* a context switch is required. This function is called with the
|
||||
* scheduler suspended so xYieldPending is set so the context switch
|
||||
* occurs immediately that the scheduler is resumed (unsuspended). */
|
||||
xYieldPending[ xCurCoreID ] = pdTRUE;
|
||||
xYieldPending = pdTRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
Reference in New Issue
Block a user