]> git.sur5r.net Git - freertos/blobdiff - FreeRTOS/Source/queue.c
Next revision of queue set implementation.
[freertos] / FreeRTOS / Source / queue.c
index c4e371229a24657b28f8ab43639f8803f93801a1..db21c3c071dabfebd7e061ff66ba94cacc69d88c 100644 (file)
@@ -83,10 +83,6 @@ task.h is included from an application file. */
 \r
 #undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE\r
 \r
-/*-----------------------------------------------------------\r
- * PUBLIC LIST API documented in list.h\r
- *----------------------------------------------------------*/\r
-\r
 /* Constants used with the cRxLock and xTxLock structure members. */\r
 #define queueUNLOCKED                                  ( ( signed portBASE_TYPE ) -1 )\r
 #define queueLOCKED_UNMODIFIED                 ( ( signed portBASE_TYPE ) 0 )\r
@@ -115,6 +111,7 @@ zero. */
 #define queueQUEUE_TYPE_COUNTING_SEMAPHORE     ( 2U )\r
 #define queueQUEUE_TYPE_BINARY_SEMAPHORE       ( 3U )\r
 #define queueQUEUE_TYPE_RECURSIVE_MUTEX                ( 4U )\r
+#define queueQUEUE_TYPE_SET                                    ( 5U )\r
 \r
 /*\r
  * Definition of the queue used by the scheduler.\r
@@ -122,11 +119,11 @@ zero. */
  */\r
 typedef struct QueueDefinition\r
 {\r
-       signed char *pcHead;                            /*< Points to the beginning of the queue storage area. */\r
-       signed char *pcTail;                            /*< Points to the byte at the end of the queue storage area.  Once more byte is allocated than necessary to store the queue items, this is used as a marker. */\r
+       signed char *pcHead;                                    /*< Points to the beginning of the queue storage area. */\r
+       signed char *pcTail;                                    /*< Points to the byte at the end of the queue storage area.  Once more byte is allocated than necessary to store the queue items, this is used as a marker. */\r
 \r
-       signed char *pcWriteTo;                         /*< Points to the free next place in the storage area. */\r
-       signed char *pcReadFrom;                        /*< Points to the last place that a queued item was read from. */\r
+       signed char *pcWriteTo;                                 /*< Points to the free next place in the storage area. */\r
+       signed char *pcReadFrom;                                /*< Points to the last place that a queued item was read from. */\r
 \r
        xList xTasksWaitingToSend;                              /*< List of tasks that are blocked waiting to post onto this queue.  Stored in priority order. */\r
        xList xTasksWaitingToReceive;                   /*< List of tasks that are blocked waiting to read from this queue.  Stored in priority order. */\r
@@ -143,6 +140,10 @@ typedef struct QueueDefinition
                unsigned char ucQueueType;\r
        #endif\r
 \r
+       #if ( configUSE_QUEUE_SETS == 1 )\r
+               struct QueueDefinition *pxQueueSetContainer;\r
+       #endif\r
+\r
 } xQUEUE;\r
 /*-----------------------------------------------------------*/\r
 \r
@@ -152,11 +153,14 @@ typedef struct QueueDefinition
  * pointer to void.\r
  */\r
 typedef xQUEUE * xQueueHandle;\r
+typedef xQUEUE * xQueueSetHandle;\r
 \r
 /*\r
- * Prototypes for public functions are included here so we don't have to\r
- * include the API header file (as it defines xQueueHandle differently).  These\r
- * functions are documented in the API header file.\r
+ * In order to implement strict data hiding, the queue.h header file defines \r
+ * xQueueHandle and xQueueSetHandle as pointers to void.  In this file\r
+ * xQueueHandle and xQueueSetHandle are defined as pointers to xQUEUE objects.\r
+ * Therefore the queue.h header file cannot be included in this source file,\r
+ * and the function prototypes are provided directly.\r
  */\r
 xQueueHandle xQueueGenericCreate( unsigned portBASE_TYPE uxQueueLength, unsigned portBASE_TYPE uxItemSize, unsigned char ucQueueType ) PRIVILEGED_FUNCTION;\r
 signed portBASE_TYPE xQueueGenericSend( xQueueHandle pxQueue, const void * const pvItemToQueue, portTickType xTicksToWait, portBASE_TYPE xCopyPosition ) PRIVILEGED_FUNCTION;\r
@@ -180,12 +184,16 @@ void vQueueSetQueueNumber( xQueueHandle pxQueue, unsigned char ucQueueNumber ) P
 unsigned char ucQueueGetQueueType( xQueueHandle pxQueue ) PRIVILEGED_FUNCTION;\r
 portBASE_TYPE xQueueGenericReset( xQueueHandle pxQueue, portBASE_TYPE xNewQueue ) PRIVILEGED_FUNCTION;\r
 xTaskHandle xQueueGetMutexHolder( xQueueHandle xSemaphore ) PRIVILEGED_FUNCTION;\r
