]> git.sur5r.net Git - freertos/blob - FreeRTOS/Source/queue.c
7eec2160b4e8342e4d45ce8f20237866422de10c
[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 uxMaxCount, unsigned portBASE_TYPE uxInitialCount )\r
538         {\r
539         xQueueHandle xHandle;\r
540 \r
541                 configASSERT( uxMaxCount != 0 );\r
542                 configASSERT( uxInitialCount <= uxMaxCount );\r
543 \r
544                 xHandle = xQueueGenericCreate( uxMaxCount, queueSEMAPHORE_QUEUE_ITEM_LENGTH, queueQUEUE_TYPE_COUNTING_SEMAPHORE );\r
545 \r
546                 if( xHandle != NULL )\r
547                 {\r
548                         ( ( xQUEUE * ) xHandle )->uxMessagesWaiting = uxInitialCount;\r
549 \r
550                         traceCREATE_COUNTING_SEMAPHORE();\r
551                 }\r
552                 else\r
553                 {\r
554                         traceCREATE_COUNTING_SEMAPHORE_FAILED();\r
555                 }\r
556 \r
557                 configASSERT( xHandle );\r
558                 return xHandle;\r
559         }\r
560 \r
561 #endif /* configUSE_COUNTING_SEMAPHORES */\r
562 /*-----------------------------------------------------------*/\r
563 \r
564 signed portBASE_TYPE xQueueGenericSend( xQueueHandle xQueue, const void * const pvItemToQueue, portTickType xTicksToWait, portBASE_TYPE xCopyPosition )\r
565 {\r
566 signed portBASE_TYPE xEntryTimeSet = pdFALSE;\r
567 xTimeOutType xTimeOut;\r
568 xQUEUE * const pxQueue = ( xQUEUE * ) xQueue;\r
569 \r
570         configASSERT( pxQueue );\r
571         configASSERT( !( ( pvItemToQueue == NULL ) && ( pxQueue->uxItemSize != ( unsigned portBASE_TYPE ) 0U ) ) );\r
572         configASSERT( !( ( xCopyPosition == queueOVERWRITE ) && ( pxQueue->uxLength != 1 ) ) );\r
573 \r
574         /* This function relaxes the coding standard somewhat to allow return\r
575         statements within the function itself.  This is done in the interest\r
576         of execution time efficiency. */\r
577         for( ;; )\r
578         {\r
579                 taskENTER_CRITICAL();\r
580                 {\r
581                         /* Is there room on the queue now?  The running task must be\r
582                         the highest priority task wanting to access the queue.  If\r
583                         the head item in the queue is to be overwritten then it does\r
584                         not matter if the queue is full. */\r
585                         if( ( pxQueue->uxMessagesWaiting < pxQueue->uxLength ) || ( xCopyPosition == queueOVERWRITE ) )\r
586                         {\r
587                                 traceQUEUE_SEND( pxQueue );\r
588                                 prvCopyDataToQueue( pxQueue, pvItemToQueue, xCopyPosition );\r
589 \r
590                                 #if ( configUSE_QUEUE_SETS == 1 )\r
591                                 {\r
592                                         if( pxQueue->pxQueueSetContainer != NULL )\r
593                                         {\r
594                                                 if( prvNotifyQueueSetContainer( pxQueue, xCopyPosition ) == pdTRUE )\r
595                                                 {\r
596                                                         /* The queue is a member of a queue set, and posting\r
597                                                         to the queue set caused a higher priority task to\r
598                                                         unblock. A context switch is required. */\r
599                                                         queueYIELD_IF_USING_PREEMPTION();\r
600                                                 }\r
601                                         }\r
602                                         else\r
603                                         {\r
604                                                 /* If there was a task waiting for data to arrive on the\r
605                                                 queue then unblock it now. */\r
606                                                 if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE )\r
607                                                 {\r
608                                                         if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) == pdTRUE )\r
609                                                         {\r
610                                                                 /* The unblocked task has a priority higher than\r
611                                                                 our own so yield immediately.  Yes it is ok to\r
612                                                                 do this from within the critical section - the\r
613                                                                 kernel takes care of that. */\r
614                                                                 queueYIELD_IF_USING_PREEMPTION();\r
615                                                         }\r
616                                                 }\r
617                                         }\r
618                                 }\r
619                                 #else /* configUSE_QUEUE_SETS */\r
620                                 {\r
621                                         /* If there was a task waiting for data to arrive on the\r
622                                         queue then unblock it now. */\r
623                                         if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE )\r
624                                         {\r
625                                                 if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) == pdTRUE )\r
626                                                 {\r
627                                                         /* The unblocked task has a priority higher than\r
628                                                         our own so yield immediately.  Yes it is ok to do\r
629                                                         this from within the critical section - the kernel\r
630                                                         takes care of that. */\r
631                                                         queueYIELD_IF_USING_PREEMPTION();\r
632                                                 }\r
633                                         }\r
634                                 }\r
635                                 #endif /* configUSE_QUEUE_SETS */\r
636 \r
637                                 taskEXIT_CRITICAL();\r
638 \r
639                                 /* Return to the original privilege level before exiting the\r
640                                 function. */\r
641                                 return pdPASS;\r
642                         }\r
643                         else\r
644                         {\r
645                                 if( xTicksToWait == ( portTickType ) 0 )\r
646                                 {\r
647                                         /* The queue was full and no block time is specified (or\r
648                                         the block time has expired) so leave now. */\r
649                                         taskEXIT_CRITICAL();\r
650 \r
651                                         /* Return to the original privilege level before exiting\r
652                                         the function. */\r
653                                         traceQUEUE_SEND_FAILED( pxQueue );\r
654                                         return errQUEUE_FULL;\r
655                                 }\r
656                                 else if( xEntryTimeSet == pdFALSE )\r
657                                 {\r
658                                         /* The queue was full and a block time was specified so\r
659                                         configure the timeout structure. */\r
660                                         vTaskSetTimeOutState( &xTimeOut );\r
661                                         xEntryTimeSet = pdTRUE;\r
662                                 }\r
663                                 else\r
664                                 {\r
665                                         /* Entry time was already set. */\r
666                                 }\r
667                         }\r
668                 }\r
669                 taskEXIT_CRITICAL();\r
670 \r
671                 /* Interrupts and other tasks can send to and receive from the queue\r
672                 now the critical section has been exited. */\r
673 \r
674                 vTaskSuspendAll();\r
675                 prvLockQueue( pxQueue );\r
676 \r
677                 /* Update the timeout state to see if it has expired yet. */\r
678                 if( xTaskCheckForTimeOut( &xTimeOut, &xTicksToWait ) == pdFALSE )\r
679                 {\r
680                         if( prvIsQueueFull( pxQueue ) != pdFALSE )\r
681                         {\r
682                                 traceBLOCKING_ON_QUEUE_SEND( pxQueue );\r
683                                 vTaskPlaceOnEventList( &( pxQueue->xTasksWaitingToSend ), xTicksToWait );\r
684 \r
685                                 /* Unlocking the queue means queue events can effect the\r
686                                 event list.  It is possible     that interrupts occurring now\r
687                                 remove this task from the event list again - but as the\r
688                                 scheduler is suspended the task will go onto the pending\r
689                                 ready last instead of the actual ready list. */\r
690                                 prvUnlockQueue( pxQueue );\r
691 \r
692                                 /* Resuming the scheduler will move tasks from the pending\r
693                                 ready list into the ready list - so it is feasible that this\r
694                                 task is already in a ready list before it yields - in which\r
695                                 case the yield will not cause a context switch unless there\r
696                                 is also a higher priority task in the pending ready list. */\r
697                                 if( xTaskResumeAll() == pdFALSE )\r
698                                 {\r
699                                         portYIELD_WITHIN_API();\r
700                                 }\r
701                         }\r
702                         else\r
703                         {\r
704                                 /* Try again. */\r
705                                 prvUnlockQueue( pxQueue );\r
706                                 ( void ) xTaskResumeAll();\r
707                         }\r
708                 }\r
709                 else\r
710                 {\r
711                         /* The timeout has expired. */\r
712                         prvUnlockQueue( pxQueue );\r
713                         ( void ) xTaskResumeAll();\r
714 \r
715                         /* Return to the original privilege level before exiting the\r
716                         function. */\r
717                         traceQUEUE_SEND_FAILED( pxQueue );\r
718                         return errQUEUE_FULL;\r
719                 }\r
720         }\r
721 }\r
722 /*-----------------------------------------------------------*/\r
723 \r
724 #if ( configUSE_ALTERNATIVE_API == 1 )\r
725 \r
726         signed portBASE_TYPE xQueueAltGenericSend( xQueueHandle xQueue, const void * const pvItemToQueue, portTickType xTicksToWait, portBASE_TYPE xCopyPosition )\r
727         {\r
728         signed portBASE_TYPE xEntryTimeSet = pdFALSE;\r
729         xTimeOutType xTimeOut;\r
730         xQUEUE * const pxQueue = ( xQUEUE * ) xQueue;\r
731 \r
732                 configASSERT( pxQueue );\r
733                 configASSERT( !( ( pvItemToQueue == NULL ) && ( pxQueue->uxItemSize != ( unsigned portBASE_TYPE ) 0U ) ) );\r
734 \r
735                 for( ;; )\r
736                 {\r
737                         taskENTER_CRITICAL();\r
738                         {\r
739                                 /* Is there room on the queue now?  To be running we must be\r
740                                 the highest priority task wanting to access the queue. */\r
741                                 if( pxQueue->uxMessagesWaiting < pxQueue->uxLength )\r
742                                 {\r
743                                         traceQUEUE_SEND( pxQueue );\r
744                                         prvCopyDataToQueue( pxQueue, pvItemToQueue, xCopyPosition );\r
745 \r
746                                         /* If there was a task waiting for data to arrive on the\r
747                                         queue then unblock it now. */\r
748                                         if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE )\r
749                                         {\r
750                                                 if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) == pdTRUE )\r
751                                                 {\r
752                                                         /* The unblocked task has a priority higher than\r
753                                                         our own so yield immediately. */\r
754                                                         portYIELD_WITHIN_API();\r
755                                                 }\r
756                                         }\r
757 \r
758                                         taskEXIT_CRITICAL();\r
759                                         return pdPASS;\r
760                                 }\r
761                                 else\r
762                                 {\r
763                                         if( xTicksToWait == ( portTickType ) 0 )\r
764                                         {\r
765                                                 taskEXIT_CRITICAL();\r
766                                                 return errQUEUE_FULL;\r
767                                         }\r
768                                         else if( xEntryTimeSet == pdFALSE )\r
769                                         {\r
770                                                 vTaskSetTimeOutState( &xTimeOut );\r
771                                                 xEntryTimeSet = pdTRUE;\r
772                                         }\r
773                                 }\r
774                         }\r
775                         taskEXIT_CRITICAL();\r
776 \r
777                         taskENTER_CRITICAL();\r
778                         {\r
779                                 if( xTaskCheckForTimeOut( &xTimeOut, &xTicksToWait ) == pdFALSE )\r
780                                 {\r
781                                         if( prvIsQueueFull( pxQueue ) != pdFALSE )\r
782                                         {\r
783                                                 traceBLOCKING_ON_QUEUE_SEND( pxQueue );\r
784                                                 vTaskPlaceOnEventList( &( pxQueue->xTasksWaitingToSend ), xTicksToWait );\r
785                                                 portYIELD_WITHIN_API();\r
786                                         }\r
787                                 }\r
788                                 else\r
789                                 {\r
790                                         taskEXIT_CRITICAL();\r
791                                         traceQUEUE_SEND_FAILED( pxQueue );\r
792                                         return errQUEUE_FULL;\r
793                                 }\r
794                         }\r
795                         taskEXIT_CRITICAL();\r
796                 }\r
797         }\r
798 \r
799 #endif /* configUSE_ALTERNATIVE_API */\r
800 /*-----------------------------------------------------------*/\r
801 \r
802 #if ( configUSE_ALTERNATIVE_API == 1 )\r
803 \r
804         signed portBASE_TYPE xQueueAltGenericReceive( xQueueHandle xQueue, void * const pvBuffer, portTickType xTicksToWait, portBASE_TYPE xJustPeeking )\r
805         {\r
806         signed portBASE_TYPE xEntryTimeSet = pdFALSE;\r
807         xTimeOutType xTimeOut;\r
808         signed char *pcOriginalReadPosition;\r
809         xQUEUE * const pxQueue = ( xQUEUE * ) xQueue;\r
810 \r
811                 configASSERT( pxQueue );\r
812                 configASSERT( !( ( pvBuffer == NULL ) && ( pxQueue->uxItemSize != ( unsigned portBASE_TYPE ) 0U ) ) );\r
813 \r
814                 for( ;; )\r
815                 {\r
816                         taskENTER_CRITICAL();\r
817                         {\r
818                                 if( pxQueue->uxMessagesWaiting > ( unsigned portBASE_TYPE ) 0 )\r
819                                 {\r
820                                         /* Remember our read position in case we are just peeking. */\r
821                                         pcOriginalReadPosition = pxQueue->u.pcReadFrom;\r
822 \r
823                                         prvCopyDataFromQueue( pxQueue, pvBuffer );\r
824 \r
825                                         if( xJustPeeking == pdFALSE )\r
826                                         {\r
827                                                 traceQUEUE_RECEIVE( pxQueue );\r
828 \r
829                                                 /* Data is actually being removed (not just peeked). */\r
830                                                 --( pxQueue->uxMessagesWaiting );\r
831 \r
832                                                 #if ( configUSE_MUTEXES == 1 )\r
833                                                 {\r
834                                                         if( pxQueue->uxQueueType == queueQUEUE_IS_MUTEX )\r
835                                                         {\r
836                                                                 /* Record the information required to implement\r
837                                                                 priority inheritance should it become necessary. */\r
838                                                                 pxQueue->pxMutexHolder = ( signed char * ) xTaskGetCurrentTaskHandle();\r
839                                                         }\r
840                                                 }\r
841                                                 #endif\r
842 \r
843                                                 if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) == pdFALSE )\r
844                                                 {\r
845                                                         if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) == pdTRUE )\r
846                                                         {\r
847                                                                 portYIELD_WITHIN_API();\r
848                                                         }\r
849                                                 }\r
850                                         }\r
851                                         else\r
852                                         {\r
853                                                 traceQUEUE_PEEK( pxQueue );\r
854 \r
855                                                 /* We are not removing the data, so reset our read\r
856                                                 pointer. */\r
857                                                 pxQueue->u.pcReadFrom = pcOriginalReadPosition;\r
858 \r
859                                                 /* The data is being left in the queue, so see if there are\r
860                                                 any other tasks waiting for the data. */\r
861                                                 if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE )\r
862                                                 {\r
863                                                         /* Tasks that are removed from the event list will get added to\r
864                                                         the pending ready list as the scheduler is still suspended. */\r
865                                                         if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE )\r
866                                                         {\r
867                                                                 /* The task waiting has a higher priority than this task. */\r
868                                                                 portYIELD_WITHIN_API();\r
869                                                         }\r
870                                                 }\r
871 \r
872                                         }\r
873 \r
874                                         taskEXIT_CRITICAL();\r
875                                         return pdPASS;\r
876                                 }\r
877                                 else\r
878                                 {\r
879                                         if( xTicksToWait == ( portTickType ) 0 )\r
880                                         {\r
881                                                 taskEXIT_CRITICAL();\r
882                                                 traceQUEUE_RECEIVE_FAILED( pxQueue );\r
883                                                 return errQUEUE_EMPTY;\r
884                                         }\r
885                                         else if( xEntryTimeSet == pdFALSE )\r
886                                         {\r
887                                                 vTaskSetTimeOutState( &xTimeOut );\r
888                                                 xEntryTimeSet = pdTRUE;\r
889                                         }\r
890                                 }\r
891                         }\r
892                         taskEXIT_CRITICAL();\r
893 \r
894                         taskENTER_CRITICAL();\r
895                         {\r
896                                 if( xTaskCheckForTimeOut( &xTimeOut, &xTicksToWait ) == pdFALSE )\r
897                                 {\r
898                                         if( prvIsQueueEmpty( pxQueue ) != pdFALSE )\r
899                                         {\r
900                                                 traceBLOCKING_ON_QUEUE_RECEIVE( pxQueue );\r
901 \r
902                                                 #if ( configUSE_MUTEXES == 1 )\r
903                                                 {\r
904                                                         if( pxQueue->uxQueueType == queueQUEUE_IS_MUTEX )\r
905                                                         {\r
906                                                                 portENTER_CRITICAL();\r
907                                                                 {\r
908                                                                         vTaskPriorityInherit( ( void * ) pxQueue->pxMutexHolder );\r
909                                                                 }\r
910                                                                 portEXIT_CRITICAL();\r
911                                                         }\r
912                                                 }\r
913                                                 #endif\r
914 \r
915                                                 vTaskPlaceOnEventList( &( pxQueue->xTasksWaitingToReceive ), xTicksToWait );\r
916                                                 portYIELD_WITHIN_API();\r
917                                         }\r
918                                 }\r
919                                 else\r
920                                 {\r
921                                         taskEXIT_CRITICAL();\r
922                                         traceQUEUE_RECEIVE_FAILED( pxQueue );\r
923                                         return errQUEUE_EMPTY;\r
924                                 }\r
925                         }\r
926                         taskEXIT_CRITICAL();\r
927                 }\r
928         }\r
929 \r
930 \r
931 #endif /* configUSE_ALTERNATIVE_API */\r
932 /*-----------------------------------------------------------*/\r
933 \r
934 signed portBASE_TYPE xQueueGenericSendFromISR( xQueueHandle xQueue, const void * const pvItemToQueue, signed portBASE_TYPE *pxHigherPriorityTaskWoken, portBASE_TYPE xCopyPosition )\r
935 {\r
936 signed portBASE_TYPE xReturn;\r
937 unsigned portBASE_TYPE uxSavedInterruptStatus;\r
938 xQUEUE * const pxQueue = ( xQUEUE * ) xQueue;\r
939 \r
940         configASSERT( pxQueue );\r
941         configASSERT( !( ( pvItemToQueue == NULL ) && ( pxQueue->uxItemSize != ( unsigned portBASE_TYPE ) 0U ) ) );\r
942         configASSERT( !( ( xCopyPosition == queueOVERWRITE ) && ( pxQueue->uxLength != 1 ) ) );\r
943 \r
944         /* RTOS ports that support interrupt nesting have the concept of a maximum\r
945         system call (or maximum API call) interrupt priority.  Interrupts that are\r
946         above the maximum system call priority are keep permanently enabled, even\r
947         when the RTOS kernel is in a critical section, but cannot make any calls to\r
948         FreeRTOS API functions.  If configASSERT() is defined in FreeRTOSConfig.h\r
949         then portASSERT_IF_INTERRUPT_PRIORITY_INVALID() will result in an assertion\r
950         failure if a FreeRTOS API function is called from an interrupt that has been\r
951         assigned a priority above the configured maximum system call priority.\r
952         Only FreeRTOS functions that end in FromISR can be called from interrupts\r
953         that have been assigned a priority at or (logically) below the maximum\r
954         system call     interrupt priority.  FreeRTOS maintains a separate interrupt\r
955         safe API to ensure interrupt entry is as fast and as simple as possible.\r
956         More information (albeit Cortex-M specific) is provided on the following\r
957         link: http://www.freertos.org/RTOS-Cortex-M3-M4.html */\r
958         portASSERT_IF_INTERRUPT_PRIORITY_INVALID();\r
959 \r
960         /* Similar to xQueueGenericSend, except we don't block if there is no room\r
961         in the queue.  Also we don't directly wake a task that was blocked on a\r
962         queue read, instead we return a flag to say whether a context switch is\r
963         required or not (i.e. has a task with a higher priority than us been woken\r
964         by this post). */\r
965         uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR();\r
966         {\r
967                 if( ( pxQueue->uxMessagesWaiting < pxQueue->uxLength ) || ( xCopyPosition == queueOVERWRITE ) )\r
968                 {\r
969                         traceQUEUE_SEND_FROM_ISR( pxQueue );\r
970 \r
971                         prvCopyDataToQueue( pxQueue, pvItemToQueue, xCopyPosition );\r
972 \r
973                         /* If the queue is locked we do not alter the event list.  This will\r
974                         be done when the queue is unlocked later. */\r
975                         if( pxQueue->xTxLock == queueUNLOCKED )\r
976                         {\r
977                                 #if ( configUSE_QUEUE_SETS == 1 )\r
978                                 {\r
979                                         if( pxQueue->pxQueueSetContainer != NULL )\r
980                                         {\r
981                                                 if( prvNotifyQueueSetContainer( pxQueue, xCopyPosition ) == pdTRUE )\r
982                                                 {\r
983                                                         /* The queue is a member of a queue set, and posting\r
984                                                         to the queue set caused a higher priority task to\r
985                                                         unblock.  A context switch is required. */\r
986                                                         if( pxHigherPriorityTaskWoken != NULL )\r
987                                                         {\r
988                                                                 *pxHigherPriorityTaskWoken = pdTRUE;\r
989                                                         }\r
990                                                 }\r
991                                         }\r
992                                         else\r
993                                         {\r
994                                                 if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE )\r
995                                                 {\r
996                                                         if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE )\r
997                                                         {\r
998                                                                 /* The task waiting has a higher priority so record that a\r
999                                                                 context switch is required. */\r
1000                                                                 if( pxHigherPriorityTaskWoken != NULL )\r
1001                                                                 {\r
1002                                                                         *pxHigherPriorityTaskWoken = pdTRUE;\r
1003                                                                 }\r
1004                                                         }\r
1005                                                 }\r
1006                                         }\r
1007                                 }\r
1008                                 #else /* configUSE_QUEUE_SETS */\r
1009                                 {\r
1010                                         if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE )\r
1011                                         {\r
1012                                                 if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE )\r
1013                                                 {\r
1014                                                         /* The task waiting has a higher priority so record that a\r
1015                                                         context switch is required. */\r
1016                                                         if( pxHigherPriorityTaskWoken != NULL )\r
1017                                                         {\r
1018                                                                 *pxHigherPriorityTaskWoken = pdTRUE;\r
1019                                                         }\r
1020                                                 }\r
1021                                         }\r
1022                                 }\r
1023                                 #endif /* configUSE_QUEUE_SETS */\r
1024                         }\r
1025                         else\r
1026                         {\r
1027                                 /* Increment the lock count so the task that unlocks the queue\r
1028                                 knows that data was posted while it was locked. */\r
1029                                 ++( pxQueue->xTxLock );\r
1030                         }\r
1031 \r
1032                         xReturn = pdPASS;\r
1033                 }\r
1034                 else\r
1035                 {\r
1036                         traceQUEUE_SEND_FROM_ISR_FAILED( pxQueue );\r
1037                         xReturn = errQUEUE_FULL;\r
1038                 }\r
1039         }\r
1040         portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus );\r
1041 \r
1042         return xReturn;\r
1043 }\r
1044 /*-----------------------------------------------------------*/\r
1045 \r
1046 signed portBASE_TYPE xQueueGenericReceive( xQueueHandle xQueue, void * const pvBuffer, portTickType xTicksToWait, portBASE_TYPE xJustPeeking )\r
1047 {\r
1048 signed portBASE_TYPE xEntryTimeSet = pdFALSE;\r
1049 xTimeOutType xTimeOut;\r
1050 signed char *pcOriginalReadPosition;\r
1051 xQUEUE * const pxQueue = ( xQUEUE * ) xQueue;\r
1052 \r
1053         configASSERT( pxQueue );\r
1054         configASSERT( !( ( pvBuffer == NULL ) && ( pxQueue->uxItemSize != ( unsigned portBASE_TYPE ) 0U ) ) );\r
1055 \r
1056         /* This function relaxes the coding standard somewhat to allow return\r
1057         statements within the function itself.  This is done in the interest\r
1058         of execution time efficiency. */\r
1059 \r
1060         for( ;; )\r
1061         {\r
1062                 taskENTER_CRITICAL();\r
1063                 {\r
1064                         /* Is there data in the queue now?  To be running we must be\r
1065                         the highest priority task wanting to access the queue. */\r
1066                         if( pxQueue->uxMessagesWaiting > ( unsigned portBASE_TYPE ) 0 )\r
1067                         {\r
1068                                 /* Remember the read position in case the queue is only being\r
1069                                 peeked. */\r
1070                                 pcOriginalReadPosition = pxQueue->u.pcReadFrom;\r
1071 \r
1072                                 prvCopyDataFromQueue( pxQueue, pvBuffer );\r
1073 \r
1074                                 if( xJustPeeking == pdFALSE )\r
1075                                 {\r
1076                                         traceQUEUE_RECEIVE( pxQueue );\r
1077 \r
1078                                         /* Actually removing data, not just peeking. */\r
1079                                         --( pxQueue->uxMessagesWaiting );\r
1080 \r
1081                                         #if ( configUSE_MUTEXES == 1 )\r
1082                                         {\r
1083                                                 if( pxQueue->uxQueueType == queueQUEUE_IS_MUTEX )\r
1084                                                 {\r
1085                                                         /* Record the information required to implement\r
1086                                                         priority inheritance should it become necessary. */\r
1087                                                         pxQueue->pxMutexHolder = ( signed char * ) xTaskGetCurrentTaskHandle(); /*lint !e961 Cast is not redundant as xTaskHandle is a typedef. */\r
1088                                                 }\r
1089                                         }\r
1090                                         #endif\r
1091 \r
1092                                         if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) == pdFALSE )\r
1093                                         {\r
1094                                                 if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) == pdTRUE )\r
1095                                                 {\r
1096                                                         queueYIELD_IF_USING_PREEMPTION();\r
1097                                                 }\r
1098                                         }\r
1099                                 }\r
1100                                 else\r
1101                                 {\r
1102                                         traceQUEUE_PEEK( pxQueue );\r
1103 \r
1104                                         /* The data is not being removed, so reset the read\r
1105                                         pointer. */\r
1106                                         pxQueue->u.pcReadFrom = pcOriginalReadPosition;\r
1107 \r
1108                                         /* The data is being left in the queue, so see if there are\r
1109                                         any other tasks waiting for the data. */\r
1110                                         if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE )\r
1111                                         {\r
1112                                                 /* Tasks that are removed from the event list will get added to\r
1113                                                 the pending ready list as the scheduler is still suspended. */\r
1114                                                 if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE )\r
1115                                                 {\r
1116                                                         /* The task waiting has a higher priority than this task. */\r
1117                                                         queueYIELD_IF_USING_PREEMPTION();\r
1118                                                 }\r
1119                                         }\r
1120                                 }\r
1121 \r
1122                                 taskEXIT_CRITICAL();\r
1123                                 return pdPASS;\r
1124                         }\r
1125                         else\r
1126                         {\r
1127                                 if( xTicksToWait == ( portTickType ) 0 )\r
1128                                 {\r
1129                                         /* The queue was empty and no block time is specified (or\r
1130                                         the block time has expired) so leave now. */\r
1131                                         taskEXIT_CRITICAL();\r
1132                                         traceQUEUE_RECEIVE_FAILED( pxQueue );\r
1133                                         return errQUEUE_EMPTY;\r
1134                                 }\r
1135                                 else if( xEntryTimeSet == pdFALSE )\r
1136                                 {\r
1137                                         /* The queue was empty and a block time was specified so\r
1138                                         configure the timeout structure. */\r
1139                                         vTaskSetTimeOutState( &xTimeOut );\r
1140                                         xEntryTimeSet = pdTRUE;\r
1141                                 }\r
1142                                 else\r
1143                                 {\r
1144                                         /* Entry time was already set. */\r
1145                                 }\r
1146                         }\r
1147                 }\r
1148                 taskEXIT_CRITICAL();\r
1149 \r
1150                 /* Interrupts and other tasks can send to and receive from the queue\r
1151                 now the critical section has been exited. */\r
1152 \r
1153                 vTaskSuspendAll();\r
1154                 prvLockQueue( pxQueue );\r
1155 \r
1156                 /* Update the timeout state to see if it has expired yet. */\r
1157                 if( xTaskCheckForTimeOut( &xTimeOut, &xTicksToWait ) == pdFALSE )\r
1158                 {\r
1159                         if( prvIsQueueEmpty( pxQueue ) != pdFALSE )\r
1160                         {\r
1161                                 traceBLOCKING_ON_QUEUE_RECEIVE( pxQueue );\r
1162 \r
1163                                 #if ( configUSE_MUTEXES == 1 )\r
1164                                 {\r
1165                                         if( pxQueue->uxQueueType == queueQUEUE_IS_MUTEX )\r
1166                                         {\r
1167                                                 portENTER_CRITICAL();\r
1168                                                 {\r
1169                                                         vTaskPriorityInherit( ( void * ) pxQueue->pxMutexHolder );\r
1170                                                 }\r
1171                                                 portEXIT_CRITICAL();\r
1172                                         }\r
1173                                 }\r
1174                                 #endif\r
1175 \r
1176                                 vTaskPlaceOnEventList( &( pxQueue->xTasksWaitingToReceive ), xTicksToWait );\r
1177                                 prvUnlockQueue( pxQueue );\r
1178                                 if( xTaskResumeAll() == pdFALSE )\r
1179                                 {\r
1180                                         portYIELD_WITHIN_API();\r
1181                                 }\r
1182                         }\r
1183                         else\r
1184                         {\r
1185                                 /* Try again. */\r
1186                                 prvUnlockQueue( pxQueue );\r
1187                                 ( void ) xTaskResumeAll();\r
1188                         }\r
1189                 }\r
1190                 else\r
1191                 {\r
1192                         prvUnlockQueue( pxQueue );\r
1193                         ( void ) xTaskResumeAll();\r
1194                         traceQUEUE_RECEIVE_FAILED( pxQueue );\r
1195                         return errQUEUE_EMPTY;\r
1196                 }\r
1197         }\r
1198 }\r
1199 /*-----------------------------------------------------------*/\r
1200 \r
1201 signed portBASE_TYPE xQueueReceiveFromISR( xQueueHandle xQueue, void * const pvBuffer, signed portBASE_TYPE *pxHigherPriorityTaskWoken )\r
1202 {\r
1203 signed portBASE_TYPE xReturn;\r
1204 unsigned portBASE_TYPE uxSavedInterruptStatus;\r
1205 xQUEUE * const pxQueue = ( xQUEUE * ) xQueue;\r
1206 \r
1207         configASSERT( pxQueue );\r
1208         configASSERT( !( ( pvBuffer == NULL ) && ( pxQueue->uxItemSize != ( unsigned portBASE_TYPE ) 0U ) ) );\r
1209 \r
1210         /* RTOS ports that support interrupt nesting have the concept of a maximum\r
1211         system call (or maximum API call) interrupt priority.  Interrupts that are\r
1212         above the maximum system call priority are keep permanently enabled, even\r
1213         when the RTOS kernel is in a critical section, but cannot make any calls to\r
1214         FreeRTOS API functions.  If configASSERT() is defined in FreeRTOSConfig.h\r
1215         then portASSERT_IF_INTERRUPT_PRIORITY_INVALID() will result in an assertion\r
1216         failure if a FreeRTOS API function is called from an interrupt that has been\r
1217         assigned a priority above the configured maximum system call priority.\r
1218         Only FreeRTOS functions that end in FromISR can be called from interrupts\r
1219         that have been assigned a priority at or (logically) below the maximum\r
1220         system call     interrupt priority.  FreeRTOS maintains a separate interrupt\r
1221         safe API to ensure interrupt entry is as fast and as simple as possible.\r
1222         More information (albeit Cortex-M specific) is provided on the following\r
1223         link: http://www.freertos.org/RTOS-Cortex-M3-M4.html */\r
1224         portASSERT_IF_INTERRUPT_PRIORITY_INVALID();\r
1225 \r
1226         uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR();\r
1227         {\r
1228                 /* Cannot block in an ISR, so check there is data available. */\r
1229                 if( pxQueue->uxMessagesWaiting > ( unsigned portBASE_TYPE ) 0 )\r
1230                 {\r
1231                         traceQUEUE_RECEIVE_FROM_ISR( pxQueue );\r
1232 \r
1233                         prvCopyDataFromQueue( pxQueue, pvBuffer );\r
1234                         --( pxQueue->uxMessagesWaiting );\r
1235 \r
1236                         /* If the queue is locked the event list will not be modified.\r
1237                         Instead update the lock count so the task that unlocks the queue\r
1238                         will know that an ISR has removed data while the queue was\r
1239                         locked. */\r
1240                         if( pxQueue->xRxLock == queueUNLOCKED )\r
1241                         {\r
1242                                 if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) == pdFALSE )\r
1243                                 {\r
1244                                         if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) != pdFALSE )\r
1245                                         {\r
1246                                                 /* The task waiting has a higher priority than us so\r
1247                                                 force a context switch. */\r
1248                                                 if( pxHigherPriorityTaskWoken != NULL )\r
1249                                                 {\r
1250                                                         *pxHigherPriorityTaskWoken = pdTRUE;\r
1251                                                 }\r
1252                                         }\r
1253                                 }\r
1254                         }\r
1255                         else\r
1256                         {\r
1257                                 /* Increment the lock count so the task that unlocks the queue\r
1258                                 knows that data was removed while it was locked. */\r
1259                                 ++( pxQueue->xRxLock );\r
1260                         }\r
1261 \r
1262                         xReturn = pdPASS;\r
1263                 }\r
1264                 else\r
1265                 {\r
1266                         xReturn = pdFAIL;\r
1267                         traceQUEUE_RECEIVE_FROM_ISR_FAILED( pxQueue );\r
1268                 }\r
1269         }\r
1270         portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus );\r
1271 \r
1272         return xReturn;\r
1273 }\r
1274 /*-----------------------------------------------------------*/\r
1275 \r
1276 signed portBASE_TYPE xQueuePeekFromISR( xQueueHandle xQueue,  void * const pvBuffer )\r
1277 {\r
1278 signed portBASE_TYPE xReturn;\r
1279 unsigned portBASE_TYPE uxSavedInterruptStatus;\r
1280 signed char *pcOriginalReadPosition;\r
1281 xQUEUE * const pxQueue = ( xQUEUE * ) xQueue;\r
1282 \r
1283         configASSERT( pxQueue );\r
1284         configASSERT( !( ( pvBuffer == NULL ) && ( pxQueue->uxItemSize != ( unsigned portBASE_TYPE ) 0U ) ) );\r
1285 \r
1286         /* RTOS ports that support interrupt nesting have the concept of a maximum\r
1287         system call (or maximum API call) interrupt priority.  Interrupts that are\r
1288         above the maximum system call priority are keep permanently enabled, even\r
1289         when the RTOS kernel is in a critical section, but cannot make any calls to\r
1290         FreeRTOS API functions.  If configASSERT() is defined in FreeRTOSConfig.h\r
1291         then portASSERT_IF_INTERRUPT_PRIORITY_INVALID() will result in an assertion\r
1292         failure if a FreeRTOS API function is called from an interrupt that has been\r
1293         assigned a priority above the configured maximum system call priority.\r
1294         Only FreeRTOS functions that end in FromISR can be called from interrupts\r
1295         that have been assigned a priority at or (logically) below the maximum\r
1296         system call     interrupt priority.  FreeRTOS maintains a separate interrupt\r
1297         safe API to ensure interrupt entry is as fast and as simple as possible.\r
1298         More information (albeit Cortex-M specific) is provided on the following\r
1299         link: http://www.freertos.org/RTOS-Cortex-M3-M4.html */\r
1300         portASSERT_IF_INTERRUPT_PRIORITY_INVALID();\r
1301 \r
1302         uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR();\r
1303         {\r
1304                 /* Cannot block in an ISR, so check there is data available. */\r
1305                 if( pxQueue->uxMessagesWaiting > ( unsigned portBASE_TYPE ) 0 )\r
1306                 {\r
1307                         traceQUEUE_PEEK_FROM_ISR( pxQueue );\r
1308 \r
1309                         /* Remember the read position so it can be reset as nothing is\r
1310                         actually being removed from the queue. */\r
1311                         pcOriginalReadPosition = pxQueue->u.pcReadFrom;\r
1312                         prvCopyDataFromQueue( pxQueue, pvBuffer );\r
1313                         pxQueue->u.pcReadFrom = pcOriginalReadPosition;\r
1314 \r
1315                         xReturn = pdPASS;\r
1316                 }\r
1317                 else\r
1318                 {\r
1319                         xReturn = pdFAIL;\r
1320                         traceQUEUE_PEEK_FROM_ISR_FAILED( pxQueue );\r
1321                 }\r
1322         }\r
1323         portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus );\r
1324 \r
1325         return xReturn;\r
1326 }\r
1327 /*-----------------------------------------------------------*/\r
1328 \r
1329 unsigned portBASE_TYPE uxQueueMessagesWaiting( const xQueueHandle xQueue )\r
1330 {\r
1331 unsigned portBASE_TYPE uxReturn;\r
1332 \r
1333         configASSERT( xQueue );\r
1334 \r
1335         taskENTER_CRITICAL();\r
1336                 uxReturn = ( ( xQUEUE * ) xQueue )->uxMessagesWaiting;\r
1337         taskEXIT_CRITICAL();\r
1338 \r
1339         return uxReturn;\r
1340 } /*lint !e818 Pointer cannot be declared const as xQueue is a typedef not pointer. */\r
1341 /*-----------------------------------------------------------*/\r
1342 \r
1343 unsigned portBASE_TYPE uxQueueSpacesAvailable( const xQueueHandle xQueue )\r
1344 {\r
1345 unsigned portBASE_TYPE uxReturn;\r
1346 xQUEUE *pxQueue;\r
1347 \r
1348         pxQueue = ( xQUEUE * ) xQueue;\r
1349         configASSERT( pxQueue );\r
1350 \r
1351         taskENTER_CRITICAL();\r
1352                 uxReturn = pxQueue->uxLength - pxQueue->uxMessagesWaiting;\r
1353         taskEXIT_CRITICAL();\r
1354 \r
1355         return uxReturn;\r
1356 } /*lint !e818 Pointer cannot be declared const as xQueue is a typedef not pointer. */\r
1357 /*-----------------------------------------------------------*/\r
1358 \r
1359 unsigned portBASE_TYPE uxQueueMessagesWaitingFromISR( const xQueueHandle xQueue )\r
1360 {\r
1361 unsigned portBASE_TYPE uxReturn;\r
1362 \r
1363         configASSERT( xQueue );\r
1364 \r
1365         uxReturn = ( ( xQUEUE * ) xQueue )->uxMessagesWaiting;\r
1366 \r
1367         return uxReturn;\r
1368 } /*lint !e818 Pointer cannot be declared const as xQueue is a typedef not pointer. */\r
1369 /*-----------------------------------------------------------*/\r
1370 \r
1371 void vQueueDelete( xQueueHandle xQueue )\r
1372 {\r
1373 xQUEUE * const pxQueue = ( xQUEUE * ) xQueue;\r
1374 \r
1375         configASSERT( pxQueue );\r
1376 \r
1377         traceQUEUE_DELETE( pxQueue );\r
1378         #if ( configQUEUE_REGISTRY_SIZE > 0 )\r
1379         {\r
1380                 vQueueUnregisterQueue( pxQueue );\r
1381         }\r
1382         #endif\r
1383         vPortFree( pxQueue->pcHead );\r
1384         vPortFree( pxQueue );\r
1385 }\r
1386 /*-----------------------------------------------------------*/\r
1387 \r
1388 #if ( configUSE_TRACE_FACILITY == 1 )\r
1389 \r
1390         unsigned char ucQueueGetQueueNumber( xQueueHandle xQueue )\r
1391         {\r
1392                 return ( ( xQUEUE * ) xQueue )->ucQueueNumber;\r
1393         }\r
1394 \r
1395 #endif /* configUSE_TRACE_FACILITY */\r
1396 /*-----------------------------------------------------------*/\r
1397 \r
1398 #if ( configUSE_TRACE_FACILITY == 1 )\r
1399 \r
1400         void vQueueSetQueueNumber( xQueueHandle xQueue, unsigned char ucQueueNumber )\r
1401         {\r
1402                 ( ( xQUEUE * ) xQueue )->ucQueueNumber = ucQueueNumber;\r
1403         }\r
1404 \r
1405 #endif /* configUSE_TRACE_FACILITY */\r
1406 /*-----------------------------------------------------------*/\r
1407 \r
1408 #if ( configUSE_TRACE_FACILITY == 1 )\r
1409 \r
1410         unsigned char ucQueueGetQueueType( xQueueHandle xQueue )\r
1411         {\r
1412                 return ( ( xQUEUE * ) xQueue )->ucQueueType;\r
1413         }\r
1414 \r
1415 #endif /* configUSE_TRACE_FACILITY */\r
1416 /*-----------------------------------------------------------*/\r
1417 \r
1418 static void prvCopyDataToQueue( xQUEUE *pxQueue, const void *pvItemToQueue, portBASE_TYPE xPosition )\r
1419 {\r
1420         if( pxQueue->uxItemSize == ( unsigned portBASE_TYPE ) 0 )\r
1421         {\r
1422                 #if ( configUSE_MUTEXES == 1 )\r
1423                 {\r
1424                         if( pxQueue->uxQueueType == queueQUEUE_IS_MUTEX )\r
1425                         {\r
1426                                 /* The mutex is no longer being held. */\r
1427                                 vTaskPriorityDisinherit( ( void * ) pxQueue->pxMutexHolder );\r
1428                                 pxQueue->pxMutexHolder = NULL;\r
1429                         }\r
1430                 }\r
1431                 #endif /* configUSE_MUTEXES */\r
1432         }\r
1433         else if( xPosition == queueSEND_TO_BACK )\r
1434         {\r
1435                 ( 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
1436                 pxQueue->pcWriteTo += pxQueue->uxItemSize;\r
1437                 if( pxQueue->pcWriteTo >= pxQueue->pcTail ) /*lint !e946 MISRA exception justified as comparison of pointers is the cleanest solution. */\r
1438                 {\r
1439                         pxQueue->pcWriteTo = pxQueue->pcHead;\r
1440                 }\r
1441         }\r
1442         else\r
1443         {\r
1444                 ( 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
1445                 pxQueue->u.pcReadFrom -= pxQueue->uxItemSize;\r
1446                 if( pxQueue->u.pcReadFrom < pxQueue->pcHead ) /*lint !e946 MISRA exception justified as comparison of pointers is the cleanest solution. */\r
1447                 {\r
1448                         pxQueue->u.pcReadFrom = ( pxQueue->pcTail - pxQueue->uxItemSize );\r
1449                 }\r
1450 \r
1451                 if( xPosition == queueOVERWRITE )\r
1452                 {\r
1453                         if( pxQueue->uxMessagesWaiting > ( unsigned portBASE_TYPE ) 0 )\r
1454                         {\r
1455                                 /* An item is not being added but overwritten, so subtract\r
1456                                 one from the recorded number of items in the queue so when\r
1457                                 one is added again below the number of recorded items remains\r
1458                                 correct. */\r
1459                                 --( pxQueue->uxMessagesWaiting );\r
1460                         }\r
1461                 }\r
1462         }\r
1463 \r
1464         ++( pxQueue->uxMessagesWaiting );\r
1465 }\r
1466 /*-----------------------------------------------------------*/\r
1467 \r
1468 static void prvCopyDataFromQueue( xQUEUE * const pxQueue, void * const pvBuffer )\r
1469 {\r
1470         if( pxQueue->uxQueueType != queueQUEUE_IS_MUTEX )\r
1471         {\r
1472                 pxQueue->u.pcReadFrom += pxQueue->uxItemSize;\r
1473                 if( pxQueue->u.pcReadFrom >= pxQueue->pcTail ) /*lint !e946 MISRA exception justified as use of the relational operator is the cleanest solutions. */\r
1474                 {\r
1475                         pxQueue->u.pcReadFrom = pxQueue->pcHead;\r
1476                 }\r
1477                 ( 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
1478         }\r
1479 }\r
1480 /*-----------------------------------------------------------*/\r
1481 \r
1482 static void prvUnlockQueue( xQUEUE *pxQueue )\r
1483 {\r
1484         /* THIS FUNCTION MUST BE CALLED WITH THE SCHEDULER SUSPENDED. */\r
1485 \r
1486         /* The lock counts contains the number of extra data items placed or\r
1487         removed from the queue while the queue was locked.  When a queue is\r
1488         locked items can be added or removed, but the event lists cannot be\r
1489         updated. */\r
1490         taskENTER_CRITICAL();\r
1491         {\r
1492                 /* See if data was added to the queue while it was locked. */\r
1493                 while( pxQueue->xTxLock > queueLOCKED_UNMODIFIED )\r
1494                 {\r
1495                         /* Data was posted while the queue was locked.  Are any tasks\r
1496                         blocked waiting for data to become available? */\r
1497                         #if ( configUSE_QUEUE_SETS == 1 )\r
1498                         {\r
1499                                 if( pxQueue->pxQueueSetContainer != NULL )\r
1500                                 {\r
1501                                         if( prvNotifyQueueSetContainer( pxQueue, queueSEND_TO_BACK ) == pdTRUE )\r
1502                                         {\r
1503                                                 /* The queue is a member of a queue set, and posting to\r
1504                                                 the queue set caused a higher priority task to unblock.\r
1505                                                 A context switch is required. */\r
1506                                                 vTaskMissedYield();\r
1507                                         }\r
1508                                 }\r
1509                                 else\r
1510                                 {\r
1511                                         /* Tasks that are removed from the event list will get added to\r
1512                                         the pending ready list as the scheduler is still suspended. */\r
1513                                         if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE )\r
1514                                         {\r
1515                                                 if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE )\r
1516                                                 {\r
1517                                                         /* The task waiting has a higher priority so record that a\r
1518                                                         context switch is required. */\r
1519                                                         vTaskMissedYield();\r
1520                                                 }\r
1521                                         }\r
1522                                         else\r
1523                                         {\r
1524                                                 break;\r
1525                                         }\r
1526                                 }\r
1527                         }\r
1528                         #else /* configUSE_QUEUE_SETS */\r
1529                         {\r
1530                                 /* Tasks that are removed from the event list will get added to\r
1531                                 the pending ready list as the scheduler is still suspended. */\r
1532                                 if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE )\r
1533                                 {\r
1534                                         if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE )\r
1535                                         {\r
1536                                                 /* The task waiting has a higher priority so record that a\r
1537                                                 context switch is required. */\r
1538                                                 vTaskMissedYield();\r
1539                                         }\r
1540                                 }\r
1541                                 else\r
1542                                 {\r
1543                                         break;\r
1544                                 }\r
1545                         }\r
1546                         #endif /* configUSE_QUEUE_SETS */\r
1547 \r
1548                         --( pxQueue->xTxLock );\r
1549                 }\r
1550 \r
1551                 pxQueue->xTxLock = queueUNLOCKED;\r
1552         }\r
1553         taskEXIT_CRITICAL();\r
1554 \r
1555         /* Do the same for the Rx lock. */\r
1556         taskENTER_CRITICAL();\r
1557         {\r
1558                 while( pxQueue->xRxLock > queueLOCKED_UNMODIFIED )\r
1559                 {\r
1560                         if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) == pdFALSE )\r
1561                         {\r
1562                                 if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) != pdFALSE )\r
1563                                 {\r
1564                                         vTaskMissedYield();\r
1565                                 }\r
1566 \r
1567                                 --( pxQueue->xRxLock );\r
1568                         }\r
1569                         else\r
1570                         {\r
1571                                 break;\r
1572                         }\r
1573                 }\r
1574 \r
1575                 pxQueue->xRxLock = queueUNLOCKED;\r
1576         }\r
1577         taskEXIT_CRITICAL();\r
1578 }\r
1579 /*-----------------------------------------------------------*/\r
1580 \r
1581 static signed portBASE_TYPE prvIsQueueEmpty( const xQUEUE *pxQueue )\r
1582 {\r
1583 signed portBASE_TYPE xReturn;\r
1584 \r
1585         taskENTER_CRITICAL();\r
1586         {\r
1587                 if( pxQueue->uxMessagesWaiting == ( unsigned portBASE_TYPE )  0 )\r
1588                 {\r
1589                         xReturn = pdTRUE;\r
1590                 }\r
1591                 else\r
1592                 {\r
1593                         xReturn = pdFALSE;\r
1594                 }\r
1595         }\r
1596         taskEXIT_CRITICAL();\r
1597 \r
1598         return xReturn;\r
1599 }\r
1600 /*-----------------------------------------------------------*/\r
1601 \r
1602 signed portBASE_TYPE xQueueIsQueueEmptyFromISR( const xQueueHandle xQueue )\r
1603 {\r
1604 signed portBASE_TYPE xReturn;\r
1605 \r
1606         configASSERT( xQueue );\r
1607         if( ( ( xQUEUE * ) xQueue )->uxMessagesWaiting == ( unsigned portBASE_TYPE ) 0 )\r
1608         {\r
1609                 xReturn = pdTRUE;\r
1610         }\r
1611         else\r
1612         {\r
1613                 xReturn = pdFALSE;\r
1614         }\r
1615 \r
1616         return xReturn;\r
1617 } /*lint !e818 xQueue could not be pointer to const because it is a typedef. */\r
1618 /*-----------------------------------------------------------*/\r
1619 \r
1620 static signed portBASE_TYPE prvIsQueueFull( const xQUEUE *pxQueue )\r
1621 {\r
1622 signed portBASE_TYPE xReturn;\r
1623 \r
1624         taskENTER_CRITICAL();\r
1625         {\r
1626                 if( pxQueue->uxMessagesWaiting == pxQueue->uxLength )\r
1627                 {\r
1628                         xReturn = pdTRUE;\r
1629                 }\r
1630                 else\r
1631                 {\r
1632                         xReturn = pdFALSE;\r
1633                 }\r
1634         }\r
1635         taskEXIT_CRITICAL();\r
1636 \r
1637         return xReturn;\r
1638 }\r
1639 /*-----------------------------------------------------------*/\r
1640 \r
1641 signed portBASE_TYPE xQueueIsQueueFullFromISR( const xQueueHandle xQueue )\r
1642 {\r
1643 signed portBASE_TYPE xReturn;\r
1644 \r
1645         configASSERT( xQueue );\r
1646         if( ( ( xQUEUE * ) xQueue )->uxMessagesWaiting == ( ( xQUEUE * ) xQueue )->uxLength )\r
1647         {\r
1648                 xReturn = pdTRUE;\r
1649         }\r
1650         else\r
1651         {\r
1652                 xReturn = pdFALSE;\r
1653         }\r
1654 \r
1655         return xReturn;\r
1656 } /*lint !e818 xQueue could not be pointer to const because it is a typedef. */\r
1657 /*-----------------------------------------------------------*/\r
1658 \r
1659 #if ( configUSE_CO_ROUTINES == 1 )\r
1660 \r
1661         signed portBASE_TYPE xQueueCRSend( xQueueHandle xQueue, const void *pvItemToQueue, portTickType xTicksToWait )\r
1662         {\r
1663         signed portBASE_TYPE xReturn;\r
1664         xQUEUE * const pxQueue = ( xQUEUE * ) xQueue;\r
1665 \r
1666                 /* If the queue is already full we may have to block.  A critical section\r
1667                 is required to prevent an interrupt removing something from the queue\r
1668                 between the check to see if the queue is full and blocking on the queue. */\r
1669                 portDISABLE_INTERRUPTS();\r
1670                 {\r
1671                         if( prvIsQueueFull( pxQueue ) != pdFALSE )\r
1672                         {\r
1673                                 /* The queue is full - do we want to block or just leave without\r
1674                                 posting? */\r
1675                                 if( xTicksToWait > ( portTickType ) 0 )\r
1676                                 {\r
1677                                         /* As this is called from a coroutine we cannot block directly, but\r
1678                                         return indicating that we need to block. */\r
1679                                         vCoRoutineAddToDelayedList( xTicksToWait, &( pxQueue->xTasksWaitingToSend ) );\r
1680                                         portENABLE_INTERRUPTS();\r
1681                                         return errQUEUE_BLOCKED;\r
1682                                 }\r
1683                                 else\r
1684                                 {\r
1685                                         portENABLE_INTERRUPTS();\r
1686                                         return errQUEUE_FULL;\r
1687                                 }\r
1688                         }\r
1689                 }\r
1690                 portENABLE_INTERRUPTS();\r
1691 \r
1692                 portDISABLE_INTERRUPTS();\r
1693                 {\r
1694                         if( pxQueue->uxMessagesWaiting < pxQueue->uxLength )\r
1695                         {\r
1696                                 /* There is room in the queue, copy the data into the queue. */\r
1697                                 prvCopyDataToQueue( pxQueue, pvItemToQueue, queueSEND_TO_BACK );\r
1698                                 xReturn = pdPASS;\r
1699 \r
1700                                 /* Were any co-routines waiting for data to become available? */\r
1701                                 if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE )\r
1702                                 {\r
1703                                         /* In this instance the co-routine could be placed directly\r
1704                                         into the ready list as we are within a critical section.\r
1705                                         Instead the same pending ready list mechanism is used as if\r
1706                                         the event were caused from within an interrupt. */\r
1707                                         if( xCoRoutineRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE )\r
1708                                         {\r
1709                                                 /* The co-routine waiting has a higher priority so record\r
1710                                                 that a yield might be appropriate. */\r
1711                                                 xReturn = errQUEUE_YIELD;\r
1712                                         }\r
1713                                 }\r
1714                         }\r
1715                         else\r
1716                         {\r
1717                                 xReturn = errQUEUE_FULL;\r
1718                         }\r
1719                 }\r
1720                 portENABLE_INTERRUPTS();\r
1721 \r
1722                 return xReturn;\r
1723         }\r
1724 \r
1725 #endif /* configUSE_CO_ROUTINES */\r
1726 /*-----------------------------------------------------------*/\r
1727 \r
1728 #if ( configUSE_CO_ROUTINES == 1 )\r
1729 \r
1730         signed portBASE_TYPE xQueueCRReceive( xQueueHandle xQueue, void *pvBuffer, portTickType xTicksToWait )\r
1731         {\r
1732         signed portBASE_TYPE xReturn;\r
1733         xQUEUE * const pxQueue = ( xQUEUE * ) xQueue;\r
1734 \r
1735                 /* If the queue is already empty we may have to block.  A critical section\r
1736                 is required to prevent an interrupt adding something to the queue\r
1737                 between the check to see if the queue is empty and blocking on the queue. */\r
1738                 portDISABLE_INTERRUPTS();\r
1739                 {\r
1740                         if( pxQueue->uxMessagesWaiting == ( unsigned portBASE_TYPE ) 0 )\r
1741                         {\r
1742                                 /* There are no messages in the queue, do we want to block or just\r
1743                                 leave with nothing? */\r
1744                                 if( xTicksToWait > ( portTickType ) 0 )\r
1745                                 {\r
1746                                         /* As this is a co-routine we cannot block directly, but return\r
1747                                         indicating that we need to block. */\r
1748                                         vCoRoutineAddToDelayedList( xTicksToWait, &( pxQueue->xTasksWaitingToReceive ) );\r
1749                                         portENABLE_INTERRUPTS();\r
1750                                         return errQUEUE_BLOCKED;\r
1751                                 }\r
1752                                 else\r
1753                                 {\r
1754                                         portENABLE_INTERRUPTS();\r
1755                                         return errQUEUE_FULL;\r
1756                                 }\r
1757                         }\r
1758                 }\r
1759                 portENABLE_INTERRUPTS();\r
1760 \r
1761                 portDISABLE_INTERRUPTS();\r
1762                 {\r
1763                         if( pxQueue->uxMessagesWaiting > ( unsigned portBASE_TYPE ) 0 )\r
1764                         {\r
1765                                 /* Data is available from the queue. */\r
1766                                 pxQueue->u.pcReadFrom += pxQueue->uxItemSize;\r
1767                                 if( pxQueue->u.pcReadFrom >= pxQueue->pcTail )\r
1768                                 {\r
1769                                         pxQueue->u.pcReadFrom = pxQueue->pcHead;\r
1770                                 }\r
1771                                 --( pxQueue->uxMessagesWaiting );\r
1772                                 ( void ) memcpy( ( void * ) pvBuffer, ( void * ) pxQueue->u.pcReadFrom, ( unsigned ) pxQueue->uxItemSize );\r
1773 \r
1774                                 xReturn = pdPASS;\r
1775 \r
1776                                 /* Were any co-routines waiting for space to become available? */\r
1777                                 if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) == pdFALSE )\r
1778                                 {\r
1779                                         /* In this instance the co-routine could be placed directly\r
1780                                         into the ready list as we are within a critical section.\r
1781                                         Instead the same pending ready list mechanism is used as if\r
1782                                         the event were caused from within an interrupt. */\r
1783                                         if( xCoRoutineRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) != pdFALSE )\r
1784                                         {\r
1785                                                 xReturn = errQUEUE_YIELD;\r
1786                                         }\r
1787                                 }\r
1788                         }\r
1789                         else\r
1790                         {\r
1791                                 xReturn = pdFAIL;\r
1792                         }\r
1793                 }\r
1794                 portENABLE_INTERRUPTS();\r
1795 \r
1796                 return xReturn;\r
1797         }\r
1798 \r
1799 #endif /* configUSE_CO_ROUTINES */\r
1800 /*-----------------------------------------------------------*/\r
1801 \r
1802 #if ( configUSE_CO_ROUTINES == 1 )\r
1803 \r
1804         signed portBASE_TYPE xQueueCRSendFromISR( xQueueHandle xQueue, const void *pvItemToQueue, signed portBASE_TYPE xCoRoutinePreviouslyWoken )\r
1805         {\r
1806         xQUEUE * const pxQueue = ( xQUEUE * ) xQueue;\r
1807 \r
1808                 /* Cannot block within an ISR so if there is no space on the queue then\r
1809                 exit without doing anything. */\r
1810                 if( pxQueue->uxMessagesWaiting < pxQueue->uxLength )\r
1811                 {\r
1812                         prvCopyDataToQueue( pxQueue, pvItemToQueue, queueSEND_TO_BACK );\r
1813 \r
1814                         /* We only want to wake one co-routine per ISR, so check that a\r
1815                         co-routine has not already been woken. */\r
1816                         if( xCoRoutinePreviouslyWoken == pdFALSE )\r
1817                         {\r
1818                                 if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE )\r
1819                                 {\r
1820                                         if( xCoRoutineRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE )\r
1821                                         {\r
1822                                                 return pdTRUE;\r
1823                                         }\r
1824                                 }\r
1825                         }\r
1826                 }\r
1827 \r
1828                 return xCoRoutinePreviouslyWoken;\r
1829         }\r
1830 \r
1831 #endif /* configUSE_CO_ROUTINES */\r
1832 /*-----------------------------------------------------------*/\r
1833 \r
1834 #if ( configUSE_CO_ROUTINES == 1 )\r
1835 \r
1836         signed portBASE_TYPE xQueueCRReceiveFromISR( xQueueHandle xQueue, void *pvBuffer, signed portBASE_TYPE *pxCoRoutineWoken )\r
1837         {\r
1838         signed portBASE_TYPE xReturn;\r
1839         xQUEUE * const pxQueue = ( xQUEUE * ) xQueue;\r
1840 \r
1841                 /* We cannot block from an ISR, so check there is data available. If\r
1842                 not then just leave without doing anything. */\r
1843                 if( pxQueue->uxMessagesWaiting > ( unsigned portBASE_TYPE ) 0 )\r
1844                 {\r
1845                         /* Copy the data from the queue. */\r
1846                         pxQueue->u.pcReadFrom += pxQueue->uxItemSize;\r
1847                         if( pxQueue->u.pcReadFrom >= pxQueue->pcTail )\r
1848                         {\r
1849                                 pxQueue->u.pcReadFrom = pxQueue->pcHead;\r
1850                         }\r
1851                         --( pxQueue->uxMessagesWaiting );\r
1852                         ( void ) memcpy( ( void * ) pvBuffer, ( void * ) pxQueue->u.pcReadFrom, ( unsigned ) pxQueue->uxItemSize );\r
1853 \r
1854                         if( ( *pxCoRoutineWoken ) == pdFALSE )\r
1855                         {\r
1856                                 if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) == pdFALSE )\r
1857                                 {\r
1858                                         if( xCoRoutineRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) != pdFALSE )\r
1859                                         {\r
1860                                                 *pxCoRoutineWoken = pdTRUE;\r
1861                                         }\r
1862                                 }\r
1863                         }\r
1864 \r
1865                         xReturn = pdPASS;\r
1866                 }\r
1867                 else\r
1868                 {\r
1869                         xReturn = pdFAIL;\r
1870                 }\r
1871 \r
1872                 return xReturn;\r
1873         }\r
1874 \r
1875 #endif /* configUSE_CO_ROUTINES */\r
1876 /*-----------------------------------------------------------*/\r
1877 \r
1878 #if ( configQUEUE_REGISTRY_SIZE > 0 )\r
1879 \r
1880         void vQueueAddToRegistry( xQueueHandle xQueue, signed char *pcQueueName )\r
1881         {\r
1882         unsigned portBASE_TYPE ux;\r
1883 \r
1884                 /* See if there is an empty space in the registry.  A NULL name denotes\r
1885                 a free slot. */\r
1886                 for( ux = ( unsigned portBASE_TYPE ) 0U; ux < ( unsigned portBASE_TYPE ) configQUEUE_REGISTRY_SIZE; ux++ )\r
1887                 {\r
1888                         if( xQueueRegistry[ ux ].pcQueueName == NULL )\r
1889                         {\r
1890                                 /* Store the information on this queue. */\r
1891                                 xQueueRegistry[ ux ].pcQueueName = pcQueueName;\r
1892                                 xQueueRegistry[ ux ].xHandle = xQueue;\r
1893                                 break;\r
1894                         }\r
1895                 }\r
1896         }\r
1897 \r
1898 #endif /* configQUEUE_REGISTRY_SIZE */\r
1899 /*-----------------------------------------------------------*/\r
1900 \r
1901 #if ( configQUEUE_REGISTRY_SIZE > 0 )\r
1902 \r
1903         void vQueueUnregisterQueue( xQueueHandle xQueue )\r
1904         {\r
1905         unsigned portBASE_TYPE ux;\r
1906 \r
1907                 /* See if the handle of the queue being unregistered in actually in the\r
1908                 registry. */\r
1909                 for( ux = ( unsigned portBASE_TYPE ) 0U; ux < ( unsigned portBASE_TYPE ) configQUEUE_REGISTRY_SIZE; ux++ )\r
1910                 {\r
1911                         if( xQueueRegistry[ ux ].xHandle == xQueue )\r
1912                         {\r
1913                                 /* Set the name to NULL to show that this slot if free again. */\r
1914                                 xQueueRegistry[ ux ].pcQueueName = NULL;\r
1915                                 break;\r
1916                         }\r
1917                 }\r
1918 \r
1919         } /*lint !e818 xQueue could not be pointer to const because it is a typedef. */\r
1920 \r
1921 #endif /* configQUEUE_REGISTRY_SIZE */\r
1922 /*-----------------------------------------------------------*/\r
1923 \r
1924 #if ( configUSE_TIMERS == 1 )\r
1925 \r
1926         void vQueueWaitForMessageRestricted( xQueueHandle xQueue, portTickType xTicksToWait )\r
1927         {\r
1928         xQUEUE * const pxQueue = ( xQUEUE * ) xQueue;\r
1929 \r
1930                 /* This function should not be called by application code hence the\r
1931                 'Restricted' in its name.  It is not part of the public API.  It is\r
1932                 designed for use by kernel code, and has special calling requirements.\r
1933                 It can result in vListInsert() being called on a list that can only\r
1934                 possibly ever have one item in it, so the list will be fast, but even\r
1935                 so it should be called with the scheduler locked and not from a critical\r
1936                 section. */\r
1937 \r
1938                 /* Only do anything if there are no messages in the queue.  This function\r
1939                 will not actually cause the task to block, just place it on a blocked\r
1940                 list.  It will not block until the scheduler is unlocked - at which\r
1941                 time a yield will be performed.  If an item is added to the queue while\r
1942                 the queue is locked, and the calling task blocks on the queue, then the\r
1943                 calling task will be immediately unblocked when the queue is unlocked. */\r
1944                 prvLockQueue( pxQueue );\r
1945                 if( pxQueue->uxMessagesWaiting == ( unsigned portBASE_TYPE ) 0U )\r
1946                 {\r
1947                         /* There is nothing in the queue, block for the specified period. */\r
1948                         vTaskPlaceOnEventListRestricted( &( pxQueue->xTasksWaitingToReceive ), xTicksToWait );\r
1949                 }\r
1950                 prvUnlockQueue( pxQueue );\r
1951         }\r
1952 \r
1953 #endif /* configUSE_TIMERS */\r
1954 /*-----------------------------------------------------------*/\r
1955 \r
1956 #if ( configUSE_QUEUE_SETS == 1 )\r
1957 \r
1958         xQueueSetHandle xQueueCreateSet( unsigned portBASE_TYPE uxEventQueueLength )\r
1959         {\r
1960         xQueueSetHandle pxQueue;\r
1961 \r
1962                 pxQueue = xQueueGenericCreate( uxEventQueueLength, sizeof( xQUEUE * ), queueQUEUE_TYPE_SET );\r
1963 \r
1964                 return pxQueue;\r
1965         }\r
1966 \r
1967 #endif /* configUSE_QUEUE_SETS */\r
1968 /*-----------------------------------------------------------*/\r
1969 \r
1970 #if ( configUSE_QUEUE_SETS == 1 )\r
1971 \r
1972         portBASE_TYPE xQueueAddToSet( xQueueSetMemberHandle xQueueOrSemaphore, xQueueSetHandle xQueueSet )\r
1973         {\r
1974         portBASE_TYPE xReturn;\r
1975 \r
1976                 if( ( ( xQUEUE * ) xQueueOrSemaphore )->pxQueueSetContainer != NULL )\r
1977                 {\r
1978                         /* Cannot add a queue/semaphore to more than one queue set. */\r
1979                         xReturn = pdFAIL;\r
1980                 }\r
1981                 else if( ( ( xQUEUE * ) xQueueOrSemaphore )->uxMessagesWaiting != ( unsigned portBASE_TYPE ) 0 )\r
1982                 {\r
1983                         /* Cannot add a queue/semaphore to a queue set if there are already\r
1984                         items in the queue/semaphore. */\r
1985                         xReturn = pdFAIL;\r
1986                 }\r
1987                 else\r
1988                 {\r
1989                         taskENTER_CRITICAL();\r
1990                         {\r
1991                                 ( ( xQUEUE * ) xQueueOrSemaphore )->pxQueueSetContainer = xQueueSet;\r
1992                         }\r
1993                         taskEXIT_CRITICAL();\r
1994                         xReturn = pdPASS;\r
1995                 }\r
1996 \r
1997                 return xReturn;\r
1998         }\r
1999 \r
2000 #endif /* configUSE_QUEUE_SETS */\r
2001 /*-----------------------------------------------------------*/\r
2002 \r
2003 #if ( configUSE_QUEUE_SETS == 1 )\r
2004 \r
2005         portBASE_TYPE xQueueRemoveFromSet( xQueueSetMemberHandle xQueueOrSemaphore, xQueueSetHandle xQueueSet )\r
2006         {\r
2007         portBASE_TYPE xReturn;\r
2008         xQUEUE * const pxQueueOrSemaphore = ( xQUEUE * ) xQueueOrSemaphore;\r
2009 \r
2010                 if( pxQueueOrSemaphore->pxQueueSetContainer != xQueueSet )\r
2011                 {\r
2012                         /* The queue was not a member of the set. */\r
2013                         xReturn = pdFAIL;\r
2014                 }\r
2015                 else if( pxQueueOrSemaphore->uxMessagesWaiting != ( unsigned portBASE_TYPE ) 0 )\r
2016                 {\r
2017                         /* It is dangerous to remove a queue from a set when the queue is\r
2018                         not empty because the queue set will still hold pending events for\r
2019                         the queue. */\r
2020                         xReturn = pdFAIL;\r
2021                 }\r
2022                 else\r
2023                 {\r
2024                         taskENTER_CRITICAL();\r
2025                         {\r
2026                                 /* The queue is no longer contained in the set. */\r
2027                                 pxQueueOrSemaphore->pxQueueSetContainer = NULL;\r
2028                         }\r
2029                         taskEXIT_CRITICAL();\r
2030                         xReturn = pdPASS;\r
2031                 }\r
2032 \r
2033                 return xReturn;\r
2034         } /*lint !e818 xQueueSet could not be declared as pointing to const as it is a typedef. */\r
2035 \r
2036 #endif /* configUSE_QUEUE_SETS */\r
2037 /*-----------------------------------------------------------*/\r
2038 \r
2039 #if ( configUSE_QUEUE_SETS == 1 )\r
2040 \r
2041         xQueueSetMemberHandle xQueueSelectFromSet( xQueueSetHandle xQueueSet, portTickType xBlockTimeTicks )\r
2042         {\r
2043         xQueueSetMemberHandle xReturn = NULL;\r
2044 \r
2045                 ( void ) xQueueGenericReceive( ( xQueueHandle ) xQueueSet, &xReturn, xBlockTimeTicks, pdFALSE ); /*lint !e961 Casting from one typedef to another is not redundant. */\r
2046                 return xReturn;\r
2047         }\r
2048 \r
2049 #endif /* configUSE_QUEUE_SETS */\r
2050 /*-----------------------------------------------------------*/\r
2051 \r
2052 #if ( configUSE_QUEUE_SETS == 1 )\r
2053 \r
2054         xQueueSetMemberHandle xQueueSelectFromSetFromISR( xQueueSetHandle xQueueSet )\r
2055         {\r
2056         xQueueSetMemberHandle xReturn = NULL;\r
2057 \r
2058                 ( void ) xQueueReceiveFromISR( ( xQueueHandle ) xQueueSet, &xReturn, NULL ); /*lint !e961 Casting from one typedef to another is not redundant. */\r
2059                 return xReturn;\r
2060         }\r
2061 \r
2062 #endif /* configUSE_QUEUE_SETS */\r
2063 /*-----------------------------------------------------------*/\r
2064 \r
2065 #if ( configUSE_QUEUE_SETS == 1 )\r
2066 \r
2067         static portBASE_TYPE prvNotifyQueueSetContainer( const xQUEUE * const pxQueue, portBASE_TYPE xCopyPosition )\r
2068         {\r
2069         xQUEUE *pxQueueSetContainer = pxQueue->pxQueueSetContainer;\r
2070         portBASE_TYPE xReturn = pdFALSE;\r
2071 \r
2072                 configASSERT( pxQueueSetContainer );\r
2073                 configASSERT( pxQueueSetContainer->uxMessagesWaiting < pxQueueSetContainer->uxLength );\r
2074 \r
2075                 if( pxQueueSetContainer->uxMessagesWaiting < pxQueueSetContainer->uxLength )\r
2076                 {\r
2077                         traceQUEUE_SEND( pxQueueSetContainer );\r
2078                         /* The data copies is the handle of the queue that contains data. */\r
2079                         prvCopyDataToQueue( pxQueueSetContainer, &pxQueue, xCopyPosition );\r
2080                         if( listLIST_IS_EMPTY( &( pxQueueSetContainer->xTasksWaitingToReceive ) ) == pdFALSE )\r
2081                         {\r
2082                                 if( xTaskRemoveFromEventList( &( pxQueueSetContainer->xTasksWaitingToReceive ) ) != pdFALSE )\r
2083                                 {\r
2084                                         /* The task waiting has a higher priority */\r
2085                                         xReturn = pdTRUE;\r
2086                                 }\r
2087                         }\r
2088                 }\r
2089 \r
2090                 return xReturn;\r
2091         }\r
2092 \r
2093 #endif /* configUSE_QUEUE_SETS */\r
2094 \r
2095 \r
2096 \r
2097 \r
2098 \r
2099 \r
2100 \r
2101 \r
2102 \r
2103 \r
2104 \r
2105 \r