\r
signed portBASE_TYPE xQueueSend( xQueueHandle pxQueue, const void *pvItemToQueue, portTickType xTicksToWait )\r
{\r
-signed portBASE_TYPE xReturn;\r
+signed portBASE_TYPE xReturn = pdFAIL;\r
xTimeOutType xTimeOut;\r
\r
/* Make sure other tasks do not access the queue. */\r
{\r
taskYIELD();\r
}\r
+\r
+ /* We want to check to see if the queue is still full\r
+ before leaving the critical section. This is to prevent\r
+ this task placing an item into the queue due to an\r
+ interrupt making space on the queue between critical\r
+ sections (when there might be a higher priority task\r
+ blocked on the queue that cannot run yet because the\r
+ scheduler gets suspended). */\r
+ if( pxQueue->uxMessagesWaiting == pxQueue->uxLength )\r
+ {\r
+ /* We unblocked but there is no space in the queue,\r
+ we probably timed out. */\r
+ xReturn = errQUEUE_FULL;\r
+ }\r
\r
/* Before leaving the critical section we have to ensure\r
exclusive access again. */\r
}\r
}\r
\r
- /* When we are here it is possible that we unblocked as space became\r
- available on the queue. It is also possible that an ISR posted to the\r
- queue since we left the critical section, so it may be that again there\r
- is no space. This would only happen if a task and ISR post onto the\r
- same queue. */\r
- taskENTER_CRITICAL();\r
+ /* If xReturn is errQUEUE_FULL then we unblocked when the queue\r
+ was still full. Don't check it again now as it is possible that\r
+ an interrupt has removed an item from the queue since we left the\r
+ critical section and we don't want to write to the queue in case\r
+ there is a task of higher priority blocked waiting for space to\r
+ be available on the queue. If this is the case the higher priority\r
+ task will execute when the scheduler is unsupended. */\r
+ if( xReturn != errQUEUE_FULL )\r
{\r
- if( pxQueue->uxMessagesWaiting < pxQueue->uxLength )\r
+ /* When we are here it is possible that we unblocked as space became\r
+ available on the queue. It is also possible that an ISR posted to the\r
+ queue since we left the critical section, so it may be that again there\r
+ is no space. This would only happen if a task and ISR post onto the\r
+ same queue. */\r
+ taskENTER_CRITICAL();\r
{\r
- /* There is room in the queue, copy the data into the queue. */ \r
- prvCopyQueueData( pxQueue, pvItemToQueue ); \r
- xReturn = pdPASS;\r
- \r
- /* Update the TxLock count so prvUnlockQueue knows to check for\r
- tasks waiting for data to become available in the queue. */\r
- ++( pxQueue->xTxLock );\r
- }\r
- else\r
- {\r
- xReturn = errQUEUE_FULL;\r
+ if( pxQueue->uxMessagesWaiting < pxQueue->uxLength )\r
+ {\r
+ /* There is room in the queue, copy the data into the queue. */ \r
+ prvCopyQueueData( pxQueue, pvItemToQueue ); \r
+ xReturn = pdPASS;\r
+ \r
+ /* Update the TxLock count so prvUnlockQueue knows to check for\r
+ tasks waiting for data to become available in the queue. */\r
+ ++( pxQueue->xTxLock );\r
+ }\r
+ else\r
+ {\r
+ xReturn = errQUEUE_FULL;\r
+ }\r
}\r
+ taskEXIT_CRITICAL();\r
}\r
- taskEXIT_CRITICAL();\r
\r
if( xReturn == errQUEUE_FULL )\r
{\r
\r
signed portBASE_TYPE xQueueReceive( xQueueHandle pxQueue, void *pvBuffer, portTickType xTicksToWait )\r
{\r
-signed portBASE_TYPE xReturn;\r
+signed portBASE_TYPE xReturn = pdFAIL;\r
xTimeOutType xTimeOut;\r
\r
/* This function is very similar to xQueueSend(). See comments within\r
{\r
taskYIELD();\r
}\r
+\r
+ if( pxQueue->uxMessagesWaiting == ( unsigned portBASE_TYPE ) 0 )\r
+ {\r
+ /* We unblocked but the queue is empty. We probably\r
+ timed out. */\r
+ xReturn = errQUEUE_EMPTY;\r
+ }\r
\r
vTaskSuspendAll();\r
prvLockQueue( pxQueue );\r
}\r
}\r
\r
- taskENTER_CRITICAL();\r
+ if( xReturn != errQUEUE_EMPTY )\r
{\r
- if( pxQueue->uxMessagesWaiting > ( unsigned portBASE_TYPE ) 0 )\r
+ taskENTER_CRITICAL();\r
{\r
- pxQueue->pcReadFrom += pxQueue->uxItemSize;\r
- if( pxQueue->pcReadFrom >= pxQueue->pcTail )\r
+ if( pxQueue->uxMessagesWaiting > ( unsigned portBASE_TYPE ) 0 )\r
{\r
- pxQueue->pcReadFrom = pxQueue->pcHead;\r
+ pxQueue->pcReadFrom += pxQueue->uxItemSize;\r
+ if( pxQueue->pcReadFrom >= pxQueue->pcTail )\r
+ {\r
+ pxQueue->pcReadFrom = pxQueue->pcHead;\r
+ }\r
+ --( pxQueue->uxMessagesWaiting );\r
+ memcpy( ( void * ) pvBuffer, ( void * ) pxQueue->pcReadFrom, ( unsigned ) pxQueue->uxItemSize );\r
+ \r
+ /* Increment the lock count so prvUnlockQueue knows to check for\r
+ tasks waiting for space to become available on the queue. */\r
+ ++( pxQueue->xRxLock );\r
+ xReturn = pdPASS;\r
+ }\r
+ else\r
+ {\r
+ xReturn = errQUEUE_EMPTY;\r
}\r
- --( pxQueue->uxMessagesWaiting );\r
- memcpy( ( void * ) pvBuffer, ( void * ) pxQueue->pcReadFrom, ( unsigned ) pxQueue->uxItemSize );\r
- \r
- /* Increment the lock count so prvUnlockQueue knows to check for\r
- tasks waiting for space to become available on the queue. */\r
- ++( pxQueue->xRxLock );\r
- xReturn = pdPASS;\r
- }\r
- else\r
- {\r
- xReturn = errQUEUE_EMPTY;\r
}\r
+ taskEXIT_CRITICAL();\r
}\r
- taskEXIT_CRITICAL();\r
\r
if( xReturn == errQUEUE_EMPTY )\r
{\r