+xQueueSetHandle xQueueSetCreate( unsigned portBASE_TYPE uxEventQueueLength ) PRIVILEGED_FUNCTION;\r
+xQueueHandle xQueueReadMultiple( xQueueSetHandle xQueueSet, portTickType xBlockTimeTicks ) PRIVILEGED_FUNCTION;\r
+portBASE_TYPE xQueueAddToQueueSet( xQueueHandle xQueue, xQueueSetHandle xQueueSet ) PRIVILEGED_FUNCTION;\r
+portBASE_TYPE xQueueRemoveFromQueueSet( xQueueSetHandle xQueueSet, xQueueHandle xQueue ) PRIVILEGED_FUNCTION;\r
 \r
 /*\r
  * Co-routine queue functions differ from task queue functions.  Co-routines are\r
  * an optional component.\r
  */\r
-#if configUSE_CO_ROUTINES == 1\r
+#if ( configUSE_CO_ROUTINES == 1 )\r
        signed portBASE_TYPE xQueueCRSendFromISR( xQueueHandle pxQueue, const void *pvItemToQueue, signed portBASE_TYPE xCoRoutinePreviouslyWoken ) PRIVILEGED_FUNCTION;\r
        signed portBASE_TYPE xQueueCRReceiveFromISR( xQueueHandle pxQueue, void *pvBuffer, signed portBASE_TYPE *pxTaskWoken ) PRIVILEGED_FUNCTION;\r
        signed portBASE_TYPE xQueueCRSend( xQueueHandle pxQueue, const void *pvItemToQueue, portTickType xTicksToWait ) PRIVILEGED_FUNCTION;\r
@@ -196,7 +204,7 @@ xTaskHandle xQueueGetMutexHolder( xQueueHandle xSemaphore ) PRIVILEGED_FUNCTION;
  * The queue registry is just a means for kernel aware debuggers to locate\r
  * queue structures.  It has no other purpose so is an optional component.\r
  */\r
-#if configQUEUE_REGISTRY_SIZE > 0\r
+#if ( configQUEUE_REGISTRY_SIZE > 0 )\r
 \r
        /* The type stored within the queue registry array.  This allows a name\r
        to be assigned to each queue making kernel aware debugging a little\r
@@ -252,6 +260,15 @@ static void prvCopyDataToQueue( xQUEUE *pxQueue, const void *pvItemToQueue, port
  * Copies an item out of a queue.\r
  */\r
 static void prvCopyDataFromQueue( xQUEUE * const pxQueue, const void *pvBuffer ) PRIVILEGED_FUNCTION;\r
+\r
+#if ( configUSE_QUEUE_SETS == 1 )\r
+       /*\r
+        * Checks to see if a queue is a member of a queue set, and if so, notifies\r
+        * the queue set that the queue contains data.\r
+        */\r
+       static portBASE_TYPE prvCheckForMembershipOfQueueSet( xQUEUE *pxQueue, portBASE_TYPE xCopyPosition );\r
+#endif\r
+\r
 /*-----------------------------------------------------------*/\r
 \r
 /*\r
@@ -273,11 +290,6 @@ static void prvCopyDataFromQueue( xQUEUE * const pxQueue, const void *pvBuffer )
        taskEXIT_CRITICAL()\r
 /*-----------------------------------------------------------*/\r
 \r
-\r
-/*-----------------------------------------------------------\r
- * PUBLIC QUEUE MANAGEMENT API documented in queue.h\r
- *----------------------------------------------------------*/\r
-\r
 portBASE_TYPE xQueueGenericReset( xQueueHandle pxQueue, portBASE_TYPE xNewQueue )\r
 {\r
        configASSERT( pxQueue );\r
@@ -349,12 +361,19 @@ xQueueHandle xReturn = NULL;
                                pxNewQueue->uxLength = uxQueueLength;\r
                                pxNewQueue->uxItemSize = uxItemSize;\r
                                xQueueGenericReset( pxNewQueue, pdTRUE );\r
+                               \r
                                #if ( configUSE_TRACE_FACILITY == 1 )\r
                                {\r
                                        pxNewQueue->ucQueueType = ucQueueType;\r
                                }\r
                                #endif /* configUSE_TRACE_FACILITY */\r
 \r
+                               #if( configUSE_QUEUE_SETS == 1 )\r
+                               {\r
+                                       pxNewQueue->pxQueueSetContainer = NULL;\r
+                               }\r
+                               #endif /* configUSE_QUEUE_SETS */\r
+\r
                                traceQUEUE_CREATE( pxNewQueue );\r
                                xReturn = pxNewQueue;\r
                        }\r
@@ -410,6 +429,12 @@ xQueueHandle xReturn = NULL;
                        }\r
                        #endif\r
 \r
+                       #if ( configUSE_QUEUE_SETS == 1 )\r
+                       {\r
+                               pxNewQueue->pxQueueSetContainer = NULL;\r
+                       }\r
+                       #endif\r
+\r
                        /* Ensure the event queues start with the correct state. */\r
                        vListInitialise( &( pxNewQueue->xTasksWaitingToSend ) );\r
                        vListInitialise( &( pxNewQueue->xTasksWaitingToReceive ) );\r
