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