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