@@ -431,7 +456,7 @@ xQueueHandle xReturn = NULL;
 #endif /* configUSE_MUTEXES */\r
 /*-----------------------------------------------------------*/\r
 \r
-#if ( ( configUSE_MUTEXES == 1 ) && ( INCLUDE_xQueueGetMutexHolder == 1 ) )\r
+#if ( ( configUSE_MUTEXES == 1 ) && ( INCLUDE_xSemaphoreGetMutexHolder == 1 ) )\r
 \r
        void* xQueueGetMutexHolder( xQueueHandle xSemaphore )\r
        {\r
@@ -510,7 +535,7 @@ xQueueHandle xReturn = NULL;
 #endif /* configUSE_RECURSIVE_MUTEXES */\r
 /*-----------------------------------------------------------*/\r
 \r
-#if configUSE_RECURSIVE_MUTEXES == 1\r
+#if ( configUSE_RECURSIVE_MUTEXES == 1 )\r
 \r
        portBASE_TYPE xQueueTakeMutexRecursive( xQueueHandle pxMutex, portTickType xBlockTime )\r
        {\r
@@ -550,7 +575,7 @@ xQueueHandle xReturn = NULL;
 #endif /* configUSE_RECURSIVE_MUTEXES */\r
 /*-----------------------------------------------------------*/\r
 \r
-#if configUSE_COUNTING_SEMAPHORES == 1\r
+#if ( configUSE_COUNTING_SEMAPHORES == 1 )\r
 \r
        xQueueHandle xQueueCreateCountingSemaphore( unsigned portBASE_TYPE uxCountValue, unsigned portBASE_TYPE uxInitialCount )\r
        {\r
@@ -611,6 +636,20 @@ xTimeOutType xTimeOut;
                                                portYIELD_WITHIN_API();\r
                                        }\r
                                }\r
+                               else\r
+                               {\r
+                                       #if ( configUSE_QUEUE_SETS == 1 )\r
+                                       {\r
+                                               if( prvCheckForMembershipOfQueueSet( pxQueue, xCopyPosition ) == pdTRUE )\r
+                                               {\r
+                                                       /* The queue is a member of a queue set, and posting to\r
+                                                       the queue set caused a higher priority task to unblock.\r
+                                                       A context switch is required. */\r
+                                                       portYIELD_WITHIN_API();\r
+                                               }\r
+                                       }\r
+                                       #endif /* configUSE_QUEUE_SETS */\r
+                               }\r
 \r
                                taskEXIT_CRITICAL();\r
 \r
@@ -695,7 +734,7 @@ xTimeOutType xTimeOut;
 }\r
 /*-----------------------------------------------------------*/\r
 \r
-#if configUSE_ALTERNATIVE_API == 1\r
+#if ( configUSE_ALTERNATIVE_API == 1 )\r
 \r
        signed portBASE_TYPE xQueueAltGenericSend( xQueueHandle pxQueue, const void * const pvItemToQueue, portTickType xTicksToWait, portBASE_TYPE xCopyPosition )\r
        {\r
@@ -772,7 +811,7 @@ xTimeOutType xTimeOut;
 #endif /* configUSE_ALTERNATIVE_API */\r
 /*-----------------------------------------------------------*/\r
 \r
-#if configUSE_ALTERNATIVE_API == 1\r
+#if ( configUSE_ALTERNATIVE_API == 1 )\r
 \r
        signed portBASE_TYPE xQueueAltGenericReceive( xQueueHandle pxQueue, void * const pvBuffer, portTickType xTicksToWait, portBASE_TYPE xJustPeeking )\r
        {\r
@@ -940,6 +979,17 @@ unsigned portBASE_TYPE uxSavedInterruptStatus;
                                                }\r
                                        }\r
                                }\r
+                               else\r
+                               {\r
+                                       #if ( configUSE_QUEUE_SETS == 1 )\r
+                                       {\r
+                                               if( pxQueue->pxQueueSetContainer != NULL )\r
+                                               {\r
+                                                       xQueueGenericSendFromISR( pxQueue->pxQueueSetContainer, &pxQueue, pxHigherPriorityTaskWoken, queueSEND_TO_BACK );\r
+                                               }\r
+                                       }\r
+                                       #endif /* configUSE_QUEUE_SETS */\r
+                               }\r
                        }\r
                        else\r
                        {\r
@@ -1018,7 +1068,7 @@ signed char *pcOriginalReadPosition;
                                {\r
                                        traceQUEUE_PEEK( pxQueue );\r
 \r
-                                       /* We are not removing the data, so reset our read\r
+                                       /* The data is not being removed, so reset the read     \r
                                        pointer. */\r
                                        pxQueue->pcReadFrom = pcOriginalReadPosition;\r
 \r
@@ -1034,6 +1084,17 @@ signed char *pcOriginalReadPosition;
                                                        portYIELD_WITHIN_API();\r
                                                }\r
                                        }\r
