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