]> rtime.felk.cvut.cz Git - pes-rpp/rpp-lib.git/blob - os/7.4.0/src/os/queue.c
Remove the name of the platform from the OS folder name
[pes-rpp/rpp-lib.git] / os / 7.4.0 / src / os / queue.c
1 /*
2     FreeRTOS V7.4.0 - Copyright (C) 2013 Real Time Engineers Ltd.
3
4     FEATURES AND PORTS ARE ADDED TO FREERTOS ALL THE TIME.  PLEASE VISIT
5     http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
6
7     ***************************************************************************
8      *                                                                       *
9      *    FreeRTOS tutorial books are available in pdf and paperback.        *
10      *    Complete, revised, and edited pdf reference manuals are also       *
11      *    available.                                                         *
12      *                                                                       *
13      *    Purchasing FreeRTOS documentation will not only help you, by       *
14      *    ensuring you get running as quickly as possible and with an        *
15      *    in-depth knowledge of how to use FreeRTOS, it will also help       *
16      *    the FreeRTOS project to continue with its mission of providing     *
17      *    professional grade, cross platform, de facto standard solutions    *
18      *    for microcontrollers - completely free of charge!                  *
19      *                                                                       *
20      *    >>> See http://www.FreeRTOS.org/Documentation for details. <<<     *
21      *                                                                       *
22      *    Thank you for using FreeRTOS, and thank you for your support!      *
23      *                                                                       *
24     ***************************************************************************
25
26
27     This file is part of the FreeRTOS distribution.
28
29     FreeRTOS is free software; you can redistribute it and/or modify it under
30     the terms of the GNU General Public License (version 2) as published by the
31     Free Software Foundation AND MODIFIED BY the FreeRTOS exception.
32
33     >>>>>>NOTE<<<<<< The modification to the GPL is included to allow you to
34     distribute a combined work that includes FreeRTOS without being obliged to
35     provide the source code for proprietary components outside of the FreeRTOS
36     kernel.
37
38     FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY
39     WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
40     FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
41     details. You should have received a copy of the GNU General Public License
42     and the FreeRTOS license exception along with FreeRTOS; if not itcan be
43     viewed here: http://www.freertos.org/a00114.html and also obtained by
44     writing to Real Time Engineers Ltd., contact details for whom are available
45     on the FreeRTOS WEB site.
46
47     1 tab == 4 spaces!
48
49     ***************************************************************************
50      *                                                                       *
51      *    Having a problem?  Start by reading the FAQ "My application does   *
52      *    not run, what could be wrong?"                                     *
53      *                                                                       *
54      *    http://www.FreeRTOS.org/FAQHelp.html                               *
55      *                                                                       *
56     ***************************************************************************
57
58
59     http://www.FreeRTOS.org - Documentation, books, training, latest versions,
60     license and Real Time Engineers Ltd. contact details.
61
62     http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,
63     including FreeRTOS+Trace - an indispensable productivity tool, and our new
64     fully thread aware and reentrant UDP/IP stack.
65
66     http://www.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High
67     Integrity Systems, who sell the code with commercial support,
68     indemnification and middleware, under the OpenRTOS brand.
69
70     http://www.SafeRTOS.com - High Integrity Systems also provide a safety
71     engineered and independently SIL3 certified version for use in safety and
72     mission critical applications that require provable dependability.
73 */
74
75 #include <stdlib.h>
76 #include <string.h>
77
78 /* Defining MPU_WRAPPERS_INCLUDED_FROM_API_FILE prevents task.h from redefining
79 all the API functions to use the MPU wrappers.  That should only be done when
80 task.h is included from an application file. */
81 #define MPU_WRAPPERS_INCLUDED_FROM_API_FILE
82
83 #include "os/FreeRTOS.h"
84 #include "os/task.h"
85 #include "os/queue.h"
86
87 #if ( configUSE_CO_ROUTINES == 1 )
88     #include "croutine.h"
89 #endif
90
91 #undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE
92
93 /* Constants used with the cRxLock and xTxLock structure members. */
94 #define queueUNLOCKED                   ( ( signed portBASE_TYPE ) -1 )
95 #define queueLOCKED_UNMODIFIED          ( ( signed portBASE_TYPE ) 0 )
96
97 #define queueERRONEOUS_UNBLOCK          ( -1 )
98
99 /* Effectively make a union out of the xQUEUE structure. */
100 #define pxMutexHolder                   pcTail
101 #define uxQueueType                     pcHead
102 #define uxRecursiveCallCount            pcReadFrom
103 #define queueQUEUE_IS_MUTEX             NULL
104
105 /* Semaphores do not actually store or copy data, so have an items size of
106 zero. */
107 #define queueSEMAPHORE_QUEUE_ITEM_LENGTH ( ( unsigned portBASE_TYPE ) 0 )
108 #define queueDONT_BLOCK                  ( ( portTickType ) 0U )
109 #define queueMUTEX_GIVE_BLOCK_TIME       ( ( portTickType ) 0U )
110
111
112 /*
113  * Definition of the queue used by the scheduler.
114  * Items are queued by copy, not reference.
115  */
116 typedef struct QueueDefinition
117 {
118     signed char *pcHead;                    /*< Points to the beginning of the queue storage area. */
119     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. */
120
121     signed char *pcWriteTo;                 /*< Points to the free next place in the storage area. */
122     signed char *pcReadFrom;                /*< Points to the last place that a queued item was read from. */
123
124     xList xTasksWaitingToSend;              /*< List of tasks that are blocked waiting to post onto this queue.  Stored in priority order. */
125     xList xTasksWaitingToReceive;           /*< List of tasks that are blocked waiting to read from this queue.  Stored in priority order. */
126
127     volatile unsigned portBASE_TYPE uxMessagesWaiting;/*< The number of items currently in the queue. */
128     unsigned portBASE_TYPE uxLength;        /*< The length of the queue defined as the number of items it will hold, not the number of bytes. */
129     unsigned portBASE_TYPE uxItemSize;      /*< The size of each items that the queue will hold. */
130
131     volatile signed portBASE_TYPE xRxLock;  /*< Stores the number of items received from the queue (removed from the queue) while the queue was locked.  Set to queueUNLOCKED when the queue is not locked. */
132     volatile signed portBASE_TYPE xTxLock;  /*< Stores the number of items transmitted to the queue (added to the queue) while the queue was locked.  Set to queueUNLOCKED when the queue is not locked. */
133
134     #if ( configUSE_TRACE_FACILITY == 1 )
135         unsigned char ucQueueNumber;
136         unsigned char ucQueueType;
137     #endif
138
139     #if ( configUSE_QUEUE_SETS == 1 )
140         struct QueueDefinition *pxQueueSetContainer;
141     #endif
142
143 } xQUEUE;
144 /*-----------------------------------------------------------*/
145
146 /*
147  * The queue registry is just a means for kernel aware debuggers to locate
148  * queue structures.  It has no other purpose so is an optional component.
149  */
150 #if ( configQUEUE_REGISTRY_SIZE > 0 )
151
152     /* The type stored within the queue registry array.  This allows a name
153     to be assigned to each queue making kernel aware debugging a little
154     more user friendly. */
155     typedef struct QUEUE_REGISTRY_ITEM
156     {
157         signed char *pcQueueName;
158         xQueueHandle xHandle;
159     } xQueueRegistryItem;
160
161     /* The queue registry is simply an array of xQueueRegistryItem structures.
162     The pcQueueName member of a structure being NULL is indicative of the
163     array position being vacant. */
164     xQueueRegistryItem xQueueRegistry[ configQUEUE_REGISTRY_SIZE ];
165
166     /* Removes a queue from the registry by simply setting the pcQueueName
167     member to NULL. */
168     static void prvQueueUnregisterQueue( xQueueHandle xQueue ) PRIVILEGED_FUNCTION;
169
170 #endif /* configQUEUE_REGISTRY_SIZE */
171
172 /*
173  * Unlocks a queue locked by a call to prvLockQueue.  Locking a queue does not
174  * prevent an ISR from adding or removing items to the queue, but does prevent
175  * an ISR from removing tasks from the queue event lists.  If an ISR finds a
176  * queue is locked it will instead increment the appropriate queue lock count
177  * to indicate that a task may require unblocking.  When the queue in unlocked
178  * these lock counts are inspected, and the appropriate action taken.
179  */
180 static void prvUnlockQueue( xQUEUE *pxQueue ) PRIVILEGED_FUNCTION;
181
182 /*
183  * Uses a critical section to determine if there is any data in a queue.
184  *
185  * @return pdTRUE if the queue contains no items, otherwise pdFALSE.
186  */
187 static signed portBASE_TYPE prvIsQueueEmpty( const xQUEUE *pxQueue ) PRIVILEGED_FUNCTION;
188
189 /*
190  * Uses a critical section to determine if there is any space in a queue.
191  *
192  * @return pdTRUE if there is no space, otherwise pdFALSE;
193  */
194 static signed portBASE_TYPE prvIsQueueFull( const xQUEUE *pxQueue ) PRIVILEGED_FUNCTION;
195
196 /*
197  * Copies an item into the queue, either at the front of the queue or the
198  * back of the queue.
199  */
200 static void prvCopyDataToQueue( xQUEUE *pxQueue, const void *pvItemToQueue, portBASE_TYPE xPosition ) PRIVILEGED_FUNCTION;
201
202 /*
203  * Copies an item out of a queue.
204  */
205 static void prvCopyDataFromQueue( xQUEUE * const pxQueue, const void *pvBuffer ) PRIVILEGED_FUNCTION;
206
207 #if ( configUSE_QUEUE_SETS == 1 )
208     /*
209      * Checks to see if a queue is a member of a queue set, and if so, notifies
210      * the queue set that the queue contains data.
211      */
212     static portBASE_TYPE prvNotifyQueueSetContainer( xQUEUE *pxQueue, portBASE_TYPE xCopyPosition );
213 #endif
214
215 /*-----------------------------------------------------------*/
216
217 /*
218  * Macro to mark a queue as locked.  Locking a queue prevents an ISR from
219  * accessing the queue event lists.
220  */
221 #define prvLockQueue( pxQueue )                             \
222     taskENTER_CRITICAL();                                   \
223     {                                                       \
224         if( ( pxQueue )->xRxLock == queueUNLOCKED )         \
225         {                                                   \
226             ( pxQueue )->xRxLock = queueLOCKED_UNMODIFIED;  \
227         }                                                   \
228         if( ( pxQueue )->xTxLock == queueUNLOCKED )         \
229         {                                                   \
230             ( pxQueue )->xTxLock = queueLOCKED_UNMODIFIED;  \
231         }                                                   \
232     }                                                       \
233     taskEXIT_CRITICAL()
234 /*-----------------------------------------------------------*/
235
236 portBASE_TYPE xQueueGenericReset( xQueueHandle xQueue, portBASE_TYPE xNewQueue )
237 {
238 xQUEUE *pxQueue;
239
240     pxQueue = ( xQUEUE * ) xQueue;
241     configASSERT( pxQueue );
242
243     taskENTER_CRITICAL();
244     {
245         pxQueue->pcTail = pxQueue->pcHead + ( pxQueue->uxLength * pxQueue->uxItemSize );
246         pxQueue->uxMessagesWaiting = ( unsigned portBASE_TYPE ) 0U;
247         pxQueue->pcWriteTo = pxQueue->pcHead;
248         pxQueue->pcReadFrom = pxQueue->pcHead + ( ( pxQueue->uxLength - ( unsigned portBASE_TYPE ) 1U ) * pxQueue->uxItemSize );
249         pxQueue->xRxLock = queueUNLOCKED;
250         pxQueue->xTxLock = queueUNLOCKED;
251
252         if( xNewQueue == pdFALSE )
253         {
254             /* If there are tasks blocked waiting to read from the queue, then
255             the tasks will remain blocked as after this function exits the queue
256             will still be empty.  If there are tasks blocked waiting to write to
257             the queue, then one should be unblocked as after this function exits
258             it will be possible to write to it. */
259             if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) == pdFALSE )
260             {
261                 if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) == pdTRUE )
262                 {
263                     portYIELD_WITHIN_API();
264                 }
265             }
266         }
267         else
268         {
269             /* Ensure the event queues start in the correct state. */
270             vListInitialise( &( pxQueue->xTasksWaitingToSend ) );
271             vListInitialise( &( pxQueue->xTasksWaitingToReceive ) );
272         }
273     }
274     taskEXIT_CRITICAL();
275
276     /* A value is returned for calling semantic consistency with previous
277     versions. */
278     return pdPASS;
279 }
280 /*-----------------------------------------------------------*/
281
282 xQueueHandle xQueueGenericCreate( unsigned portBASE_TYPE uxQueueLength, unsigned portBASE_TYPE uxItemSize, unsigned char ucQueueType )
283 {
284 xQUEUE *pxNewQueue;
285 size_t xQueueSizeInBytes;
286 xQueueHandle xReturn = NULL;
287
288     /* Remove compiler warnings about unused parameters should
289     configUSE_TRACE_FACILITY not be set to 1. */
290     ( void ) ucQueueType;
291
292     /* Allocate the new queue structure. */
293     if( uxQueueLength > ( unsigned portBASE_TYPE ) 0 )
294     {
295         pxNewQueue = ( xQUEUE * ) pvPortMalloc( sizeof( xQUEUE ) );
296         if( pxNewQueue != NULL )
297         {
298             /* Create the list of pointers to queue items.  The queue is one byte
299             longer than asked for to make wrap checking easier/faster. */
300             xQueueSizeInBytes = ( size_t ) ( uxQueueLength * uxItemSize ) + ( size_t ) 1;
301
302             pxNewQueue->pcHead = ( signed char * ) pvPortMalloc( xQueueSizeInBytes );
303             if( pxNewQueue->pcHead != NULL )
304             {
305                 /* Initialise the queue members as described above where the
306                 queue type is defined. */
307                 pxNewQueue->uxLength = uxQueueLength;
308                 pxNewQueue->uxItemSize = uxItemSize;
309                 xQueueGenericReset( pxNewQueue, pdTRUE );
310
311                 #if ( configUSE_TRACE_FACILITY == 1 )
312                 {
313                     pxNewQueue->ucQueueType = ucQueueType;
314                 }
315                 #endif /* configUSE_TRACE_FACILITY */
316
317                 #if( configUSE_QUEUE_SETS == 1 )
318                 {
319                     pxNewQueue->pxQueueSetContainer = NULL;
320                 }
321                 #endif /* configUSE_QUEUE_SETS */
322
323                 traceQUEUE_CREATE( pxNewQueue );
324                 xReturn = pxNewQueue;
325             }
326             else
327             {
328                 traceQUEUE_CREATE_FAILED( ucQueueType );
329                 vPortFree( pxNewQueue );
330             }
331         }
332     }
333
334     configASSERT( xReturn );
335
336     return xReturn;
337 }
338 /*-----------------------------------------------------------*/
339
340 #if ( configUSE_MUTEXES == 1 )
341
342     xQueueHandle xQueueCreateMutex( unsigned char ucQueueType )
343     {
344     xQUEUE *pxNewQueue;
345
346         /* Prevent compiler warnings about unused parameters if
347         configUSE_TRACE_FACILITY does not equal 1. */
348         ( void ) ucQueueType;
349
350         /* Allocate the new queue structure. */
351         pxNewQueue = ( xQUEUE * ) pvPortMalloc( sizeof( xQUEUE ) );
352         if( pxNewQueue != NULL )
353         {
354             /* Information required for priority inheritance. */
355             pxNewQueue->pxMutexHolder = NULL;
356             pxNewQueue->uxQueueType = queueQUEUE_IS_MUTEX;
357
358             /* Queues used as a mutex no data is actually copied into or out
359             of the queue. */
360             pxNewQueue->pcWriteTo = NULL;
361             pxNewQueue->pcReadFrom = NULL;
362
363             /* Each mutex has a length of 1 (like a binary semaphore) and
364             an item size of 0 as nothing is actually copied into or out
365             of the mutex. */
366             pxNewQueue->uxMessagesWaiting = ( unsigned portBASE_TYPE ) 0U;
367             pxNewQueue->uxLength = ( unsigned portBASE_TYPE ) 1U;
368             pxNewQueue->uxItemSize = ( unsigned portBASE_TYPE ) 0U;
369             pxNewQueue->xRxLock = queueUNLOCKED;
370             pxNewQueue->xTxLock = queueUNLOCKED;
371
372             #if ( configUSE_TRACE_FACILITY == 1 )
373             {
374                 pxNewQueue->ucQueueType = ucQueueType;
375             }
376             #endif
377
378             #if ( configUSE_QUEUE_SETS == 1 )
379             {
380                 pxNewQueue->pxQueueSetContainer = NULL;
381             }
382             #endif
383
384             /* Ensure the event queues start with the correct state. */
385             vListInitialise( &( pxNewQueue->xTasksWaitingToSend ) );
386             vListInitialise( &( pxNewQueue->xTasksWaitingToReceive ) );
387
388             traceCREATE_MUTEX( pxNewQueue );
389
390             /* Start with the semaphore in the expected state. */
391             xQueueGenericSend( pxNewQueue, NULL, ( portTickType ) 0U, queueSEND_TO_BACK );
392         }
393         else
394         {
395             traceCREATE_MUTEX_FAILED();
396         }
397
398         configASSERT( pxNewQueue );
399         return pxNewQueue;
400     }
401
402 #endif /* configUSE_MUTEXES */
403 /*-----------------------------------------------------------*/
404
405 #if ( ( configUSE_MUTEXES == 1 ) && ( INCLUDE_xSemaphoreGetMutexHolder == 1 ) )
406
407     void* xQueueGetMutexHolder( xQueueHandle xSemaphore )
408     {
409     void *pxReturn;
410
411         /* This function is called by xSemaphoreGetMutexHolder(), and should not
412         be called directly.  Note:  This is is a good way of determining if the
413         calling task is the mutex holder, but not a good way of determining the
414         identity of the mutex holder, as the holder may change between the
415         following critical section exiting and the function returning. */
416         taskENTER_CRITICAL();
417         {
418             if( ( ( xQUEUE * ) xSemaphore )->uxQueueType == queueQUEUE_IS_MUTEX )
419             {
420                 pxReturn = ( void * ) ( ( xQUEUE * ) xSemaphore )->pxMutexHolder;
421             }
422             else
423             {
424                 pxReturn = NULL;
425             }
426         }
427         taskEXIT_CRITICAL();
428
429         return pxReturn;
430     }
431
432 #endif
433 /*-----------------------------------------------------------*/
434
435 #if ( configUSE_RECURSIVE_MUTEXES == 1 )
436
437     portBASE_TYPE xQueueGiveMutexRecursive( xQueueHandle xMutex )
438     {
439     portBASE_TYPE xReturn;
440     xQUEUE *pxMutex;
441
442         pxMutex = ( xQUEUE * ) xMutex;
443         configASSERT( pxMutex );
444
445         /* If this is the task that holds the mutex then pxMutexHolder will not
446         change outside of this task.  If this task does not hold the mutex then
447         pxMutexHolder can never coincidentally equal the tasks handle, and as
448         this is the only condition we are interested in it does not matter if
449         pxMutexHolder is accessed simultaneously by another task.  Therefore no
450         mutual exclusion is required to test the pxMutexHolder variable. */
451         if( pxMutex->pxMutexHolder == xTaskGetCurrentTaskHandle() )
452         {
453             traceGIVE_MUTEX_RECURSIVE( pxMutex );
454
455             /* uxRecursiveCallCount cannot be zero if pxMutexHolder is equal to
456             the task handle, therefore no underflow check is required.  Also,
457             uxRecursiveCallCount is only modified by the mutex holder, and as
458             there can only be one, no mutual exclusion is required to modify the
459             uxRecursiveCallCount member. */
460             ( pxMutex->uxRecursiveCallCount )--;
461
462             /* Have we unwound the call count? */
463             if( pxMutex->uxRecursiveCallCount == 0 )
464             {
465                 /* Return the mutex.  This will automatically unblock any other
466                 task that might be waiting to access the mutex. */
467                 xQueueGenericSend( pxMutex, NULL, queueMUTEX_GIVE_BLOCK_TIME, queueSEND_TO_BACK );
468             }
469
470             xReturn = pdPASS;
471         }
472         else
473         {
474             /* We cannot give the mutex because we are not the holder. */
475             xReturn = pdFAIL;
476
477             traceGIVE_MUTEX_RECURSIVE_FAILED( pxMutex );
478         }
479
480         return xReturn;
481     }
482
483 #endif /* configUSE_RECURSIVE_MUTEXES */
484 /*-----------------------------------------------------------*/
485
486 #if ( configUSE_RECURSIVE_MUTEXES == 1 )
487
488     portBASE_TYPE xQueueTakeMutexRecursive( xQueueHandle xMutex, portTickType xBlockTime )
489     {
490     portBASE_TYPE xReturn;
491     xQUEUE *pxMutex;
492
493         pxMutex = ( xQUEUE * ) xMutex;
494         configASSERT( pxMutex );
495
496         /* Comments regarding mutual exclusion as per those within
497         xQueueGiveMutexRecursive(). */
498
499         traceTAKE_MUTEX_RECURSIVE( pxMutex );
500
501         if( pxMutex->pxMutexHolder == xTaskGetCurrentTaskHandle() )
502         {
503             ( pxMutex->uxRecursiveCallCount )++;
504             xReturn = pdPASS;
505         }
506         else
507         {
508             xReturn = xQueueGenericReceive( pxMutex, NULL, xBlockTime, pdFALSE );
509
510             /* pdPASS will only be returned if we successfully obtained the mutex,
511             we may have blocked to reach here. */
512             if( xReturn == pdPASS )
513             {
514                 ( pxMutex->uxRecursiveCallCount )++;
515             }
516             else
517             {
518                 traceTAKE_MUTEX_RECURSIVE_FAILED( pxMutex );
519             }
520         }
521
522         return xReturn;
523     }
524
525 #endif /* configUSE_RECURSIVE_MUTEXES */
526 /*-----------------------------------------------------------*/
527
528 #if ( configUSE_COUNTING_SEMAPHORES == 1 )
529
530     xQueueHandle xQueueCreateCountingSemaphore( unsigned portBASE_TYPE uxCountValue, unsigned portBASE_TYPE uxInitialCount )
531     {
532     xQueueHandle xHandle;
533
534         xHandle = xQueueGenericCreate( ( unsigned portBASE_TYPE ) uxCountValue, queueSEMAPHORE_QUEUE_ITEM_LENGTH, queueQUEUE_TYPE_COUNTING_SEMAPHORE );
535
536         if( xHandle != NULL )
537         {
538             ( ( xQUEUE * ) xHandle )->uxMessagesWaiting = uxInitialCount;
539
540             traceCREATE_COUNTING_SEMAPHORE();
541         }
542         else
543         {
544             traceCREATE_COUNTING_SEMAPHORE_FAILED();
545         }
546
547         configASSERT( xHandle );
548         return xHandle;
549     }
550
551 #endif /* configUSE_COUNTING_SEMAPHORES */
552 /*-----------------------------------------------------------*/
553
554 signed portBASE_TYPE xQueueGenericSend( xQueueHandle xQueue, const void * const pvItemToQueue, portTickType xTicksToWait, portBASE_TYPE xCopyPosition )
555 {
556 signed portBASE_TYPE xEntryTimeSet = pdFALSE;
557 xTimeOutType xTimeOut;
558 xQUEUE *pxQueue;
559
560     pxQueue = ( xQUEUE * ) xQueue;
561     configASSERT( pxQueue );
562     configASSERT( !( ( pvItemToQueue == NULL ) && ( pxQueue->uxItemSize != ( unsigned portBASE_TYPE ) 0U ) ) );
563
564     /* This function relaxes the coding standard somewhat to allow return
565     statements within the function itself.  This is done in the interest
566     of execution time efficiency. */
567     for( ;; )
568     {
569         taskENTER_CRITICAL();
570         {
571             /* Is there room on the queue now?  To be running we must be
572             the highest priority task wanting to access the queue. */
573             if( pxQueue->uxMessagesWaiting < pxQueue->uxLength )
574             {
575                 traceQUEUE_SEND( pxQueue );
576                 prvCopyDataToQueue( pxQueue, pvItemToQueue, xCopyPosition );
577
578                 #if ( configUSE_QUEUE_SETS == 1 )
579                 {
580                     if( pxQueue->pxQueueSetContainer != NULL )
581                     {
582                         if( prvNotifyQueueSetContainer( pxQueue, xCopyPosition ) == pdTRUE )
583                         {
584                             /* The queue is a member of a queue set, and posting
585                             to the queue set caused a higher priority task to
586                             unblock. A context switch is required. */
587                             portYIELD_WITHIN_API();
588                         }
589                     }
590                     else
591                     {
592                         /* If there was a task waiting for data to arrive on the
593                         queue then unblock it now. */
594                         if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE )
595                         {
596                             if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) == pdTRUE )
597                             {
598                                 /* The unblocked task has a priority higher than
599                                 our own so yield immediately.  Yes it is ok to
600                                 do this from within the critical section - the
601                                 kernel takes care of that. */
602                                 portYIELD_WITHIN_API();
603                             }
604                         }
605                     }
606                 }
607                 #else /* configUSE_QUEUE_SETS */
608                 {
609                     /* If there was a task waiting for data to arrive on the
610                     queue then unblock it now. */
611                     if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE )
612                     {
613                         if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) == pdTRUE )
614                         {
615                             /* The unblocked task has a priority higher than
616                             our own so yield immediately.  Yes it is ok to do
617                             this from within the critical section - the kernel
618                             takes care of that. */
619                             portYIELD_WITHIN_API();
620                         }
621                     }
622                 }
623                 #endif /* configUSE_QUEUE_SETS */
624
625                 taskEXIT_CRITICAL();
626
627                 /* Return to the original privilege level before exiting the
628                 function. */
629                 return pdPASS;
630             }
631             else
632             {
633                 if( xTicksToWait == ( portTickType ) 0 )
634                 {
635                     /* The queue was full and no block time is specified (or
636                     the block time has expired) so leave now. */
637                     taskEXIT_CRITICAL();
638
639                     /* Return to the original privilege level before exiting
640                     the function. */
641                     traceQUEUE_SEND_FAILED( pxQueue );
642                     return errQUEUE_FULL;
643                 }
644                 else if( xEntryTimeSet == pdFALSE )
645                 {
646                     /* The queue was full and a block time was specified so
647                     configure the timeout structure. */
648                     vTaskSetTimeOutState( &xTimeOut );
649                     xEntryTimeSet = pdTRUE;
650                 }
651             }
652         }
653         taskEXIT_CRITICAL();
654
655         /* Interrupts and other tasks can send to and receive from the queue
656         now the critical section has been exited. */
657
658         vTaskSuspendAll();
659         prvLockQueue( pxQueue );
660
661         /* Update the timeout state to see if it has expired yet. */
662         if( xTaskCheckForTimeOut( &xTimeOut, &xTicksToWait ) == pdFALSE )
663         {
664             if( prvIsQueueFull( pxQueue ) != pdFALSE )
665             {
666                 traceBLOCKING_ON_QUEUE_SEND( pxQueue );
667                 vTaskPlaceOnEventList( &( pxQueue->xTasksWaitingToSend ), xTicksToWait );
668
669                 /* Unlocking the queue means queue events can effect the
670                 event list.  It is possible that interrupts occurring now
671                 remove this task from the event list again - but as the
672                 scheduler is suspended the task will go onto the pending
673                 ready last instead of the actual ready list. */
674                 prvUnlockQueue( pxQueue );
675
676                 /* Resuming the scheduler will move tasks from the pending
677                 ready list into the ready list - so it is feasible that this
678                 task is already in a ready list before it yields - in which
679                 case the yield will not cause a context switch unless there
680                 is also a higher priority task in the pending ready list. */
681                 if( xTaskResumeAll() == pdFALSE )
682                 {
683                     portYIELD_WITHIN_API();
684                 }
685             }
686             else
687             {
688                 /* Try again. */
689                 prvUnlockQueue( pxQueue );
690                 ( void ) xTaskResumeAll();
691             }
692         }
693         else
694         {
695             /* The timeout has expired. */
696             prvUnlockQueue( pxQueue );
697             ( void ) xTaskResumeAll();
698
699             /* Return to the original privilege level before exiting the
700             function. */
701             traceQUEUE_SEND_FAILED( pxQueue );
702             return errQUEUE_FULL;
703         }
704     }
705 }
706 /*-----------------------------------------------------------*/
707
708 #if ( configUSE_ALTERNATIVE_API == 1 )
709
710     signed portBASE_TYPE xQueueAltGenericSend( xQueueHandle xQueue, const void * const pvItemToQueue, portTickType xTicksToWait, portBASE_TYPE xCopyPosition )
711     {
712     signed portBASE_TYPE xEntryTimeSet = pdFALSE;
713     xTimeOutType xTimeOut;
714     xQUEUE *pxQueue;
715
716         pxQueue = ( xQUEUE * ) xQueue;
717         configASSERT( pxQueue );
718         configASSERT( !( ( pvItemToQueue == NULL ) && ( pxQueue->uxItemSize != ( unsigned portBASE_TYPE ) 0U ) ) );
719
720         for( ;; )
721         {
722             taskENTER_CRITICAL();
723             {
724                 /* Is there room on the queue now?  To be running we must be
725                 the highest priority task wanting to access the queue. */
726                 if( pxQueue->uxMessagesWaiting < pxQueue->uxLength )
727                 {
728                     traceQUEUE_SEND( pxQueue );
729                     prvCopyDataToQueue( pxQueue, pvItemToQueue, xCopyPosition );
730
731                     /* If there was a task waiting for data to arrive on the
732                     queue then unblock it now. */
733                     if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE )
734                     {
735                         if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) == pdTRUE )
736                         {
737                             /* The unblocked task has a priority higher than
738                             our own so yield immediately. */
739                             portYIELD_WITHIN_API();
740                         }
741                     }
742
743                     taskEXIT_CRITICAL();
744                     return pdPASS;
745                 }
746                 else
747                 {
748                     if( xTicksToWait == ( portTickType ) 0 )
749                     {
750                         taskEXIT_CRITICAL();
751                         return errQUEUE_FULL;
752                     }
753                     else if( xEntryTimeSet == pdFALSE )
754                     {
755                         vTaskSetTimeOutState( &xTimeOut );
756                         xEntryTimeSet = pdTRUE;
757                     }
758                 }
759             }
760             taskEXIT_CRITICAL();
761
762             taskENTER_CRITICAL();
763             {
764                 if( xTaskCheckForTimeOut( &xTimeOut, &xTicksToWait ) == pdFALSE )
765                 {
766                     if( prvIsQueueFull( pxQueue ) != pdFALSE )
767                     {
768                         traceBLOCKING_ON_QUEUE_SEND( pxQueue );
769                         vTaskPlaceOnEventList( &( pxQueue->xTasksWaitingToSend ), xTicksToWait );
770                         portYIELD_WITHIN_API();
771                     }
772                 }
773                 else
774                 {
775                     taskEXIT_CRITICAL();
776                     traceQUEUE_SEND_FAILED( pxQueue );
777                     return errQUEUE_FULL;
778                 }
779             }
780             taskEXIT_CRITICAL();
781         }
782     }
783
784 #endif /* configUSE_ALTERNATIVE_API */
785 /*-----------------------------------------------------------*/
786
787 #if ( configUSE_ALTERNATIVE_API == 1 )
788
789     signed portBASE_TYPE xQueueAltGenericReceive( xQueueHandle xQueue, void * const pvBuffer, portTickType xTicksToWait, portBASE_TYPE xJustPeeking )
790     {
791     signed portBASE_TYPE xEntryTimeSet = pdFALSE;
792     xTimeOutType xTimeOut;
793     signed char *pcOriginalReadPosition;
794     xQUEUE *pxQueue;
795
796         pxQueue = ( xQUEUE * ) xQueue;
797         configASSERT( pxQueue );
798         configASSERT( !( ( pvBuffer == NULL ) && ( pxQueue->uxItemSize != ( unsigned portBASE_TYPE ) 0U ) ) );
799
800         for( ;; )
801         {
802             taskENTER_CRITICAL();
803             {
804                 if( pxQueue->uxMessagesWaiting > ( unsigned portBASE_TYPE ) 0 )
805                 {
806                     /* Remember our read position in case we are just peeking. */
807                     pcOriginalReadPosition = pxQueue->pcReadFrom;
808
809                     prvCopyDataFromQueue( pxQueue, pvBuffer );
810
811                     if( xJustPeeking == pdFALSE )
812                     {
813                         traceQUEUE_RECEIVE( pxQueue );
814
815                         /* We are actually removing data. */
816                         --( pxQueue->uxMessagesWaiting );
817
818                         #if ( configUSE_MUTEXES == 1 )
819                         {
820                             if( pxQueue->uxQueueType == queueQUEUE_IS_MUTEX )
821                             {
822                                 /* Record the information required to implement
823                                 priority inheritance should it become necessary. */
824                                 pxQueue->pxMutexHolder = xTaskGetCurrentTaskHandle();
825                             }
826                         }
827                         #endif
828
829                         if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) == pdFALSE )
830                         {
831                             if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) == pdTRUE )
832                             {
833                                 portYIELD_WITHIN_API();
834                             }
835                         }
836                     }
837                     else
838                     {
839                         traceQUEUE_PEEK( pxQueue );
840
841                         /* We are not removing the data, so reset our read
842                         pointer. */
843                         pxQueue->pcReadFrom = pcOriginalReadPosition;
844
845                         /* The data is being left in the queue, so see if there are
846                         any other tasks waiting for the data. */
847                         if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE )
848                         {
849                             /* Tasks that are removed from the event list will get added to
850                             the pending ready list as the scheduler is still suspended. */
851                             if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE )
852                             {
853                                 /* The task waiting has a higher priority than this task. */
854                                 portYIELD_WITHIN_API();
855                             }
856                         }
857
858                     }
859
860                     taskEXIT_CRITICAL();
861                     return pdPASS;
862                 }
863                 else
864                 {
865                     if( xTicksToWait == ( portTickType ) 0 )
866                     {
867                         taskEXIT_CRITICAL();
868                         traceQUEUE_RECEIVE_FAILED( pxQueue );
869                         return errQUEUE_EMPTY;
870                     }
871                     else if( xEntryTimeSet == pdFALSE )
872                     {
873                         vTaskSetTimeOutState( &xTimeOut );
874                         xEntryTimeSet = pdTRUE;
875                     }
876                 }
877             }
878             taskEXIT_CRITICAL();
879
880             taskENTER_CRITICAL();
881             {
882                 if( xTaskCheckForTimeOut( &xTimeOut, &xTicksToWait ) == pdFALSE )
883                 {
884                     if( prvIsQueueEmpty( pxQueue ) != pdFALSE )
885                     {
886                         traceBLOCKING_ON_QUEUE_RECEIVE( pxQueue );
887
888                         #if ( configUSE_MUTEXES == 1 )
889                         {
890                             if( pxQueue->uxQueueType == queueQUEUE_IS_MUTEX )
891                             {
892                                 portENTER_CRITICAL();
893                                 {
894                                     vTaskPriorityInherit( ( void * ) pxQueue->pxMutexHolder );
895                                 }
896                                 portEXIT_CRITICAL();
897                             }
898                         }
899                         #endif
900
901                         vTaskPlaceOnEventList( &( pxQueue->xTasksWaitingToReceive ), xTicksToWait );
902                         portYIELD_WITHIN_API();
903                     }
904                 }
905                 else
906                 {
907                     taskEXIT_CRITICAL();
908                     traceQUEUE_RECEIVE_FAILED( pxQueue );
909                     return errQUEUE_EMPTY;
910                 }
911             }
912             taskEXIT_CRITICAL();
913         }
914     }
915
916
917 #endif /* configUSE_ALTERNATIVE_API */
918 /*-----------------------------------------------------------*/
919
920 signed portBASE_TYPE xQueueGenericSendFromISR( xQueueHandle xQueue, const void * const pvItemToQueue, signed portBASE_TYPE *pxHigherPriorityTaskWoken, portBASE_TYPE xCopyPosition )
921 {
922 signed portBASE_TYPE xReturn;
923 unsigned portBASE_TYPE uxSavedInterruptStatus;
924 xQUEUE *pxQueue;
925
926     pxQueue = ( xQUEUE * ) xQueue;
927     configASSERT( pxQueue );
928     configASSERT( !( ( pvItemToQueue == NULL ) && ( pxQueue->uxItemSize != ( unsigned portBASE_TYPE ) 0U ) ) );
929
930     /* Similar to xQueueGenericSend, except we don't block if there is no room
931     in the queue.  Also we don't directly wake a task that was blocked on a
932     queue read, instead we return a flag to say whether a context switch is
933     required or not (i.e. has a task with a higher priority than us been woken
934     by this post). */
935     uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR();
936     {
937         if( pxQueue->uxMessagesWaiting < pxQueue->uxLength )
938         {
939             traceQUEUE_SEND_FROM_ISR( pxQueue );
940
941             prvCopyDataToQueue( pxQueue, pvItemToQueue, xCopyPosition );
942
943             /* If the queue is locked we do not alter the event list.  This will
944             be done when the queue is unlocked later. */
945             if( pxQueue->xTxLock == queueUNLOCKED )
946             {
947                 #if ( configUSE_QUEUE_SETS == 1 )
948                 {
949                     if( pxQueue->pxQueueSetContainer != NULL )
950                     {
951                         if( prvNotifyQueueSetContainer( pxQueue, xCopyPosition ) == pdTRUE )
952                         {
953                             /* The queue is a member of a queue set, and posting
954                             to the queue set caused a higher priority task to
955                             unblock.  A context switch is required. */
956                             if( pxHigherPriorityTaskWoken != NULL )
957                             {
958                                 *pxHigherPriorityTaskWoken = pdTRUE;
959                             }
960                         }
961                     }
962                     else
963                     {
964                         if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE )
965                         {
966                             if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE )
967                             {
968                                 /* The task waiting has a higher priority so record that a
969                                 context switch is required. */
970                                 if( pxHigherPriorityTaskWoken != NULL )
971                                 {
972                                     *pxHigherPriorityTaskWoken = pdTRUE;
973                                 }
974                             }
975                         }
976                     }
977                 }
978                 #else /* configUSE_QUEUE_SETS */
979                 {
980                     if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE )
981                     {
982                         if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE )
983                         {
984                             /* The task waiting has a higher priority so record that a
985                             context switch is required. */
986                             if( pxHigherPriorityTaskWoken != NULL )
987                             {
988                                 *pxHigherPriorityTaskWoken = pdTRUE;
989                             }
990                         }
991                     }
992                 }
993                 #endif /* configUSE_QUEUE_SETS */
994             }
995             else
996             {
997                 /* Increment the lock count so the task that unlocks the queue
998                 knows that data was posted while it was locked. */
999                 ++( pxQueue->xTxLock );
1000             }
1001
1002             xReturn = pdPASS;
1003         }
1004         else
1005         {
1006             traceQUEUE_SEND_FROM_ISR_FAILED( pxQueue );
1007             xReturn = errQUEUE_FULL;
1008         }
1009     }
1010     portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus );
1011
1012     return xReturn;
1013 }
1014 /*-----------------------------------------------------------*/
1015
1016 signed portBASE_TYPE xQueueGenericReceive( xQueueHandle xQueue, void * const pvBuffer, portTickType xTicksToWait, portBASE_TYPE xJustPeeking )
1017 {
1018 signed portBASE_TYPE xEntryTimeSet = pdFALSE;
1019 xTimeOutType xTimeOut;
1020 signed char *pcOriginalReadPosition;
1021 xQUEUE *pxQueue;
1022
1023     pxQueue = ( xQUEUE * ) xQueue;
1024     configASSERT( pxQueue );
1025     configASSERT( !( ( pvBuffer == NULL ) && ( pxQueue->uxItemSize != ( unsigned portBASE_TYPE ) 0U ) ) );
1026
1027     /* This function relaxes the coding standard somewhat to allow return
1028     statements within the function itself.  This is done in the interest
1029     of execution time efficiency. */
1030
1031     for( ;; )
1032     {
1033         taskENTER_CRITICAL();
1034         {
1035             /* Is there data in the queue now?  To be running we must be
1036             the highest priority task wanting to access the queue. */
1037             if( pxQueue->uxMessagesWaiting > ( unsigned portBASE_TYPE ) 0 )
1038             {
1039                 /* Remember our read position in case we are just peeking. */
1040                 pcOriginalReadPosition = pxQueue->pcReadFrom;
1041
1042                 prvCopyDataFromQueue( pxQueue, pvBuffer );
1043
1044                 if( xJustPeeking == pdFALSE )
1045                 {
1046                     traceQUEUE_RECEIVE( pxQueue );
1047
1048                     /* We are actually removing data. */
1049                     --( pxQueue->uxMessagesWaiting );
1050
1051                     #if ( configUSE_MUTEXES == 1 )
1052                     {
1053                         if( pxQueue->uxQueueType == queueQUEUE_IS_MUTEX )
1054                         {
1055                             /* Record the information required to implement
1056                             priority inheritance should it become necessary. */
1057                             pxQueue->pxMutexHolder = xTaskGetCurrentTaskHandle();
1058                         }
1059                     }
1060                     #endif
1061
1062                     if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) == pdFALSE )
1063                     {
1064                         if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) == pdTRUE )
1065                         {
1066                             portYIELD_WITHIN_API();
1067                         }
1068                     }
1069                 }
1070                 else
1071                 {
1072                     traceQUEUE_PEEK( pxQueue );
1073
1074                     /* The data is not being removed, so reset the read
1075                     pointer. */
1076                     pxQueue->pcReadFrom = pcOriginalReadPosition;
1077
1078                     /* The data is being left in the queue, so see if there are
1079                     any other tasks waiting for the data. */
1080                     if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE )
1081                     {
1082                         /* Tasks that are removed from the event list will get added to
1083                         the pending ready list as the scheduler is still suspended. */
1084                         if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE )
1085                         {
1086                             /* The task waiting has a higher priority than this task. */
1087                             portYIELD_WITHIN_API();
1088                         }
1089                     }
1090                 }
1091
1092                 taskEXIT_CRITICAL();
1093                 return pdPASS;
1094             }
1095             else
1096             {
1097                 if( xTicksToWait == ( portTickType ) 0 )
1098                 {
1099                     /* The queue was empty and no block time is specified (or
1100                     the block time has expired) so leave now. */
1101                     taskEXIT_CRITICAL();
1102                     traceQUEUE_RECEIVE_FAILED( pxQueue );
1103                     return errQUEUE_EMPTY;
1104                 }
1105                 else if( xEntryTimeSet == pdFALSE )
1106                 {
1107                     /* The queue was empty and a block time was specified so
1108                     configure the timeout structure. */
1109                     vTaskSetTimeOutState( &xTimeOut );
1110                     xEntryTimeSet = pdTRUE;
1111                 }
1112             }
1113         }
1114         taskEXIT_CRITICAL();
1115
1116         /* Interrupts and other tasks can send to and receive from the queue
1117         now the critical section has been exited. */
1118
1119         vTaskSuspendAll();
1120         prvLockQueue( pxQueue );
1121
1122         /* Update the timeout state to see if it has expired yet. */
1123         if( xTaskCheckForTimeOut( &xTimeOut, &xTicksToWait ) == pdFALSE )
1124         {
1125             if( prvIsQueueEmpty( pxQueue ) != pdFALSE )
1126             {
1127                 traceBLOCKING_ON_QUEUE_RECEIVE( pxQueue );
1128
1129                 #if ( configUSE_MUTEXES == 1 )
1130                 {
1131                     if( pxQueue->uxQueueType == queueQUEUE_IS_MUTEX )
1132                     {
1133                         portENTER_CRITICAL();
1134                         {
1135                             vTaskPriorityInherit( ( void * ) pxQueue->pxMutexHolder );
1136                         }
1137                         portEXIT_CRITICAL();
1138                     }
1139                 }
1140                 #endif
1141
1142                 vTaskPlaceOnEventList( &( pxQueue->xTasksWaitingToReceive ), xTicksToWait );
1143                 prvUnlockQueue( pxQueue );
1144                 if( xTaskResumeAll() == pdFALSE )
1145                 {
1146                     portYIELD_WITHIN_API();
1147                 }
1148             }
1149             else
1150             {
1151                 /* Try again. */
1152                 prvUnlockQueue( pxQueue );
1153                 ( void ) xTaskResumeAll();
1154             }
1155         }
1156         else
1157         {
1158             prvUnlockQueue( pxQueue );
1159             ( void ) xTaskResumeAll();
1160             traceQUEUE_RECEIVE_FAILED( pxQueue );
1161             return errQUEUE_EMPTY;
1162         }
1163     }
1164 }
1165 /*-----------------------------------------------------------*/
1166
1167 signed portBASE_TYPE xQueueReceiveFromISR( xQueueHandle xQueue, void * const pvBuffer, signed portBASE_TYPE *pxHigherPriorityTaskWoken )
1168 {
1169 signed portBASE_TYPE xReturn;
1170 unsigned portBASE_TYPE uxSavedInterruptStatus;
1171 xQUEUE *pxQueue;
1172
1173     pxQueue = ( xQUEUE * ) xQueue;
1174     configASSERT( pxQueue );
1175     configASSERT( !( ( pvBuffer == NULL ) && ( pxQueue->uxItemSize != ( unsigned portBASE_TYPE ) 0U ) ) );
1176
1177     uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR();
1178     {
1179         /* We cannot block from an ISR, so check there is data available. */
1180         if( pxQueue->uxMessagesWaiting > ( unsigned portBASE_TYPE ) 0 )
1181         {
1182             traceQUEUE_RECEIVE_FROM_ISR( pxQueue );
1183
1184             prvCopyDataFromQueue( pxQueue, pvBuffer );
1185             --( pxQueue->uxMessagesWaiting );
1186
1187             /* If the queue is locked we will not modify the event list.  Instead
1188             we update the lock count so the task that unlocks the queue will know
1189             that an ISR has removed data while the queue was locked. */
1190             if( pxQueue->xRxLock == queueUNLOCKED )
1191             {
1192                 if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) == pdFALSE )
1193                 {
1194                     if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) != pdFALSE )
1195                     {
1196                         /* The task waiting has a higher priority than us so
1197                         force a context switch. */
1198                         if( pxHigherPriorityTaskWoken != NULL )
1199                         {
1200                             *pxHigherPriorityTaskWoken = pdTRUE;
1201                         }
1202                     }
1203                 }
1204             }
1205             else
1206             {
1207                 /* Increment the lock count so the task that unlocks the queue
1208                 knows that data was removed while it was locked. */
1209                 ++( pxQueue->xRxLock );
1210             }
1211
1212             xReturn = pdPASS;
1213         }
1214         else
1215         {
1216             xReturn = pdFAIL;
1217             traceQUEUE_RECEIVE_FROM_ISR_FAILED( pxQueue );
1218         }
1219     }
1220     portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus );
1221
1222     return xReturn;
1223 }
1224 /*-----------------------------------------------------------*/
1225
1226 unsigned portBASE_TYPE uxQueueMessagesWaiting( const xQueueHandle xQueue )
1227 {
1228 unsigned portBASE_TYPE uxReturn;
1229
1230     configASSERT( xQueue );
1231
1232     taskENTER_CRITICAL();
1233         uxReturn = ( ( xQUEUE * ) xQueue )->uxMessagesWaiting;
1234     taskEXIT_CRITICAL();
1235
1236     return uxReturn;
1237 }
1238 /*-----------------------------------------------------------*/
1239
1240 unsigned portBASE_TYPE uxQueueMessagesWaitingFromISR( const xQueueHandle xQueue )
1241 {
1242 unsigned portBASE_TYPE uxReturn;
1243
1244     configASSERT( xQueue );
1245
1246     uxReturn = ( ( xQUEUE * ) xQueue )->uxMessagesWaiting;
1247
1248     return uxReturn;
1249 }
1250 /*-----------------------------------------------------------*/
1251
1252 void vQueueDelete( xQueueHandle xQueue )
1253 {
1254 xQUEUE *pxQueue;
1255
1256     pxQueue = ( xQUEUE * ) xQueue;
1257     configASSERT( pxQueue );
1258
1259     traceQUEUE_DELETE( pxQueue );
1260     #if ( configQUEUE_REGISTRY_SIZE > 0 )
1261     {
1262         prvQueueUnregisterQueue( pxQueue );
1263     }
1264     #endif
1265     vPortFree( pxQueue->pcHead );
1266     vPortFree( pxQueue );
1267 }
1268 /*-----------------------------------------------------------*/
1269
1270 #if ( configUSE_TRACE_FACILITY == 1 )
1271
1272     unsigned char ucQueueGetQueueNumber( xQueueHandle xQueue )
1273     {
1274         return ( ( xQUEUE * ) xQueue )->ucQueueNumber;
1275     }
1276
1277 #endif /* configUSE_TRACE_FACILITY */
1278 /*-----------------------------------------------------------*/
1279
1280 #if ( configUSE_TRACE_FACILITY == 1 )
1281
1282     void vQueueSetQueueNumber( xQueueHandle xQueue, unsigned char ucQueueNumber )
1283     {
1284         ( ( xQUEUE * ) xQueue )->ucQueueNumber = ucQueueNumber;
1285     }
1286
1287 #endif /* configUSE_TRACE_FACILITY */
1288 /*-----------------------------------------------------------*/
1289
1290 #if ( configUSE_TRACE_FACILITY == 1 )
1291
1292     unsigned char ucQueueGetQueueType( xQueueHandle xQueue )
1293     {
1294         return ( ( xQUEUE * ) xQueue )->ucQueueType;
1295     }
1296
1297 #endif /* configUSE_TRACE_FACILITY */
1298 /*-----------------------------------------------------------*/
1299
1300 static void prvCopyDataToQueue( xQUEUE *pxQueue, const void *pvItemToQueue, portBASE_TYPE xPosition )
1301 {
1302     if( pxQueue->uxItemSize == ( unsigned portBASE_TYPE ) 0 )
1303     {
1304         #if ( configUSE_MUTEXES == 1 )
1305         {
1306             if( pxQueue->uxQueueType == queueQUEUE_IS_MUTEX )
1307             {
1308                 /* The mutex is no longer being held. */
1309                 vTaskPriorityDisinherit( ( void * ) pxQueue->pxMutexHolder );
1310                 pxQueue->pxMutexHolder = NULL;
1311             }
1312         }
1313         #endif
1314     }
1315     else if( xPosition == queueSEND_TO_BACK )
1316     {
1317         memcpy( ( void * ) pxQueue->pcWriteTo, pvItemToQueue, ( unsigned ) pxQueue->uxItemSize );
1318         pxQueue->pcWriteTo += pxQueue->uxItemSize;
1319         if( pxQueue->pcWriteTo >= pxQueue->pcTail )
1320         {
1321             pxQueue->pcWriteTo = pxQueue->pcHead;
1322         }
1323     }
1324     else
1325     {
1326         memcpy( ( void * ) pxQueue->pcReadFrom, pvItemToQueue, ( unsigned ) pxQueue->uxItemSize );
1327         pxQueue->pcReadFrom -= pxQueue->uxItemSize;
1328         if( pxQueue->pcReadFrom < pxQueue->pcHead )
1329         {
1330             pxQueue->pcReadFrom = ( pxQueue->pcTail - pxQueue->uxItemSize );
1331         }
1332     }
1333
1334     ++( pxQueue->uxMessagesWaiting );
1335 }
1336 /*-----------------------------------------------------------*/
1337
1338 static void prvCopyDataFromQueue( xQUEUE * const pxQueue, const void *pvBuffer )
1339 {
1340     if( pxQueue->uxQueueType != queueQUEUE_IS_MUTEX )
1341     {
1342         pxQueue->pcReadFrom += pxQueue->uxItemSize;
1343         if( pxQueue->pcReadFrom >= pxQueue->pcTail )
1344         {
1345             pxQueue->pcReadFrom = pxQueue->pcHead;
1346         }
1347         memcpy( ( void * ) pvBuffer, ( void * ) pxQueue->pcReadFrom, ( unsigned ) pxQueue->uxItemSize );
1348     }
1349 }
1350 /*-----------------------------------------------------------*/
1351
1352 static void prvUnlockQueue( xQUEUE *pxQueue )
1353 {
1354     /* THIS FUNCTION MUST BE CALLED WITH THE SCHEDULER SUSPENDED. */
1355
1356     /* The lock counts contains the number of extra data items placed or
1357     removed from the queue while the queue was locked.  When a queue is
1358     locked items can be added or removed, but the event lists cannot be
1359     updated. */
1360     taskENTER_CRITICAL();
1361     {
1362         /* See if data was added to the queue while it was locked. */
1363         while( pxQueue->xTxLock > queueLOCKED_UNMODIFIED )
1364         {
1365             /* Data was posted while the queue was locked.  Are any tasks
1366             blocked waiting for data to become available? */
1367             #if ( configUSE_QUEUE_SETS == 1 )
1368             {
1369                 if( pxQueue->pxQueueSetContainer != NULL )
1370                 {
1371                     if( prvNotifyQueueSetContainer( pxQueue, queueSEND_TO_BACK ) == pdTRUE )
1372                     {
1373                         /* The queue is a member of a queue set, and posting to
1374                         the queue set caused a higher priority task to unblock.
1375                         A context switch is required. */
1376                         vTaskMissedYield();
1377                     }
1378                 }
1379                 else
1380                 {
1381                     /* Tasks that are removed from the event list will get added to
1382                     the pending ready list as the scheduler is still suspended. */
1383                     if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE )
1384                     {
1385                         if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE )
1386                         {
1387                             /* The task waiting has a higher priority so record that a
1388                             context switch is required. */
1389                             vTaskMissedYield();
1390                         }
1391                     }
1392                     else
1393                     {
1394                         break;
1395                     }
1396                 }
1397             }
1398             #else /* configUSE_QUEUE_SETS */
1399             {
1400                 /* Tasks that are removed from the event list will get added to
1401                 the pending ready list as the scheduler is still suspended. */
1402                 if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE )
1403                 {
1404                     if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE )
1405                     {
1406                         /* The task waiting has a higher priority so record that a
1407                         context switch is required. */
1408                         vTaskMissedYield();
1409                     }
1410                 }
1411                 else
1412                 {
1413                     break;
1414                 }
1415             }
1416             #endif /* configUSE_QUEUE_SETS */
1417
1418             --( pxQueue->xTxLock );
1419         }
1420
1421         pxQueue->xTxLock = queueUNLOCKED;
1422     }
1423     taskEXIT_CRITICAL();
1424
1425     /* Do the same for the Rx lock. */
1426     taskENTER_CRITICAL();
1427     {
1428         while( pxQueue->xRxLock > queueLOCKED_UNMODIFIED )
1429         {
1430             if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) == pdFALSE )
1431             {
1432                 if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) != pdFALSE )
1433                 {
1434                     vTaskMissedYield();
1435                 }
1436
1437                 --( pxQueue->xRxLock );
1438             }
1439             else
1440             {
1441                 break;
1442             }
1443         }
1444
1445         pxQueue->xRxLock = queueUNLOCKED;
1446     }
1447     taskEXIT_CRITICAL();
1448 }
1449 /*-----------------------------------------------------------*/
1450
1451 static signed portBASE_TYPE prvIsQueueEmpty( const xQUEUE *pxQueue )
1452 {
1453 signed portBASE_TYPE xReturn;
1454
1455     taskENTER_CRITICAL();
1456     {
1457         if( pxQueue->uxMessagesWaiting == 0 )
1458         {
1459             xReturn = pdTRUE;
1460         }
1461         else
1462         {
1463             xReturn = pdFALSE;
1464         }
1465     }
1466     taskEXIT_CRITICAL();
1467
1468     return xReturn;
1469 }
1470 /*-----------------------------------------------------------*/
1471
1472 signed portBASE_TYPE xQueueIsQueueEmptyFromISR( const xQueueHandle xQueue )
1473 {
1474 signed portBASE_TYPE xReturn;
1475
1476     configASSERT( xQueue );
1477     if( ( ( xQUEUE * ) xQueue )->uxMessagesWaiting == 0 )
1478     {
1479         xReturn = pdTRUE;
1480     }
1481     else
1482     {
1483         xReturn = pdFALSE;
1484     }
1485
1486     return xReturn;
1487 }
1488 /*-----------------------------------------------------------*/
1489
1490 static signed portBASE_TYPE prvIsQueueFull( const xQUEUE *pxQueue )
1491 {
1492 signed portBASE_TYPE xReturn;
1493
1494     taskENTER_CRITICAL();
1495     {
1496         if( pxQueue->uxMessagesWaiting == pxQueue->uxLength )
1497         {
1498             xReturn = pdTRUE;
1499         }
1500         else
1501         {
1502             xReturn = pdFALSE;
1503         }
1504     }
1505     taskEXIT_CRITICAL();
1506
1507     return xReturn;
1508 }
1509 /*-----------------------------------------------------------*/
1510
1511 signed portBASE_TYPE xQueueIsQueueFullFromISR( const xQueueHandle xQueue )
1512 {
1513 signed portBASE_TYPE xReturn;
1514
1515     configASSERT( xQueue );
1516     if( ( ( xQUEUE * ) xQueue )->uxMessagesWaiting == ( ( xQUEUE * ) xQueue )->uxLength )
1517     {
1518         xReturn = pdTRUE;
1519     }
1520     else
1521     {
1522         xReturn = pdFALSE;
1523     }
1524
1525     return xReturn;
1526 }
1527 /*-----------------------------------------------------------*/
1528
1529 #if ( configUSE_CO_ROUTINES == 1 )
1530
1531     signed portBASE_TYPE xQueueCRSend( xQueueHandle xQueue, const void *pvItemToQueue, portTickType xTicksToWait )
1532     {
1533     signed portBASE_TYPE xReturn;
1534     xQUEUE *pxQueue;
1535
1536         pxQueue = ( xQUEUE * ) xQueue;
1537
1538         /* If the queue is already full we may have to block.  A critical section
1539         is required to prevent an interrupt removing something from the queue
1540         between the check to see if the queue is full and blocking on the queue. */
1541         portDISABLE_INTERRUPTS();
1542         {
1543             if( prvIsQueueFull( pxQueue ) != pdFALSE )
1544             {
1545                 /* The queue is full - do we want to block or just leave without
1546                 posting? */
1547                 if( xTicksToWait > ( portTickType ) 0 )
1548                 {
1549                     /* As this is called from a coroutine we cannot block directly, but
1550                     return indicating that we need to block. */
1551                     vCoRoutineAddToDelayedList( xTicksToWait, &( pxQueue->xTasksWaitingToSend ) );
1552                     portENABLE_INTERRUPTS();
1553                     return errQUEUE_BLOCKED;
1554                 }
1555                 else
1556                 {
1557                     portENABLE_INTERRUPTS();
1558                     return errQUEUE_FULL;
1559                 }
1560             }
1561         }
1562         portENABLE_INTERRUPTS();
1563
1564         portDISABLE_INTERRUPTS();
1565         {
1566             if( pxQueue->uxMessagesWaiting < pxQueue->uxLength )
1567             {
1568                 /* There is room in the queue, copy the data into the queue. */
1569                 prvCopyDataToQueue( pxQueue, pvItemToQueue, queueSEND_TO_BACK );
1570                 xReturn = pdPASS;
1571
1572                 /* Were any co-routines waiting for data to become available? */
1573                 if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE )
1574                 {
1575                     /* In this instance the co-routine could be placed directly
1576                     into the ready list as we are within a critical section.
1577                     Instead the same pending ready list mechanism is used as if
1578                     the event were caused from within an interrupt. */
1579                     if( xCoRoutineRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE )
1580                     {
1581                         /* The co-routine waiting has a higher priority so record
1582                         that a yield might be appropriate. */
1583                         xReturn = errQUEUE_YIELD;
1584                     }
1585                 }
1586             }
1587             else
1588             {
1589                 xReturn = errQUEUE_FULL;
1590             }
1591         }
1592         portENABLE_INTERRUPTS();
1593
1594         return xReturn;
1595     }
1596
1597 #endif /* configUSE_CO_ROUTINES */
1598 /*-----------------------------------------------------------*/
1599
1600 #if ( configUSE_CO_ROUTINES == 1 )
1601
1602     signed portBASE_TYPE xQueueCRReceive( xQueueHandle xQueue, void *pvBuffer, portTickType xTicksToWait )
1603     {
1604     signed portBASE_TYPE xReturn;
1605     xQUEUE *pxQueue;
1606
1607         pxQueue = ( xQUEUE * ) xQueue;
1608
1609         /* If the queue is already empty we may have to block.  A critical section
1610         is required to prevent an interrupt adding something to the queue
1611         between the check to see if the queue is empty and blocking on the queue. */
1612         portDISABLE_INTERRUPTS();
1613         {
1614             if( pxQueue->uxMessagesWaiting == ( unsigned portBASE_TYPE ) 0 )
1615             {
1616                 /* There are no messages in the queue, do we want to block or just
1617                 leave with nothing? */
1618                 if( xTicksToWait > ( portTickType ) 0 )
1619                 {
1620                     /* As this is a co-routine we cannot block directly, but return
1621                     indicating that we need to block. */
1622                     vCoRoutineAddToDelayedList( xTicksToWait, &( pxQueue->xTasksWaitingToReceive ) );
1623                     portENABLE_INTERRUPTS();
1624                     return errQUEUE_BLOCKED;
1625                 }
1626                 else
1627                 {
1628                     portENABLE_INTERRUPTS();
1629                     return errQUEUE_FULL;
1630                 }
1631             }
1632         }
1633         portENABLE_INTERRUPTS();
1634
1635         portDISABLE_INTERRUPTS();
1636         {
1637             if( pxQueue->uxMessagesWaiting > ( unsigned portBASE_TYPE ) 0 )
1638             {
1639                 /* Data is available from the queue. */
1640                 pxQueue->pcReadFrom += pxQueue->uxItemSize;
1641                 if( pxQueue->pcReadFrom >= pxQueue->pcTail )
1642                 {
1643                     pxQueue->pcReadFrom = pxQueue->pcHead;
1644                 }
1645                 --( pxQueue->uxMessagesWaiting );
1646                 memcpy( ( void * ) pvBuffer, ( void * ) pxQueue->pcReadFrom, ( unsigned ) pxQueue->uxItemSize );
1647
1648                 xReturn = pdPASS;
1649
1650                 /* Were any co-routines waiting for space to become available? */
1651                 if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) == pdFALSE )
1652                 {
1653                     /* In this instance the co-routine could be placed directly
1654                     into the ready list as we are within a critical section.
1655                     Instead the same pending ready list mechanism is used as if
1656                     the event were caused from within an interrupt. */
1657                     if( xCoRoutineRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) != pdFALSE )
1658                     {
1659                         xReturn = errQUEUE_YIELD;
1660                     }
1661                 }
1662             }
1663             else
1664             {
1665                 xReturn = pdFAIL;
1666             }
1667         }
1668         portENABLE_INTERRUPTS();
1669
1670         return xReturn;
1671     }
1672
1673 #endif /* configUSE_CO_ROUTINES */
1674 /*-----------------------------------------------------------*/
1675
1676 #if ( configUSE_CO_ROUTINES == 1 )
1677
1678     signed portBASE_TYPE xQueueCRSendFromISR( xQueueHandle xQueue, const void *pvItemToQueue, signed portBASE_TYPE xCoRoutinePreviouslyWoken )
1679     {
1680     xQUEUE *pxQueue;
1681
1682         pxQueue = ( xQUEUE * ) xQueue;
1683
1684         /* Cannot block within an ISR so if there is no space on the queue then
1685         exit without doing anything. */
1686         if( pxQueue->uxMessagesWaiting < pxQueue->uxLength )
1687         {
1688             prvCopyDataToQueue( pxQueue, pvItemToQueue, queueSEND_TO_BACK );
1689
1690             /* We only want to wake one co-routine per ISR, so check that a
1691             co-routine has not already been woken. */
1692             if( xCoRoutinePreviouslyWoken == pdFALSE )
1693             {
1694                 if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE )
1695                 {
1696                     if( xCoRoutineRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE )
1697                     {
1698                         return pdTRUE;
1699                     }
1700                 }
1701             }
1702         }
1703
1704         return xCoRoutinePreviouslyWoken;
1705     }
1706
1707 #endif /* configUSE_CO_ROUTINES */
1708 /*-----------------------------------------------------------*/
1709
1710 #if ( configUSE_CO_ROUTINES == 1 )
1711
1712     signed portBASE_TYPE xQueueCRReceiveFromISR( xQueueHandle xQueue, void *pvBuffer, signed portBASE_TYPE *pxCoRoutineWoken )
1713     {
1714     signed portBASE_TYPE xReturn;
1715     xQUEUE * pxQueue;
1716
1717         pxQueue = ( xQUEUE * ) xQueue;
1718
1719         /* We cannot block from an ISR, so check there is data available. If
1720         not then just leave without doing anything. */
1721         if( pxQueue->uxMessagesWaiting > ( unsigned portBASE_TYPE ) 0 )
1722         {
1723             /* Copy the data from the queue. */
1724             pxQueue->pcReadFrom += pxQueue->uxItemSize;
1725             if( pxQueue->pcReadFrom >= pxQueue->pcTail )
1726             {
1727                 pxQueue->pcReadFrom = pxQueue->pcHead;
1728             }
1729             --( pxQueue->uxMessagesWaiting );
1730             memcpy( ( void * ) pvBuffer, ( void * ) pxQueue->pcReadFrom, ( unsigned ) pxQueue->uxItemSize );
1731
1732             if( ( *pxCoRoutineWoken ) == pdFALSE )
1733             {
1734                 if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) == pdFALSE )
1735                 {
1736                     if( xCoRoutineRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) != pdFALSE )
1737                     {
1738                         *pxCoRoutineWoken = pdTRUE;
1739                     }
1740                 }
1741             }
1742
1743             xReturn = pdPASS;
1744         }
1745         else
1746         {
1747             xReturn = pdFAIL;
1748         }
1749
1750         return xReturn;
1751     }
1752
1753 #endif /* configUSE_CO_ROUTINES */
1754 /*-----------------------------------------------------------*/
1755
1756 #if ( configQUEUE_REGISTRY_SIZE > 0 )
1757
1758     void vQueueAddToRegistry( xQueueHandle xQueue, signed char *pcQueueName )
1759     {
1760     unsigned portBASE_TYPE ux;
1761
1762         /* See if there is an empty space in the registry.  A NULL name denotes
1763         a free slot. */
1764         for( ux = ( unsigned portBASE_TYPE ) 0U; ux < ( unsigned portBASE_TYPE ) configQUEUE_REGISTRY_SIZE; ux++ )
1765         {
1766             if( xQueueRegistry[ ux ].pcQueueName == NULL )
1767             {
1768                 /* Store the information on this queue. */
1769                 xQueueRegistry[ ux ].pcQueueName = pcQueueName;
1770                 xQueueRegistry[ ux ].xHandle = xQueue;
1771                 break;
1772             }
1773         }
1774     }
1775
1776 #endif /* configQUEUE_REGISTRY_SIZE */
1777 /*-----------------------------------------------------------*/
1778
1779 #if ( configQUEUE_REGISTRY_SIZE > 0 )
1780
1781     static void prvQueueUnregisterQueue( xQueueHandle xQueue )
1782     {
1783     unsigned portBASE_TYPE ux;
1784
1785         /* See if the handle of the queue being unregistered in actually in the
1786         registry. */
1787         for( ux = ( unsigned portBASE_TYPE ) 0U; ux < ( unsigned portBASE_TYPE ) configQUEUE_REGISTRY_SIZE; ux++ )
1788         {
1789             if( xQueueRegistry[ ux ].xHandle == xQueue )
1790             {
1791                 /* Set the name to NULL to show that this slot if free again. */
1792                 xQueueRegistry[ ux ].pcQueueName = NULL;
1793                 break;
1794             }
1795         }
1796
1797     }
1798
1799 #endif /* configQUEUE_REGISTRY_SIZE */
1800 /*-----------------------------------------------------------*/
1801
1802 #if ( configUSE_TIMERS == 1 )
1803
1804     void vQueueWaitForMessageRestricted( xQueueHandle xQueue, portTickType xTicksToWait )
1805     {
1806     xQUEUE *pxQueue;
1807
1808         pxQueue = ( xQUEUE * ) xQueue;
1809
1810         /* This function should not be called by application code hence the
1811         'Restricted' in its name.  It is not part of the public API.  It is
1812         designed for use by kernel code, and has special calling requirements.
1813         It can result in vListInsert() being called on a list that can only
1814         possibly ever have one item in it, so the list will be fast, but even
1815         so it should be called with the scheduler locked and not from a critical
1816         section. */
1817
1818         /* Only do anything if there are no messages in the queue.  This function
1819         will not actually cause the task to block, just place it on a blocked
1820         list.  It will not block until the scheduler is unlocked - at which
1821         time a yield will be performed.  If an item is added to the queue while
1822         the queue is locked, and the calling task blocks on the queue, then the
1823         calling task will be immediately unblocked when the queue is unlocked. */
1824         prvLockQueue( pxQueue );
1825         if( pxQueue->uxMessagesWaiting == ( unsigned portBASE_TYPE ) 0U )
1826         {
1827             /* There is nothing in the queue, block for the specified period. */
1828             vTaskPlaceOnEventListRestricted( &( pxQueue->xTasksWaitingToReceive ), xTicksToWait );
1829         }
1830         prvUnlockQueue( pxQueue );
1831     }
1832
1833 #endif /* configUSE_TIMERS */
1834 /*-----------------------------------------------------------*/
1835
1836 #if ( configUSE_QUEUE_SETS == 1 )
1837
1838     xQueueSetHandle xQueueCreateSet( unsigned portBASE_TYPE uxEventQueueLength )
1839     {
1840     xQueueSetHandle pxQueue;
1841
1842         pxQueue = xQueueGenericCreate( uxEventQueueLength, sizeof( xQUEUE * ), queueQUEUE_TYPE_SET );
1843
1844         return pxQueue;
1845     }
1846
1847 #endif /* configUSE_QUEUE_SETS */
1848 /*-----------------------------------------------------------*/
1849
1850 #if ( configUSE_QUEUE_SETS == 1 )
1851
1852     portBASE_TYPE xQueueAddToSet( xQueueSetMemberHandle xQueueOrSemaphore, xQueueSetHandle xQueueSet )
1853     {
1854     portBASE_TYPE xReturn;
1855
1856         if( ( ( xQUEUE * ) xQueueOrSemaphore )->pxQueueSetContainer != NULL )
1857         {
1858             xReturn = pdFAIL;
1859         }
1860         else
1861         {
1862             taskENTER_CRITICAL();
1863             {
1864                 ( ( xQUEUE * ) xQueueOrSemaphore )->pxQueueSetContainer = xQueueSet;
1865             }
1866             taskEXIT_CRITICAL();
1867             xReturn = pdPASS;
1868         }
1869
1870         return xReturn;
1871     }
1872
1873 #endif /* configUSE_QUEUE_SETS */
1874 /*-----------------------------------------------------------*/
1875
1876 #if ( configUSE_QUEUE_SETS == 1 )
1877
1878     portBASE_TYPE xQueueRemoveFromSet( xQueueSetMemberHandle xQueueOrSemaphore, xQueueSetHandle xQueueSet )
1879     {
1880     portBASE_TYPE xReturn;
1881     xQUEUE *pxQueueOrSemaphore;
1882
1883         pxQueueOrSemaphore = ( xQUEUE * ) xQueueOrSemaphore;
1884
1885         if( pxQueueOrSemaphore->pxQueueSetContainer != xQueueSet )
1886         {
1887             /* The queue was not a member of the set. */
1888             xReturn = pdFAIL;
1889         }
1890         else if( pxQueueOrSemaphore->uxMessagesWaiting != 0 )
1891         {
1892             /* It is dangerous to remove a queue from a set when the queue is
1893             not empty because the queue set will still hold pending events for
1894             the queue. */
1895             xReturn = pdFAIL;
1896         }
1897         else
1898         {
1899             taskENTER_CRITICAL();
1900             {
1901                 /* The queue is no longer contained in the set. */
1902                 pxQueueOrSemaphore->pxQueueSetContainer = NULL;
1903             }
1904             taskEXIT_CRITICAL();
1905             xReturn = pdPASS;
1906         }
1907
1908         return xReturn;
1909     }
1910
1911 #endif /* configUSE_QUEUE_SETS */
1912 /*-----------------------------------------------------------*/
1913
1914 #if ( configUSE_QUEUE_SETS == 1 )
1915
1916     xQueueSetMemberHandle xQueueSelectFromSet( xQueueSetHandle xQueueSet, portTickType xBlockTimeTicks )
1917     {
1918     xQueueSetMemberHandle xReturn = NULL;
1919
1920         xQueueGenericReceive( ( xQueueHandle ) xQueueSet, &xReturn, xBlockTimeTicks, pdFALSE );
1921         return xReturn;
1922     }
1923
1924 #endif /* configUSE_QUEUE_SETS */
1925 /*-----------------------------------------------------------*/
1926
1927 #if ( configUSE_QUEUE_SETS == 1 )
1928
1929     xQueueSetMemberHandle xQueueSelectFromSetFromISR( xQueueSetHandle xQueueSet )
1930     {
1931     xQueueSetMemberHandle xReturn = NULL;
1932
1933         xQueueReceiveFromISR( ( xQueueHandle ) xQueueSet, &xReturn, NULL );
1934         return xReturn;
1935     }
1936
1937 #endif /* configUSE_QUEUE_SETS */
1938 /*-----------------------------------------------------------*/
1939
1940 #if ( configUSE_QUEUE_SETS == 1 )
1941
1942     static portBASE_TYPE prvNotifyQueueSetContainer( xQUEUE *pxQueue, portBASE_TYPE xCopyPosition )
1943     {
1944     xQUEUE *pxQueueSetContainer = pxQueue->pxQueueSetContainer;
1945     portBASE_TYPE xReturn = pdFALSE;
1946
1947         configASSERT( pxQueueSetContainer );
1948         configASSERT( pxQueueSetContainer->uxMessagesWaiting < pxQueueSetContainer->uxLength );
1949
1950         if( pxQueueSetContainer->uxMessagesWaiting < pxQueueSetContainer->uxLength )
1951         {
1952             traceQUEUE_SEND( pxQueueSetContainer );
1953             /* The data copies is the handle of the queue that contains data. */
1954             prvCopyDataToQueue( pxQueueSetContainer, &pxQueue, xCopyPosition );
1955             if( listLIST_IS_EMPTY( &( pxQueueSetContainer->xTasksWaitingToReceive ) ) == pdFALSE )
1956             {
1957                 if( xTaskRemoveFromEventList( &( pxQueueSetContainer->xTasksWaitingToReceive ) ) != pdFALSE )
1958                 {
1959                     /* The task waiting has a higher priority */
1960                     xReturn = pdTRUE;
1961                 }
1962             }
1963         }
1964
1965         return xReturn;
1966     }
1967
1968 #endif /* configUSE_QUEUE_SETS */
1969