feat(freertos-smp): Added xTaskRemoveFromEventListFromISR()

This commit is contained in:
Sudeep Mohanty 2025-08-21 13:02:53 +02:00
parent 592177f42e
commit fbd37a219e
4 changed files with 200 additions and 119 deletions

View file

@ -2146,10 +2146,18 @@
#define traceENTER_xTaskRemoveFromEventList( pxEventList )
#endif
#ifndef traceENTER_xTaskRemoveFromEventListFromISR
#define traceENTER_xTaskRemoveFromEventListFromISR( pxEventList )
#endif
#ifndef traceRETURN_xTaskRemoveFromEventList
#define traceRETURN_xTaskRemoveFromEventList( xReturn )
#endif
#ifndef traceRETURN_xTaskRemoveFromEventListFromISR
#define traceRETURN_xTaskRemoveFromEventListFromISR( xReturn )
#endif
#ifndef traceENTER_vTaskRemoveFromUnorderedEventList
#define traceENTER_vTaskRemoveFromUnorderedEventList( pxEventListItem, xItemValue )
#endif

View file

@ -3720,6 +3720,8 @@ void vTaskPlaceOnEventListRestricted( List_t * const pxEventList,
* Removes a task from both the specified event list and the list of blocked
* tasks, and places it on a ready queue.
*
* Do not call this function from an ISR context. Call xTaskRemoveFromEventListFromISR() instead.
*
* xTaskRemoveFromEventList()/vTaskRemoveFromUnorderedEventList() will be called
* if either an event occurs to unblock a task, or the block timeout period
* expires.
@ -3736,6 +3738,23 @@ void vTaskPlaceOnEventListRestricted( List_t * const pxEventList,
* making the call, otherwise pdFALSE.
*/
BaseType_t xTaskRemoveFromEventList( const List_t * const pxEventList ) PRIVILEGED_FUNCTION;
/*
* THIS FUNCTION MUST NOT BE USED FROM APPLICATION CODE. IT IS ONLY
* INTENDED FOR USE WHEN IMPLEMENTING A PORT OF THE SCHEDULER AND IS
* AN INTERFACE WHICH IS FOR THE EXCLUSIVE USE OF THE SCHEDULER.
*
* THIS FUNCTION MUST BE CALLED WITH INTERRUPTS DISABLED.
*
* Removes a task from both the specified event list and the list of blocked
* tasks, and places it on a ready queue. This function is the ISR-safe version
* of xTaskRemoveFromEventList().
*
* @return pdTRUE if the task being removed has a higher priority than the task
* making the call, otherwise pdFALSE.
*/
BaseType_t xTaskRemoveFromEventListFromISR( const List_t * const pxEventList ) PRIVILEGED_FUNCTION;
void vTaskRemoveFromUnorderedEventList( ListItem_t * pxEventListItem,
const TickType_t xItemValue ) PRIVILEGED_FUNCTION;

55
queue.c
View file

@ -222,7 +222,20 @@ static void prvCopyDataFromQueue( Queue_t * const pxQueue,
* the queue set that the queue contains data.
*/
static BaseType_t prvNotifyQueueSetContainer( const Queue_t * const pxQueue ) PRIVILEGED_FUNCTION;
#endif
/*
* A version of prvNotifyQueueSetContainer() that can be called from an
* interrupt service routine (ISR).
*/
static BaseType_t prvNotifyQueueSetContainerFromISR( const Queue_t * const pxQueue ) PRIVILEGED_FUNCTION;
/*
* This function serves as a generic implementation for prvNotifyQueueSetContainer()
* and prvNotifyQueueSetContainerFromISR().
*/
static BaseType_t prvNotifyQueueSetContainerGeneric( const Queue_t * const pxQueue,
const BaseType_t xIsISR ) PRIVILEGED_FUNCTION;
#endif /* if ( configUSE_QUEUE_SETS == 1 ) */
/*
* Called after a Queue_t structure has been allocated either statically or
@ -1294,7 +1307,7 @@ BaseType_t xQueueGenericSendFromISR( QueueHandle_t xQueue,
* in the queue has not changed. */
mtCOVERAGE_TEST_MARKER();
}
else if( prvNotifyQueueSetContainer( pxQueue ) != pdFALSE )
else if( prvNotifyQueueSetContainerFromISR( pxQueue ) != pdFALSE )
{
/* The queue is a member of a queue set, and posting
* to the queue set caused a higher priority task to
@ -1317,7 +1330,7 @@ BaseType_t xQueueGenericSendFromISR( QueueHandle_t xQueue,
{
if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE )
{
if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE )
if( xTaskRemoveFromEventListFromISR( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE )
{
/* The task waiting has a higher priority so
* record that a context switch is required. */
@ -1345,7 +1358,7 @@ BaseType_t xQueueGenericSendFromISR( QueueHandle_t xQueue,
{
if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE )
{
if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE )
if( xTaskRemoveFromEventListFromISR( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE )
{
/* The task waiting has a higher priority so record that a
* context switch is required. */
@ -1468,7 +1481,7 @@ BaseType_t xQueueGiveFromISR( QueueHandle_t xQueue,
{
if( pxQueue->pxQueueSetContainer != NULL )
{
if( prvNotifyQueueSetContainer( pxQueue ) != pdFALSE )
if( prvNotifyQueueSetContainerFromISR( pxQueue ) != pdFALSE )
{
/* The semaphore is a member of a queue set, and
* posting to the queue set caused a higher priority
@ -1491,7 +1504,7 @@ BaseType_t xQueueGiveFromISR( QueueHandle_t xQueue,
{
if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE )
{
if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE )
if( xTaskRemoveFromEventListFromISR( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE )
{
/* The task waiting has a higher priority so
* record that a context switch is required. */
@ -1519,7 +1532,7 @@ BaseType_t xQueueGiveFromISR( QueueHandle_t xQueue,
{
if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE )
{
if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE )
if( xTaskRemoveFromEventListFromISR( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE )
{
/* The task waiting has a higher priority so record that a
* context switch is required. */
@ -2111,7 +2124,7 @@ BaseType_t xQueueReceiveFromISR( QueueHandle_t xQueue,
{
if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) == pdFALSE )
{
if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) != pdFALSE )
if( xTaskRemoveFromEventListFromISR( &( pxQueue->xTasksWaitingToSend ) ) != pdFALSE )
{
/* The task waiting has a higher priority than us so
* force a context switch. */
@ -3354,6 +3367,19 @@ BaseType_t xQueueIsQueueFullFromISR( const QueueHandle_t xQueue )
#if ( configUSE_QUEUE_SETS == 1 )
static BaseType_t prvNotifyQueueSetContainer( const Queue_t * const pxQueue )
{
/* Call the generic version with xIsISR = pdFALSE to indicate task context */
return prvNotifyQueueSetContainerGeneric( pxQueue, pdFALSE );
}
static BaseType_t prvNotifyQueueSetContainerFromISR( const Queue_t * const pxQueue )
{
/* Call the generic version with xIsISR = pdTRUE to indicate ISR context */
return prvNotifyQueueSetContainerGeneric( pxQueue, pdTRUE );
}
static BaseType_t prvNotifyQueueSetContainerGeneric( const Queue_t * const pxQueue,
const BaseType_t xIsISR )
{
Queue_t * pxQueueSetContainer = pxQueue->pxQueueSetContainer;
BaseType_t xReturn = pdFALSE;
@ -3379,7 +3405,18 @@ BaseType_t xQueueIsQueueFullFromISR( const QueueHandle_t xQueue )
{
if( listLIST_IS_EMPTY( &( pxQueueSetContainer->xTasksWaitingToReceive ) ) == pdFALSE )
{
if( xTaskRemoveFromEventList( &( pxQueueSetContainer->xTasksWaitingToReceive ) ) != pdFALSE )
BaseType_t xHigherPriorityTaskWoken;
if( xIsISR == pdTRUE )
{
xHigherPriorityTaskWoken = xTaskRemoveFromEventListFromISR( &( pxQueueSetContainer->xTasksWaitingToReceive ) );
}
else
{
xHigherPriorityTaskWoken = xTaskRemoveFromEventList( &( pxQueueSetContainer->xTasksWaitingToReceive ) );
}
if( xHigherPriorityTaskWoken != pdFALSE )
{
/* The task waiting has a higher priority. */
xReturn = pdTRUE;

93
tasks.c
View file

@ -704,6 +704,12 @@ static portTASK_FUNCTION_PROTO( prvIdleTask, pvParameters ) PRIVILEGED_FUNCTION;
*/
static void prvCheckTasksWaitingTermination( void ) PRIVILEGED_FUNCTION;
/*
* Private helper function to remove a task from an event list. This function
* is shared between the task context and ISR context versions.
*/
static BaseType_t prvTaskRemoveFromEventList( const List_t * const pxEventList ) PRIVILEGED_FUNCTION;
/*
* The currently executing task is entering the Blocked state. Add the task to
* either the current or the overflow delayed task list.
@ -5749,38 +5755,63 @@ void vTaskPlaceOnUnorderedEventList( List_t * pxEventList,
BaseType_t xTaskRemoveFromEventList( const List_t * const pxEventList )
{
TCB_t * pxUnblockedTCB;
traceENTER_xTaskRemoveFromEventList( pxEventList );
BaseType_t xReturn;
#if ( ( portUSING_GRANULAR_LOCKS == 1 ) && ( configNUMBER_OF_CORES > 1 ) )
/* Lock the kernel data group as we are about to access its members */
kernelENTER_CRITICAL();
{
xReturn = prvTaskRemoveFromEventList( pxEventList );
}
kernelEXIT_CRITICAL();
#else
xReturn = prvTaskRemoveFromEventList( pxEventList );
#endif
traceRETURN_xTaskRemoveFromEventList( xReturn );
return xReturn;
}
/*-----------------------------------------------------------*/
BaseType_t xTaskRemoveFromEventListFromISR( const List_t * const pxEventList )
{
traceENTER_xTaskRemoveFromEventListFromISR( pxEventList );
BaseType_t xReturn;
#if ( ( portUSING_GRANULAR_LOCKS == 1 ) && ( configNUMBER_OF_CORES > 1 ) )
UBaseType_t uxSavedInterruptStatus;
#endif /* #if ( ( portUSING_GRANULAR_LOCKS == 1 ) && ( configNUMBER_OF_CORES > 1 ) ) */
traceENTER_xTaskRemoveFromEventList( pxEventList );
/* Lock the kernel data group as we are about to access its members */
uxSavedInterruptStatus = kernelENTER_CRITICAL_FROM_ISR();
{
xReturn = prvTaskRemoveFromEventList( pxEventList );
}
kernelEXIT_CRITICAL_FROM_ISR( uxSavedInterruptStatus );
#else
xReturn = prvTaskRemoveFromEventList( pxEventList );
#endif
#if ( !( ( portUSING_GRANULAR_LOCKS == 1 ) && ( configNUMBER_OF_CORES > 1 ) ) )
traceRETURN_xTaskRemoveFromEventListFromISR( xReturn );
return xReturn;
}
/*-----------------------------------------------------------*/
static BaseType_t prvTaskRemoveFromEventList( const List_t * const pxEventList )
{
TCB_t * pxUnblockedTCB;
BaseType_t xReturn;
/* THIS FUNCTION MUST BE CALLED FROM A CRITICAL SECTION. It can also be
* called from a critical section within an ISR. */
#else /* #if ( ! ( ( portUSING_GRANULAR_LOCKS == 1 ) && ( configNUMBER_OF_CORES > 1 ) ) ) */
/* Lock the kernel data group as we are about to access its members */
if( portCHECK_IF_IN_ISR() == pdTRUE )
{
uxSavedInterruptStatus = kernelENTER_CRITICAL_FROM_ISR();
}
else
{
uxSavedInterruptStatus = 0;
kernelENTER_CRITICAL();
}
/* Before taking the kernel lock, another task/ISR could have already
* emptied the pxEventList. So we insert a check here to see if
* pxEventList is empty before attempting to remove an item from it. */
/* Before proceeding, check if the event list is empty */
if( listLIST_IS_EMPTY( pxEventList ) == pdFALSE )
{
#endif /* #if ( ! ( ( portUSING_GRANULAR_LOCKS == 1 ) && ( configNUMBER_OF_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.
@ -5858,28 +5889,14 @@ BaseType_t xTaskRemoveFromEventList( const List_t * const pxEventList )
#endif /* #if ( configUSE_PREEMPTION == 1 ) */
}
#endif /* #if ( configNUMBER_OF_CORES == 1 ) */
#if ( ( portUSING_GRANULAR_LOCKS == 1 ) && ( configNUMBER_OF_CORES > 1 ) )
}
else
{
}
else
{
/* The pxEventList was emptied before we entered the critical
* section, Nothing to do except return pdFALSE. */
xReturn = pdFALSE;
}
}
/* We are done accessing the kernel data group. Unlock it. */
if( portCHECK_IF_IN_ISR() == pdTRUE )
{
kernelEXIT_CRITICAL_FROM_ISR( uxSavedInterruptStatus );
}
else
{
kernelEXIT_CRITICAL();
}
#endif /* #if ( ( portUSING_GRANULAR_LOCKS == 1 ) && ( configNUMBER_OF_CORES > 1 ) ) */
traceRETURN_xTaskRemoveFromEventList( xReturn );
return xReturn;
}
/*-----------------------------------------------------------*/