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