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