+                                       else\r
+                                       {\r
+                                               #if ( configUSE_QUEUE_SETS == 1 )\r
+                                               {\r
+                                                       if( pxQueue->pxQueueSetContainer != NULL )\r
+                                                       {\r
+                                                               xQueueGenericSend( pxQueue->pxQueueSetContainer, &pxQueue, 0, queueSEND_TO_BACK );\r
+                                                       }\r
+                                               }\r
+                                               #endif /* configUSE_QUEUE_SETS */\r
+                                       }\r
                                }\r
 \r
                                taskEXIT_CRITICAL();\r
@@ -1212,7 +1273,7 @@ void vQueueDelete( xQueueHandle pxQueue )
                return pxQueue->ucQueueNumber;\r
        }\r
 \r
-#endif\r
+#endif /* configUSE_TRACE_FACILITY */\r
 /*-----------------------------------------------------------*/\r
 \r
 #if ( configUSE_TRACE_FACILITY == 1 )\r
@@ -1222,7 +1283,7 @@ void vQueueDelete( xQueueHandle pxQueue )
                pxQueue->ucQueueNumber = ucQueueNumber;\r
        }\r
 \r
-#endif\r
+#endif /* configUSE_TRACE_FACILITY */\r
 /*-----------------------------------------------------------*/\r
 \r
 #if ( configUSE_TRACE_FACILITY == 1 )\r
@@ -1232,7 +1293,7 @@ void vQueueDelete( xQueueHandle pxQueue )
                return pxQueue->ucQueueType;\r
        }\r
 \r
-#endif\r
+#endif /* configUSE_TRACE_FACILITY */\r
 /*-----------------------------------------------------------*/\r
 \r
 static void prvCopyDataToQueue( xQUEUE *pxQueue, const void *pvItemToQueue, portBASE_TYPE xPosition )\r
@@ -1312,6 +1373,22 @@ static void prvUnlockQueue( xQueueHandle pxQueue )
                                        context switch is required. */\r
                                        vTaskMissedYield();\r
                                }\r
+                               else\r
+                               {\r
+                                       #if ( configUSE_QUEUE_SETS == 1 )\r
+                                       {\r
+                                               if( pxQueue->pxQueueSetContainer != NULL )\r
+                                               {\r
+                                                       portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE;\r
+                                                       xQueueGenericSendFromISR( pxQueue->pxQueueSetContainer, &pxQueue, &xHigherPriorityTaskWoken, queueSEND_TO_BACK );\r
+                                                       if( xHigherPriorityTaskWoken != pdFALSE )\r
+                                                       {\r
+                                                               vTaskMissedYield();\r
+                                                       }\r
+                                               }\r
+                                       }\r
+                                       #endif /* configUSE_QUEUE_SETS */\r
+                               }\r
 \r
                                --( pxQueue->xTxLock );\r
                        }\r
@@ -1397,219 +1474,225 @@ signed portBASE_TYPE xReturn;
 }\r
 /*-----------------------------------------------------------*/\r
 \r
