]> git.sur5r.net Git - freertos/blobdiff - Source/queue.c
Ensure the first task starts with interrupts enabled.
[freertos] / Source / queue.c
index 46f102860227196babcd9200ac6401e1dbf5ef9a..d043f95ecc2b48e2c0bbecd53cd2d9c70b737f77 100644 (file)
@@ -1,5 +1,5 @@
 /*\r
-       FreeRTOS.org V4.7.2 - Copyright (C) 2003-2008 Richard Barry.\r
+       FreeRTOS.org V4.8.0 - Copyright (C) 2003-2008 Richard Barry.\r
 \r
        This file is part of the FreeRTOS.org distribution.\r
 \r
        of http://www.FreeRTOS.org for full details of how and when the exception\r
        can be applied.\r
 \r
-       ***************************************************************************\r
-\r
-       Please ensure to read the configuration and relevant port sections of the \r
+    ***************************************************************************\r
+    ***************************************************************************\r
+    *                                                                         *\r
+    * SAVE TIME AND MONEY!  We can port FreeRTOS.org to your own hardware,    *\r
+    * and even write all or part of your application on your behalf.          *\r
+    * See http://www.OpenRTOS.com for details of the services we provide to   *\r
+    * expedite your project.                                                  *\r
+    *                                                                         *\r
+    ***************************************************************************\r
+    ***************************************************************************\r
+\r
+       Please ensure to read the configuration and relevant port sections of the\r
        online documentation.\r
 \r
-       +++ http://www.FreeRTOS.org +++\r
-       Documentation, latest information, license and contact details.  \r
-\r
-       +++ http://www.SafeRTOS.com +++\r
-       A version that is certified for use in safety critical systems.\r
+       http://www.FreeRTOS.org - Documentation, latest information, license and \r
+       contact details.\r
 \r
-       +++ http://www.OpenRTOS.com +++\r
-       Commercial support, development, porting, licensing and training services.\r
+       http://www.SafeRTOS.com - A version that is certified for use in safety \r
+       critical systems.\r
 \r
-       ***************************************************************************\r
+       http://www.OpenRTOS.com - Commercial support, development, porting, \r
+       licensing and training services.\r
 */\r
 \r
 #include <stdlib.h>\r
@@ -51,7 +58,9 @@
  *----------------------------------------------------------*/\r
 \r
 /* Constants used with the cRxLock and cTxLock structure members. */\r
-#define queueUNLOCKED  ( ( signed portBASE_TYPE ) -1 )\r
+#define queueUNLOCKED                                                  ( ( signed portBASE_TYPE ) -1 )\r
+#define queueLOCKED_UNMODIFIED                                 ( ( signed portBASE_TYPE ) 0 )\r
+\r
 #define queueERRONEOUS_UNBLOCK                                 ( -1 )\r
 \r
 /* For internal use only. */\r
