]> git.sur5r.net Git - freertos/commitdiff
Modification to the behaviour of xQueueSend() and xQueueReceive() in the case that...
authorrichardbarry <richardbarry@1d2547de-c912-0410-9cb9-b8ca96c0e9e2>
Sun, 28 Jan 2007 10:20:56 +0000 (10:20 +0000)
committerrichardbarry <richardbarry@1d2547de-c912-0410-9cb9-b8ca96c0e9e2>
Sun, 28 Jan 2007 10:20:56 +0000 (10:20 +0000)
git-svn-id: https://svn.code.sf.net/p/freertos/code/trunk@60 1d2547de-c912-0410-9cb9-b8ca96c0e9e2

Source/queue.c

index d4da4a759efa5c0be3521209c15dc061d001dbb1..8eea22b6e4892fcf734078d6adead54fe04df34b 100644 (file)
@@ -240,7 +240,7 @@ size_t xQueueSizeInBytes;
 \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
@@ -337,6 +337,20 @@ xTimeOutType xTimeOut;
                                        {\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
@@ -347,29 +361,39 @@ xTimeOutType xTimeOut;
                        }\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
@@ -435,7 +459,7 @@ signed portBASE_TYPE xQueueSendFromISR( xQueueHandle pxQueue, const void *pvItem
 \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
@@ -467,6 +491,13 @@ xTimeOutType xTimeOut;
                                        {\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
@@ -475,29 +506,32 @@ xTimeOutType xTimeOut;
                        }\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