-#if configUSE_CO_ROUTINES == 1\r
-signed portBASE_TYPE xQueueCRSend( xQueueHandle pxQueue, const void *pvItemToQueue, portTickType xTicksToWait )\r
-{\r
-signed portBASE_TYPE xReturn;\r
+#if ( configUSE_CO_ROUTINES == 1 )\r
 \r
-       /* If the queue is already full we may have to block.  A critical section\r
-       is required to prevent an interrupt removing something from the queue\r
-       between the check to see if the queue is full and blocking on the queue. */\r
-       portDISABLE_INTERRUPTS();\r
+       signed portBASE_TYPE xQueueCRSend( xQueueHandle pxQueue, const void *pvItemToQueue, portTickType xTicksToWait )\r
        {\r
-               if( prvIsQueueFull( pxQueue ) != pdFALSE )\r
+       signed portBASE_TYPE xReturn;\r
+\r
+               /* If the queue is already full we may have to block.  A critical section\r
+               is required to prevent an interrupt removing something from the queue\r
+               between the check to see if the queue is full and blocking on the queue. */\r
+               portDISABLE_INTERRUPTS();\r
                {\r
-                       /* The queue is full - do we want to block or just leave without\r
-                       posting? */\r
-                       if( xTicksToWait > ( portTickType ) 0 )\r
-                       {\r
-                               /* As this is called from a coroutine we cannot block directly, but\r
-                               return indicating that we need to block. */\r
-                               vCoRoutineAddToDelayedList( xTicksToWait, &( pxQueue->xTasksWaitingToSend ) );\r
-                               portENABLE_INTERRUPTS();\r
-                               return errQUEUE_BLOCKED;\r
-                       }\r
-                       else\r
+                       if( prvIsQueueFull( pxQueue ) != pdFALSE )\r
                        {\r
-                               portENABLE_INTERRUPTS();\r
-                               return errQUEUE_FULL;\r
+                               /* The queue is full - do we want to block or just leave without\r
+                               posting? */\r
+                               if( xTicksToWait > ( portTickType ) 0 )\r
+                               {\r
+                                       /* As this is called from a coroutine we cannot block directly, but\r
+                                       return indicating that we need to block. */\r
+                                       vCoRoutineAddToDelayedList( xTicksToWait, &( pxQueue->xTasksWaitingToSend ) );\r
+                                       portENABLE_INTERRUPTS();\r
+                                       return errQUEUE_BLOCKED;\r
+                               }\r
+                               else\r
+                               {\r
+                                       portENABLE_INTERRUPTS();\r
+                                       return errQUEUE_FULL;\r
+                               }\r
                        }\r
                }\r
-       }\r
-       portENABLE_INTERRUPTS();\r
+               portENABLE_INTERRUPTS();\r
 \r
-       portNOP();\r
+               portNOP();\r
 \r
-       portDISABLE_INTERRUPTS();\r
-       {\r
-               if( pxQueue->uxMessagesWaiting < pxQueue->uxLength )\r
+               portDISABLE_INTERRUPTS();\r
                {\r
-                       /* There is room in the queue, copy the data into the queue. */\r
-                       prvCopyDataToQueue( pxQueue, pvItemToQueue, queueSEND_TO_BACK );\r
-                       xReturn = pdPASS;\r
-\r
-                       /* Were any co-routines waiting for data to become available? */\r
-                       if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE )\r
+                       if( pxQueue->uxMessagesWaiting < pxQueue->uxLength )\r
                        {\r
-                               /* In this instance the co-routine could be placed directly\r
-                               into the ready list as we are within a critical section.\r
-                               Instead the same pending ready list mechanism is used as if\r
-                               the event were caused from within an interrupt. */\r
-                               if( xCoRoutineRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE )\r
+                               /* There is room in the queue, copy the data into the queue. */\r
+                               prvCopyDataToQueue( pxQueue, pvItemToQueue, queueSEND_TO_BACK );\r
+                               xReturn = pdPASS;\r
+\r
+                               /* Were any co-routines waiting for data to become available? */\r
+                               if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE )\r
                                {\r
-                                       /* The co-routine waiting has a higher priority so record\r
-                                       that a yield might be appropriate. */\r
-                                       xReturn = errQUEUE_YIELD;\r
+                                       /* In this instance the co-routine could be placed directly\r
+                                       into the ready list as we are within a critical section.\r
+                                       Instead the same pending ready list mechanism is used as if\r
+                                       the event were caused from within an interrupt. */\r
+                                       if( xCoRoutineRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE )\r
+                                       {\r
+                                               /* The co-routine waiting has a higher priority so record\r
+                                               that a yield might be appropriate. */\r
+                                               xReturn = errQUEUE_YIELD;\r
+                                       }\r
                                }\r
                        }\r
+                       else\r
+                       {\r
+                               xReturn = errQUEUE_FULL;\r
+                       }\r
                }\r
-               else\r
-               {\r
-                       xReturn = errQUEUE_FULL;\r
-               }\r
+               portENABLE_INTERRUPTS();\r
+\r
+               return xReturn;\r
        }\r
-       portENABLE_INTERRUPTS();\r
 \r
-       return xReturn;\r
-}\r
-#endif\r
+#endif /* configUSE_CO_ROUTINES */\r
 /*-----------------------------------------------------------*/\r
 \r