@@ -118,9 +127,9 @@ portBASE_TYPE xQueueTakeMutexRecursive( xQueueHandle xMutex, portTickType xBlock
 portBASE_TYPE xQueueGiveMutexRecursive( xQueueHandle xMutex );\r
 signed portBASE_TYPE xQueueAltGenericSend( xQueueHandle pxQueue, const void * const pvItemToQueue, portTickType xTicksToWait, portBASE_TYPE xCopyPosition );\r
 signed portBASE_TYPE xQueueAltGenericReceive( xQueueHandle pxQueue, const void * const pvBuffer, portTickType xTicksToWait, portBASE_TYPE xJustPeeking );\r
-portBASE_TYPE xQueueIsQueueEmptyFromISR( const xQueueHandle pxQueue );\r
-portBASE_TYPE xQueueIsQueueFullFromISR( const xQueueHandle pxQueue );\r
-portBASE_TYPE xQueueMessagesWaitingFromISR( const xQueueHandle pxQueue );\r
+signed portBASE_TYPE xQueueIsQueueEmptyFromISR( const xQueueHandle pxQueue );\r
+signed portBASE_TYPE xQueueIsQueueFullFromISR( const xQueueHandle pxQueue );\r
+unsigned portBASE_TYPE uxQueueMessagesWaitingFromISR( const xQueueHandle pxQueue );\r
 \r
 \r
 #if configUSE_CO_ROUTINES == 1\r
@@ -170,12 +179,20 @@ static void prvCopyDataFromQueue( xQUEUE * const pxQueue, const void *pvBuffer )
  * Macro to mark a queue as locked.  Locking a queue prevents an ISR from\r
  * accessing the queue event lists.\r
  */\r
-#define prvLockQueue( pxQueue )                        \\r
-{                                                                              \\r
-       taskENTER_CRITICAL();                           \\r
-               ++( pxQueue->xRxLock );                 \\r
-               ++( pxQueue->xTxLock );                 \\r
-       taskEXIT_CRITICAL();                            \\r
+#define prvLockQueue( pxQueue )                                                        \\r
+{                                                                                                              \\r
+       taskENTER_CRITICAL();                                                           \\r
+       {                                                                                                       \\r
+               if( pxQueue->xRxLock == queueUNLOCKED )                 \\r
+               {                                                                                               \\r
+                       pxQueue->xRxLock = queueLOCKED_UNMODIFIED;      \\r
+               }                                                                                               \\r
+               if( pxQueue->xTxLock == queueUNLOCKED )                 \\r
+               {                                                                                               \\r
+                       pxQueue->xTxLock = queueLOCKED_UNMODIFIED;      \\r
+               }                                                                                               \\r
+       }                                                                                                       \\r
+       taskEXIT_CRITICAL();                                                            \\r
 }\r
 /*-----------------------------------------------------------*/\r
 \r
@@ -289,7 +306,7 @@ size_t xQueueSizeInBytes;
        {\r
        portBASE_TYPE xReturn;\r
 \r
-               /* If this is the task that holds the mutex then pxMutexHolder will not \r
+               /* If this is the task that holds the mutex then pxMutexHolder will not\r
                change outside of this task.  If this task does not hold the mutex then\r
                pxMutexHolder can never coincidentally equal the tasks handle, and as\r
                this is the only condition we are interested in it does not matter if\r
@@ -297,8 +314,10 @@ size_t xQueueSizeInBytes;
                mutual exclusion is required to test the pxMutexHolder variable. */\r
                if( pxMutex->pxMutexHolder == xTaskGetCurrentTaskHandle() )\r
                {\r
+                       traceGIVE_MUTEX_RECURSIVE( pxMutex );\r
+\r
                        /* uxRecursiveCallCount cannot be zero if pxMutexHolder is equal to\r
-                       the task handle, therefore no underflow check is required.  Also, \r
+                       the task handle, therefore no underflow check is required.  Also,\r
                        uxRecursiveCallCount is only modified by the mutex holder, and as\r
                        there can only be one, no mutual exclusion is required to modify the\r
                        uxRecursiveCallCount member. */\r
@@ -312,9 +331,7 @@ size_t xQueueSizeInBytes;
                 xQueueGenericSend( pxMutex, NULL, queueMUTEX_GIVE_BLOCK_TIME, queueSEND_TO_BACK );\r
                        }\r
 \r
-                       xReturn = pdPASS;\r
-\r
-                       traceGIVE_MUTEX_RECURSIVE( pxMutex );\r
+                       xReturn = pdPASS;                       \r
                }\r
                else\r
                {\r
@@ -336,9 +353,11 @@ size_t xQueueSizeInBytes;
        {\r
        portBASE_TYPE xReturn;\r
 \r
-               /* Comments regarding mutual exclusion as per those within \r
+               /* Comments regarding mutual exclusion as per those within\r
                xQueueGiveMutexRecursive(). */\r
 \r
+               traceTAKE_MUTEX_RECURSIVE( pxMutex );\r
+\r
                if( pxMutex->pxMutexHolder == xTaskGetCurrentTaskHandle() )\r
                {\r
                        ( pxMutex->uxRecursiveCallCount )++;\r
@@ -354,9 +373,7 @@ size_t xQueueSizeInBytes;
                        {\r
                                ( pxMutex->uxRecursiveCallCount )++;\r
                        }\r
-               }\r
-\r
-               traceTAKE_MUTEX_RECURSIVE( pxMutex );\r
+               }               \r
 \r
                return xReturn;\r
        }\r
@@ -406,7 +423,7 @@ xTimeOutType xTimeOut;
                        if( xReturn == pdTRUE )\r
                        {\r
                                /* This is the first time through - we need to capture the\r
-                               time while the scheduler is locked to ensure we attempt to \r
+                               time while the scheduler is locked to ensure we attempt to\r
                                block at least once. */\r
                                vTaskSetTimeOutState( &xTimeOut );\r
                        }\r
@@ -422,10 +439,10 @@ xTimeOutType xTimeOut;
                                        vTaskPlaceOnEventList( &( pxQueue->xTasksWaitingToSend ), xTicksToWait );\r
                                                \r
                                        /* Unlocking the queue means queue events can effect the\r
-                                       event list.  It is possible     that interrupts occurring now \r
+                                       event list.  It is possible     that interrupts occurring now\r
                                        remove this task from the event list again - but as the\r
                                        scheduler is suspended the task will go onto the pending\r
-                                       ready last instead of the actual ready list. */ \r
+                                       ready last instead of the actual ready list. */\r
                                        prvUnlockQueue( pxQueue );\r
                                                \r
                                        /* Resuming the scheduler will move tasks from the pending\r
@@ -453,7 +470,7 @@ xTimeOutType xTimeOut;
                        }\r
                }\r
                        \r
-               /* Higher priority tasks and interrupts can execute during \r
+               /* Higher priority tasks and interrupts can execute during\r
                this time and could possible refill the queue - even if we\r
                unblocked because space became available. */\r
                \r
@@ -493,7 +510,7 @@ xTimeOutType xTimeOut;
 \r
                if( xReturn == errQUEUE_FULL )\r
                {\r
-                       if( xTicksToWait > 0 )\r
+                       if( xTicksToWait > ( portTickType ) 0 )\r
                        {\r
                                if( xTaskCheckForTimeOut( &xTimeOut, &xTicksToWait ) == pdFALSE )\r
                                {\r
@@ -525,9 +542,9 @@ xTimeOutType xTimeOut;
 \r
                /* The source code that implements the alternative (Alt) API is\r
                simpler because it makes more use of critical sections.  This is        \r
-               the approach taken by many other RTOSes, but FreeRTOS.org has the \r
-               preferred fully featured API too.  The fully featured API has more \r
-               complex code that takes longer to execute, but makes less use of \r
+               the approach taken by many other RTOSes, but FreeRTOS.org has the\r
+               preferred fully featured API too.  The fully featured API has more\r
+               complex code that takes longer to execute, but makes less use of\r
                critical sections.  */\r
 \r
                do\r
@@ -541,7 +558,7 @@ xTimeOutType xTimeOut;
                                        if( xReturn == pdPASS )\r
                                        {\r
                                                /* This is the first time through - capture the time\r
-                                               inside the critical section to ensure we attempt to \r
+                                               inside the critical section to ensure we attempt to\r
                                                block at least once. */\r
                                                vTaskSetTimeOutState( &xTimeOut );\r
                                        }\r
@@ -565,7 +582,7 @@ xTimeOutType xTimeOut;
                                portEXIT_CRITICAL();\r
                        }\r
                                \r
-                       /* Higher priority tasks and interrupts can execute during \r
+                       /* Higher priority tasks and interrupts can execute during\r
                        this time and could possible refill the queue - even if we\r
                        unblocked because space became available. */\r
                        \r
@@ -605,7 +622,7 @@ xTimeOutType xTimeOut;
 \r
                        if( xReturn == errQUEUE_FULL )\r
                        {\r
-                               if( xTicksToWait > 0 )\r
+                               if( xTicksToWait > ( portTickType ) 0 )\r
                                {\r
                                        if( xTaskCheckForTimeOut( &xTimeOut, &xTicksToWait ) == pdFALSE )\r
                                        {\r
@@ -640,9 +657,9 @@ xTimeOutType xTimeOut;
 \r
                /* The source code that implements the alternative (Alt) API is\r
                simpler because it makes more use of critical sections.  This is        \r
-               the approach taken by many other RTOSes, but FreeRTOS.org has the \r
-               preferred fully featured API too.  The fully featured API has more \r
-               complex code that takes longer to execute, but makes less use of \r
+               the approach taken by many other RTOSes, but FreeRTOS.org has the\r
+               preferred fully featured API too.  The fully featured API has more\r
+               complex code that takes longer to execute, but makes less use of\r
                critical sections.  */\r
 \r
                do\r
@@ -655,7 +672,7 @@ xTimeOutType xTimeOut;
                                        if( xReturn == pdPASS )\r
                                        {\r
                                                /* This is the first time through - capture the time\r
-                                               inside the critical section to ensure we attempt to \r
+                                               inside the critical section to ensure we attempt to\r
                                                block at least once. */\r
                                                vTaskSetTimeOutState( &xTimeOut );\r
                                        }\r
@@ -757,7 +774,7 @@ xTimeOutType xTimeOut;
 \r
                        if( xReturn == errQUEUE_EMPTY )\r
                        {\r
-                               if( xTicksToWait > 0 )\r
+                               if( xTicksToWait > ( portTickType ) 0 )\r
                                {\r
                                        if( xTaskCheckForTimeOut( &xTimeOut, &xTicksToWait ) == pdFALSE )\r
                                        {\r
@@ -847,7 +864,7 @@ signed portCHAR *pcOriginalReadPosition;
                        if( xReturn == pdTRUE )\r
                        {\r
                                /* This is the first time through - we need to capture the\r
-                               time while the scheduler is locked to ensure we attempt to \r
+                               time while the scheduler is locked to ensure we attempt to\r
                                block at least once. */\r
                                vTaskSetTimeOutState( &xTimeOut );\r
                        }\r
@@ -1127,13 +1144,9 @@ static void prvUnlockQueue( xQueueHandle pxQueue )
        updated. */\r
        taskENTER_CRITICAL();\r
        {\r
-               --( pxQueue->xTxLock );\r
-\r
                /* See if data was added to the queue while it was locked. */\r
-               if( pxQueue->xTxLock > queueUNLOCKED )\r
+               while( pxQueue->xTxLock > queueLOCKED_UNMODIFIED )\r
                {\r
-                       pxQueue->xTxLock = queueUNLOCKED;\r
-\r
                        /* Data was posted while the queue was locked.  Are any tasks\r
                        blocked waiting for data to become available? */\r
                        if( !listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) )\r
@@ -1146,28 +1159,40 @@ static void prvUnlockQueue( xQueueHandle pxQueue )
                                        context switch is required. */\r
                                        vTaskMissedYield();\r
                                }\r
-                       }                       \r
+\r
+                               --( pxQueue->xTxLock );\r
+                       }\r
+                       else\r
+                       {\r
+                               break;\r
+                       }\r
                }\r
+\r
+               pxQueue->xTxLock = queueUNLOCKED;\r
        }\r
        taskEXIT_CRITICAL();\r
 \r
        /* Do the same for the Rx lock. */\r
        taskENTER_CRITICAL();\r
        {\r
-               --( pxQueue->xRxLock );\r
-\r
-               if( pxQueue->xRxLock > queueUNLOCKED )\r
+               while( pxQueue->xRxLock > queueLOCKED_UNMODIFIED )\r
                {\r
-                       pxQueue->xRxLock = queueUNLOCKED;\r
-\r
                        if( !listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) )\r
                        {\r
                                if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) != pdFALSE )\r
                                {\r
                                        vTaskMissedYield();\r
                                }\r
-                       }                       \r
+\r
+                               --( pxQueue->xRxLock );\r
+                       }\r
+                       else\r
+                       {\r
+                               break;\r
+                       }\r
                }\r
+\r
+               pxQueue->xRxLock = queueUNLOCKED;\r
        }\r
        taskEXIT_CRITICAL();\r
 }\r