diff --git a/include/FreeRTOS.h b/include/FreeRTOS.h index 1d50a3c6e..31eb4d7ae 100644 --- a/include/FreeRTOS.h +++ b/include/FreeRTOS.h @@ -3337,6 +3337,11 @@ typedef struct xSTATIC_QUEUE #if ( ( portUSING_GRANULAR_LOCKS == 1 ) && ( configNUMBER_OF_CORES > 1 ) ) portSPINLOCK_TYPE xDummySpinlock[ 2 ]; #endif /* #if ( ( portUSING_GRANULAR_LOCKS == 1 ) && ( configNUMBER_OF_CORES > 1 ) ) */ + + #if ( configQUEUE_DIRECT_TRANSFER == 1 ) + void * pvDummyDirectTransferBuffer; + BaseType_t xDummyDirectTransferPosition; + #endif } StaticQueue_t; typedef StaticQueue_t StaticSemaphore_t; diff --git a/queue.c b/queue.c index 886cdfb78..6ac171619 100644 --- a/queue.c +++ b/queue.c @@ -53,6 +53,11 @@ #define queueLOCKED_UNMODIFIED ( ( int8_t ) 0 ) #define queueINT8_MAX ( ( int8_t ) 127 ) +#if ( configQUEUE_DIRECT_TRANSFER == 1 ) +/* Initialization value for direct transfer position. */ + #define queueDIRECT_TRANSFER_POSITION_INIT ( ( BaseType_t ) -1 ) +#endif + /* When the Queue_t structure is used to represent a base queue its pcHead and * pcTail members are used as pointers into the queue storage area. When the * Queue_t structure is used to represent a mutex pcHead and pcTail pointers are @@ -62,8 +67,8 @@ * is maintained. The QueuePointers_t and SemaphoreData_t types are used to form * a union as their usage is mutually exclusive dependent on what the queue is * being used for. */ -#define uxQueueType pcHead -#define queueQUEUE_IS_MUTEX NULL +#define uxQueueType pcHead +#define queueQUEUE_IS_MUTEX NULL typedef struct QueuePointers { @@ -138,6 +143,14 @@ typedef struct QueueDefinition /* The old naming convention is used to prevent b portSPINLOCK_TYPE xTaskSpinlock; portSPINLOCK_TYPE xISRSpinlock; #endif /* #if ( ( portUSING_GRANULAR_LOCKS == 1 ) && ( configNUMBER_OF_CORES > 1 ) ) */ + + #if ( configQUEUE_DIRECT_TRANSFER == 1 ) + void * pvDirectTransferBuffer; /**< Direct transfer buffer pointer: + * - When queue is EMPTY: points to receiver's buffer + * - When queue is FULL: points to sender's data + * NULL when idle */ + BaseType_t xDirectTransferPosition; /**< Position for direct transfer (queueSEND_TO_BACK, queueSEND_TO_FRONT, queueOVERWRITE) */ + #endif } xQUEUE; /* The old xQUEUE name is maintained above then typedefed to the new Queue_t @@ -256,16 +269,16 @@ static void prvInitialiseNewQueue( const UBaseType_t uxQueueLength, static void prvInitialiseMutex( Queue_t * pxNewQueue ) PRIVILEGED_FUNCTION; #endif -#if ( configUSE_MUTEXES == 1 ) +#if ( ( configUSE_MUTEXES == 1 ) || ( configQUEUE_DIRECT_TRANSFER == 1 ) ) /* - * If a task waiting for a mutex causes the mutex holder to inherit a - * priority, but the waiting task times out, then the holder should - * disinherit the priority - but only down to the highest priority of any - * other tasks that are waiting for the same mutex. This function returns - * that priority. + * Returns the highest priority of any task waiting on the specified event list. + * Used for: + * - Mutex priority disinheritance (xTasksWaitingToReceive) + * - Direct queue transfer (xTasksWaitingToReceive or xTasksWaitingToSend) + * Returns tskIDLE_PRIORITY if the list is empty. */ - static UBaseType_t prvGetHighestPriorityOfWaitToReceiveList( const Queue_t * const pxQueue ) PRIVILEGED_FUNCTION; + static UBaseType_t prvGetHighestPriorityOfWaitingTasks( const List_t * const pxEventList ) PRIVILEGED_FUNCTION; #endif /*-----------------------------------------------------------*/ @@ -450,6 +463,13 @@ BaseType_t xQueueGenericReset( QueueHandle_t xQueue, pxQueue->cRxLock = queueUNLOCKED; pxQueue->cTxLock = queueUNLOCKED; + #if ( configQUEUE_DIRECT_TRANSFER == 1 ) + { + pxQueue->pvDirectTransferBuffer = NULL; + pxQueue->xDirectTransferPosition = queueDIRECT_TRANSFER_POSITION_INIT; + } + #endif + if( xNewQueue == pdFALSE ) { /* If there are tasks blocked waiting to read from the queue, then @@ -1081,6 +1101,10 @@ BaseType_t xQueueGenericSend( QueueHandle_t xQueue, TimeOut_t xTimeOut; Queue_t * const pxQueue = xQueue; + #if ( configQUEUE_DIRECT_TRANSFER == 1 ) + BaseType_t xDirectTransferArmed = pdFALSE; + #endif + traceENTER_xQueueGenericSend( xQueue, pvItemToQueue, xTicksToWait, xCopyPosition ); configASSERT( pxQueue ); @@ -1096,6 +1120,35 @@ BaseType_t xQueueGenericSend( QueueHandle_t xQueue, { queueENTER_CRITICAL( pxQueue ); { + #if ( configQUEUE_DIRECT_TRANSFER == 1 ) + { + /* Check if we were unblocked due to a direct transfer completion. */ + if( ( pxQueue->pvDirectTransferBuffer == NULL ) && ( xDirectTransferArmed == pdTRUE ) ) + { + /* Buffer pointer is cleared and we armed it. The receiver executed the + * direct transfer and our data was copied to the queue. */ + xDirectTransferArmed = pdFALSE; + queueEXIT_CRITICAL( pxQueue ); + + traceQUEUE_SEND( pxQueue ); + traceRETURN_xQueueGenericSend( pdPASS ); + return pdPASS; + } + else if( pxQueue->pvDirectTransferBuffer == pvItemToQueue ) + { + /* We armed direct transfer but receiver didn't execute it - clear and try normal path. */ + pxQueue->pvDirectTransferBuffer = NULL; + xDirectTransferArmed = pdFALSE; + } + else + { + /* Buffer doesn't match our data (someone else armed it or it was cleared + * for another task) - just clear our flag and continue. */ + xDirectTransferArmed = pdFALSE; + } + } + #endif /* if ( configQUEUE_DIRECT_TRANSFER == 1 ) */ + /* 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 * in the queue is to be overwritten then it does not matter if the @@ -1166,12 +1219,53 @@ BaseType_t xQueueGenericSend( QueueHandle_t xQueue, } #else /* configUSE_QUEUE_SETS */ { + #if ( configQUEUE_DIRECT_TRANSFER == 1 ) + { + /* Check if direct transfer is armed (receiver is waiting on empty queue). */ + if( ( pxQueue->pvDirectTransferBuffer != NULL ) && + ( pxQueue->uxMessagesWaiting == ( UBaseType_t ) 0 ) && + ( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE ) ) + { + /* Direct copy to waiting receiver's buffer. */ + ( void ) memcpy( pxQueue->pvDirectTransferBuffer, pvItemToQueue, ( size_t ) pxQueue->uxItemSize ); + + /* Clear buffer pointer - receiver will detect this. */ + pxQueue->pvDirectTransferBuffer = NULL; + + /* Unblock the waiting receiver. */ + if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE ) + { + queueYIELD_IF_USING_PREEMPTION(); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + + queueEXIT_CRITICAL( pxQueue ); + traceRETURN_xQueueGenericSend( pdPASS ); + return pdPASS; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + #endif /* configQUEUE_DIRECT_TRANSFER */ + xYieldRequired = prvCopyDataToQueue( pxQueue, pvItemToQueue, xCopyPosition ); /* 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 ( configQUEUE_DIRECT_TRANSFER == 1 ) + { + /* Clear direct transfer state as task being unblocked. */ + pxQueue->pvDirectTransferBuffer = NULL; + } + #endif + if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE ) { /* The unblocked task has a priority higher than @@ -1248,6 +1342,27 @@ BaseType_t xQueueGenericSend( QueueHandle_t xQueue, if( prvIsQueueFull( pxQueue ) != pdFALSE ) { traceBLOCKING_ON_QUEUE_SEND( pxQueue ); + + #if ( configQUEUE_DIRECT_TRANSFER == 1 ) + { + /* Arm direct transfer only if we'll be the highest priority waiter. + * This happens when: (1) list is empty, OR (2) our priority is higher + * than the current highest priority waiting task. */ + const UBaseType_t uxCurrentPriority = uxTaskPriorityGet( NULL ); + const UBaseType_t uxHighestWaitingPriority = prvGetHighestPriorityOfWaitingTasks( &( pxQueue->xTasksWaitingToSend ) ); + + if( uxCurrentPriority > uxHighestWaitingPriority ) + { + /* We're higher priority than any current waiter (or list is empty, + * in which case uxHighestWaitingPriority is tskIDLE_PRIORITY). + * Arm direct transfer using pvDirectTransferBuffer (queue is full). */ + pxQueue->pvDirectTransferBuffer = ( void * ) pvItemToQueue; + pxQueue->xDirectTransferPosition = xCopyPosition; + xDirectTransferArmed = pdTRUE; + } + } + #endif /* if ( configQUEUE_DIRECT_TRANSFER == 1 ) */ + vTaskPlaceOnEventList( &( pxQueue->xTasksWaitingToSend ), xTicksToWait ); queueUNLOCK( pxQueue, pdTRUE ); @@ -1324,6 +1439,42 @@ BaseType_t xQueueGenericSendFromISR( QueueHandle_t xQueue, * in a task disinheriting a priority and prvCopyDataToQueue() can be * called here even though the disinherit function does not check if * the scheduler is suspended before accessing the ready lists. */ + + #if ( configQUEUE_DIRECT_TRANSFER == 1 ) + { + /* Check if direct transfer is armed (receiver is waiting on empty queue). */ + if( ( pxQueue->pvDirectTransferBuffer != NULL ) && + ( pxQueue->uxMessagesWaiting == ( UBaseType_t ) 0 ) && + ( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE ) && + ( cTxLock == queueUNLOCKED ) ) + { + /* Direct copy to waiting receiver's buffer. */ + ( void ) memcpy( pxQueue->pvDirectTransferBuffer, pvItemToQueue, ( size_t ) pxQueue->uxItemSize ); + + /* Clear buffer pointer - receiver will detect this. */ + pxQueue->pvDirectTransferBuffer = NULL; + + /* Unblock the waiting receiver. */ + if( xTaskRemoveFromEventListFromISR( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE ) + { + if( pxHigherPriorityTaskWoken != NULL ) + { + *pxHigherPriorityTaskWoken = pdTRUE; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + + xReturn = pdPASS; + queueEXIT_CRITICAL_FROM_ISR( uxSavedInterruptStatus, pxQueue ); + traceRETURN_xQueueGenericSendFromISR( xReturn ); + return xReturn; + } + } + #endif /* configQUEUE_DIRECT_TRANSFER */ + ( void ) prvCopyDataToQueue( pxQueue, pvItemToQueue, xCopyPosition ); /* The event list is not altered if the queue is locked. This will @@ -1392,6 +1543,13 @@ BaseType_t xQueueGenericSendFromISR( QueueHandle_t xQueue, { if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE ) { + #if ( configQUEUE_DIRECT_TRANSFER == 1 ) + { + /* Clear direct transfer state as task being unblocked. */ + pxQueue->pvDirectTransferBuffer = NULL; + } + #endif + if( xTaskRemoveFromEventListFromISR( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE ) { /* The task waiting has a higher priority so record that a @@ -1622,6 +1780,10 @@ BaseType_t xQueueReceive( QueueHandle_t xQueue, TimeOut_t xTimeOut; Queue_t * const pxQueue = xQueue; + #if ( configQUEUE_DIRECT_TRANSFER == 1 ) + BaseType_t xDirectTransferArmed = pdFALSE; + #endif + traceENTER_xQueueReceive( xQueue, pvBuffer, xTicksToWait ); /* Check the pointer is not NULL. */ @@ -1642,6 +1804,47 @@ BaseType_t xQueueReceive( QueueHandle_t xQueue, { queueENTER_CRITICAL( pxQueue ); { + #if ( configQUEUE_DIRECT_TRANSFER == 1 ) + { + /* Check if we were unblocked due to direct transfer completion. */ + if( ( pxQueue->pvDirectTransferBuffer == NULL ) && ( xDirectTransferArmed == pdTRUE ) ) + { + /* Buffer is cleared and we armed it. Verify this was actually a direct + * transfer to us by checking the queue is still empty. If queue has data, + * it means we were unblocked for normal receive (our buffer was overwritten + * by higher priority task, and data was queued normally). */ + if( pxQueue->uxMessagesWaiting == ( UBaseType_t ) 0 ) + { + /* Queue empty - direct transfer to us succeeded! */ + xDirectTransferArmed = pdFALSE; + queueEXIT_CRITICAL( pxQueue ); + + traceQUEUE_RECEIVE( pxQueue ); + traceRETURN_xQueueReceive( pdPASS ); + return pdPASS; + } + else + { + /* Queue has data - this wasn't a direct transfer to us. + * Continue to normal receive path. */ + xDirectTransferArmed = pdFALSE; + } + } + else if( pxQueue->pvDirectTransferBuffer == pvBuffer ) + { + /* We armed direct transfer but sender didn't deliver - clear and try normal path. */ + pxQueue->pvDirectTransferBuffer = NULL; + xDirectTransferArmed = pdFALSE; + } + else + { + /* Buffer doesn't match our buffer (someone else armed it or it was cleared + * for another task) - just clear our flag and continue. */ + xDirectTransferArmed = pdFALSE; + } + } + #endif /* if ( configQUEUE_DIRECT_TRANSFER == 1 ) */ + const UBaseType_t uxMessagesWaiting = pxQueue->uxMessagesWaiting; /* Is there data in the queue now? To be running the calling task @@ -1658,6 +1861,27 @@ BaseType_t xQueueReceive( QueueHandle_t xQueue, * task. */ if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) == pdFALSE ) { + #if ( configQUEUE_DIRECT_TRANSFER == 1 ) + { + /* Check if a direct transfer is armed (sender is waiting on a full queue). */ + if( pxQueue->pvDirectTransferBuffer != NULL ) + { + /* Verify that position was set to a valid value */ + configASSERT( pxQueue->xDirectTransferPosition != queueDIRECT_TRANSFER_POSITION_INIT ); + configASSERT( ( pxQueue->xDirectTransferPosition == queueSEND_TO_BACK ) || + ( pxQueue->xDirectTransferPosition == queueSEND_TO_FRONT ) || + ( pxQueue->xDirectTransferPosition == queueOVERWRITE ) ); + + /* Direct copy from waiting sender's buffer to the queue. */ + ( void ) prvCopyDataToQueue( pxQueue, pxQueue->pvDirectTransferBuffer, pxQueue->xDirectTransferPosition ); + + /* Clear buffer pointer - sender will be unblocked below. */ + pxQueue->pvDirectTransferBuffer = NULL; + } + } + #endif /* configQUEUE_DIRECT_TRANSFER */ + + /* Unblock the waiting sender. */ if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) != pdFALSE ) { queueYIELD_IF_USING_PREEMPTION(); @@ -1720,6 +1944,25 @@ BaseType_t xQueueReceive( QueueHandle_t xQueue, if( prvIsQueueEmpty( pxQueue ) != pdFALSE ) { traceBLOCKING_ON_QUEUE_RECEIVE( pxQueue ); + + #if ( configQUEUE_DIRECT_TRANSFER == 1 ) + { + /* Arm direct transfer only if we'll be the highest priority waiter. + * This happens when: (1) list is empty, OR (2) our priority is higher + * than the current highest waiting task. */ + const UBaseType_t uxCurrentPriority = uxTaskPriorityGet( NULL ); + const UBaseType_t uxHighestWaitingPriority = prvGetHighestPriorityOfWaitingTasks( &( pxQueue->xTasksWaitingToReceive ) ); + + if( uxCurrentPriority > uxHighestWaitingPriority ) + { + /* We're higher priority than any current waiter (or list is empty, + * in which case uxHighestWaitingPriority is tskIDLE_PRIORITY). */ + pxQueue->pvDirectTransferBuffer = pvBuffer; + xDirectTransferArmed = pdTRUE; + } + } + #endif /* if ( configQUEUE_DIRECT_TRANSFER == 1 ) */ + vTaskPlaceOnEventList( &( pxQueue->xTasksWaitingToReceive ), xTicksToWait ); queueUNLOCK( pxQueue, pdTRUE ); } @@ -1931,13 +2174,13 @@ BaseType_t xQueueSemaphoreTake( QueueHandle_t xQueue, * has timed out the priority should be disinherited * again, but only as low as the next highest priority * task that is waiting for the same mutex. */ - uxHighestWaitingPriority = prvGetHighestPriorityOfWaitToReceiveList( pxQueue ); + uxHighestWaitingPriority = prvGetHighestPriorityOfWaitingTasks( &( pxQueue->xTasksWaitingToReceive ) ); /* vTaskPriorityDisinheritAfterTimeout uses the uxHighestWaitingPriority * parameter to index pxReadyTasksLists when adding the task holding * mutex to the ready list for its new priority. Coverity thinks that * it can result in out-of-bounds access which is not true because - * uxHighestWaitingPriority, as returned by prvGetHighestPriorityOfWaitToReceiveList, + * uxHighestWaitingPriority, as returned by prvGetHighestPriorityOfWaitingTasks, * is capped at ( configMAX_PRIORITIES - 1 ). */ /* coverity[overrun] */ vTaskPriorityDisinheritAfterTimeout( pxQueue->u.xSemaphore.xMutexHolder, uxHighestWaitingPriority ); @@ -2158,6 +2401,28 @@ BaseType_t xQueueReceiveFromISR( QueueHandle_t xQueue, { if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) == pdFALSE ) { + #if ( configQUEUE_DIRECT_TRANSFER == 1 ) + { + /* Check if a direct transfer is armed (sender is waiting on full queue). + * When queue is not empty, pvDirectTransferBuffer is used to point to sender's data. */ + if( pxQueue->pvDirectTransferBuffer != NULL ) + { + /* Verify that position was set to a valid value. */ + configASSERT( pxQueue->xDirectTransferPosition != queueDIRECT_TRANSFER_POSITION_INIT ); + configASSERT( ( pxQueue->xDirectTransferPosition == queueSEND_TO_BACK ) || + ( pxQueue->xDirectTransferPosition == queueSEND_TO_FRONT ) || + ( pxQueue->xDirectTransferPosition == queueOVERWRITE ) ); + + /* Direct copy from waiting sender's buffer to the queue. */ + ( void ) prvCopyDataToQueue( pxQueue, pxQueue->pvDirectTransferBuffer, pxQueue->xDirectTransferPosition ); + + /* Clear buffer pointer - sender will be unblocked below. */ + pxQueue->pvDirectTransferBuffer = NULL; + } + } + #endif /* configQUEUE_DIRECT_TRANSFER */ + + /* Unblock the waiting sender. */ if( xTaskRemoveFromEventListFromISR( &( pxQueue->xTasksWaitingToSend ) ) != pdFALSE ) { /* The task waiting has a higher priority than us so @@ -2331,6 +2596,13 @@ void vQueueDelete( QueueHandle_t xQueue ) configASSERT( pxQueue ); traceQUEUE_DELETE( pxQueue ); + #if ( configQUEUE_DIRECT_TRANSFER == 1 ) + { + /* Clear direct transfer state before deleting queue. */ + pxQueue->pvDirectTransferBuffer = NULL; + } + #endif + #if ( configQUEUE_REGISTRY_SIZE > 0 ) { vQueueUnregisterQueue( pxQueue ); @@ -2431,21 +2703,18 @@ UBaseType_t uxQueueGetQueueLength( QueueHandle_t xQueue ) /* PRIVILEGED_FUNCTION } /*-----------------------------------------------------------*/ -#if ( configUSE_MUTEXES == 1 ) +#if ( ( configUSE_MUTEXES == 1 ) || ( configQUEUE_DIRECT_TRANSFER == 1 ) ) - static UBaseType_t prvGetHighestPriorityOfWaitToReceiveList( const Queue_t * const pxQueue ) + static UBaseType_t prvGetHighestPriorityOfWaitingTasks( const List_t * const pxEventList ) { UBaseType_t uxHighestPriorityOfWaitingTasks; - /* If a task waiting for a mutex causes the mutex holder to inherit a - * priority, but the waiting task times out, then the holder should - * disinherit the priority - but only down to the highest priority of any - * other tasks that are waiting for the same mutex. For this purpose, - * return the priority of the highest priority task that is waiting for the - * mutex. */ - if( listCURRENT_LIST_LENGTH( &( pxQueue->xTasksWaitingToReceive ) ) > 0U ) + /* Returns the priority of the highest priority task waiting on the given + * event list. If the list is empty, returns tskIDLE_PRIORITY. + * Used for mutex priority disinheritance and direct transfer optimization. */ + if( listCURRENT_LIST_LENGTH( pxEventList ) > 0U ) { - uxHighestPriorityOfWaitingTasks = ( UBaseType_t ) ( ( UBaseType_t ) configMAX_PRIORITIES - ( UBaseType_t ) listGET_ITEM_VALUE_OF_HEAD_ENTRY( &( pxQueue->xTasksWaitingToReceive ) ) ); + uxHighestPriorityOfWaitingTasks = ( UBaseType_t ) ( ( UBaseType_t ) configMAX_PRIORITIES - ( UBaseType_t ) listGET_ITEM_VALUE_OF_HEAD_ENTRY( pxEventList ) ); } else { @@ -2455,7 +2724,7 @@ UBaseType_t uxQueueGetQueueLength( QueueHandle_t xQueue ) /* PRIVILEGED_FUNCTION return uxHighestPriorityOfWaitingTasks; } -#endif /* configUSE_MUTEXES */ +#endif /* ( configUSE_MUTEXES == 1 ) || ( configQUEUE_DIRECT_TRANSFER == 1 ) */ /*-----------------------------------------------------------*/ static BaseType_t prvCopyDataToQueue( Queue_t * const pxQueue, @@ -2610,6 +2879,13 @@ static void prvUnlockQueue( Queue_t * const pxQueue ) * suspended. */ if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE ) { + #if ( configQUEUE_DIRECT_TRANSFER == 1 ) + { + /* Clear direct transfer state as task being unblocked. */ + pxQueue->pvDirectTransferBuffer = NULL; + } + #endif + if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE ) { /* The task waiting has a higher priority so record that a @@ -2633,6 +2909,13 @@ static void prvUnlockQueue( Queue_t * const pxQueue ) * the pending ready list as the scheduler is still suspended. */ if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE ) { + #if ( configQUEUE_DIRECT_TRANSFER == 1 ) + { + /* Clear direct transfer state as task being unblocked. */ + pxQueue->pvDirectTransferBuffer = NULL; + } + #endif + if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE ) { /* The task waiting has a higher priority so record that