-#if configUSE_CO_ROUTINES == 1\r
-signed portBASE_TYPE xQueueCRReceive( xQueueHandle pxQueue, void *pvBuffer, portTickType xTicksToWait )\r
-{\r
-signed portBASE_TYPE xReturn;\r
+#if ( configUSE_CO_ROUTINES == 1 )\r
 \r
-       /* If the queue is already empty we may have to block.  A critical section\r
-       is required to prevent an interrupt adding something to the queue\r
-       between the check to see if the queue is empty and blocking on the queue. */\r
-       portDISABLE_INTERRUPTS();\r
+       signed portBASE_TYPE xQueueCRReceive( xQueueHandle pxQueue, void *pvBuffer, portTickType xTicksToWait )\r
        {\r
-               if( pxQueue->uxMessagesWaiting == ( unsigned portBASE_TYPE ) 0 )\r
+       signed portBASE_TYPE xReturn;\r
+\r
+               /* If the queue is already empty we may have to block.  A critical section\r
+               is required to prevent an interrupt adding something to the queue\r
+               between the check to see if the queue is empty and blocking on the queue. */\r
+               portDISABLE_INTERRUPTS();\r
                {\r
-                       /* There are no messages in the queue, do we want to block or just\r
-                       leave with nothing? */\r
-                       if( xTicksToWait > ( portTickType ) 0 )\r
+                       if( pxQueue->uxMessagesWaiting == ( unsigned portBASE_TYPE ) 0 )\r
                        {\r
-                               /* As this is a co-routine we cannot block directly, but return\r
-                               indicating that we need to block. */\r
-                               vCoRoutineAddToDelayedList( xTicksToWait, &( pxQueue->xTasksWaitingToReceive ) );\r
-                               portENABLE_INTERRUPTS();\r
-                               return errQUEUE_BLOCKED;\r
-                       }\r
-                       else\r
-                       {\r
-                               portENABLE_INTERRUPTS();\r
-                               return errQUEUE_FULL;\r
+                               /* There are no messages in the queue, do we want to block or just\r
+                               leave with nothing? */\r
+                               if( xTicksToWait > ( portTickType ) 0 )\r
+                               {\r
+                                       /* As this is a co-routine we cannot block directly, but return\r
+                                       indicating that we need to block. */\r
+                                       vCoRoutineAddToDelayedList( xTicksToWait, &( pxQueue->xTasksWaitingToReceive ) );\r
+                                       portENABLE_INTERRUPTS();\r
+                                       return errQUEUE_BLOCKED;\r
+                               }\r
+                               else\r
+                               {\r
+                                       portENABLE_INTERRUPTS();\r
+                                       return errQUEUE_FULL;\r
+                               }\r
                        }\r
                }\r
-       }\r
-       portENABLE_INTERRUPTS();\r
+               portENABLE_INTERRUPTS();\r
 \r
-       portNOP();\r
+               portNOP();\r
 \r
-       portDISABLE_INTERRUPTS();\r
-       {\r
-               if( pxQueue->uxMessagesWaiting > ( unsigned portBASE_TYPE ) 0 )\r
+               portDISABLE_INTERRUPTS();\r
                {\r
-                       /* Data is available from the queue. */\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
-                       }\r
-                       --( pxQueue->uxMessagesWaiting );\r
-                       memcpy( ( void * ) pvBuffer, ( void * ) pxQueue->pcReadFrom, ( unsigned ) pxQueue->uxItemSize );\r
+                               /* Data is available from the queue. */\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
-                       xReturn = pdPASS;\r
+                               xReturn = pdPASS;\r
 \r
-                       /* Were any co-routines waiting for space to become available? */\r
-                       if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) == pdFALSE )\r
-                       {\r
-                               /* In this instance the co-routine could be placed directly\r
-                               into the ready list as we are within a critical section.\r
-                               Instead the same pending ready list mechanism is used as if\r
-                               the event were caused from within an interrupt. */\r
-                               if( xCoRoutineRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) != pdFALSE )\r
+                               /* Were any co-routines waiting for space to become available? */\r
+                               if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) == pdFALSE )\r
                                {\r
-                                       xReturn = errQUEUE_YIELD;\r
+                                       /* In this instance the co-routine could be placed directly\r
+                                       into the ready list as we are within a critical section.\r
+                                       Instead the same pending ready list mechanism is used as if\r
+                                       the event were caused from within an interrupt. */\r
+                                       if( xCoRoutineRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) != pdFALSE )\r
+                                       {\r
+                                               xReturn = errQUEUE_YIELD;\r
+                                       }\r
                                }\r
                        }\r
+                       else\r
+                       {\r
+                               xReturn = pdFAIL;\r
+                       }\r
                }\r
-               else\r
-               {\r
-                       xReturn = pdFAIL;\r
-               }\r
+               portENABLE_INTERRUPTS();\r
+\r
+               return xReturn;\r
        }\r
-       portENABLE_INTERRUPTS();\r
 \r
-       return xReturn;\r
-}\r
-#endif\r
+#endif /* configUSE_CO_ROUTINES */\r
 /*-----------------------------------------------------------*/\r
 \r
+#if ( configUSE_CO_ROUTINES == 1 )\r
 \r
-\r
-#if configUSE_CO_ROUTINES == 1\r
-signed portBASE_TYPE xQueueCRSendFromISR( xQueueHandle pxQueue, const void *pvItemToQueue, signed portBASE_TYPE xCoRoutinePreviouslyWoken )\r
-{\r
-       /* Cannot block within an ISR so if there is no space on the queue then\r
-       exit without doing anything. */\r
-       if( pxQueue->uxMessagesWaiting < pxQueue->uxLength )\r
+       signed portBASE_TYPE xQueueCRSendFromISR( xQueueHandle pxQueue, const void *pvItemToQueue, signed portBASE_TYPE xCoRoutinePreviouslyWoken )\r
        {\r
-               prvCopyDataToQueue( pxQueue, pvItemToQueue, queueSEND_TO_BACK );\r
-\r
-               /* We only want to wake one co-routine per ISR, so check that a\r
-               co-routine has not already been woken. */\r
-               if( xCoRoutinePreviouslyWoken == pdFALSE )\r
+               /* Cannot block within an ISR so if there is no space on the queue then\r
+               exit without doing anything. */\r
+               if( pxQueue->uxMessagesWaiting < pxQueue->uxLength )\r
                {\r
-                       if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE )\r
+                       prvCopyDataToQueue( pxQueue, pvItemToQueue, queueSEND_TO_BACK );\r
+\r
+                       /* We only want to wake one co-routine per ISR, so check that a\r
+                       co-routine has not already been woken. */\r
+                       if( xCoRoutinePreviouslyWoken == pdFALSE )\r
                        {\r
-                               if( xCoRoutineRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE )\r
+                               if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE )\r
                                {\r
-                                       return pdTRUE;\r
+                                       if( xCoRoutineRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE )\r
+                                       {\r
+                                               return pdTRUE;\r
+                                       }\r
                                }\r
                        }\r
                }\r
