From: richardbarry Date: Sun, 28 Jan 2007 10:20:56 +0000 (+0000) Subject: Modification to the behaviour of xQueueSend() and xQueueReceive() in the case that... X-Git-Tag: V4.2.0~4 X-Git-Url: https://git.sur5r.net/?a=commitdiff_plain;h=d17ae378e1b8f1630b8865e6f44b64cfd773ddfa;p=freertos Modification to the behaviour of xQueueSend() and xQueueReceive() in the case that a blocked task times out (bug fix). git-svn-id: https://svn.code.sf.net/p/freertos/code/trunk@60 1d2547de-c912-0410-9cb9-b8ca96c0e9e2 --- diff --git a/Source/queue.c b/Source/queue.c index d4da4a759..8eea22b6e 100644 --- a/Source/queue.c +++ b/Source/queue.c @@ -240,7 +240,7 @@ size_t xQueueSizeInBytes; signed portBASE_TYPE xQueueSend( xQueueHandle pxQueue, const void *pvItemToQueue, portTickType xTicksToWait ) { -signed portBASE_TYPE xReturn; +signed portBASE_TYPE xReturn = pdFAIL; xTimeOutType xTimeOut; /* Make sure other tasks do not access the queue. */ @@ -337,6 +337,20 @@ xTimeOutType xTimeOut; { taskYIELD(); } + + /* We want to check to see if the queue is still full + before leaving the critical section. This is to prevent + this task placing an item into the queue due to an + interrupt making space on the queue between critical + sections (when there might be a higher priority task + blocked on the queue that cannot run yet because the + scheduler gets suspended). */ + if( pxQueue->uxMessagesWaiting == pxQueue->uxLength ) + { + /* We unblocked but there is no space in the queue, + we probably timed out. */ + xReturn = errQUEUE_FULL; + } /* Before leaving the critical section we have to ensure exclusive access again. */ @@ -347,29 +361,39 @@ xTimeOutType xTimeOut; } } - /* When we are here it is possible that we unblocked as space became - available on the queue. It is also possible that an ISR posted to the - queue since we left the critical section, so it may be that again there - is no space. This would only happen if a task and ISR post onto the - same queue. */ - taskENTER_CRITICAL(); + /* If xReturn is errQUEUE_FULL then we unblocked when the queue + was still full. Don't check it again now as it is possible that + an interrupt has removed an item from the queue since we left the + critical section and we don't want to write to the queue in case + there is a task of higher priority blocked waiting for space to + be available on the queue. If this is the case the higher priority + task will execute when the scheduler is unsupended. */ + if( xReturn != errQUEUE_FULL ) { - if( pxQueue->uxMessagesWaiting < pxQueue->uxLength ) + /* When we are here it is possible that we unblocked as space became + available on the queue. It is also possible that an ISR posted to the + queue since we left the critical section, so it may be that again there + is no space. This would only happen if a task and ISR post onto the + same queue. */ + taskENTER_CRITICAL(); { - /* There is room in the queue, copy the data into the queue. */ - prvCopyQueueData( pxQueue, pvItemToQueue ); - xReturn = pdPASS; - - /* Update the TxLock count so prvUnlockQueue knows to check for - tasks waiting for data to become available in the queue. */ - ++( pxQueue->xTxLock ); - } - else - { - xReturn = errQUEUE_FULL; + if( pxQueue->uxMessagesWaiting < pxQueue->uxLength ) + { + /* There is room in the queue, copy the data into the queue. */ + prvCopyQueueData( pxQueue, pvItemToQueue ); + xReturn = pdPASS; + + /* Update the TxLock count so prvUnlockQueue knows to check for + tasks waiting for data to become available in the queue. */ + ++( pxQueue->xTxLock ); + } + else + { + xReturn = errQUEUE_FULL; + } } + taskEXIT_CRITICAL(); } - taskEXIT_CRITICAL(); if( xReturn == errQUEUE_FULL ) { @@ -435,7 +459,7 @@ signed portBASE_TYPE xQueueSendFromISR( xQueueHandle pxQueue, const void *pvItem signed portBASE_TYPE xQueueReceive( xQueueHandle pxQueue, void *pvBuffer, portTickType xTicksToWait ) { -signed portBASE_TYPE xReturn; +signed portBASE_TYPE xReturn = pdFAIL; xTimeOutType xTimeOut; /* This function is very similar to xQueueSend(). See comments within @@ -467,6 +491,13 @@ xTimeOutType xTimeOut; { taskYIELD(); } + + if( pxQueue->uxMessagesWaiting == ( unsigned portBASE_TYPE ) 0 ) + { + /* We unblocked but the queue is empty. We probably + timed out. */ + xReturn = errQUEUE_EMPTY; + } vTaskSuspendAll(); prvLockQueue( pxQueue ); @@ -475,29 +506,32 @@ xTimeOutType xTimeOut; } } - taskENTER_CRITICAL(); + if( xReturn != errQUEUE_EMPTY ) { - if( pxQueue->uxMessagesWaiting > ( unsigned portBASE_TYPE ) 0 ) + taskENTER_CRITICAL(); { - pxQueue->pcReadFrom += pxQueue->uxItemSize; - if( pxQueue->pcReadFrom >= pxQueue->pcTail ) + if( pxQueue->uxMessagesWaiting > ( unsigned portBASE_TYPE ) 0 ) { - pxQueue->pcReadFrom = pxQueue->pcHead; + pxQueue->pcReadFrom += pxQueue->uxItemSize; + if( pxQueue->pcReadFrom >= pxQueue->pcTail ) + { + pxQueue->pcReadFrom = pxQueue->pcHead; + } + --( pxQueue->uxMessagesWaiting ); + memcpy( ( void * ) pvBuffer, ( void * ) pxQueue->pcReadFrom, ( unsigned ) pxQueue->uxItemSize ); + + /* Increment the lock count so prvUnlockQueue knows to check for + tasks waiting for space to become available on the queue. */ + ++( pxQueue->xRxLock ); + xReturn = pdPASS; + } + else + { + xReturn = errQUEUE_EMPTY; } - --( pxQueue->uxMessagesWaiting ); - memcpy( ( void * ) pvBuffer, ( void * ) pxQueue->pcReadFrom, ( unsigned ) pxQueue->uxItemSize ); - - /* Increment the lock count so prvUnlockQueue knows to check for - tasks waiting for space to become available on the queue. */ - ++( pxQueue->xRxLock ); - xReturn = pdPASS; - } - else - { - xReturn = errQUEUE_EMPTY; } + taskEXIT_CRITICAL(); } - taskEXIT_CRITICAL(); if( xReturn == errQUEUE_EMPTY ) {