From 813017082e268c76ab3ae7e136169e8ed89445f7 Mon Sep 17 00:00:00 2001 From: Darian Leung Date: Sun, 16 Jun 2024 00:53:03 +0800 Subject: [PATCH] change(freertos/smp): Update queue.c locking Updated queue.c to use granular locking - Added xTaskSpinlock and xISRSpinlock - Replaced critical section macros with data group critical section macros such as taskENTER/EXIT_CRITICAL/_FROM_ISR() with queueENTER/EXIT_CRITICAL_FROM_ISR(). - Added vQueueEnterCritical/FromISR() and vQueueExitCritical/FromISR() which map to the data group critical section macros. - Added prvLockQueueForTasks() and prvUnlockQueueForTasks() as the granular locking equivalents to prvLockQueue() and prvUnlockQueue() respectively Co-authored-by: Sudeep Mohanty --- include/FreeRTOS.h | 19 ++ queue.c | 513 ++++++++++++++++++++++++--------------------- 2 files changed, 288 insertions(+), 244 deletions(-) diff --git a/include/FreeRTOS.h b/include/FreeRTOS.h index dc2748d97..d9a3542cc 100644 --- a/include/FreeRTOS.h +++ b/include/FreeRTOS.h @@ -2150,10 +2150,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 @@ -3324,6 +3332,10 @@ typedef struct xSTATIC_QUEUE UBaseType_t uxDummy8; uint8_t ucDummy9; #endif + + #if ( ( portUSING_GRANULAR_LOCKS == 1 ) && ( configNUMBER_OF_CORES > 1 ) ) + portSPINLOCK_TYPE xDummySpinlock[ 2 ]; + #endif /* #if ( ( portUSING_GRANULAR_LOCKS == 1 ) && ( configNUMBER_OF_CORES > 1 ) ) */ } StaticQueue_t; typedef StaticQueue_t StaticSemaphore_t; @@ -3353,6 +3365,10 @@ typedef struct xSTATIC_EVENT_GROUP #if ( ( configSUPPORT_STATIC_ALLOCATION == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) ) uint8_t ucDummy4; #endif + + #if ( ( portUSING_GRANULAR_LOCKS == 1 ) && ( configNUMBER_OF_CORES > 1 ) ) + portSPINLOCK_TYPE xDummySpinlock[ 2 ]; + #endif /* #if ( ( portUSING_GRANULAR_LOCKS == 1 ) && ( configNUMBER_OF_CORES > 1 ) ) */ } StaticEventGroup_t; /* @@ -3408,6 +3424,9 @@ typedef struct xSTATIC_STREAM_BUFFER void * pvDummy5[ 2 ]; #endif UBaseType_t uxDummy6; + #if ( ( portUSING_GRANULAR_LOCKS == 1 ) && ( configNUMBER_OF_CORES > 1 ) ) + portSPINLOCK_TYPE xDummySpinlock[ 2 ]; + #endif /* #if ( ( portUSING_GRANULAR_LOCKS == 1 ) && ( configNUMBER_OF_CORES > 1 ) ) */ } StaticStreamBuffer_t; /* Message buffers are built on stream buffers. */ diff --git a/queue.c b/queue.c index f8198348d..69277851d 100644 --- a/queue.c +++ b/queue.c @@ -133,6 +133,11 @@ typedef struct QueueDefinition /* The old naming convention is used to prevent b UBaseType_t uxQueueNumber; uint8_t ucQueueType; #endif + + #if ( ( portUSING_GRANULAR_LOCKS == 1 ) && ( configNUMBER_OF_CORES > 1 ) ) + portSPINLOCK_TYPE xTaskSpinlock; + portSPINLOCK_TYPE xISRSpinlock; + #endif /* #if ( ( portUSING_GRANULAR_LOCKS == 1 ) && ( configNUMBER_OF_CORES > 1 ) ) */ } xQUEUE; /* The old xQUEUE name is maintained above then typedefed to the new Queue_t @@ -187,7 +192,7 @@ static void prvUnlockQueue( Queue_t * const pxQueue ) PRIVILEGED_FUNCTION; * * @return pdTRUE if the queue contains no items, otherwise pdFALSE. */ -static BaseType_t prvIsQueueEmpty( const Queue_t * pxQueue ) PRIVILEGED_FUNCTION; +static BaseType_t prvIsQueueEmpty( Queue_t * pxQueue ) PRIVILEGED_FUNCTION; /* * Uses a critical section to determine if there is any space in a queue. @@ -217,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 @@ -251,12 +269,59 @@ static void prvInitialiseNewQueue( const UBaseType_t uxQueueLength, #endif /*-----------------------------------------------------------*/ +/* + * Macros to mark the start and end of a critical code region. + */ +#if ( portUSING_GRANULAR_LOCKS == 1 ) + #define queueENTER_CRITICAL( pxQueue ) taskDATA_GROUP_ENTER_CRITICAL( ( portSPINLOCK_TYPE * ) &( pxQueue )->xTaskSpinlock, ( portSPINLOCK_TYPE * ) &( pxQueue )->xISRSpinlock ) + #define queueENTER_CRITICAL_FROM_ISR( pxQueue, puxSavedInterruptStatus ) taskDATA_GROUP_ENTER_CRITICAL_FROM_ISR( ( portSPINLOCK_TYPE * ) &( pxQueue )->xISRSpinlock, puxSavedInterruptStatus ) + #define queueEXIT_CRITICAL( pxQueue ) taskDATA_GROUP_EXIT_CRITICAL( ( portSPINLOCK_TYPE * ) &( pxQueue )->xTaskSpinlock, ( portSPINLOCK_TYPE * ) &( pxQueue )->xISRSpinlock ) + #define queueEXIT_CRITICAL_FROM_ISR( uxSavedInterruptStatus, pxQueue ) taskDATA_GROUP_EXIT_CRITICAL_FROM_ISR( uxSavedInterruptStatus, ( portSPINLOCK_TYPE * ) &( pxQueue )->xISRSpinlock ) +#else /* #if ( portUSING_GRANULAR_LOCKS == 1 ) */ + #define queueENTER_CRITICAL( pxQueue ) taskENTER_CRITICAL() + #define queueENTER_CRITICAL_FROM_ISR( pxQueue, puxSavedInterruptStatus ) do { *( puxSavedInterruptStatus ) = taskENTER_CRITICAL_FROM_ISR(); } while( 0 ) + #define queueEXIT_CRITICAL( pxQueue ) taskEXIT_CRITICAL() + #define queueEXIT_CRITICAL_FROM_ISR( uxSavedInterruptStatus, pxQueue ) taskEXIT_CRITICAL_FROM_ISR( uxSavedInterruptStatus ) +#endif /* #if ( portUSING_GRANULAR_LOCKS == 1 ) */ + /* * Macro to mark a queue as locked. Locking a queue prevents an ISR from * accessing the queue event lists. + * + * Under granular locks, queueLOCK()/queueUNLOCK() already surround this with + * task-level spinlock + preemption-disabled region. To avoid redundant + * data-group enter/exit (which would re-disable preemption and re-acquire the + * same task spinlock), we minimize to interrupt masking only for the small + * metadata updates here. For the non-granular path, retain the full + * queueENTER_CRITICAL/queueEXIT_CRITICAL. */ -#define prvLockQueue( pxQueue ) \ - taskENTER_CRITICAL(); \ +#if ( ( portUSING_GRANULAR_LOCKS == 1 ) && ( configNUMBER_OF_CORES > 1 ) ) + #define prvLockQueue( pxQueue ) \ + do { \ + UBaseType_t ulState = portSET_INTERRUPT_MASK(); \ + const BaseType_t xCoreID = ( BaseType_t ) portGET_CORE_ID(); \ + portINCREMENT_CRITICAL_NESTING_COUNT( xCoreID ); \ + portGET_SPINLOCK( xCoreID, ( portSPINLOCK_TYPE * ) &( ( pxQueue )->xISRSpinlock ) ); \ + { \ + if( ( pxQueue )->cRxLock == queueUNLOCKED ) \ + { \ + ( pxQueue )->cRxLock = queueLOCKED_UNMODIFIED; \ + } \ + if( ( pxQueue )->cTxLock == queueUNLOCKED ) \ + { \ + ( pxQueue )->cTxLock = queueLOCKED_UNMODIFIED; \ + } \ + } \ + portRELEASE_SPINLOCK( xCoreID, ( portSPINLOCK_TYPE * ) &( ( pxQueue )->xISRSpinlock ) ); \ + portDECREMENT_CRITICAL_NESTING_COUNT( xCoreID ); \ + if( portGET_CRITICAL_NESTING_COUNT( xCoreID ) == 0 ) \ + { \ + portCLEAR_INTERRUPT_MASK( ulState ); \ + } \ + } while( 0 ) +#else /* if ( ( portUSING_GRANULAR_LOCKS == 1 ) && ( configNUMBER_OF_CORES > 1 ) ) */ + #define prvLockQueue( pxQueue ) \ + queueENTER_CRITICAL( pxQueue ); \ { \ if( ( pxQueue )->cRxLock == queueUNLOCKED ) \ { \ @@ -267,7 +332,8 @@ static void prvInitialiseNewQueue( const UBaseType_t uxQueueLength, ( pxQueue )->cTxLock = queueLOCKED_UNMODIFIED; \ } \ } \ - taskEXIT_CRITICAL() + queueEXIT_CRITICAL( pxQueue ) +#endif /* if ( ( portUSING_GRANULAR_LOCKS == 1 ) && ( configNUMBER_OF_CORES > 1 ) ) */ /* * Macro to increment cTxLock member of the queue data structure. It is @@ -298,6 +364,56 @@ static void prvInitialiseNewQueue( const UBaseType_t uxQueueLength, ( pxQueue )->cRxLock = ( int8_t ) ( ( cRxLock ) + ( int8_t ) 1 ); \ } \ } while( 0 ) + +/* + * Macro used to lock and unlock a queue. When a task locks a queue, the + * task will have thread safe non-deterministic access to the queue. + * - Concurrent access from other tasks will be blocked by the xTaskSpinlock + * - Concurrent access from ISRs will be pended + * + * When the tasks unlocks the queue, all pended access attempts are handled. + */ +#if ( ( portUSING_GRANULAR_LOCKS == 1 ) && ( configNUMBER_OF_CORES > 1 ) ) + #define queueLOCK( pxQueue ) \ + do { \ + taskDATA_GROUP_LOCK( &( ( pxQueue )->xTaskSpinlock ) ); \ + prvLockQueue( ( pxQueue ) ); \ + } while( 0 ) + #define queueUNLOCK( pxQueue, xYieldAPI ) \ + do { \ + BaseType_t xAlreadyYielded; \ + prvUnlockQueue( ( pxQueue ) ); \ + xAlreadyYielded = taskDATA_GROUP_UNLOCK( &( ( pxQueue )->xTaskSpinlock ) ); \ + if( ( xAlreadyYielded == pdFALSE ) && ( ( xYieldAPI ) == pdTRUE ) ) \ + { \ + taskYIELD_WITHIN_API(); \ + } \ + else \ + { \ + mtCOVERAGE_TEST_MARKER(); \ + } \ + } while( 0 ) +#else /* #if ( ( portUSING_GRANULAR_LOCKS == 1 ) && ( configNUMBER_OF_CORES > 1 ) ) */ + #define queueLOCK( pxQueue ) \ + do { \ + vTaskSuspendAll(); \ + prvLockQueue( ( pxQueue ) ); \ + } while( 0 ) + #define queueUNLOCK( pxQueue, xYieldAPI ) \ + do { \ + BaseType_t xAlreadyYielded; \ + prvUnlockQueue( ( pxQueue ) ); \ + xAlreadyYielded = xTaskResumeAll(); \ + if( ( xAlreadyYielded == pdFALSE ) && ( ( xYieldAPI ) == pdTRUE ) ) \ + { \ + taskYIELD_WITHIN_API(); \ + } \ + else \ + { \ + mtCOVERAGE_TEST_MARKER(); \ + } \ + } while( 0 ) +#endif /* #if ( ( portUSING_GRANULAR_LOCKS == 1 ) && ( configNUMBER_OF_CORES > 1 ) ) */ /*-----------------------------------------------------------*/ BaseType_t xQueueGenericReset( QueueHandle_t xQueue, @@ -310,12 +426,22 @@ BaseType_t xQueueGenericReset( QueueHandle_t xQueue, configASSERT( pxQueue ); + #if ( ( portUSING_GRANULAR_LOCKS == 1 ) && ( configNUMBER_OF_CORES > 1 ) ) + { + if( xNewQueue == pdTRUE ) + { + portINIT_SPINLOCK( &( pxQueue->xTaskSpinlock ) ); + portINIT_SPINLOCK( &( pxQueue->xISRSpinlock ) ); + } + } + #endif /* #if ( ( portUSING_GRANULAR_LOCKS == 1 ) && ( configNUMBER_OF_CORES > 1 ) ) */ + if( ( pxQueue != NULL ) && ( pxQueue->uxLength >= 1U ) && /* Check for multiplication overflow. */ ( ( SIZE_MAX / pxQueue->uxLength ) >= pxQueue->uxItemSize ) ) { - taskENTER_CRITICAL(); + queueENTER_CRITICAL( pxQueue ); { pxQueue->u.xQueue.pcTail = pxQueue->pcHead + ( pxQueue->uxLength * pxQueue->uxItemSize ); pxQueue->uxMessagesWaiting = ( UBaseType_t ) 0U; @@ -331,16 +457,9 @@ BaseType_t xQueueGenericReset( QueueHandle_t xQueue, * will still be empty. If there are tasks blocked waiting to write to * the queue, then one should be unblocked as after this function exits * it will be possible to write to it. */ - if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) == pdFALSE ) + if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) != pdFALSE ) { - if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) != pdFALSE ) - { - queueYIELD_IF_USING_PREEMPTION(); - } - else - { - mtCOVERAGE_TEST_MARKER(); - } + queueYIELD_IF_USING_PREEMPTION(); } else { @@ -354,7 +473,7 @@ BaseType_t xQueueGenericReset( QueueHandle_t xQueue, vListInitialise( &( pxQueue->xTasksWaitingToReceive ) ); } } - taskEXIT_CRITICAL(); + queueEXIT_CRITICAL( pxQueue ); } else { @@ -703,7 +822,7 @@ static void prvInitialiseNewQueue( const UBaseType_t uxQueueLength, * calling task is the mutex holder, but not a good way of determining the * identity of the mutex holder, as the holder may change between the * following critical section exiting and the function returning. */ - taskENTER_CRITICAL(); + queueENTER_CRITICAL( pxSemaphore ); { if( pxSemaphore->uxQueueType == queueQUEUE_IS_MUTEX ) { @@ -714,7 +833,7 @@ static void prvInitialiseNewQueue( const UBaseType_t uxQueueLength, pxReturn = NULL; } } - taskEXIT_CRITICAL(); + queueEXIT_CRITICAL( pxSemaphore ); traceRETURN_xQueueGetMutexHolder( pxReturn ); @@ -968,7 +1087,7 @@ BaseType_t xQueueGenericSend( QueueHandle_t xQueue, for( ; ; ) { - taskENTER_CRITICAL(); + queueENTER_CRITICAL( pxQueue ); { /* Is there room on the queue now? The running task must be the * highest priority task wanting to access the queue. If the head item @@ -1009,20 +1128,13 @@ BaseType_t xQueueGenericSend( QueueHandle_t xQueue, { /* If there was a task waiting for data to arrive on the * queue then unblock it now. */ - if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE ) + if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE ) { - if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE ) - { - /* The unblocked task has a priority higher than - * our own so yield immediately. Yes it is ok to - * do this from within the critical section - the - * kernel takes care of that. */ - queueYIELD_IF_USING_PREEMPTION(); - } - else - { - mtCOVERAGE_TEST_MARKER(); - } + /* The unblocked task has a priority higher than + * our own so yield immediately. Yes it is ok to + * do this from within the critical section - the + * kernel takes care of that. */ + queueYIELD_IF_USING_PREEMPTION(); } else if( xYieldRequired != pdFALSE ) { @@ -1044,20 +1156,13 @@ BaseType_t xQueueGenericSend( QueueHandle_t xQueue, /* If there was a task waiting for data to arrive on the * queue then unblock it now. */ - if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE ) + if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE ) { - if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE ) - { - /* The unblocked task has a priority higher than - * our own so yield immediately. Yes it is ok to do - * this from within the critical section - the kernel - * takes care of that. */ - queueYIELD_IF_USING_PREEMPTION(); - } - else - { - mtCOVERAGE_TEST_MARKER(); - } + /* The unblocked task has a priority higher than + * our own so yield immediately. Yes it is ok to do + * this from within the critical section - the kernel + * takes care of that. */ + queueYIELD_IF_USING_PREEMPTION(); } else if( xYieldRequired != pdFALSE ) { @@ -1074,7 +1179,7 @@ BaseType_t xQueueGenericSend( QueueHandle_t xQueue, } #endif /* configUSE_QUEUE_SETS */ - taskEXIT_CRITICAL(); + queueEXIT_CRITICAL( pxQueue ); traceRETURN_xQueueGenericSend( pdPASS ); @@ -1086,7 +1191,7 @@ BaseType_t xQueueGenericSend( QueueHandle_t xQueue, { /* The queue was full and no block time is specified (or * the block time has expired) so leave now. */ - taskEXIT_CRITICAL(); + queueEXIT_CRITICAL( pxQueue ); /* Return to the original privilege level before exiting * the function. */ @@ -1109,13 +1214,12 @@ BaseType_t xQueueGenericSend( QueueHandle_t xQueue, } } } - taskEXIT_CRITICAL(); + queueEXIT_CRITICAL( pxQueue ); /* Interrupts and other tasks can send to and receive from the queue * now the critical section has been exited. */ - vTaskSuspendAll(); - prvLockQueue( pxQueue ); + queueLOCK( pxQueue ); /* Update the timeout state to see if it has expired yet. */ if( xTaskCheckForTimeOut( &xTimeOut, &xTicksToWait ) == pdFALSE ) @@ -1125,35 +1229,18 @@ BaseType_t xQueueGenericSend( QueueHandle_t xQueue, traceBLOCKING_ON_QUEUE_SEND( pxQueue ); vTaskPlaceOnEventList( &( pxQueue->xTasksWaitingToSend ), xTicksToWait ); - /* Unlocking the queue means queue events can effect the - * event list. It is possible that interrupts occurring now - * remove this task from the event list again - but as the - * scheduler is suspended the task will go onto the pending - * ready list instead of the actual ready list. */ - prvUnlockQueue( pxQueue ); - - /* Resuming the scheduler will move tasks from the pending - * ready list into the ready list - so it is feasible that this - * task is already in the ready list before it yields - in which - * case the yield will not cause a context switch unless there - * is also a higher priority task in the pending ready list. */ - if( xTaskResumeAll() == pdFALSE ) - { - taskYIELD_WITHIN_API(); - } + queueUNLOCK( pxQueue, pdTRUE ); } else { /* Try again. */ - prvUnlockQueue( pxQueue ); - ( void ) xTaskResumeAll(); + queueUNLOCK( pxQueue, pdFALSE ); } } else { /* The timeout has expired. */ - prvUnlockQueue( pxQueue ); - ( void ) xTaskResumeAll(); + queueUNLOCK( pxQueue, pdFALSE ); traceQUEUE_SEND_FAILED( pxQueue ); traceRETURN_xQueueGenericSend( errQUEUE_FULL ); @@ -1202,7 +1289,7 @@ BaseType_t xQueueGenericSendFromISR( QueueHandle_t xQueue, /* MISRA Ref 4.7.1 [Return value shall be checked] */ /* More details at: https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/MISRA.md#dir-47 */ /* coverity[misra_c_2012_directive_4_7_violation] */ - uxSavedInterruptStatus = ( UBaseType_t ) taskENTER_CRITICAL_FROM_ISR(); + queueENTER_CRITICAL_FROM_ISR( pxQueue, &uxSavedInterruptStatus ); { if( ( pxQueue->uxMessagesWaiting < pxQueue->uxLength ) || ( xCopyPosition == queueOVERWRITE ) ) { @@ -1233,7 +1320,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 @@ -1254,20 +1341,13 @@ BaseType_t xQueueGenericSendFromISR( QueueHandle_t xQueue, } else { - if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE ) + if( xTaskRemoveFromEventListFromISR( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE ) { - if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE ) + /* The task waiting has a higher priority so + * record that a context switch is required. */ + if( pxHigherPriorityTaskWoken != NULL ) { - /* The task waiting has a higher priority so - * record that a context switch is required. */ - if( pxHigherPriorityTaskWoken != NULL ) - { - *pxHigherPriorityTaskWoken = pdTRUE; - } - else - { - mtCOVERAGE_TEST_MARKER(); - } + *pxHigherPriorityTaskWoken = pdTRUE; } else { @@ -1282,20 +1362,13 @@ BaseType_t xQueueGenericSendFromISR( QueueHandle_t xQueue, } #else /* configUSE_QUEUE_SETS */ { - if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE ) + if( xTaskRemoveFromEventListFromISR( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE ) { - if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE ) + /* The task waiting has a higher priority so record that a + * context switch is required. */ + if( pxHigherPriorityTaskWoken != NULL ) { - /* The task waiting has a higher priority so record that a - * context switch is required. */ - if( pxHigherPriorityTaskWoken != NULL ) - { - *pxHigherPriorityTaskWoken = pdTRUE; - } - else - { - mtCOVERAGE_TEST_MARKER(); - } + *pxHigherPriorityTaskWoken = pdTRUE; } else { @@ -1327,7 +1400,7 @@ BaseType_t xQueueGenericSendFromISR( QueueHandle_t xQueue, xReturn = errQUEUE_FULL; } } - taskEXIT_CRITICAL_FROM_ISR( uxSavedInterruptStatus ); + queueEXIT_CRITICAL_FROM_ISR( uxSavedInterruptStatus, pxQueue ); traceRETURN_xQueueGenericSendFromISR( xReturn ); @@ -1378,7 +1451,7 @@ BaseType_t xQueueGiveFromISR( QueueHandle_t xQueue, /* MISRA Ref 4.7.1 [Return value shall be checked] */ /* More details at: https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/MISRA.md#dir-47 */ /* coverity[misra_c_2012_directive_4_7_violation] */ - uxSavedInterruptStatus = ( UBaseType_t ) taskENTER_CRITICAL_FROM_ISR(); + queueENTER_CRITICAL_FROM_ISR( pxQueue, &uxSavedInterruptStatus ); { const UBaseType_t uxMessagesWaiting = pxQueue->uxMessagesWaiting; @@ -1407,7 +1480,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 @@ -1428,20 +1501,13 @@ BaseType_t xQueueGiveFromISR( QueueHandle_t xQueue, } else { - if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE ) + if( xTaskRemoveFromEventListFromISR( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE ) { - if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE ) + /* The task waiting has a higher priority so + * record that a context switch is required. */ + if( pxHigherPriorityTaskWoken != NULL ) { - /* The task waiting has a higher priority so - * record that a context switch is required. */ - if( pxHigherPriorityTaskWoken != NULL ) - { - *pxHigherPriorityTaskWoken = pdTRUE; - } - else - { - mtCOVERAGE_TEST_MARKER(); - } + *pxHigherPriorityTaskWoken = pdTRUE; } else { @@ -1456,20 +1522,13 @@ BaseType_t xQueueGiveFromISR( QueueHandle_t xQueue, } #else /* configUSE_QUEUE_SETS */ { - if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE ) + if( xTaskRemoveFromEventListFromISR( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE ) { - if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE ) + /* The task waiting has a higher priority so record that a + * context switch is required. */ + if( pxHigherPriorityTaskWoken != NULL ) { - /* The task waiting has a higher priority so record that a - * context switch is required. */ - if( pxHigherPriorityTaskWoken != NULL ) - { - *pxHigherPriorityTaskWoken = pdTRUE; - } - else - { - mtCOVERAGE_TEST_MARKER(); - } + *pxHigherPriorityTaskWoken = pdTRUE; } else { @@ -1498,7 +1557,7 @@ BaseType_t xQueueGiveFromISR( QueueHandle_t xQueue, xReturn = errQUEUE_FULL; } } - taskEXIT_CRITICAL_FROM_ISR( uxSavedInterruptStatus ); + queueEXIT_CRITICAL_FROM_ISR( uxSavedInterruptStatus, pxQueue ); traceRETURN_xQueueGiveFromISR( xReturn ); @@ -1532,7 +1591,7 @@ BaseType_t xQueueReceive( QueueHandle_t xQueue, for( ; ; ) { - taskENTER_CRITICAL(); + queueENTER_CRITICAL( pxQueue ); { const UBaseType_t uxMessagesWaiting = pxQueue->uxMessagesWaiting; @@ -1564,7 +1623,7 @@ BaseType_t xQueueReceive( QueueHandle_t xQueue, mtCOVERAGE_TEST_MARKER(); } - taskEXIT_CRITICAL(); + queueEXIT_CRITICAL( pxQueue ); traceRETURN_xQueueReceive( pdPASS ); @@ -1576,7 +1635,7 @@ BaseType_t xQueueReceive( QueueHandle_t xQueue, { /* The queue was empty and no block time is specified (or * the block time has expired) so leave now. */ - taskEXIT_CRITICAL(); + queueEXIT_CRITICAL( pxQueue ); traceQUEUE_RECEIVE_FAILED( pxQueue ); traceRETURN_xQueueReceive( errQUEUE_EMPTY ); @@ -1597,13 +1656,12 @@ BaseType_t xQueueReceive( QueueHandle_t xQueue, } } } - taskEXIT_CRITICAL(); + queueEXIT_CRITICAL( pxQueue ); /* Interrupts and other tasks can send to and receive from the queue * now the critical section has been exited. */ - vTaskSuspendAll(); - prvLockQueue( pxQueue ); + queueLOCK( pxQueue ); /* Update the timeout state to see if it has expired yet. */ if( xTaskCheckForTimeOut( &xTimeOut, &xTicksToWait ) == pdFALSE ) @@ -1614,31 +1672,20 @@ BaseType_t xQueueReceive( QueueHandle_t xQueue, { traceBLOCKING_ON_QUEUE_RECEIVE( pxQueue ); vTaskPlaceOnEventList( &( pxQueue->xTasksWaitingToReceive ), xTicksToWait ); - prvUnlockQueue( pxQueue ); - - if( xTaskResumeAll() == pdFALSE ) - { - taskYIELD_WITHIN_API(); - } - else - { - mtCOVERAGE_TEST_MARKER(); - } + queueUNLOCK( pxQueue, pdTRUE ); } else { /* The queue contains data again. Loop back to try and read the * data. */ - prvUnlockQueue( pxQueue ); - ( void ) xTaskResumeAll(); + queueUNLOCK( pxQueue, pdFALSE ); } } else { /* Timed out. If there is no data in the queue exit, otherwise loop * back and attempt to read the data. */ - prvUnlockQueue( pxQueue ); - ( void ) xTaskResumeAll(); + queueUNLOCK( pxQueue, pdFALSE ); if( prvIsQueueEmpty( pxQueue ) != pdFALSE ) { @@ -1685,7 +1732,7 @@ BaseType_t xQueueSemaphoreTake( QueueHandle_t xQueue, for( ; ; ) { - taskENTER_CRITICAL(); + queueENTER_CRITICAL( pxQueue ); { /* Semaphores are queues with an item size of 0, and where the * number of messages in the queue is the semaphore's count value. */ @@ -1718,23 +1765,16 @@ BaseType_t xQueueSemaphoreTake( QueueHandle_t xQueue, /* Check to see if other tasks are blocked waiting to give the * semaphore, and if so, unblock the highest priority such task. */ - if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) == pdFALSE ) + if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) != pdFALSE ) { - if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) != pdFALSE ) - { - queueYIELD_IF_USING_PREEMPTION(); - } - else - { - mtCOVERAGE_TEST_MARKER(); - } + queueYIELD_IF_USING_PREEMPTION(); } else { mtCOVERAGE_TEST_MARKER(); } - taskEXIT_CRITICAL(); + queueEXIT_CRITICAL( pxQueue ); traceRETURN_xQueueSemaphoreTake( pdPASS ); @@ -1746,7 +1786,7 @@ BaseType_t xQueueSemaphoreTake( QueueHandle_t xQueue, { /* The semaphore count was 0 and no block time is specified * (or the block time has expired) so exit now. */ - taskEXIT_CRITICAL(); + queueEXIT_CRITICAL( pxQueue ); traceQUEUE_RECEIVE_FAILED( pxQueue ); traceRETURN_xQueueSemaphoreTake( errQUEUE_EMPTY ); @@ -1767,13 +1807,12 @@ BaseType_t xQueueSemaphoreTake( QueueHandle_t xQueue, } } } - taskEXIT_CRITICAL(); + queueEXIT_CRITICAL( pxQueue ); /* Interrupts and other tasks can give to and take from the semaphore * now the critical section has been exited. */ - vTaskSuspendAll(); - prvLockQueue( pxQueue ); + queueLOCK( pxQueue ); /* Update the timeout state to see if it has expired yet. */ if( xTaskCheckForTimeOut( &xTimeOut, &xTicksToWait ) == pdFALSE ) @@ -1800,30 +1839,19 @@ BaseType_t xQueueSemaphoreTake( QueueHandle_t xQueue, #endif /* if ( configUSE_MUTEXES == 1 ) */ vTaskPlaceOnEventList( &( pxQueue->xTasksWaitingToReceive ), xTicksToWait ); - prvUnlockQueue( pxQueue ); - - if( xTaskResumeAll() == pdFALSE ) - { - taskYIELD_WITHIN_API(); - } - else - { - mtCOVERAGE_TEST_MARKER(); - } + queueUNLOCK( pxQueue, pdTRUE ); } else { /* There was no timeout and the semaphore count was not 0, so * attempt to take the semaphore again. */ - prvUnlockQueue( pxQueue ); - ( void ) xTaskResumeAll(); + queueUNLOCK( pxQueue, pdFALSE ); } } else { /* Timed out. */ - prvUnlockQueue( pxQueue ); - ( void ) xTaskResumeAll(); + queueUNLOCK( pxQueue, pdFALSE ); /* If the semaphore count is 0 exit now as the timeout has * expired. Otherwise return to attempt to take the semaphore that is @@ -1838,7 +1866,7 @@ BaseType_t xQueueSemaphoreTake( QueueHandle_t xQueue, * test the mutex type again to check it is actually a mutex. */ if( xInheritanceOccurred != pdFALSE ) { - taskENTER_CRITICAL(); + queueENTER_CRITICAL( pxQueue ); { UBaseType_t uxHighestWaitingPriority; @@ -1858,7 +1886,7 @@ BaseType_t xQueueSemaphoreTake( QueueHandle_t xQueue, /* coverity[overrun] */ vTaskPriorityDisinheritAfterTimeout( pxQueue->u.xSemaphore.xMutexHolder, uxHighestWaitingPriority ); } - taskEXIT_CRITICAL(); + queueEXIT_CRITICAL( pxQueue ); } } #endif /* configUSE_MUTEXES */ @@ -1901,7 +1929,7 @@ BaseType_t xQueuePeek( QueueHandle_t xQueue, for( ; ; ) { - taskENTER_CRITICAL(); + queueENTER_CRITICAL( pxQueue ); { const UBaseType_t uxMessagesWaiting = pxQueue->uxMessagesWaiting; @@ -1922,24 +1950,17 @@ BaseType_t xQueuePeek( QueueHandle_t xQueue, /* The data is being left in the queue, so see if there are * any other tasks waiting for the data. */ - if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE ) + if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE ) { - if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE ) - { - /* The task waiting has a higher priority than this task. */ - queueYIELD_IF_USING_PREEMPTION(); - } - else - { - mtCOVERAGE_TEST_MARKER(); - } + /* The task waiting has a higher priority than this task. */ + queueYIELD_IF_USING_PREEMPTION(); } else { mtCOVERAGE_TEST_MARKER(); } - taskEXIT_CRITICAL(); + queueEXIT_CRITICAL( pxQueue ); traceRETURN_xQueuePeek( pdPASS ); @@ -1951,7 +1972,7 @@ BaseType_t xQueuePeek( QueueHandle_t xQueue, { /* The queue was empty and no block time is specified (or * the block time has expired) so leave now. */ - taskEXIT_CRITICAL(); + queueEXIT_CRITICAL( pxQueue ); traceQUEUE_PEEK_FAILED( pxQueue ); traceRETURN_xQueuePeek( errQUEUE_EMPTY ); @@ -1973,13 +1994,12 @@ BaseType_t xQueuePeek( QueueHandle_t xQueue, } } } - taskEXIT_CRITICAL(); + queueEXIT_CRITICAL( pxQueue ); /* Interrupts and other tasks can send to and receive from the queue * now that the critical section has been exited. */ - vTaskSuspendAll(); - prvLockQueue( pxQueue ); + queueLOCK( pxQueue ); /* Update the timeout state to see if it has expired yet. */ if( xTaskCheckForTimeOut( &xTimeOut, &xTicksToWait ) == pdFALSE ) @@ -1990,31 +2010,20 @@ BaseType_t xQueuePeek( QueueHandle_t xQueue, { traceBLOCKING_ON_QUEUE_PEEK( pxQueue ); vTaskPlaceOnEventList( &( pxQueue->xTasksWaitingToReceive ), xTicksToWait ); - prvUnlockQueue( pxQueue ); - - if( xTaskResumeAll() == pdFALSE ) - { - taskYIELD_WITHIN_API(); - } - else - { - mtCOVERAGE_TEST_MARKER(); - } + queueUNLOCK( pxQueue, pdTRUE ); } else { /* There is data in the queue now, so don't enter the blocked * state, instead return to try and obtain the data. */ - prvUnlockQueue( pxQueue ); - ( void ) xTaskResumeAll(); + queueUNLOCK( pxQueue, pdFALSE ); } } else { /* The timeout has expired. If there is still no data in the queue * exit, otherwise go back and try to read the data again. */ - prvUnlockQueue( pxQueue ); - ( void ) xTaskResumeAll(); + queueUNLOCK( pxQueue, pdFALSE ); if( prvIsQueueEmpty( pxQueue ) != pdFALSE ) { @@ -2064,7 +2073,7 @@ BaseType_t xQueueReceiveFromISR( QueueHandle_t xQueue, /* MISRA Ref 4.7.1 [Return value shall be checked] */ /* More details at: https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/MISRA.md#dir-47 */ /* coverity[misra_c_2012_directive_4_7_violation] */ - uxSavedInterruptStatus = ( UBaseType_t ) taskENTER_CRITICAL_FROM_ISR(); + queueENTER_CRITICAL_FROM_ISR( pxQueue, &uxSavedInterruptStatus ); { const UBaseType_t uxMessagesWaiting = pxQueue->uxMessagesWaiting; @@ -2086,7 +2095,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. */ @@ -2124,7 +2133,7 @@ BaseType_t xQueueReceiveFromISR( QueueHandle_t xQueue, traceQUEUE_RECEIVE_FROM_ISR_FAILED( pxQueue ); } } - taskEXIT_CRITICAL_FROM_ISR( uxSavedInterruptStatus ); + queueEXIT_CRITICAL_FROM_ISR( uxSavedInterruptStatus, pxQueue ); traceRETURN_xQueueReceiveFromISR( xReturn ); @@ -2164,7 +2173,7 @@ BaseType_t xQueuePeekFromISR( QueueHandle_t xQueue, /* MISRA Ref 4.7.1 [Return value shall be checked] */ /* More details at: https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/MISRA.md#dir-47 */ /* coverity[misra_c_2012_directive_4_7_violation] */ - uxSavedInterruptStatus = ( UBaseType_t ) taskENTER_CRITICAL_FROM_ISR(); + queueENTER_CRITICAL_FROM_ISR( pxQueue, &uxSavedInterruptStatus ); { /* Cannot block in an ISR, so check there is data available. */ if( pxQueue->uxMessagesWaiting > ( UBaseType_t ) 0 ) @@ -2185,7 +2194,7 @@ BaseType_t xQueuePeekFromISR( QueueHandle_t xQueue, traceQUEUE_PEEK_FROM_ISR_FAILED( pxQueue ); } } - taskEXIT_CRITICAL_FROM_ISR( uxSavedInterruptStatus ); + queueEXIT_CRITICAL_FROM_ISR( uxSavedInterruptStatus, pxQueue ); traceRETURN_xQueuePeekFromISR( xReturn ); @@ -2201,11 +2210,11 @@ UBaseType_t uxQueueMessagesWaiting( const QueueHandle_t xQueue ) configASSERT( xQueue ); - portBASE_TYPE_ENTER_CRITICAL(); + queueENTER_CRITICAL( xQueue ); { uxReturn = ( ( Queue_t * ) xQueue )->uxMessagesWaiting; } - portBASE_TYPE_EXIT_CRITICAL(); + queueEXIT_CRITICAL( xQueue ); traceRETURN_uxQueueMessagesWaiting( uxReturn ); @@ -2222,11 +2231,11 @@ UBaseType_t uxQueueSpacesAvailable( const QueueHandle_t xQueue ) configASSERT( pxQueue ); - portBASE_TYPE_ENTER_CRITICAL(); + queueENTER_CRITICAL( pxQueue ); { uxReturn = ( UBaseType_t ) ( pxQueue->uxLength - pxQueue->uxMessagesWaiting ); } - portBASE_TYPE_EXIT_CRITICAL(); + queueEXIT_CRITICAL( pxQueue ); traceRETURN_uxQueueSpacesAvailable( uxReturn ); @@ -2492,7 +2501,8 @@ static void prvCopyDataFromQueue( Queue_t * const pxQueue, static void prvUnlockQueue( Queue_t * const pxQueue ) { - /* THIS FUNCTION MUST BE CALLED WITH THE SCHEDULER SUSPENDED. */ + /* THIS FUNCTION MUST BE CALLED WITH THE SCHEDULER SUSPENDED WHEN portUSING_GRANULAR_LOCKS IS 0. + * IT MUST BE CALLED WITH TASK PREEMTION DISABLED WHEN portUSING_GRANULAR_LOCKS IS 1. */ /* The lock counts contains the number of extra data items placed or * removed from the queue while the queue was locked. When a queue is @@ -2630,15 +2640,25 @@ static void prvUnlockQueue( Queue_t * const pxQueue ) pxQueue->cRxLock = queueUNLOCKED; } - taskEXIT_CRITICAL(); + #if ( ( portUSING_GRANULAR_LOCKS == 1 ) && ( configNUMBER_OF_CORES > 1 ) ) + portRELEASE_SPINLOCK( xCoreID, ( portSPINLOCK_TYPE * ) &( pxQueue->xISRSpinlock ) ); + portDECREMENT_CRITICAL_NESTING_COUNT( xCoreID ); + + if( portGET_CRITICAL_NESTING_COUNT( xCoreID ) == 0 ) + { + portENABLE_INTERRUPTS(); + } + #else + queueEXIT_CRITICAL( pxQueue ); + #endif } /*-----------------------------------------------------------*/ -static BaseType_t prvIsQueueEmpty( const Queue_t * pxQueue ) +static BaseType_t prvIsQueueEmpty( Queue_t * pxQueue ) { BaseType_t xReturn; - taskENTER_CRITICAL(); + queueENTER_CRITICAL( pxQueue ); { if( pxQueue->uxMessagesWaiting == ( UBaseType_t ) 0 ) { @@ -2649,7 +2669,7 @@ static BaseType_t prvIsQueueEmpty( const Queue_t * pxQueue ) xReturn = pdFALSE; } } - taskEXIT_CRITICAL(); + queueEXIT_CRITICAL( pxQueue ); return xReturn; } @@ -2683,7 +2703,7 @@ static BaseType_t prvIsQueueFull( const Queue_t * pxQueue ) { BaseType_t xReturn; - taskENTER_CRITICAL(); + queueENTER_CRITICAL( pxQueue ); { if( pxQueue->uxMessagesWaiting == pxQueue->uxLength ) { @@ -2694,7 +2714,7 @@ static BaseType_t prvIsQueueFull( const Queue_t * pxQueue ) xReturn = pdFALSE; } } - taskEXIT_CRITICAL(); + queueEXIT_CRITICAL( pxQueue ); return xReturn; } @@ -3174,7 +3194,7 @@ BaseType_t xQueueIsQueueFullFromISR( const QueueHandle_t xQueue ) * time a yield will be performed. If an item is added to the queue while * the queue is locked, and the calling task blocks on the queue, then the * calling task will be immediately unblocked when the queue is unlocked. */ - prvLockQueue( pxQueue ); + queueLOCK( pxQueue ); if( pxQueue->uxMessagesWaiting == ( UBaseType_t ) 0U ) { @@ -3186,7 +3206,7 @@ BaseType_t xQueueIsQueueFullFromISR( const QueueHandle_t xQueue ) mtCOVERAGE_TEST_MARKER(); } - prvUnlockQueue( pxQueue ); + queueUNLOCK( pxQueue, pdFALSE ); traceRETURN_vQueueWaitForMessageRestricted(); } @@ -3238,17 +3258,18 @@ BaseType_t xQueueIsQueueFullFromISR( const QueueHandle_t xQueue ) QueueSetHandle_t xQueueSet ) { BaseType_t xReturn; + Queue_t * const pxQueue = xQueueOrSemaphore; traceENTER_xQueueAddToSet( xQueueOrSemaphore, xQueueSet ); - taskENTER_CRITICAL(); + queueENTER_CRITICAL( pxQueue ); { - if( ( ( Queue_t * ) xQueueOrSemaphore )->pxQueueSetContainer != NULL ) + if( pxQueue->pxQueueSetContainer != NULL ) { /* Cannot add a queue/semaphore to more than one queue set. */ xReturn = pdFAIL; } - else if( ( ( Queue_t * ) xQueueOrSemaphore )->uxMessagesWaiting != ( UBaseType_t ) 0 ) + else if( pxQueue->uxMessagesWaiting != ( UBaseType_t ) 0 ) { /* Cannot add a queue/semaphore to a queue set if there are already * items in the queue/semaphore. */ @@ -3256,11 +3277,11 @@ BaseType_t xQueueIsQueueFullFromISR( const QueueHandle_t xQueue ) } else { - ( ( Queue_t * ) xQueueOrSemaphore )->pxQueueSetContainer = xQueueSet; + pxQueue->pxQueueSetContainer = xQueueSet; xReturn = pdPASS; } } - taskEXIT_CRITICAL(); + queueEXIT_CRITICAL( pxQueue ); traceRETURN_xQueueAddToSet( xReturn ); @@ -3294,12 +3315,12 @@ BaseType_t xQueueIsQueueFullFromISR( const QueueHandle_t xQueue ) } else { - taskENTER_CRITICAL(); + queueENTER_CRITICAL( pxQueueOrSemaphore ); { /* The queue is no longer contained in the set. */ pxQueueOrSemaphore->pxQueueSetContainer = NULL; } - taskEXIT_CRITICAL(); + queueEXIT_CRITICAL( pxQueueOrSemaphore ); xReturn = pdPASS; } @@ -3363,15 +3384,15 @@ BaseType_t xQueueIsQueueFullFromISR( const QueueHandle_t xQueue ) { const BaseType_t xCoreID = portGET_CORE_ID(); - /* This API must be called in a critical section which already has preemption - * and interrupt disabled. */ - portGET_SPINLOCK( xCoreID, ( portSPINLOCK_TYPE * ) &( pxQueue->pxQueueSetContainer->xTaskSpinlock ) ); + /* This API is called within the queue critical section (which + * already holds the source queue's task spinlock and disables + * interrupts), so only the queue-set container's ISR spinlock + * needs to be acquired here. */ portGET_SPINLOCK( xCoreID, ( portSPINLOCK_TYPE * ) &( pxQueue->pxQueueSetContainer->xISRSpinlock ) ); { xReturn = prvNotifyQueueSetContainerGeneric( pxQueue, pdFALSE ); } portRELEASE_SPINLOCK( xCoreID, ( portSPINLOCK_TYPE * ) &( pxQueue->pxQueueSetContainer->xISRSpinlock ) ); - portRELEASE_SPINLOCK( xCoreID, ( portSPINLOCK_TYPE * ) &( pxQueue->pxQueueSetContainer->xTaskSpinlock ) ); } #endif /* if ( portUSING_GRANULAR_LOCKS == 0 ) */ @@ -3431,17 +3452,21 @@ BaseType_t xQueueIsQueueFullFromISR( const QueueHandle_t xQueue ) if( cTxLock == queueUNLOCKED ) { - if( listLIST_IS_EMPTY( &( pxQueueSetContainer->xTasksWaitingToReceive ) ) == pdFALSE ) + BaseType_t xHigherPriorityTaskWoken; + + if( xIsISR == pdTRUE ) { - if( xTaskRemoveFromEventList( &( pxQueueSetContainer->xTasksWaitingToReceive ) ) != pdFALSE ) - { - /* The task waiting has a higher priority. */ - xReturn = pdTRUE; - } - else - { - mtCOVERAGE_TEST_MARKER(); - } + xHigherPriorityTaskWoken = xTaskRemoveFromEventListFromISR( &( pxQueueSetContainer->xTasksWaitingToReceive ) ); + } + else + { + xHigherPriorityTaskWoken = xTaskRemoveFromEventList( &( pxQueueSetContainer->xTasksWaitingToReceive ) ); + } + + if( xHigherPriorityTaskWoken != pdFALSE ) + { + /* The task waiting has a higher priority. */ + xReturn = pdTRUE; } else {