From abe5311a22b53174097eae317510a70d3e79bba4 Mon Sep 17 00:00:00 2001 From: Sudeep Mohanty Date: Wed, 5 Apr 2023 14:54:31 +0200 Subject: [PATCH] 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. --- components/freertos/FreeRTOS-Kernel/tasks.c | 60 ++++++++++++++------- 1 file changed, 42 insertions(+), 18 deletions(-) diff --git a/components/freertos/FreeRTOS-Kernel/tasks.c b/components/freertos/FreeRTOS-Kernel/tasks.c index 5478fef96b..274fb6a553 100644 --- a/components/freertos/FreeRTOS-Kernel/tasks.c +++ b/components/freertos/FreeRTOS-Kernel/tasks.c @@ -4064,25 +4064,49 @@ void vTaskRemoveFromUnorderedEventList( ListItem_t * pxEventListItem, configASSERT( pxUnblockedTCB ); ( void ) uxListRemove( pxEventListItem ); - #if ( configUSE_TICKLESS_IDLE != 0 ) - { - /* If a task is blocked on a kernel object then xNextTaskUnblockTime - * might be set to the blocked task's time out time. If the task is - * 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 + /* 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 ); - /* 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 ( configUSE_TICKLESS_IDLE != 0 ) + { + /* If a task is blocked on a kernel object then xNextTaskUnblockTime + * might be set to the blocked task's time out time. If the task is + * 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 ) ) {