+\r
+               return xCoRoutinePreviouslyWoken;\r
        }\r
 \r
-       return xCoRoutinePreviouslyWoken;\r
-}\r
-#endif\r
+#endif /* configUSE_CO_ROUTINES */\r
 /*-----------------------------------------------------------*/\r
 \r
-#if configUSE_CO_ROUTINES == 1\r
-signed portBASE_TYPE xQueueCRReceiveFromISR( xQueueHandle pxQueue, void *pvBuffer, signed portBASE_TYPE *pxCoRoutineWoken )\r
-{\r
-signed portBASE_TYPE xReturn;\r
+#if ( configUSE_CO_ROUTINES == 1 )\r
 \r
-       /* We cannot block from an ISR, so check there is data available. If\r
-       not then just leave without doing anything. */\r
-       if( pxQueue->uxMessagesWaiting > ( unsigned portBASE_TYPE ) 0 )\r
+       signed portBASE_TYPE xQueueCRReceiveFromISR( xQueueHandle pxQueue, void *pvBuffer, signed portBASE_TYPE *pxCoRoutineWoken )\r
        {\r
-               /* Copy the data from the queue. */\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
+       signed portBASE_TYPE xReturn;\r
 \r
-               if( ( *pxCoRoutineWoken ) == pdFALSE )\r
+               /* We cannot block from an ISR, so check there is data available. If\r
+               not then just leave without doing anything. */\r
+               if( pxQueue->uxMessagesWaiting > ( unsigned portBASE_TYPE ) 0 )\r
                {\r
-                       if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) == pdFALSE )\r
+                       /* Copy the data from the queue. */\r
+                       pxQueue->pcReadFrom += pxQueue->uxItemSize;\r
+                       if( pxQueue->pcReadFrom >= pxQueue->pcTail )\r
                        {\r
-                               if( xCoRoutineRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) != pdFALSE )\r
+                               pxQueue->pcReadFrom = pxQueue->pcHead;\r
+                       }\r
+                       --( pxQueue->uxMessagesWaiting );\r
+                       memcpy( ( void * ) pvBuffer, ( void * ) pxQueue->pcReadFrom, ( unsigned ) pxQueue->uxItemSize );\r
+\r
+                       if( ( *pxCoRoutineWoken ) == pdFALSE )\r
+                       {\r
+                               if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) == pdFALSE )\r
                                {\r
-                                       *pxCoRoutineWoken = pdTRUE;\r
+                                       if( xCoRoutineRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) != pdFALSE )\r
+                                       {\r
+                                               *pxCoRoutineWoken = pdTRUE;\r
+                                       }\r
                                }\r
                        }\r
+\r
+                       xReturn = pdPASS;\r
+               }\r
+               else\r
+               {\r
+                       xReturn = pdFAIL;\r
                }\r
 \r
-               xReturn = pdPASS;\r
-       }\r
-       else\r
-       {\r
-               xReturn = pdFAIL;\r
+               return xReturn;\r
        }\r
 \r
-       return xReturn;\r
-}\r
-#endif\r
+#endif /* configUSE_CO_ROUTINES */\r
 /*-----------------------------------------------------------*/\r
 \r
-#if configQUEUE_REGISTRY_SIZE > 0\r
+#if ( configQUEUE_REGISTRY_SIZE > 0 )\r
 \r
        void vQueueAddToRegistry( xQueueHandle xQueue, signed char *pcQueueName )\r
        {\r
@@ -1629,10 +1712,10 @@ signed portBASE_TYPE xReturn;
                }\r
        }\r
 \r
-#endif\r
+#endif /* configQUEUE_REGISTRY_SIZE */\r
 /*-----------------------------------------------------------*/\r
 \r
-#if configQUEUE_REGISTRY_SIZE > 0\r
+#if ( configQUEUE_REGISTRY_SIZE > 0 )\r
 \r
        static void vQueueUnregisterQueue( xQueueHandle xQueue )\r
        {\r
@@ -1652,10 +1735,10 @@ signed portBASE_TYPE xReturn;
 \r
        }\r
 \r
-#endif\r
+#endif /* configQUEUE_REGISTRY_SIZE */\r
 /*-----------------------------------------------------------*/\r
 \r
