forked from espressif/esp-idf
Merge branch 'bugfix/freertos_event_list_removal' into 'master'
FreeRTOS: Fix and optimize event list removal functions Closes IDFGH-10652 See merge request espressif/esp-idf!25157
This commit is contained in:
@@ -294,8 +294,8 @@
|
|||||||
*/
|
*/
|
||||||
#if ( configNUM_CORES > 1 )
|
#if ( configNUM_CORES > 1 )
|
||||||
#define taskCAN_BE_SCHEDULED( pxTCB ) \
|
#define taskCAN_BE_SCHEDULED( pxTCB ) \
|
||||||
( ( pxTCB->xCoreID != tskNO_AFFINITY ) ) ? ( uxSchedulerSuspended[ pxTCB->xCoreID ] == ( UBaseType_t ) 0U ) : \
|
( ( ( pxTCB->xCoreID != tskNO_AFFINITY ) ) ? ( uxSchedulerSuspended[ pxTCB->xCoreID ] == ( UBaseType_t ) 0U ) : \
|
||||||
( ( uxSchedulerSuspended[ 0 ] == ( UBaseType_t ) 0U ) || ( uxSchedulerSuspended[ 1 ] == ( UBaseType_t ) 0U ) )
|
( ( uxSchedulerSuspended[ 0 ] == ( UBaseType_t ) 0U ) || ( uxSchedulerSuspended[ 1 ] == ( UBaseType_t ) 0U ) ) )
|
||||||
#else
|
#else
|
||||||
#define taskCAN_BE_SCHEDULED( pxTCB ) ( ( uxSchedulerSuspended[ 0 ] == ( UBaseType_t ) 0U ) )
|
#define taskCAN_BE_SCHEDULED( pxTCB ) ( ( uxSchedulerSuspended[ 0 ] == ( UBaseType_t ) 0U ) )
|
||||||
#endif /* configNUM_CORES > 1 */
|
#endif /* configNUM_CORES > 1 */
|
||||||
@@ -3932,23 +3932,31 @@ BaseType_t xTaskRemoveFromEventList( const List_t * const pxEventList )
|
|||||||
}
|
}
|
||||||
#endif /* configNUM_CORES > 1 */
|
#endif /* configNUM_CORES > 1 */
|
||||||
{
|
{
|
||||||
|
/* The event list is sorted in priority order, so the first in the list can
|
||||||
|
* be removed as it is known to be the highest priority. Remove the TCB from
|
||||||
|
* the delayed list, and add it to the ready list. */
|
||||||
|
#if ( configNUM_CORES > 1 )
|
||||||
/* Before taking the kernel lock, another task/ISR could have already
|
/* Before taking the kernel lock, another task/ISR could have already
|
||||||
* emptied the pxEventList. So we insert a check here to see if
|
* emptied the pxEventList. So we insert a check here to see if
|
||||||
* pxEventList is empty before attempting to remove an item from it. */
|
* pxEventList is empty before attempting to remove an item from it. */
|
||||||
if( listLIST_IS_EMPTY( pxEventList ) == pdFALSE )
|
if( listLIST_IS_EMPTY( pxEventList ) == pdTRUE )
|
||||||
{
|
{
|
||||||
BaseType_t xCurCoreID = xPortGetCoreID();
|
/* The pxEventList was emptied before we entered the critical section,
|
||||||
|
* Nothing to do except return pdFALSE. */
|
||||||
/* The event list is sorted in priority order, so the first in the list can
|
xReturn = pdFALSE;
|
||||||
* be removed as it is known to be the highest priority. Remove the TCB from
|
}
|
||||||
* the delayed list, and add it to the ready list.
|
else
|
||||||
*
|
#else /* configNUM_CORES > 1 */
|
||||||
* If an event is for a queue that is locked then this function will never
|
/* If an event is for a queue that is locked then this function will never
|
||||||
* get called - the lock count on the queue will get modified instead. This
|
* get called - the lock count on the queue will get modified instead. This
|
||||||
* means exclusive access to the event list is guaranteed here.
|
* means exclusive access to the event list is guaranteed here.
|
||||||
*
|
*
|
||||||
* This function assumes that a check has already been made to ensure that
|
* This function assumes that a check has already been made to ensure that
|
||||||
* pxEventList is not empty. */
|
* pxEventList is not empty. */
|
||||||
|
#endif /* configNUM_CORES > 1 */
|
||||||
|
{
|
||||||
|
BaseType_t xCurCoreID = xPortGetCoreID();
|
||||||
|
|
||||||
pxUnblockedTCB = listGET_OWNER_OF_HEAD_ENTRY( pxEventList ); /*lint !e9079 void * is used as this macro is used with timers and co-routines too. Alignment is known to be fine as the type of the pointer stored and retrieved is the same. */
|
pxUnblockedTCB = listGET_OWNER_OF_HEAD_ENTRY( pxEventList ); /*lint !e9079 void * is used as this macro is used with timers and co-routines too. Alignment is known to be fine as the type of the pointer stored and retrieved is the same. */
|
||||||
configASSERT( pxUnblockedTCB );
|
configASSERT( pxUnblockedTCB );
|
||||||
( void ) uxListRemove( &( pxUnblockedTCB->xEventListItem ) );
|
( void ) uxListRemove( &( pxUnblockedTCB->xEventListItem ) );
|
||||||
@@ -4013,12 +4021,6 @@ BaseType_t xTaskRemoveFromEventList( const List_t * const pxEventList )
|
|||||||
xReturn = pdFALSE;
|
xReturn = pdFALSE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
/* The pxEventList was emptied before we entered the critical section,
|
|
||||||
* Nothing to do except return pdFALSE. */
|
|
||||||
xReturn = pdFALSE;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
#if ( configNUM_CORES > 1 )
|
#if ( configNUM_CORES > 1 )
|
||||||
/* Release the previously taken kernel lock. */
|
/* Release the previously taken kernel lock. */
|
||||||
@@ -4077,15 +4079,6 @@ void vTaskRemoveFromUnorderedEventList( ListItem_t * pxEventListItem,
|
|||||||
configASSERT( pxUnblockedTCB );
|
configASSERT( pxUnblockedTCB );
|
||||||
( void ) uxListRemove( pxEventListItem );
|
( 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 ( configUSE_TICKLESS_IDLE != 0 )
|
||||||
{
|
{
|
||||||
/* If a task is blocked on a kernel object then xNextTaskUnblockTime
|
/* If a task is blocked on a kernel object then xNextTaskUnblockTime
|
||||||
@@ -4099,8 +4092,15 @@ void vTaskRemoveFromUnorderedEventList( ListItem_t * pxEventListItem,
|
|||||||
prvResetNextTaskUnblockTime();
|
prvResetNextTaskUnblockTime();
|
||||||
}
|
}
|
||||||
#endif
|
#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:
|
/* 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 pinned to core X and core X has suspended its scheduler
|
||||||
@@ -4108,18 +4108,26 @@ void vTaskRemoveFromUnorderedEventList( ListItem_t * pxEventListItem,
|
|||||||
* Therefore, we add the task to one of the pending lists:
|
* 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 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 */
|
* - If the task is unpinned, add it to the current core's pending list */
|
||||||
BaseType_t xPendingListCore;
|
BaseType_t xPendingListCore = ( ( pxUnblockedTCB->xCoreID == tskNO_AFFINITY ) ? xCurCoreID : pxUnblockedTCB->xCoreID );
|
||||||
#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 );
|
configASSERT( uxSchedulerSuspended[ xPendingListCore ] != ( UBaseType_t ) 0U );
|
||||||
|
|
||||||
/* The delayed and ready lists cannot be accessed, so hold this task
|
/* The delayed and ready lists cannot be accessed, so hold this task
|
||||||
* pending until the scheduler is resumed. */
|
* pending until the scheduler is resumed. */
|
||||||
vListInsertEnd( &( xPendingReadyList[ xPendingListCore ] ), &( pxUnblockedTCB->xEventListItem ) );
|
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 ) )
|
if( prvCheckForYield( pxUnblockedTCB, xCurCoreID, pdFALSE ) )
|
||||||
{
|
{
|
||||||
@@ -4129,6 +4137,7 @@ void vTaskRemoveFromUnorderedEventList( ListItem_t * pxEventListItem,
|
|||||||
* occurs immediately that the scheduler is resumed (unsuspended). */
|
* occurs immediately that the scheduler is resumed (unsuspended). */
|
||||||
xYieldPending[ xCurCoreID ] = pdTRUE;
|
xYieldPending[ xCurCoreID ] = pdTRUE;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user