Fix bug when xQueueOverwrite() and xQueueOverwrite() from ISR are used to overwrite items in two queues that are part of the same set.

Minor queue optimisations.
pull/8/head
Richard Barry 5 years ago
parent e5708b38e9
commit 9491af1fd7

@ -203,7 +203,7 @@ static void prvCopyDataFromQueue( Queue_t * const pxQueue, void * const pvBuffer
* Checks to see if a queue is a member of a queue set, and if so, notifies * Checks to see if a queue is a member of a queue set, and if so, notifies
* the queue set that the queue contains data. * the queue set that the queue contains data.
*/ */
static BaseType_t prvNotifyQueueSetContainer( const Queue_t * const pxQueue, const BaseType_t xCopyPosition ) PRIVILEGED_FUNCTION; static BaseType_t prvNotifyQueueSetContainer( const Queue_t * const pxQueue ) PRIVILEGED_FUNCTION;
#endif #endif
/* /*
@ -373,17 +373,10 @@ Queue_t * const pxQueue = xQueue;
configASSERT( uxQueueLength > ( UBaseType_t ) 0 ); configASSERT( uxQueueLength > ( UBaseType_t ) 0 );
if( uxItemSize == ( UBaseType_t ) 0 )
{
/* There is not going to be a queue storage area. */
xQueueSizeInBytes = ( size_t ) 0;
}
else
{
/* Allocate enough space to hold the maximum number of items that /* Allocate enough space to hold the maximum number of items that
can be in the queue at any time. */ can be in the queue at any time. It is valid for uxItemSize to be
zero in the case the queue is used as a semaphore. */
xQueueSizeInBytes = ( size_t ) ( uxQueueLength * uxItemSize ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */ xQueueSizeInBytes = ( size_t ) ( uxQueueLength * uxItemSize ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */
}
/* Allocate the queue and storage area. Justification for MISRA /* Allocate the queue and storage area. Justification for MISRA
deviation as follows: pvPortMalloc() always ensures returned memory deviation as follows: pvPortMalloc() always ensures returned memory
@ -777,7 +770,7 @@ Queue_t * const pxQueue = xQueue;
#if ( configUSE_QUEUE_SETS == 1 ) #if ( configUSE_QUEUE_SETS == 1 )
{ {
UBaseType_t uxPreviousMessagesWaiting = pxQueue->uxMessagesWaiting; const UBaseType_t uxPreviousMessagesWaiting = pxQueue->uxMessagesWaiting;
xYieldRequired = prvCopyDataToQueue( pxQueue, pvItemToQueue, xCopyPosition ); xYieldRequired = prvCopyDataToQueue( pxQueue, pvItemToQueue, xCopyPosition );
@ -790,7 +783,7 @@ Queue_t * const pxQueue = xQueue;
in the queue has not changed. */ in the queue has not changed. */
mtCOVERAGE_TEST_MARKER(); mtCOVERAGE_TEST_MARKER();
} }
else if( prvNotifyQueueSetContainer( pxQueue, xCopyPosition ) != pdFALSE ) else if( prvNotifyQueueSetContainer( pxQueue ) != pdFALSE )
{ {
/* The queue is a member of a queue set, and posting /* The queue is a member of a queue set, and posting
to the queue set caused a higher priority task to to the queue set caused a higher priority task to
@ -993,6 +986,14 @@ Queue_t * const pxQueue = xQueue;
traceQUEUE_SEND_FROM_ISR( pxQueue ); traceQUEUE_SEND_FROM_ISR( pxQueue );
/* The event list is not altered if the queue is locked. This will
be done when the queue is unlocked later. */
if( cTxLock == queueUNLOCKED )
{
#if ( configUSE_QUEUE_SETS == 1 )
{
const UBaseType_t uxPreviousMessagesWaiting = pxQueue->uxMessagesWaiting;
/* Semaphores use xQueueGiveFromISR(), so pxQueue will not be a /* Semaphores use xQueueGiveFromISR(), so pxQueue will not be a
semaphore or mutex. That means prvCopyDataToQueue() cannot result semaphore or mutex. That means prvCopyDataToQueue() cannot result
in a task disinheriting a priority and prvCopyDataToQueue() can be in a task disinheriting a priority and prvCopyDataToQueue() can be
@ -1000,15 +1001,16 @@ Queue_t * const pxQueue = xQueue;
the scheduler is suspended before accessing the ready lists. */ the scheduler is suspended before accessing the ready lists. */
( void ) prvCopyDataToQueue( pxQueue, pvItemToQueue, xCopyPosition ); ( void ) prvCopyDataToQueue( pxQueue, pvItemToQueue, xCopyPosition );
/* The event list is not altered if the queue is locked. This will
be done when the queue is unlocked later. */
if( cTxLock == queueUNLOCKED )
{
#if ( configUSE_QUEUE_SETS == 1 )
{
if( pxQueue->pxQueueSetContainer != NULL ) if( pxQueue->pxQueueSetContainer != NULL )
{ {
if( prvNotifyQueueSetContainer( pxQueue, xCopyPosition ) != pdFALSE ) if( ( xCopyPosition == queueOVERWRITE ) && ( uxPreviousMessagesWaiting != ( UBaseType_t ) 0 ) )
{
/* Do not notify the queue set as an existing item
was overwritten in the queue so the number of items
in the queue has not changed. */
mtCOVERAGE_TEST_MARKER();
}
else if( prvNotifyQueueSetContainer( pxQueue ) != pdFALSE )
{ {
/* The queue is a member of a queue set, and posting /* The queue is a member of a queue set, and posting
to the queue set caused a higher priority task to to the queue set caused a higher priority task to
@ -1057,6 +1059,13 @@ Queue_t * const pxQueue = xQueue;
} }
#else /* configUSE_QUEUE_SETS */ #else /* configUSE_QUEUE_SETS */
{ {
/* Semaphores use xQueueGiveFromISR(), so pxQueue will not be a
semaphore or mutex. That means prvCopyDataToQueue() cannot result
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. */
( void ) prvCopyDataToQueue( pxQueue, pvItemToQueue, xCopyPosition );
if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE ) if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE )
{ {
if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE ) if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE )
@ -1173,7 +1182,7 @@ Queue_t * const pxQueue = xQueue;
{ {
if( pxQueue->pxQueueSetContainer != NULL ) if( pxQueue->pxQueueSetContainer != NULL )
{ {
if( prvNotifyQueueSetContainer( pxQueue, queueSEND_TO_BACK ) != pdFALSE ) if( prvNotifyQueueSetContainer( pxQueue ) != pdFALSE )
{ {
/* The semaphore is a member of a queue set, and /* The semaphore is a member of a queue set, and
posting to the queue set caused a higher priority posting to the queue set caused a higher priority
@ -2185,7 +2194,7 @@ static void prvUnlockQueue( Queue_t * const pxQueue )
{ {
if( pxQueue->pxQueueSetContainer != NULL ) if( pxQueue->pxQueueSetContainer != NULL )
{ {
if( prvNotifyQueueSetContainer( pxQueue, queueSEND_TO_BACK ) != pdFALSE ) if( prvNotifyQueueSetContainer( pxQueue ) != pdFALSE )
{ {
/* The queue is a member of a queue set, and posting to /* The queue is a member of a queue set, and posting to
the queue set caused a higher priority task to unblock. the queue set caused a higher priority task to unblock.
@ -2875,7 +2884,7 @@ Queue_t * const pxQueue = xQueue;
#if ( configUSE_QUEUE_SETS == 1 ) #if ( configUSE_QUEUE_SETS == 1 )
static BaseType_t prvNotifyQueueSetContainer( const Queue_t * const pxQueue, const BaseType_t xCopyPosition ) static BaseType_t prvNotifyQueueSetContainer( const Queue_t * const pxQueue )
{ {
Queue_t *pxQueueSetContainer = pxQueue->pxQueueSetContainer; Queue_t *pxQueueSetContainer = pxQueue->pxQueueSetContainer;
BaseType_t xReturn = pdFALSE; BaseType_t xReturn = pdFALSE;
@ -2892,7 +2901,7 @@ Queue_t * const pxQueue = xQueue;
traceQUEUE_SEND( pxQueueSetContainer ); traceQUEUE_SEND( pxQueueSetContainer );
/* The data copied is the handle of the queue that contains data. */ /* The data copied is the handle of the queue that contains data. */
xReturn = prvCopyDataToQueue( pxQueueSetContainer, &pxQueue, xCopyPosition ); xReturn = prvCopyDataToQueue( pxQueueSetContainer, &pxQueue, queueSEND_TO_BACK );
if( cTxLock == queueUNLOCKED ) if( cTxLock == queueUNLOCKED )
{ {

Loading…
Cancel
Save