-#if configUSE_TIMERS == 1\r
+#if ( configUSE_TIMERS == 1 )\r
 \r
        void vQueueWaitForMessageRestricted( xQueueHandle pxQueue, portTickType xTicksToWait )\r
        {\r
@@ -1682,5 +1765,113 @@ signed portBASE_TYPE xReturn;
                prvUnlockQueue( pxQueue );\r
        }\r
 \r
-#endif\r
+#endif /* configUSE_TIMERS */\r
+/*-----------------------------------------------------------*/\r
+\r
+#if ( configUSE_QUEUE_SETS == 1 )\r
+\r
+       xQueueSetHandle xQueueSetCreate( unsigned portBASE_TYPE uxEventQueueLength )\r
+       {\r
+       xQUEUE *pxQueue;\r
+\r
+               pxQueue = xQueueGenericCreate( uxEventQueueLength, sizeof( xQUEUE * ), queueQUEUE_TYPE_SET );\r
+\r
+               return ( xQueueSetHandle ) pxQueue;\r
+       }\r
+\r
+#endif /* configUSE_QUEUE_SETS */\r
+/*-----------------------------------------------------------*/\r
+\r
+#if ( configUSE_QUEUE_SETS == 1 )\r
+\r
+       portBASE_TYPE xQueueAddToQueueSet( xQueueHandle xQueue, xQueueSetHandle xQueueSet )\r
+       {\r
+       portBASE_TYPE xReturn;\r
+\r
+               if( xQueue->pxQueueSetContainer != NULL )\r
+               {\r
+                       xReturn = pdFAIL;\r
+               }\r
+               else\r
+               {\r
+                       taskENTER_CRITICAL();\r
+                       {\r
+                               xQueue->pxQueueSetContainer = xQueueSet;\r
+                       }\r
+                       taskEXIT_CRITICAL();\r
+                       xReturn = pdPASS;\r
+               }\r
+\r
+               return xReturn;\r
+       }\r
+\r
+#endif /* configUSE_QUEUE_SETS */\r
+/*-----------------------------------------------------------*/\r
+\r
+#if ( configUSE_QUEUE_SETS == 1 )\r
+\r
+       portBASE_TYPE xQueueRemoveFromQueueSet( xQueueSetHandle xQueueSet, xQueueHandle xQueue )\r
+       {\r
+       portBASE_TYPE xReturn;\r
+\r
+               if( xQueue->pxQueueSetContainer != xQueueSet )\r
+               {\r
+                       xReturn = pdFAIL;\r
+               }\r
+               else\r
+               {\r
+                       taskENTER_CRITICAL();\r
+                       {\r
+                               xQueue->pxQueueSetContainer = NULL;\r
+                       }\r
+                       taskEXIT_CRITICAL();\r
+                       xReturn = pdPASS;\r
+               }\r
+\r
+               return xReturn;\r
+       }\r
+\r
+#endif /* configUSE_QUEUE_SETS */\r
+/*-----------------------------------------------------------*/\r
+\r
+#if ( configUSE_QUEUE_SETS == 1 )\r
+\r
+       xQueueHandle xQueueReadMultiple( xQueueSetHandle xQueueSet, portTickType xBlockTimeTicks )\r
+       {\r
+       xQueueHandle xReturn = NULL;\r
+       \r
+               xQueueGenericReceive( ( xQueueHandle ) xQueueSet, &xReturn, xBlockTimeTicks, pdFALSE );\r
+               return xReturn;\r
+       }\r
+\r
+#endif /* configUSE_QUEUE_SETS */\r
+/*-----------------------------------------------------------*/\r
+\r
+#if ( configUSE_QUEUE_SETS == 1 )\r
+\r
+       static portBASE_TYPE prvCheckForMembershipOfQueueSet( xQUEUE *pxQueue, portBASE_TYPE xCopyPosition )\r
+       {\r
+       xQUEUE *pxQueueSetContainer = pxQueue->pxQueueSetContainer;\r
+       portBASE_TYPE xReturn = pdFALSE;\r
+\r
+               if( pxQueueSetContainer != NULL )\r
+               {\r
+                       if( pxQueueSetContainer->uxMessagesWaiting < pxQueueSetContainer->uxLength )\r
+                       {\r
+                               prvCopyDataToQueue( pxQueueSetContainer, &pxQueue, xCopyPosition );\r
+                               if( listLIST_IS_EMPTY( &( pxQueueSetContainer->xTasksWaitingToReceive ) ) == pdFALSE )\r
+                               {\r
+                                       if( xTaskRemoveFromEventList( &( pxQueue->pxQueueSetContainer->xTasksWaitingToReceive ) ) != pdFALSE )\r
+                                       {\r
+                                               /* The task waiting has a higher priority */\r
+                                               xReturn = pdTRUE;\r
+                                       }\r
+                               }\r
+                       }\r
+               }\r
+\r
+               return xReturn;\r
+       }\r
+\r
+#endif /* configUSE_QUEUE_SETS */\r
 \r