]> begriffs open source - freertos/blob - queue.c
FreeRTOS MPU: Remove MPU region number check (#1261)
[freertos] / queue.c
1 /*
2  * FreeRTOS Kernel <DEVELOPMENT BRANCH>
3  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
4  *
5  * SPDX-License-Identifier: MIT
6  *
7  * Permission is hereby granted, free of charge, to any person obtaining a copy of
8  * this software and associated documentation files (the "Software"), to deal in
9  * the Software without restriction, including without limitation the rights to
10  * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
11  * the Software, and to permit persons to whom the Software is furnished to do so,
12  * subject to the following conditions:
13  *
14  * The above copyright notice and this permission notice shall be included in all
15  * copies or substantial portions of the Software.
16  *
17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
19  * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
20  * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
21  * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23  *
24  * https://www.FreeRTOS.org
25  * https://github.com/FreeRTOS
26  *
27  */
28
29 #include <stdlib.h>
30 #include <string.h>
31
32 /* Defining MPU_WRAPPERS_INCLUDED_FROM_API_FILE prevents task.h from redefining
33  * all the API functions to use the MPU wrappers.  That should only be done when
34  * task.h is included from an application file. */
35 #define MPU_WRAPPERS_INCLUDED_FROM_API_FILE
36
37 #include "FreeRTOS.h"
38 #include "task.h"
39 #include "queue.h"
40
41 #if ( configUSE_CO_ROUTINES == 1 )
42     #include "croutine.h"
43 #endif
44
45 /* The MPU ports require MPU_WRAPPERS_INCLUDED_FROM_API_FILE to be defined
46  * for the header files above, but not in this file, in order to generate the
47  * correct privileged Vs unprivileged linkage and placement. */
48 #undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE
49
50
51 /* Constants used with the cRxLock and cTxLock structure members. */
52 #define queueUNLOCKED             ( ( int8_t ) -1 )
53 #define queueLOCKED_UNMODIFIED    ( ( int8_t ) 0 )
54 #define queueINT8_MAX             ( ( int8_t ) 127 )
55
56 /* When the Queue_t structure is used to represent a base queue its pcHead and
57  * pcTail members are used as pointers into the queue storage area.  When the
58  * Queue_t structure is used to represent a mutex pcHead and pcTail pointers are
59  * not necessary, and the pcHead pointer is set to NULL to indicate that the
60  * structure instead holds a pointer to the mutex holder (if any).  Map alternative
61  * names to the pcHead and structure member to ensure the readability of the code
62  * is maintained.  The QueuePointers_t and SemaphoreData_t types are used to form
63  * a union as their usage is mutually exclusive dependent on what the queue is
64  * being used for. */
65 #define uxQueueType               pcHead
66 #define queueQUEUE_IS_MUTEX       NULL
67
68 typedef struct QueuePointers
69 {
70     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. */
71     int8_t * pcReadFrom; /**< Points to the last place that a queued item was read from when the structure is used as a queue. */
72 } QueuePointers_t;
73
74 typedef struct SemaphoreData
75 {
76     TaskHandle_t xMutexHolder;        /**< The handle of the task that holds the mutex. */
77     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. */
78 } SemaphoreData_t;
79
80 /* Semaphores do not actually store or copy data, so have an item size of
81  * zero. */
82 #define queueSEMAPHORE_QUEUE_ITEM_LENGTH    ( ( UBaseType_t ) 0 )
83 #define queueMUTEX_GIVE_BLOCK_TIME          ( ( TickType_t ) 0U )
84
85 #if ( configUSE_PREEMPTION == 0 )
86
87 /* If the cooperative scheduler is being used then a yield should not be
88  * performed just because a higher priority task has been woken. */
89     #define queueYIELD_IF_USING_PREEMPTION()
90 #else
91     #if ( configNUMBER_OF_CORES == 1 )
92         #define queueYIELD_IF_USING_PREEMPTION()    portYIELD_WITHIN_API()
93     #else /* #if ( configNUMBER_OF_CORES == 1 ) */
94         #define queueYIELD_IF_USING_PREEMPTION()    vTaskYieldWithinAPI()
95     #endif /* #if ( configNUMBER_OF_CORES == 1 ) */
96 #endif
97
98 /*
99  * Definition of the queue used by the scheduler.
100  * Items are queued by copy, not reference.  See the following link for the
101  * rationale: https://www.FreeRTOS.org/Embedded-RTOS-Queues.html
102  */
103 typedef struct QueueDefinition /* The old naming convention is used to prevent breaking kernel aware debuggers. */
104 {
105     int8_t * pcHead;           /**< Points to the beginning of the queue storage area. */
106     int8_t * pcWriteTo;        /**< Points to the free next place in the storage area. */
107
108     union
109     {
110         QueuePointers_t xQueue;     /**< Data required exclusively when this structure is used as a queue. */
111         SemaphoreData_t xSemaphore; /**< Data required exclusively when this structure is used as a semaphore. */
112     } u;
113
114     List_t xTasksWaitingToSend;             /**< List of tasks that are blocked waiting to post onto this queue.  Stored in priority order. */
115     List_t xTasksWaitingToReceive;          /**< List of tasks that are blocked waiting to read from this queue.  Stored in priority order. */
116
117     volatile UBaseType_t uxMessagesWaiting; /**< The number of items currently in the queue. */
118     UBaseType_t uxLength;                   /**< The length of the queue defined as the number of items it will hold, not the number of bytes. */
119     UBaseType_t uxItemSize;                 /**< The size of each items that the queue will hold. */
120
121     volatile int8_t cRxLock;                /**< 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. */
122     volatile int8_t cTxLock;                /**< 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. */
123
124     #if ( ( configSUPPORT_STATIC_ALLOCATION == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) )
125         uint8_t ucStaticallyAllocated; /**< Set to pdTRUE if the memory used by the queue was statically allocated to ensure no attempt is made to free the memory. */
126     #endif
127
128     #if ( configUSE_QUEUE_SETS == 1 )
129         struct QueueDefinition * pxQueueSetContainer;
130     #endif
131
132     #if ( configUSE_TRACE_FACILITY == 1 )
133         UBaseType_t uxQueueNumber;
134         uint8_t ucQueueType;
135     #endif
136 } xQUEUE;
137
138 /* The old xQUEUE name is maintained above then typedefed to the new Queue_t
139  * name below to enable the use of older kernel aware debuggers. */
140 typedef xQUEUE Queue_t;
141
142 /*-----------------------------------------------------------*/
143
144 /*
145  * The queue registry is just a means for kernel aware debuggers to locate
146  * queue structures.  It has no other purpose so is an optional component.
147  */
148 #if ( configQUEUE_REGISTRY_SIZE > 0 )
149
150 /* The type stored within the queue registry array.  This allows a name
151  * to be assigned to each queue making kernel aware debugging a little
152  * more user friendly. */
153     typedef struct QUEUE_REGISTRY_ITEM
154     {
155         const char * pcQueueName;
156         QueueHandle_t xHandle;
157     } xQueueRegistryItem;
158
159 /* The old xQueueRegistryItem name is maintained above then typedefed to the
160  * new xQueueRegistryItem name below to enable the use of older kernel aware
161  * debuggers. */
162     typedef xQueueRegistryItem QueueRegistryItem_t;
163
164 /* The queue registry is simply an array of QueueRegistryItem_t structures.
165  * The pcQueueName member of a structure being NULL is indicative of the
166  * array position being vacant. */
167
168 /* MISRA Ref 8.4.2 [Declaration shall be visible] */
169 /* More details at: https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/MISRA.md#rule-84 */
170 /* coverity[misra_c_2012_rule_8_4_violation] */
171     PRIVILEGED_DATA QueueRegistryItem_t xQueueRegistry[ configQUEUE_REGISTRY_SIZE ];
172
173 #endif /* configQUEUE_REGISTRY_SIZE */
174
175 /*
176  * Unlocks a queue locked by a call to prvLockQueue.  Locking a queue does not
177  * prevent an ISR from adding or removing items to the queue, but does prevent
178  * an ISR from removing tasks from the queue event lists.  If an ISR finds a
179  * queue is locked it will instead increment the appropriate queue lock count
180  * to indicate that a task may require unblocking.  When the queue in unlocked
181  * these lock counts are inspected, and the appropriate action taken.
182  */
183 static void prvUnlockQueue( Queue_t * const pxQueue ) PRIVILEGED_FUNCTION;
184
185 /*
186  * Uses a critical section to determine if there is any data in a queue.
187  *
188  * @return pdTRUE if the queue contains no items, otherwise pdFALSE.
189  */
190 static BaseType_t prvIsQueueEmpty( const Queue_t * pxQueue ) PRIVILEGED_FUNCTION;
191
192 /*
193  * Uses a critical section to determine if there is any space in a queue.
194  *
195  * @return pdTRUE if there is no space, otherwise pdFALSE;
196  */
197 static BaseType_t prvIsQueueFull( const Queue_t * pxQueue ) PRIVILEGED_FUNCTION;
198
199 /*
200  * Copies an item into the queue, either at the front of the queue or the
201  * back of the queue.
202  */
203 static BaseType_t prvCopyDataToQueue( Queue_t * const pxQueue,
204                                       const void * pvItemToQueue,
205                                       const BaseType_t xPosition ) PRIVILEGED_FUNCTION;
206
207 /*
208  * Copies an item out of a queue.
209  */
210 static void prvCopyDataFromQueue( Queue_t * const pxQueue,
211                                   void * const pvBuffer ) PRIVILEGED_FUNCTION;
212
213 #if ( configUSE_QUEUE_SETS == 1 )
214
215 /*
216  * Checks to see if a queue is a member of a queue set, and if so, notifies
217  * the queue set that the queue contains data.
218  */
219     static BaseType_t prvNotifyQueueSetContainer( const Queue_t * const pxQueue ) PRIVILEGED_FUNCTION;
220 #endif
221
222 /*
223  * Called after a Queue_t structure has been allocated either statically or
224  * dynamically to fill in the structure's members.
225  */
226 static void prvInitialiseNewQueue( const UBaseType_t uxQueueLength,
227                                    const UBaseType_t uxItemSize,
228                                    uint8_t * pucQueueStorage,
229                                    const uint8_t ucQueueType,
230                                    Queue_t * pxNewQueue ) PRIVILEGED_FUNCTION;
231
232 /*
233  * Mutexes are a special type of queue.  When a mutex is created, first the
234  * queue is created, then prvInitialiseMutex() is called to configure the queue
235  * as a mutex.
236  */
237 #if ( configUSE_MUTEXES == 1 )
238     static void prvInitialiseMutex( Queue_t * pxNewQueue ) PRIVILEGED_FUNCTION;
239 #endif
240
241 #if ( configUSE_MUTEXES == 1 )
242
243 /*
244  * If a task waiting for a mutex causes the mutex holder to inherit a
245  * priority, but the waiting task times out, then the holder should
246  * disinherit the priority - but only down to the highest priority of any
247  * other tasks that are waiting for the same mutex.  This function returns
248  * that priority.
249  */
250     static UBaseType_t prvGetHighestPriorityOfWaitToReceiveList( const Queue_t * const pxQueue ) PRIVILEGED_FUNCTION;
251 #endif
252 /*-----------------------------------------------------------*/
253
254 /*
255  * Macro to mark a queue as locked.  Locking a queue prevents an ISR from
256  * accessing the queue event lists.
257  */
258 #define prvLockQueue( pxQueue )                            \
259     taskENTER_CRITICAL();                                  \
260     {                                                      \
261         if( ( pxQueue )->cRxLock == queueUNLOCKED )        \
262         {                                                  \
263             ( pxQueue )->cRxLock = queueLOCKED_UNMODIFIED; \
264         }                                                  \
265         if( ( pxQueue )->cTxLock == queueUNLOCKED )        \
266         {                                                  \
267             ( pxQueue )->cTxLock = queueLOCKED_UNMODIFIED; \
268         }                                                  \
269     }                                                      \
270     taskEXIT_CRITICAL()
271
272 /*
273  * Macro to increment cTxLock member of the queue data structure. It is
274  * capped at the number of tasks in the system as we cannot unblock more
275  * tasks than the number of tasks in the system.
276  */
277 #define prvIncrementQueueTxLock( pxQueue, cTxLock )                           \
278     do {                                                                      \
279         const UBaseType_t uxNumberOfTasks = uxTaskGetNumberOfTasks();         \
280         if( ( UBaseType_t ) ( cTxLock ) < uxNumberOfTasks )                   \
281         {                                                                     \
282             configASSERT( ( cTxLock ) != queueINT8_MAX );                     \
283             ( pxQueue )->cTxLock = ( int8_t ) ( ( cTxLock ) + ( int8_t ) 1 ); \
284         }                                                                     \
285     } while( 0 )
286
287 /*
288  * Macro to increment cRxLock member of the queue data structure. It is
289  * capped at the number of tasks in the system as we cannot unblock more
290  * tasks than the number of tasks in the system.
291  */
292 #define prvIncrementQueueRxLock( pxQueue, cRxLock )                           \
293     do {                                                                      \
294         const UBaseType_t uxNumberOfTasks = uxTaskGetNumberOfTasks();         \
295         if( ( UBaseType_t ) ( cRxLock ) < uxNumberOfTasks )                   \
296         {                                                                     \
297             configASSERT( ( cRxLock ) != queueINT8_MAX );                     \
298             ( pxQueue )->cRxLock = ( int8_t ) ( ( cRxLock ) + ( int8_t ) 1 ); \
299         }                                                                     \
300     } while( 0 )
301 /*-----------------------------------------------------------*/
302
303 BaseType_t xQueueGenericReset( QueueHandle_t xQueue,
304                                BaseType_t xNewQueue )
305 {
306     BaseType_t xReturn = pdPASS;
307     Queue_t * const pxQueue = xQueue;
308
309     traceENTER_xQueueGenericReset( xQueue, xNewQueue );
310
311     configASSERT( pxQueue );
312
313     if( ( pxQueue != NULL ) &&
314         ( pxQueue->uxLength >= 1U ) &&
315         /* Check for multiplication overflow. */
316         ( ( SIZE_MAX / pxQueue->uxLength ) >= pxQueue->uxItemSize ) )
317     {
318         taskENTER_CRITICAL();
319         {
320             pxQueue->u.xQueue.pcTail = pxQueue->pcHead + ( pxQueue->uxLength * pxQueue->uxItemSize );
321             pxQueue->uxMessagesWaiting = ( UBaseType_t ) 0U;
322             pxQueue->pcWriteTo = pxQueue->pcHead;
323             pxQueue->u.xQueue.pcReadFrom = pxQueue->pcHead + ( ( pxQueue->uxLength - 1U ) * pxQueue->uxItemSize );
324             pxQueue->cRxLock = queueUNLOCKED;
325             pxQueue->cTxLock = queueUNLOCKED;
326
327             if( xNewQueue == pdFALSE )
328             {
329                 /* If there are tasks blocked waiting to read from the queue, then
330                  * the tasks will remain blocked as after this function exits the queue
331                  * will still be empty.  If there are tasks blocked waiting to write to
332                  * the queue, then one should be unblocked as after this function exits
333                  * it will be possible to write to it. */
334                 if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) == pdFALSE )
335                 {
336                     if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) != pdFALSE )
337                     {
338                         queueYIELD_IF_USING_PREEMPTION();
339                     }
340                     else
341                     {
342                         mtCOVERAGE_TEST_MARKER();
343                     }
344                 }
345                 else
346                 {
347                     mtCOVERAGE_TEST_MARKER();
348                 }
349             }
350             else
351             {
352                 /* Ensure the event queues start in the correct state. */
353                 vListInitialise( &( pxQueue->xTasksWaitingToSend ) );
354                 vListInitialise( &( pxQueue->xTasksWaitingToReceive ) );
355             }
356         }
357         taskEXIT_CRITICAL();
358     }
359     else
360     {
361         xReturn = pdFAIL;
362     }
363
364     configASSERT( xReturn != pdFAIL );
365
366     /* A value is returned for calling semantic consistency with previous
367      * versions. */
368     traceRETURN_xQueueGenericReset( xReturn );
369
370     return xReturn;
371 }
372 /*-----------------------------------------------------------*/
373
374 #if ( configSUPPORT_STATIC_ALLOCATION == 1 )
375
376     QueueHandle_t xQueueGenericCreateStatic( const UBaseType_t uxQueueLength,
377                                              const UBaseType_t uxItemSize,
378                                              uint8_t * pucQueueStorage,
379                                              StaticQueue_t * pxStaticQueue,
380                                              const uint8_t ucQueueType )
381     {
382         Queue_t * pxNewQueue = NULL;
383
384         traceENTER_xQueueGenericCreateStatic( uxQueueLength, uxItemSize, pucQueueStorage, pxStaticQueue, ucQueueType );
385
386         /* The StaticQueue_t structure and the queue storage area must be
387          * supplied. */
388         configASSERT( pxStaticQueue );
389
390         if( ( uxQueueLength > ( UBaseType_t ) 0 ) &&
391             ( pxStaticQueue != NULL ) &&
392
393             /* A queue storage area should be provided if the item size is not 0, and
394              * should not be provided if the item size is 0. */
395             ( !( ( pucQueueStorage != NULL ) && ( uxItemSize == 0U ) ) ) &&
396             ( !( ( pucQueueStorage == NULL ) && ( uxItemSize != 0U ) ) ) )
397         {
398             #if ( configASSERT_DEFINED == 1 )
399             {
400                 /* Sanity check that the size of the structure used to declare a
401                  * variable of type StaticQueue_t or StaticSemaphore_t equals the size of
402                  * the real queue and semaphore structures. */
403                 volatile size_t xSize = sizeof( StaticQueue_t );
404
405                 /* This assertion cannot be branch covered in unit tests */
406                 configASSERT( xSize == sizeof( Queue_t ) ); /* LCOV_EXCL_BR_LINE */
407                 ( void ) xSize;                             /* Prevent unused variable warning when configASSERT() is not defined. */
408             }
409             #endif /* configASSERT_DEFINED */
410
411             /* The address of a statically allocated queue was passed in, use it.
412              * The address of a statically allocated storage area was also passed in
413              * but is already set. */
414             /* MISRA Ref 11.3.1 [Misaligned access] */
415             /* More details at: https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/MISRA.md#rule-113 */
416             /* coverity[misra_c_2012_rule_11_3_violation] */
417             pxNewQueue = ( Queue_t * ) pxStaticQueue;
418
419             #if ( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
420             {
421                 /* Queues can be allocated either statically or dynamically, so
422                  * note this queue was allocated statically in case the queue is
423                  * later deleted. */
424                 pxNewQueue->ucStaticallyAllocated = pdTRUE;
425             }
426             #endif /* configSUPPORT_DYNAMIC_ALLOCATION */
427
428             prvInitialiseNewQueue( uxQueueLength, uxItemSize, pucQueueStorage, ucQueueType, pxNewQueue );
429         }
430         else
431         {
432             configASSERT( pxNewQueue );
433             mtCOVERAGE_TEST_MARKER();
434         }
435
436         traceRETURN_xQueueGenericCreateStatic( pxNewQueue );
437
438         return pxNewQueue;
439     }
440
441 #endif /* configSUPPORT_STATIC_ALLOCATION */
442 /*-----------------------------------------------------------*/
443
444 #if ( configSUPPORT_STATIC_ALLOCATION == 1 )
445
446     BaseType_t xQueueGenericGetStaticBuffers( QueueHandle_t xQueue,
447                                               uint8_t ** ppucQueueStorage,
448                                               StaticQueue_t ** ppxStaticQueue )
449     {
450         BaseType_t xReturn;
451         Queue_t * const pxQueue = xQueue;
452
453         traceENTER_xQueueGenericGetStaticBuffers( xQueue, ppucQueueStorage, ppxStaticQueue );
454
455         configASSERT( pxQueue );
456         configASSERT( ppxStaticQueue );
457
458         #if ( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
459         {
460             /* Check if the queue was statically allocated. */
461             if( pxQueue->ucStaticallyAllocated == ( uint8_t ) pdTRUE )
462             {
463                 if( ppucQueueStorage != NULL )
464                 {
465                     *ppucQueueStorage = ( uint8_t * ) pxQueue->pcHead;
466                 }
467
468                 /* MISRA Ref 11.3.1 [Misaligned access] */
469                 /* More details at: https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/MISRA.md#rule-113 */
470                 /* coverity[misra_c_2012_rule_11_3_violation] */
471                 *ppxStaticQueue = ( StaticQueue_t * ) pxQueue;
472                 xReturn = pdTRUE;
473             }
474             else
475             {
476                 xReturn = pdFALSE;
477             }
478         }
479         #else /* configSUPPORT_DYNAMIC_ALLOCATION */
480         {
481             /* Queue must have been statically allocated. */
482             if( ppucQueueStorage != NULL )
483             {
484                 *ppucQueueStorage = ( uint8_t * ) pxQueue->pcHead;
485             }
486
487             *ppxStaticQueue = ( StaticQueue_t * ) pxQueue;
488             xReturn = pdTRUE;
489         }
490         #endif /* configSUPPORT_DYNAMIC_ALLOCATION */
491
492         traceRETURN_xQueueGenericGetStaticBuffers( xReturn );
493
494         return xReturn;
495     }
496
497 #endif /* configSUPPORT_STATIC_ALLOCATION */
498 /*-----------------------------------------------------------*/
499
500 #if ( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
501
502     QueueHandle_t xQueueGenericCreate( const UBaseType_t uxQueueLength,
503                                        const UBaseType_t uxItemSize,
504                                        const uint8_t ucQueueType )
505     {
506         Queue_t * pxNewQueue = NULL;
507         size_t xQueueSizeInBytes;
508         uint8_t * pucQueueStorage;
509
510         traceENTER_xQueueGenericCreate( uxQueueLength, uxItemSize, ucQueueType );
511
512         if( ( uxQueueLength > ( UBaseType_t ) 0 ) &&
513             /* Check for multiplication overflow. */
514             ( ( SIZE_MAX / uxQueueLength ) >= uxItemSize ) &&
515             /* Check for addition overflow. */
516             /* MISRA Ref 14.3.1 [Configuration dependent invariant] */
517             /* More details at: https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/MISRA.md#rule-143. */
518             /* coverity[misra_c_2012_rule_14_3_violation] */
519             ( ( SIZE_MAX - sizeof( Queue_t ) ) >= ( size_t ) ( ( size_t ) uxQueueLength * ( size_t ) uxItemSize ) ) )
520         {
521             /* Allocate enough space to hold the maximum number of items that
522              * can be in the queue at any time.  It is valid for uxItemSize to be
523              * zero in the case the queue is used as a semaphore. */
524             xQueueSizeInBytes = ( size_t ) ( ( size_t ) uxQueueLength * ( size_t ) uxItemSize );
525
526             /* MISRA Ref 11.5.1 [Malloc memory assignment] */
527             /* More details at: https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/MISRA.md#rule-115 */
528             /* coverity[misra_c_2012_rule_11_5_violation] */
529             pxNewQueue = ( Queue_t * ) pvPortMalloc( sizeof( Queue_t ) + xQueueSizeInBytes );
530
531             if( pxNewQueue != NULL )
532             {
533                 /* Jump past the queue structure to find the location of the queue
534                  * storage area. */
535                 pucQueueStorage = ( uint8_t * ) pxNewQueue;
536                 pucQueueStorage += sizeof( Queue_t );
537
538                 #if ( configSUPPORT_STATIC_ALLOCATION == 1 )
539                 {
540                     /* Queues can be created either statically or dynamically, so
541                      * note this task was created dynamically in case it is later
542                      * deleted. */
543                     pxNewQueue->ucStaticallyAllocated = pdFALSE;
544                 }
545                 #endif /* configSUPPORT_STATIC_ALLOCATION */
546
547                 prvInitialiseNewQueue( uxQueueLength, uxItemSize, pucQueueStorage, ucQueueType, pxNewQueue );
548             }
549             else
550             {
551                 traceQUEUE_CREATE_FAILED( ucQueueType );
552                 mtCOVERAGE_TEST_MARKER();
553             }
554         }
555         else
556         {
557             configASSERT( pxNewQueue );
558             mtCOVERAGE_TEST_MARKER();
559         }
560
561         traceRETURN_xQueueGenericCreate( pxNewQueue );
562
563         return pxNewQueue;
564     }
565
566 #endif /* configSUPPORT_STATIC_ALLOCATION */
567 /*-----------------------------------------------------------*/
568
569 static void prvInitialiseNewQueue( const UBaseType_t uxQueueLength,
570                                    const UBaseType_t uxItemSize,
571                                    uint8_t * pucQueueStorage,
572                                    const uint8_t ucQueueType,
573                                    Queue_t * pxNewQueue )
574 {
575     /* Remove compiler warnings about unused parameters should
576      * configUSE_TRACE_FACILITY not be set to 1. */
577     ( void ) ucQueueType;
578
579     if( uxItemSize == ( UBaseType_t ) 0 )
580     {
581         /* No RAM was allocated for the queue storage area, but PC head cannot
582          * be set to NULL because NULL is used as a key to say the queue is used as
583          * a mutex.  Therefore just set pcHead to point to the queue as a benign
584          * value that is known to be within the memory map. */
585         pxNewQueue->pcHead = ( int8_t * ) pxNewQueue;
586     }
587     else
588     {
589         /* Set the head to the start of the queue storage area. */
590         pxNewQueue->pcHead = ( int8_t * ) pucQueueStorage;
591     }
592
593     /* Initialise the queue members as described where the queue type is
594      * defined. */
595     pxNewQueue->uxLength = uxQueueLength;
596     pxNewQueue->uxItemSize = uxItemSize;
597     ( void ) xQueueGenericReset( pxNewQueue, pdTRUE );
598
599     #if ( configUSE_TRACE_FACILITY == 1 )
600     {
601         pxNewQueue->ucQueueType = ucQueueType;
602     }
603     #endif /* configUSE_TRACE_FACILITY */
604
605     #if ( configUSE_QUEUE_SETS == 1 )
606     {
607         pxNewQueue->pxQueueSetContainer = NULL;
608     }
609     #endif /* configUSE_QUEUE_SETS */
610
611     traceQUEUE_CREATE( pxNewQueue );
612 }
613 /*-----------------------------------------------------------*/
614
615 #if ( configUSE_MUTEXES == 1 )
616
617     static void prvInitialiseMutex( Queue_t * pxNewQueue )
618     {
619         if( pxNewQueue != NULL )
620         {
621             /* The queue create function will set all the queue structure members
622             * correctly for a generic queue, but this function is creating a
623             * mutex.  Overwrite those members that need to be set differently -
624             * in particular the information required for priority inheritance. */
625             pxNewQueue->u.xSemaphore.xMutexHolder = NULL;
626             pxNewQueue->uxQueueType = queueQUEUE_IS_MUTEX;
627
628             /* In case this is a recursive mutex. */
629             pxNewQueue->u.xSemaphore.uxRecursiveCallCount = 0;
630
631             traceCREATE_MUTEX( pxNewQueue );
632
633             /* Start with the semaphore in the expected state. */
634             ( void ) xQueueGenericSend( pxNewQueue, NULL, ( TickType_t ) 0U, queueSEND_TO_BACK );
635         }
636         else
637         {
638             traceCREATE_MUTEX_FAILED();
639         }
640     }
641
642 #endif /* configUSE_MUTEXES */
643 /*-----------------------------------------------------------*/
644
645 #if ( ( configUSE_MUTEXES == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) )
646
647     QueueHandle_t xQueueCreateMutex( const uint8_t ucQueueType )
648     {
649         QueueHandle_t xNewQueue;
650         const UBaseType_t uxMutexLength = ( UBaseType_t ) 1, uxMutexSize = ( UBaseType_t ) 0;
651
652         traceENTER_xQueueCreateMutex( ucQueueType );
653
654         xNewQueue = xQueueGenericCreate( uxMutexLength, uxMutexSize, ucQueueType );
655         prvInitialiseMutex( ( Queue_t * ) xNewQueue );
656
657         traceRETURN_xQueueCreateMutex( xNewQueue );
658
659         return xNewQueue;
660     }
661
662 #endif /* configUSE_MUTEXES */
663 /*-----------------------------------------------------------*/
664
665 #if ( ( configUSE_MUTEXES == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 1 ) )
666
667     QueueHandle_t xQueueCreateMutexStatic( const uint8_t ucQueueType,
668                                            StaticQueue_t * pxStaticQueue )
669     {
670         QueueHandle_t xNewQueue;
671         const UBaseType_t uxMutexLength = ( UBaseType_t ) 1, uxMutexSize = ( UBaseType_t ) 0;
672
673         traceENTER_xQueueCreateMutexStatic( ucQueueType, pxStaticQueue );
674
675         /* Prevent compiler warnings about unused parameters if
676          * configUSE_TRACE_FACILITY does not equal 1. */
677         ( void ) ucQueueType;
678
679         xNewQueue = xQueueGenericCreateStatic( uxMutexLength, uxMutexSize, NULL, pxStaticQueue, ucQueueType );
680         prvInitialiseMutex( ( Queue_t * ) xNewQueue );
681
682         traceRETURN_xQueueCreateMutexStatic( xNewQueue );
683
684         return xNewQueue;
685     }
686
687 #endif /* configUSE_MUTEXES */
688 /*-----------------------------------------------------------*/
689
690 #if ( ( configUSE_MUTEXES == 1 ) && ( INCLUDE_xSemaphoreGetMutexHolder == 1 ) )
691
692     TaskHandle_t xQueueGetMutexHolder( QueueHandle_t xSemaphore )
693     {
694         TaskHandle_t pxReturn;
695         Queue_t * const pxSemaphore = ( Queue_t * ) xSemaphore;
696
697         traceENTER_xQueueGetMutexHolder( xSemaphore );
698
699         configASSERT( xSemaphore );
700
701         /* This function is called by xSemaphoreGetMutexHolder(), and should not
702          * be called directly.  Note:  This is a good way of determining if the
703          * calling task is the mutex holder, but not a good way of determining the
704          * identity of the mutex holder, as the holder may change between the
705          * following critical section exiting and the function returning. */
706         taskENTER_CRITICAL();
707         {
708             if( pxSemaphore->uxQueueType == queueQUEUE_IS_MUTEX )
709             {
710                 pxReturn = pxSemaphore->u.xSemaphore.xMutexHolder;
711             }
712             else
713             {
714                 pxReturn = NULL;
715             }
716         }
717         taskEXIT_CRITICAL();
718
719         traceRETURN_xQueueGetMutexHolder( pxReturn );
720
721         return pxReturn;
722     }
723
724 #endif /* if ( ( configUSE_MUTEXES == 1 ) && ( INCLUDE_xSemaphoreGetMutexHolder == 1 ) ) */
725 /*-----------------------------------------------------------*/
726
727 #if ( ( configUSE_MUTEXES == 1 ) && ( INCLUDE_xSemaphoreGetMutexHolder == 1 ) )
728
729     TaskHandle_t xQueueGetMutexHolderFromISR( QueueHandle_t xSemaphore )
730     {
731         TaskHandle_t pxReturn;
732
733         traceENTER_xQueueGetMutexHolderFromISR( xSemaphore );
734
735         configASSERT( xSemaphore );
736
737         /* Mutexes cannot be used in interrupt service routines, so the mutex
738          * holder should not change in an ISR, and therefore a critical section is
739          * not required here. */
740         if( ( ( Queue_t * ) xSemaphore )->uxQueueType == queueQUEUE_IS_MUTEX )
741         {
742             pxReturn = ( ( Queue_t * ) xSemaphore )->u.xSemaphore.xMutexHolder;
743         }
744         else
745         {
746             pxReturn = NULL;
747         }
748
749         traceRETURN_xQueueGetMutexHolderFromISR( pxReturn );
750
751         return pxReturn;
752     }
753
754 #endif /* if ( ( configUSE_MUTEXES == 1 ) && ( INCLUDE_xSemaphoreGetMutexHolder == 1 ) ) */
755 /*-----------------------------------------------------------*/
756
757 #if ( configUSE_RECURSIVE_MUTEXES == 1 )
758
759     BaseType_t xQueueGiveMutexRecursive( QueueHandle_t xMutex )
760     {
761         BaseType_t xReturn;
762         Queue_t * const pxMutex = ( Queue_t * ) xMutex;
763
764         traceENTER_xQueueGiveMutexRecursive( xMutex );
765
766         configASSERT( pxMutex );
767
768         /* If this is the task that holds the mutex then xMutexHolder will not
769          * change outside of this task.  If this task does not hold the mutex then
770          * pxMutexHolder can never coincidentally equal the tasks handle, and as
771          * this is the only condition we are interested in it does not matter if
772          * pxMutexHolder is accessed simultaneously by another task.  Therefore no
773          * mutual exclusion is required to test the pxMutexHolder variable. */
774         if( pxMutex->u.xSemaphore.xMutexHolder == xTaskGetCurrentTaskHandle() )
775         {
776             traceGIVE_MUTEX_RECURSIVE( pxMutex );
777
778             /* uxRecursiveCallCount cannot be zero if xMutexHolder is equal to
779              * the task handle, therefore no underflow check is required.  Also,
780              * uxRecursiveCallCount is only modified by the mutex holder, and as
781              * there can only be one, no mutual exclusion is required to modify the
782              * uxRecursiveCallCount member. */
783             ( pxMutex->u.xSemaphore.uxRecursiveCallCount )--;
784
785             /* Has the recursive call count unwound to 0? */
786             if( pxMutex->u.xSemaphore.uxRecursiveCallCount == ( UBaseType_t ) 0 )
787             {
788                 /* Return the mutex.  This will automatically unblock any other
789                  * task that might be waiting to access the mutex. */
790                 ( void ) xQueueGenericSend( pxMutex, NULL, queueMUTEX_GIVE_BLOCK_TIME, queueSEND_TO_BACK );
791             }
792             else
793             {
794                 mtCOVERAGE_TEST_MARKER();
795             }
796
797             xReturn = pdPASS;
798         }
799         else
800         {
801             /* The mutex cannot be given because the calling task is not the
802              * holder. */
803             xReturn = pdFAIL;
804
805             traceGIVE_MUTEX_RECURSIVE_FAILED( pxMutex );
806         }
807
808         traceRETURN_xQueueGiveMutexRecursive( xReturn );
809
810         return xReturn;
811     }
812
813 #endif /* configUSE_RECURSIVE_MUTEXES */
814 /*-----------------------------------------------------------*/
815
816 #if ( configUSE_RECURSIVE_MUTEXES == 1 )
817
818     BaseType_t xQueueTakeMutexRecursive( QueueHandle_t xMutex,
819                                          TickType_t xTicksToWait )
820     {
821         BaseType_t xReturn;
822         Queue_t * const pxMutex = ( Queue_t * ) xMutex;
823
824         traceENTER_xQueueTakeMutexRecursive( xMutex, xTicksToWait );
825
826         configASSERT( pxMutex );
827
828         /* Comments regarding mutual exclusion as per those within
829          * xQueueGiveMutexRecursive(). */
830
831         traceTAKE_MUTEX_RECURSIVE( pxMutex );
832
833         if( pxMutex->u.xSemaphore.xMutexHolder == xTaskGetCurrentTaskHandle() )
834         {
835             ( pxMutex->u.xSemaphore.uxRecursiveCallCount )++;
836
837             /* Check if an overflow occurred. */
838             configASSERT( pxMutex->u.xSemaphore.uxRecursiveCallCount );
839
840             xReturn = pdPASS;
841         }
842         else
843         {
844             xReturn = xQueueSemaphoreTake( pxMutex, xTicksToWait );
845
846             /* pdPASS will only be returned if the mutex was successfully
847              * obtained.  The calling task may have entered the Blocked state
848              * before reaching here. */
849             if( xReturn != pdFAIL )
850             {
851                 ( pxMutex->u.xSemaphore.uxRecursiveCallCount )++;
852
853                 /* Check if an overflow occurred. */
854                 configASSERT( pxMutex->u.xSemaphore.uxRecursiveCallCount );
855             }
856             else
857             {
858                 traceTAKE_MUTEX_RECURSIVE_FAILED( pxMutex );
859             }
860         }
861
862         traceRETURN_xQueueTakeMutexRecursive( xReturn );
863
864         return xReturn;
865     }
866
867 #endif /* configUSE_RECURSIVE_MUTEXES */
868 /*-----------------------------------------------------------*/
869
870 #if ( ( configUSE_COUNTING_SEMAPHORES == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 1 ) )
871
872     QueueHandle_t xQueueCreateCountingSemaphoreStatic( const UBaseType_t uxMaxCount,
873                                                        const UBaseType_t uxInitialCount,
874                                                        StaticQueue_t * pxStaticQueue )
875     {
876         QueueHandle_t xHandle = NULL;
877
878         traceENTER_xQueueCreateCountingSemaphoreStatic( uxMaxCount, uxInitialCount, pxStaticQueue );
879
880         if( ( uxMaxCount != 0U ) &&
881             ( uxInitialCount <= uxMaxCount ) )
882         {
883             xHandle = xQueueGenericCreateStatic( uxMaxCount, queueSEMAPHORE_QUEUE_ITEM_LENGTH, NULL, pxStaticQueue, queueQUEUE_TYPE_COUNTING_SEMAPHORE );
884
885             if( xHandle != NULL )
886             {
887                 ( ( Queue_t * ) xHandle )->uxMessagesWaiting = uxInitialCount;
888
889                 traceCREATE_COUNTING_SEMAPHORE();
890             }
891             else
892             {
893                 traceCREATE_COUNTING_SEMAPHORE_FAILED();
894             }
895         }
896         else
897         {
898             configASSERT( xHandle );
899             mtCOVERAGE_TEST_MARKER();
900         }
901
902         traceRETURN_xQueueCreateCountingSemaphoreStatic( xHandle );
903
904         return xHandle;
905     }
906
907 #endif /* ( ( configUSE_COUNTING_SEMAPHORES == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) ) */
908 /*-----------------------------------------------------------*/
909
910 #if ( ( configUSE_COUNTING_SEMAPHORES == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) )
911
912     QueueHandle_t xQueueCreateCountingSemaphore( const UBaseType_t uxMaxCount,
913                                                  const UBaseType_t uxInitialCount )
914     {
915         QueueHandle_t xHandle = NULL;
916
917         traceENTER_xQueueCreateCountingSemaphore( uxMaxCount, uxInitialCount );
918
919         if( ( uxMaxCount != 0U ) &&
920             ( uxInitialCount <= uxMaxCount ) )
921         {
922             xHandle = xQueueGenericCreate( uxMaxCount, queueSEMAPHORE_QUEUE_ITEM_LENGTH, queueQUEUE_TYPE_COUNTING_SEMAPHORE );
923
924             if( xHandle != NULL )
925             {
926                 ( ( Queue_t * ) xHandle )->uxMessagesWaiting = uxInitialCount;
927
928                 traceCREATE_COUNTING_SEMAPHORE();
929             }
930             else
931             {
932                 traceCREATE_COUNTING_SEMAPHORE_FAILED();
933             }
934         }
935         else
936         {
937             configASSERT( xHandle );
938             mtCOVERAGE_TEST_MARKER();
939         }
940
941         traceRETURN_xQueueCreateCountingSemaphore( xHandle );
942
943         return xHandle;
944     }
945
946 #endif /* ( ( configUSE_COUNTING_SEMAPHORES == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) ) */
947 /*-----------------------------------------------------------*/
948
949 BaseType_t xQueueGenericSend( QueueHandle_t xQueue,
950                               const void * const pvItemToQueue,
951                               TickType_t xTicksToWait,
952                               const BaseType_t xCopyPosition )
953 {
954     BaseType_t xEntryTimeSet = pdFALSE, xYieldRequired;
955     TimeOut_t xTimeOut;
956     Queue_t * const pxQueue = xQueue;
957
958     traceENTER_xQueueGenericSend( xQueue, pvItemToQueue, xTicksToWait, xCopyPosition );
959
960     configASSERT( pxQueue );
961     configASSERT( !( ( pvItemToQueue == NULL ) && ( pxQueue->uxItemSize != ( UBaseType_t ) 0U ) ) );
962     configASSERT( !( ( xCopyPosition == queueOVERWRITE ) && ( pxQueue->uxLength != 1 ) ) );
963     #if ( ( INCLUDE_xTaskGetSchedulerState == 1 ) || ( configUSE_TIMERS == 1 ) )
964     {
965         configASSERT( !( ( xTaskGetSchedulerState() == taskSCHEDULER_SUSPENDED ) && ( xTicksToWait != 0 ) ) );
966     }
967     #endif
968
969     for( ; ; )
970     {
971         taskENTER_CRITICAL();
972         {
973             /* Is there room on the queue now?  The running task must be the
974              * highest priority task wanting to access the queue.  If the head item
975              * in the queue is to be overwritten then it does not matter if the
976              * queue is full. */
977             if( ( pxQueue->uxMessagesWaiting < pxQueue->uxLength ) || ( xCopyPosition == queueOVERWRITE ) )
978             {
979                 traceQUEUE_SEND( pxQueue );
980
981                 #if ( configUSE_QUEUE_SETS == 1 )
982                 {
983                     const UBaseType_t uxPreviousMessagesWaiting = pxQueue->uxMessagesWaiting;
984
985                     xYieldRequired = prvCopyDataToQueue( pxQueue, pvItemToQueue, xCopyPosition );
986
987                     if( pxQueue->pxQueueSetContainer != NULL )
988                     {
989                         if( ( xCopyPosition == queueOVERWRITE ) && ( uxPreviousMessagesWaiting != ( UBaseType_t ) 0 ) )
990                         {
991                             /* Do not notify the queue set as an existing item
992                              * was overwritten in the queue so the number of items
993                              * in the queue has not changed. */
994                             mtCOVERAGE_TEST_MARKER();
995                         }
996                         else if( prvNotifyQueueSetContainer( pxQueue ) != pdFALSE )
997                         {
998                             /* The queue is a member of a queue set, and posting
999                              * to the queue set caused a higher priority task to
1000                              * unblock. A context switch is required. */
1001                             queueYIELD_IF_USING_PREEMPTION();
1002                         }
1003                         else
1004                         {
1005                             mtCOVERAGE_TEST_MARKER();
1006                         }
1007                     }
1008                     else
1009                     {
1010                         /* If there was a task waiting for data to arrive on the
1011                          * queue then unblock it now. */
1012                         if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE )
1013                         {
1014                             if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE )
1015                             {
1016                                 /* The unblocked task has a priority higher than
1017                                  * our own so yield immediately.  Yes it is ok to
1018                                  * do this from within the critical section - the
1019                                  * kernel takes care of that. */
1020                                 queueYIELD_IF_USING_PREEMPTION();
1021                             }
1022                             else
1023                             {
1024                                 mtCOVERAGE_TEST_MARKER();
1025                             }
1026                         }
1027                         else if( xYieldRequired != pdFALSE )
1028                         {
1029                             /* This path is a special case that will only get
1030                              * executed if the task was holding multiple mutexes
1031                              * and the mutexes were given back in an order that is
1032                              * different to that in which they were taken. */
1033                             queueYIELD_IF_USING_PREEMPTION();
1034                         }
1035                         else
1036                         {
1037                             mtCOVERAGE_TEST_MARKER();
1038                         }
1039                     }
1040                 }
1041                 #else /* configUSE_QUEUE_SETS */
1042                 {
1043                     xYieldRequired = prvCopyDataToQueue( pxQueue, pvItemToQueue, xCopyPosition );
1044
1045                     /* If there was a task waiting for data to arrive on the
1046                      * queue then unblock it now. */
1047                     if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE )
1048                     {
1049                         if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE )
1050                         {
1051                             /* The unblocked task has a priority higher than
1052                              * our own so yield immediately.  Yes it is ok to do
1053                              * this from within the critical section - the kernel
1054                              * takes care of that. */
1055                             queueYIELD_IF_USING_PREEMPTION();
1056                         }
1057                         else
1058                         {
1059                             mtCOVERAGE_TEST_MARKER();
1060                         }
1061                     }
1062                     else if( xYieldRequired != pdFALSE )
1063                     {
1064                         /* This path is a special case that will only get
1065                          * executed if the task was holding multiple mutexes and
1066                          * the mutexes were given back in an order that is
1067                          * different to that in which they were taken. */
1068                         queueYIELD_IF_USING_PREEMPTION();
1069                     }
1070                     else
1071                     {
1072                         mtCOVERAGE_TEST_MARKER();
1073                     }
1074                 }
1075                 #endif /* configUSE_QUEUE_SETS */
1076
1077                 taskEXIT_CRITICAL();
1078
1079                 traceRETURN_xQueueGenericSend( pdPASS );
1080
1081                 return pdPASS;
1082             }
1083             else
1084             {
1085                 if( xTicksToWait == ( TickType_t ) 0 )
1086                 {
1087                     /* The queue was full and no block time is specified (or
1088                      * the block time has expired) so leave now. */
1089                     taskEXIT_CRITICAL();
1090
1091                     /* Return to the original privilege level before exiting
1092                      * the function. */
1093                     traceQUEUE_SEND_FAILED( pxQueue );
1094                     traceRETURN_xQueueGenericSend( errQUEUE_FULL );
1095
1096                     return errQUEUE_FULL;
1097                 }
1098                 else if( xEntryTimeSet == pdFALSE )
1099                 {
1100                     /* The queue was full and a block time was specified so
1101                      * configure the timeout structure. */
1102                     vTaskInternalSetTimeOutState( &xTimeOut );
1103                     xEntryTimeSet = pdTRUE;
1104                 }
1105                 else
1106                 {
1107                     /* Entry time was already set. */
1108                     mtCOVERAGE_TEST_MARKER();
1109                 }
1110             }
1111         }
1112         taskEXIT_CRITICAL();
1113
1114         /* Interrupts and other tasks can send to and receive from the queue
1115          * now the critical section has been exited. */
1116
1117         vTaskSuspendAll();
1118         prvLockQueue( pxQueue );
1119
1120         /* Update the timeout state to see if it has expired yet. */
1121         if( xTaskCheckForTimeOut( &xTimeOut, &xTicksToWait ) == pdFALSE )
1122         {
1123             if( prvIsQueueFull( pxQueue ) != pdFALSE )
1124             {
1125                 traceBLOCKING_ON_QUEUE_SEND( pxQueue );
1126                 vTaskPlaceOnEventList( &( pxQueue->xTasksWaitingToSend ), xTicksToWait );
1127
1128                 /* Unlocking the queue means queue events can effect the
1129                  * event list. It is possible that interrupts occurring now
1130                  * remove this task from the event list again - but as the
1131                  * scheduler is suspended the task will go onto the pending
1132                  * ready list instead of the actual ready list. */
1133                 prvUnlockQueue( pxQueue );
1134
1135                 /* Resuming the scheduler will move tasks from the pending
1136                  * ready list into the ready list - so it is feasible that this
1137                  * task is already in the ready list before it yields - in which
1138                  * case the yield will not cause a context switch unless there
1139                  * is also a higher priority task in the pending ready list. */
1140                 if( xTaskResumeAll() == pdFALSE )
1141                 {
1142                     taskYIELD_WITHIN_API();
1143                 }
1144             }
1145             else
1146             {
1147                 /* Try again. */
1148                 prvUnlockQueue( pxQueue );
1149                 ( void ) xTaskResumeAll();
1150             }
1151         }
1152         else
1153         {
1154             /* The timeout has expired. */
1155             prvUnlockQueue( pxQueue );
1156             ( void ) xTaskResumeAll();
1157
1158             traceQUEUE_SEND_FAILED( pxQueue );
1159             traceRETURN_xQueueGenericSend( errQUEUE_FULL );
1160
1161             return errQUEUE_FULL;
1162         }
1163     }
1164 }
1165 /*-----------------------------------------------------------*/
1166
1167 BaseType_t xQueueGenericSendFromISR( QueueHandle_t xQueue,
1168                                      const void * const pvItemToQueue,
1169                                      BaseType_t * const pxHigherPriorityTaskWoken,
1170                                      const BaseType_t xCopyPosition )
1171 {
1172     BaseType_t xReturn;
1173     UBaseType_t uxSavedInterruptStatus;
1174     Queue_t * const pxQueue = xQueue;
1175
1176     traceENTER_xQueueGenericSendFromISR( xQueue, pvItemToQueue, pxHigherPriorityTaskWoken, xCopyPosition );
1177
1178     configASSERT( pxQueue );
1179     configASSERT( !( ( pvItemToQueue == NULL ) && ( pxQueue->uxItemSize != ( UBaseType_t ) 0U ) ) );
1180     configASSERT( !( ( xCopyPosition == queueOVERWRITE ) && ( pxQueue->uxLength != 1 ) ) );
1181
1182     /* RTOS ports that support interrupt nesting have the concept of a maximum
1183      * system call (or maximum API call) interrupt priority.  Interrupts that are
1184      * above the maximum system call priority are kept permanently enabled, even
1185      * when the RTOS kernel is in a critical section, but cannot make any calls to
1186      * FreeRTOS API functions.  If configASSERT() is defined in FreeRTOSConfig.h
1187      * then portASSERT_IF_INTERRUPT_PRIORITY_INVALID() will result in an assertion
1188      * failure if a FreeRTOS API function is called from an interrupt that has been
1189      * assigned a priority above the configured maximum system call priority.
1190      * Only FreeRTOS functions that end in FromISR can be called from interrupts
1191      * that have been assigned a priority at or (logically) below the maximum
1192      * system call interrupt priority.  FreeRTOS maintains a separate interrupt
1193      * safe API to ensure interrupt entry is as fast and as simple as possible.
1194      * More information (albeit Cortex-M specific) is provided on the following
1195      * link: https://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html */
1196     portASSERT_IF_INTERRUPT_PRIORITY_INVALID();
1197
1198     /* Similar to xQueueGenericSend, except without blocking if there is no room
1199      * in the queue.  Also don't directly wake a task that was blocked on a queue
1200      * read, instead return a flag to say whether a context switch is required or
1201      * not (i.e. has a task with a higher priority than us been woken by this
1202      * post). */
1203     /* MISRA Ref 4.7.1 [Return value shall be checked] */
1204     /* More details at: https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/MISRA.md#dir-47 */
1205     /* coverity[misra_c_2012_directive_4_7_violation] */
1206     uxSavedInterruptStatus = ( UBaseType_t ) taskENTER_CRITICAL_FROM_ISR();
1207     {
1208         if( ( pxQueue->uxMessagesWaiting < pxQueue->uxLength ) || ( xCopyPosition == queueOVERWRITE ) )
1209         {
1210             const int8_t cTxLock = pxQueue->cTxLock;
1211             const UBaseType_t uxPreviousMessagesWaiting = pxQueue->uxMessagesWaiting;
1212
1213             traceQUEUE_SEND_FROM_ISR( pxQueue );
1214
1215             /* Semaphores use xQueueGiveFromISR(), so pxQueue will not be a
1216              *  semaphore or mutex.  That means prvCopyDataToQueue() cannot result
1217              *  in a task disinheriting a priority and prvCopyDataToQueue() can be
1218              *  called here even though the disinherit function does not check if
1219              *  the scheduler is suspended before accessing the ready lists. */
1220             ( void ) prvCopyDataToQueue( pxQueue, pvItemToQueue, xCopyPosition );
1221
1222             /* The event list is not altered if the queue is locked.  This will
1223              * be done when the queue is unlocked later. */
1224             if( cTxLock == queueUNLOCKED )
1225             {
1226                 #if ( configUSE_QUEUE_SETS == 1 )
1227                 {
1228                     if( pxQueue->pxQueueSetContainer != NULL )
1229                     {
1230                         if( ( xCopyPosition == queueOVERWRITE ) && ( uxPreviousMessagesWaiting != ( UBaseType_t ) 0 ) )
1231                         {
1232                             /* Do not notify the queue set as an existing item
1233                              * was overwritten in the queue so the number of items
1234                              * in the queue has not changed. */
1235                             mtCOVERAGE_TEST_MARKER();
1236                         }
1237                         else if( prvNotifyQueueSetContainer( pxQueue ) != pdFALSE )
1238                         {
1239                             /* The queue is a member of a queue set, and posting
1240                              * to the queue set caused a higher priority task to
1241                              * unblock.  A context switch is required. */
1242                             if( pxHigherPriorityTaskWoken != NULL )
1243                             {
1244                                 *pxHigherPriorityTaskWoken = pdTRUE;
1245                             }
1246                             else
1247                             {
1248                                 mtCOVERAGE_TEST_MARKER();
1249                             }
1250                         }
1251                         else
1252                         {
1253                             mtCOVERAGE_TEST_MARKER();
1254                         }
1255                     }
1256                     else
1257                     {
1258                         if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE )
1259                         {
1260                             if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE )
1261                             {
1262                                 /* The task waiting has a higher priority so
1263                                  *  record that a context switch is required. */
1264                                 if( pxHigherPriorityTaskWoken != NULL )
1265                                 {
1266                                     *pxHigherPriorityTaskWoken = pdTRUE;
1267                                 }
1268                                 else
1269                                 {
1270                                     mtCOVERAGE_TEST_MARKER();
1271                                 }
1272                             }
1273                             else
1274                             {
1275                                 mtCOVERAGE_TEST_MARKER();
1276                             }
1277                         }
1278                         else
1279                         {
1280                             mtCOVERAGE_TEST_MARKER();
1281                         }
1282                     }
1283                 }
1284                 #else /* configUSE_QUEUE_SETS */
1285                 {
1286                     if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE )
1287                     {
1288                         if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE )
1289                         {
1290                             /* The task waiting has a higher priority so record that a
1291                              * context switch is required. */
1292                             if( pxHigherPriorityTaskWoken != NULL )
1293                             {
1294                                 *pxHigherPriorityTaskWoken = pdTRUE;
1295                             }
1296                             else
1297                             {
1298                                 mtCOVERAGE_TEST_MARKER();
1299                             }
1300                         }
1301                         else
1302                         {
1303                             mtCOVERAGE_TEST_MARKER();
1304                         }
1305                     }
1306                     else
1307                     {
1308                         mtCOVERAGE_TEST_MARKER();
1309                     }
1310
1311                     /* Not used in this path. */
1312                     ( void ) uxPreviousMessagesWaiting;
1313                 }
1314                 #endif /* configUSE_QUEUE_SETS */
1315             }
1316             else
1317             {
1318                 /* Increment the lock count so the task that unlocks the queue
1319                  * knows that data was posted while it was locked. */
1320                 prvIncrementQueueTxLock( pxQueue, cTxLock );
1321             }
1322
1323             xReturn = pdPASS;
1324         }
1325         else
1326         {
1327             traceQUEUE_SEND_FROM_ISR_FAILED( pxQueue );
1328             xReturn = errQUEUE_FULL;
1329         }
1330     }
1331     taskEXIT_CRITICAL_FROM_ISR( uxSavedInterruptStatus );
1332
1333     traceRETURN_xQueueGenericSendFromISR( xReturn );
1334
1335     return xReturn;
1336 }
1337 /*-----------------------------------------------------------*/
1338
1339 BaseType_t xQueueGiveFromISR( QueueHandle_t xQueue,
1340                               BaseType_t * const pxHigherPriorityTaskWoken )
1341 {
1342     BaseType_t xReturn;
1343     UBaseType_t uxSavedInterruptStatus;
1344     Queue_t * const pxQueue = xQueue;
1345
1346     traceENTER_xQueueGiveFromISR( xQueue, pxHigherPriorityTaskWoken );
1347
1348     /* Similar to xQueueGenericSendFromISR() but used with semaphores where the
1349      * item size is 0.  Don't directly wake a task that was blocked on a queue
1350      * read, instead return a flag to say whether a context switch is required or
1351      * not (i.e. has a task with a higher priority than us been woken by this
1352      * post). */
1353
1354     configASSERT( pxQueue );
1355
1356     /* xQueueGenericSendFromISR() should be used instead of xQueueGiveFromISR()
1357      * if the item size is not 0. */
1358     configASSERT( pxQueue->uxItemSize == 0 );
1359
1360     /* Normally a mutex would not be given from an interrupt, especially if
1361      * there is a mutex holder, as priority inheritance makes no sense for an
1362      * interrupts, only tasks. */
1363     configASSERT( !( ( pxQueue->uxQueueType == queueQUEUE_IS_MUTEX ) && ( pxQueue->u.xSemaphore.xMutexHolder != NULL ) ) );
1364
1365     /* RTOS ports that support interrupt nesting have the concept of a maximum
1366      * system call (or maximum API call) interrupt priority.  Interrupts that are
1367      * above the maximum system call priority are kept permanently enabled, even
1368      * when the RTOS kernel is in a critical section, but cannot make any calls to
1369      * FreeRTOS API functions.  If configASSERT() is defined in FreeRTOSConfig.h
1370      * then portASSERT_IF_INTERRUPT_PRIORITY_INVALID() will result in an assertion
1371      * failure if a FreeRTOS API function is called from an interrupt that has been
1372      * assigned a priority above the configured maximum system call priority.
1373      * Only FreeRTOS functions that end in FromISR can be called from interrupts
1374      * that have been assigned a priority at or (logically) below the maximum
1375      * system call interrupt priority.  FreeRTOS maintains a separate interrupt
1376      * safe API to ensure interrupt entry is as fast and as simple as possible.
1377      * More information (albeit Cortex-M specific) is provided on the following
1378      * link: https://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html */
1379     portASSERT_IF_INTERRUPT_PRIORITY_INVALID();
1380
1381     /* MISRA Ref 4.7.1 [Return value shall be checked] */
1382     /* More details at: https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/MISRA.md#dir-47 */
1383     /* coverity[misra_c_2012_directive_4_7_violation] */
1384     uxSavedInterruptStatus = ( UBaseType_t ) taskENTER_CRITICAL_FROM_ISR();
1385     {
1386         const UBaseType_t uxMessagesWaiting = pxQueue->uxMessagesWaiting;
1387
1388         /* When the queue is used to implement a semaphore no data is ever
1389          * moved through the queue but it is still valid to see if the queue 'has
1390          * space'. */
1391         if( uxMessagesWaiting < pxQueue->uxLength )
1392         {
1393             const int8_t cTxLock = pxQueue->cTxLock;
1394
1395             traceQUEUE_SEND_FROM_ISR( pxQueue );
1396
1397             /* A task can only have an inherited priority if it is a mutex
1398              * holder - and if there is a mutex holder then the mutex cannot be
1399              * given from an ISR.  As this is the ISR version of the function it
1400              * can be assumed there is no mutex holder and no need to determine if
1401              * priority disinheritance is needed.  Simply increase the count of
1402              * messages (semaphores) available. */
1403             pxQueue->uxMessagesWaiting = ( UBaseType_t ) ( uxMessagesWaiting + ( UBaseType_t ) 1 );
1404
1405             /* The event list is not altered if the queue is locked.  This will
1406              * be done when the queue is unlocked later. */
1407             if( cTxLock == queueUNLOCKED )
1408             {
1409                 #if ( configUSE_QUEUE_SETS == 1 )
1410                 {
1411                     if( pxQueue->pxQueueSetContainer != NULL )
1412                     {
1413                         if( prvNotifyQueueSetContainer( pxQueue ) != pdFALSE )
1414                         {
1415                             /* The semaphore is a member of a queue set, and
1416                              * posting to the queue set caused a higher priority
1417                              * task to unblock.  A context switch is required. */
1418                             if( pxHigherPriorityTaskWoken != NULL )
1419                             {
1420                                 *pxHigherPriorityTaskWoken = pdTRUE;
1421                             }
1422                             else
1423                             {
1424                                 mtCOVERAGE_TEST_MARKER();
1425                             }
1426                         }
1427                         else
1428                         {
1429                             mtCOVERAGE_TEST_MARKER();
1430                         }
1431                     }
1432                     else
1433                     {
1434                         if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE )
1435                         {
1436                             if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE )
1437                             {
1438                                 /* The task waiting has a higher priority so
1439                                  *  record that a context switch is required. */
1440                                 if( pxHigherPriorityTaskWoken != NULL )
1441                                 {
1442                                     *pxHigherPriorityTaskWoken = pdTRUE;
1443                                 }
1444                                 else
1445                                 {
1446                                     mtCOVERAGE_TEST_MARKER();
1447                                 }
1448                             }
1449                             else
1450                             {
1451                                 mtCOVERAGE_TEST_MARKER();
1452                             }
1453                         }
1454                         else
1455                         {
1456                             mtCOVERAGE_TEST_MARKER();
1457                         }
1458                     }
1459                 }
1460                 #else /* configUSE_QUEUE_SETS */
1461                 {
1462                     if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE )
1463                     {
1464                         if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE )
1465                         {
1466                             /* The task waiting has a higher priority so record that a
1467                              * context switch is required. */
1468                             if( pxHigherPriorityTaskWoken != NULL )
1469                             {
1470                                 *pxHigherPriorityTaskWoken = pdTRUE;
1471                             }
1472                             else
1473                             {
1474                                 mtCOVERAGE_TEST_MARKER();
1475                             }
1476                         }
1477                         else
1478                         {
1479                             mtCOVERAGE_TEST_MARKER();
1480                         }
1481                     }
1482                     else
1483                     {
1484                         mtCOVERAGE_TEST_MARKER();
1485                     }
1486                 }
1487                 #endif /* configUSE_QUEUE_SETS */
1488             }
1489             else
1490             {
1491                 /* Increment the lock count so the task that unlocks the queue
1492                  * knows that data was posted while it was locked. */
1493                 prvIncrementQueueTxLock( pxQueue, cTxLock );
1494             }
1495
1496             xReturn = pdPASS;
1497         }
1498         else
1499         {
1500             traceQUEUE_SEND_FROM_ISR_FAILED( pxQueue );
1501             xReturn = errQUEUE_FULL;
1502         }
1503     }
1504     taskEXIT_CRITICAL_FROM_ISR( uxSavedInterruptStatus );
1505
1506     traceRETURN_xQueueGiveFromISR( xReturn );
1507
1508     return xReturn;
1509 }
1510 /*-----------------------------------------------------------*/
1511
1512 BaseType_t xQueueReceive( QueueHandle_t xQueue,
1513                           void * const pvBuffer,
1514                           TickType_t xTicksToWait )
1515 {
1516     BaseType_t xEntryTimeSet = pdFALSE;
1517     TimeOut_t xTimeOut;
1518     Queue_t * const pxQueue = xQueue;
1519
1520     traceENTER_xQueueReceive( xQueue, pvBuffer, xTicksToWait );
1521
1522     /* Check the pointer is not NULL. */
1523     configASSERT( ( pxQueue ) );
1524
1525     /* The buffer into which data is received can only be NULL if the data size
1526      * is zero (so no data is copied into the buffer). */
1527     configASSERT( !( ( ( pvBuffer ) == NULL ) && ( ( pxQueue )->uxItemSize != ( UBaseType_t ) 0U ) ) );
1528
1529     /* Cannot block if the scheduler is suspended. */
1530     #if ( ( INCLUDE_xTaskGetSchedulerState == 1 ) || ( configUSE_TIMERS == 1 ) )
1531     {
1532         configASSERT( !( ( xTaskGetSchedulerState() == taskSCHEDULER_SUSPENDED ) && ( xTicksToWait != 0 ) ) );
1533     }
1534     #endif
1535
1536     for( ; ; )
1537     {
1538         taskENTER_CRITICAL();
1539         {
1540             const UBaseType_t uxMessagesWaiting = pxQueue->uxMessagesWaiting;
1541
1542             /* Is there data in the queue now?  To be running the calling task
1543              * must be the highest priority task wanting to access the queue. */
1544             if( uxMessagesWaiting > ( UBaseType_t ) 0 )
1545             {
1546                 /* Data available, remove one item. */
1547                 prvCopyDataFromQueue( pxQueue, pvBuffer );
1548                 traceQUEUE_RECEIVE( pxQueue );
1549                 pxQueue->uxMessagesWaiting = ( UBaseType_t ) ( uxMessagesWaiting - ( UBaseType_t ) 1 );
1550
1551                 /* There is now space in the queue, were any tasks waiting to
1552                  * post to the queue?  If so, unblock the highest priority waiting
1553                  * task. */
1554                 if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) == pdFALSE )
1555                 {
1556                     if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) != pdFALSE )
1557                     {
1558                         queueYIELD_IF_USING_PREEMPTION();
1559                     }
1560                     else
1561                     {
1562                         mtCOVERAGE_TEST_MARKER();
1563                     }
1564                 }
1565                 else
1566                 {
1567                     mtCOVERAGE_TEST_MARKER();
1568                 }
1569
1570                 taskEXIT_CRITICAL();
1571
1572                 traceRETURN_xQueueReceive( pdPASS );
1573
1574                 return pdPASS;
1575             }
1576             else
1577             {
1578                 if( xTicksToWait == ( TickType_t ) 0 )
1579                 {
1580                     /* The queue was empty and no block time is specified (or
1581                      * the block time has expired) so leave now. */
1582                     taskEXIT_CRITICAL();
1583
1584                     traceQUEUE_RECEIVE_FAILED( pxQueue );
1585                     traceRETURN_xQueueReceive( errQUEUE_EMPTY );
1586
1587                     return errQUEUE_EMPTY;
1588                 }
1589                 else if( xEntryTimeSet == pdFALSE )
1590                 {
1591                     /* The queue was empty and a block time was specified so
1592                      * configure the timeout structure. */
1593                     vTaskInternalSetTimeOutState( &xTimeOut );
1594                     xEntryTimeSet = pdTRUE;
1595                 }
1596                 else
1597                 {
1598                     /* Entry time was already set. */
1599                     mtCOVERAGE_TEST_MARKER();
1600                 }
1601             }
1602         }
1603         taskEXIT_CRITICAL();
1604
1605         /* Interrupts and other tasks can send to and receive from the queue
1606          * now the critical section has been exited. */
1607
1608         vTaskSuspendAll();
1609         prvLockQueue( pxQueue );
1610
1611         /* Update the timeout state to see if it has expired yet. */
1612         if( xTaskCheckForTimeOut( &xTimeOut, &xTicksToWait ) == pdFALSE )
1613         {
1614             /* The timeout has not expired.  If the queue is still empty place
1615              * the task on the list of tasks waiting to receive from the queue. */
1616             if( prvIsQueueEmpty( pxQueue ) != pdFALSE )
1617             {
1618                 traceBLOCKING_ON_QUEUE_RECEIVE( pxQueue );
1619                 vTaskPlaceOnEventList( &( pxQueue->xTasksWaitingToReceive ), xTicksToWait );
1620                 prvUnlockQueue( pxQueue );
1621
1622                 if( xTaskResumeAll() == pdFALSE )
1623                 {
1624                     taskYIELD_WITHIN_API();
1625                 }
1626                 else
1627                 {
1628                     mtCOVERAGE_TEST_MARKER();
1629                 }
1630             }
1631             else
1632             {
1633                 /* The queue contains data again.  Loop back to try and read the
1634                  * data. */
1635                 prvUnlockQueue( pxQueue );
1636                 ( void ) xTaskResumeAll();
1637             }
1638         }
1639         else
1640         {
1641             /* Timed out.  If there is no data in the queue exit, otherwise loop
1642              * back and attempt to read the data. */
1643             prvUnlockQueue( pxQueue );
1644             ( void ) xTaskResumeAll();
1645
1646             if( prvIsQueueEmpty( pxQueue ) != pdFALSE )
1647             {
1648                 traceQUEUE_RECEIVE_FAILED( pxQueue );
1649                 traceRETURN_xQueueReceive( errQUEUE_EMPTY );
1650
1651                 return errQUEUE_EMPTY;
1652             }
1653             else
1654             {
1655                 mtCOVERAGE_TEST_MARKER();
1656             }
1657         }
1658     }
1659 }
1660 /*-----------------------------------------------------------*/
1661
1662 BaseType_t xQueueSemaphoreTake( QueueHandle_t xQueue,
1663                                 TickType_t xTicksToWait )
1664 {
1665     BaseType_t xEntryTimeSet = pdFALSE;
1666     TimeOut_t xTimeOut;
1667     Queue_t * const pxQueue = xQueue;
1668
1669     #if ( configUSE_MUTEXES == 1 )
1670         BaseType_t xInheritanceOccurred = pdFALSE;
1671     #endif
1672
1673     traceENTER_xQueueSemaphoreTake( xQueue, xTicksToWait );
1674
1675     /* Check the queue pointer is not NULL. */
1676     configASSERT( ( pxQueue ) );
1677
1678     /* Check this really is a semaphore, in which case the item size will be
1679      * 0. */
1680     configASSERT( pxQueue->uxItemSize == 0 );
1681
1682     /* Cannot block if the scheduler is suspended. */
1683     #if ( ( INCLUDE_xTaskGetSchedulerState == 1 ) || ( configUSE_TIMERS == 1 ) )
1684     {
1685         configASSERT( !( ( xTaskGetSchedulerState() == taskSCHEDULER_SUSPENDED ) && ( xTicksToWait != 0 ) ) );
1686     }
1687     #endif
1688
1689     for( ; ; )
1690     {
1691         taskENTER_CRITICAL();
1692         {
1693             /* Semaphores are queues with an item size of 0, and where the
1694              * number of messages in the queue is the semaphore's count value. */
1695             const UBaseType_t uxSemaphoreCount = pxQueue->uxMessagesWaiting;
1696
1697             /* Is there data in the queue now?  To be running the calling task
1698              * must be the highest priority task wanting to access the queue. */
1699             if( uxSemaphoreCount > ( UBaseType_t ) 0 )
1700             {
1701                 traceQUEUE_RECEIVE( pxQueue );
1702
1703                 /* Semaphores are queues with a data size of zero and where the
1704                  * messages waiting is the semaphore's count.  Reduce the count. */
1705                 pxQueue->uxMessagesWaiting = ( UBaseType_t ) ( uxSemaphoreCount - ( UBaseType_t ) 1 );
1706
1707                 #if ( configUSE_MUTEXES == 1 )
1708                 {
1709                     if( pxQueue->uxQueueType == queueQUEUE_IS_MUTEX )
1710                     {
1711                         /* Record the information required to implement
1712                          * priority inheritance should it become necessary. */
1713                         pxQueue->u.xSemaphore.xMutexHolder = pvTaskIncrementMutexHeldCount();
1714                     }
1715                     else
1716                     {
1717                         mtCOVERAGE_TEST_MARKER();
1718                     }
1719                 }
1720                 #endif /* configUSE_MUTEXES */
1721
1722                 /* Check to see if other tasks are blocked waiting to give the
1723                  * semaphore, and if so, unblock the highest priority such task. */
1724                 if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) == pdFALSE )
1725                 {
1726                     if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) != pdFALSE )
1727                     {
1728                         queueYIELD_IF_USING_PREEMPTION();
1729                     }
1730                     else
1731                     {
1732                         mtCOVERAGE_TEST_MARKER();
1733                     }
1734                 }
1735                 else
1736                 {
1737                     mtCOVERAGE_TEST_MARKER();
1738                 }
1739
1740                 taskEXIT_CRITICAL();
1741
1742                 traceRETURN_xQueueSemaphoreTake( pdPASS );
1743
1744                 return pdPASS;
1745             }
1746             else
1747             {
1748                 if( xTicksToWait == ( TickType_t ) 0 )
1749                 {
1750                     /* The semaphore count was 0 and no block time is specified
1751                      * (or the block time has expired) so exit now. */
1752                     taskEXIT_CRITICAL();
1753
1754                     traceQUEUE_RECEIVE_FAILED( pxQueue );
1755                     traceRETURN_xQueueSemaphoreTake( errQUEUE_EMPTY );
1756
1757                     return errQUEUE_EMPTY;
1758                 }
1759                 else if( xEntryTimeSet == pdFALSE )
1760                 {
1761                     /* The semaphore count was 0 and a block time was specified
1762                      * so configure the timeout structure ready to block. */
1763                     vTaskInternalSetTimeOutState( &xTimeOut );
1764                     xEntryTimeSet = pdTRUE;
1765                 }
1766                 else
1767                 {
1768                     /* Entry time was already set. */
1769                     mtCOVERAGE_TEST_MARKER();
1770                 }
1771             }
1772         }
1773         taskEXIT_CRITICAL();
1774
1775         /* Interrupts and other tasks can give to and take from the semaphore
1776          * now the critical section has been exited. */
1777
1778         vTaskSuspendAll();
1779         prvLockQueue( pxQueue );
1780
1781         /* Update the timeout state to see if it has expired yet. */
1782         if( xTaskCheckForTimeOut( &xTimeOut, &xTicksToWait ) == pdFALSE )
1783         {
1784             /* A block time is specified and not expired.  If the semaphore
1785              * count is 0 then enter the Blocked state to wait for a semaphore to
1786              * become available.  As semaphores are implemented with queues the
1787              * queue being empty is equivalent to the semaphore count being 0. */
1788             if( prvIsQueueEmpty( pxQueue ) != pdFALSE )
1789             {
1790                 traceBLOCKING_ON_QUEUE_RECEIVE( pxQueue );
1791
1792                 #if ( configUSE_MUTEXES == 1 )
1793                 {
1794                     if( pxQueue->uxQueueType == queueQUEUE_IS_MUTEX )
1795                     {
1796                         taskENTER_CRITICAL();
1797                         {
1798                             xInheritanceOccurred = xTaskPriorityInherit( pxQueue->u.xSemaphore.xMutexHolder );
1799                         }
1800                         taskEXIT_CRITICAL();
1801                     }
1802                     else
1803                     {
1804                         mtCOVERAGE_TEST_MARKER();
1805                     }
1806                 }
1807                 #endif /* if ( configUSE_MUTEXES == 1 ) */
1808
1809                 vTaskPlaceOnEventList( &( pxQueue->xTasksWaitingToReceive ), xTicksToWait );
1810                 prvUnlockQueue( pxQueue );
1811
1812                 if( xTaskResumeAll() == pdFALSE )
1813                 {
1814                     taskYIELD_WITHIN_API();
1815                 }
1816                 else
1817                 {
1818                     mtCOVERAGE_TEST_MARKER();
1819                 }
1820             }
1821             else
1822             {
1823                 /* There was no timeout and the semaphore count was not 0, so
1824                  * attempt to take the semaphore again. */
1825                 prvUnlockQueue( pxQueue );
1826                 ( void ) xTaskResumeAll();
1827             }
1828         }
1829         else
1830         {
1831             /* Timed out. */
1832             prvUnlockQueue( pxQueue );
1833             ( void ) xTaskResumeAll();
1834
1835             /* If the semaphore count is 0 exit now as the timeout has
1836              * expired.  Otherwise return to attempt to take the semaphore that is
1837              * known to be available.  As semaphores are implemented by queues the
1838              * queue being empty is equivalent to the semaphore count being 0. */
1839             if( prvIsQueueEmpty( pxQueue ) != pdFALSE )
1840             {
1841                 #if ( configUSE_MUTEXES == 1 )
1842                 {
1843                     /* xInheritanceOccurred could only have be set if
1844                      * pxQueue->uxQueueType == queueQUEUE_IS_MUTEX so no need to
1845                      * test the mutex type again to check it is actually a mutex. */
1846                     if( xInheritanceOccurred != pdFALSE )
1847                     {
1848                         taskENTER_CRITICAL();
1849                         {
1850                             UBaseType_t uxHighestWaitingPriority;
1851
1852                             /* This task blocking on the mutex caused another
1853                              * task to inherit this task's priority.  Now this task
1854                              * has timed out the priority should be disinherited
1855                              * again, but only as low as the next highest priority
1856                              * task that is waiting for the same mutex. */
1857                             uxHighestWaitingPriority = prvGetHighestPriorityOfWaitToReceiveList( pxQueue );
1858
1859                             /* vTaskPriorityDisinheritAfterTimeout uses the uxHighestWaitingPriority
1860                              * parameter to index pxReadyTasksLists when adding the task holding
1861                              * mutex to the ready list for its new priority. Coverity thinks that
1862                              * it can result in out-of-bounds access which is not true because
1863                              * uxHighestWaitingPriority, as returned by prvGetHighestPriorityOfWaitToReceiveList,
1864                              * is capped at ( configMAX_PRIORITIES - 1 ). */
1865                             /* coverity[overrun] */
1866                             vTaskPriorityDisinheritAfterTimeout( pxQueue->u.xSemaphore.xMutexHolder, uxHighestWaitingPriority );
1867                         }
1868                         taskEXIT_CRITICAL();
1869                     }
1870                 }
1871                 #endif /* configUSE_MUTEXES */
1872
1873                 traceQUEUE_RECEIVE_FAILED( pxQueue );
1874                 traceRETURN_xQueueSemaphoreTake( errQUEUE_EMPTY );
1875
1876                 return errQUEUE_EMPTY;
1877             }
1878             else
1879             {
1880                 mtCOVERAGE_TEST_MARKER();
1881             }
1882         }
1883     }
1884 }
1885 /*-----------------------------------------------------------*/
1886
1887 BaseType_t xQueuePeek( QueueHandle_t xQueue,
1888                        void * const pvBuffer,
1889                        TickType_t xTicksToWait )
1890 {
1891     BaseType_t xEntryTimeSet = pdFALSE;
1892     TimeOut_t xTimeOut;
1893     int8_t * pcOriginalReadPosition;
1894     Queue_t * const pxQueue = xQueue;
1895
1896     traceENTER_xQueuePeek( xQueue, pvBuffer, xTicksToWait );
1897
1898     /* Check the pointer is not NULL. */
1899     configASSERT( ( pxQueue ) );
1900
1901     /* The buffer into which data is received can only be NULL if the data size
1902      * is zero (so no data is copied into the buffer. */
1903     configASSERT( !( ( ( pvBuffer ) == NULL ) && ( ( pxQueue )->uxItemSize != ( UBaseType_t ) 0U ) ) );
1904
1905     /* Cannot block if the scheduler is suspended. */
1906     #if ( ( INCLUDE_xTaskGetSchedulerState == 1 ) || ( configUSE_TIMERS == 1 ) )
1907     {
1908         configASSERT( !( ( xTaskGetSchedulerState() == taskSCHEDULER_SUSPENDED ) && ( xTicksToWait != 0 ) ) );
1909     }
1910     #endif
1911
1912     for( ; ; )
1913     {
1914         taskENTER_CRITICAL();
1915         {
1916             const UBaseType_t uxMessagesWaiting = pxQueue->uxMessagesWaiting;
1917
1918             /* Is there data in the queue now?  To be running the calling task
1919              * must be the highest priority task wanting to access the queue. */
1920             if( uxMessagesWaiting > ( UBaseType_t ) 0 )
1921             {
1922                 /* Remember the read position so it can be reset after the data
1923                  * is read from the queue as this function is only peeking the
1924                  * data, not removing it. */
1925                 pcOriginalReadPosition = pxQueue->u.xQueue.pcReadFrom;
1926
1927                 prvCopyDataFromQueue( pxQueue, pvBuffer );
1928                 traceQUEUE_PEEK( pxQueue );
1929
1930                 /* The data is not being removed, so reset the read pointer. */
1931                 pxQueue->u.xQueue.pcReadFrom = pcOriginalReadPosition;
1932
1933                 /* The data is being left in the queue, so see if there are
1934                  * any other tasks waiting for the data. */
1935                 if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE )
1936                 {
1937                     if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE )
1938                     {
1939                         /* The task waiting has a higher priority than this task. */
1940                         queueYIELD_IF_USING_PREEMPTION();
1941                     }
1942                     else
1943                     {
1944                         mtCOVERAGE_TEST_MARKER();
1945                     }
1946                 }
1947                 else
1948                 {
1949                     mtCOVERAGE_TEST_MARKER();
1950                 }
1951
1952                 taskEXIT_CRITICAL();
1953
1954                 traceRETURN_xQueuePeek( pdPASS );
1955
1956                 return pdPASS;
1957             }
1958             else
1959             {
1960                 if( xTicksToWait == ( TickType_t ) 0 )
1961                 {
1962                     /* The queue was empty and no block time is specified (or
1963                      * the block time has expired) so leave now. */
1964                     taskEXIT_CRITICAL();
1965
1966                     traceQUEUE_PEEK_FAILED( pxQueue );
1967                     traceRETURN_xQueuePeek( errQUEUE_EMPTY );
1968
1969                     return errQUEUE_EMPTY;
1970                 }
1971                 else if( xEntryTimeSet == pdFALSE )
1972                 {
1973                     /* The queue was empty and a block time was specified so
1974                      * configure the timeout structure ready to enter the blocked
1975                      * state. */
1976                     vTaskInternalSetTimeOutState( &xTimeOut );
1977                     xEntryTimeSet = pdTRUE;
1978                 }
1979                 else
1980                 {
1981                     /* Entry time was already set. */
1982                     mtCOVERAGE_TEST_MARKER();
1983                 }
1984             }
1985         }
1986         taskEXIT_CRITICAL();
1987
1988         /* Interrupts and other tasks can send to and receive from the queue
1989          * now that the critical section has been exited. */
1990
1991         vTaskSuspendAll();
1992         prvLockQueue( pxQueue );
1993
1994         /* Update the timeout state to see if it has expired yet. */
1995         if( xTaskCheckForTimeOut( &xTimeOut, &xTicksToWait ) == pdFALSE )
1996         {
1997             /* Timeout has not expired yet, check to see if there is data in the
1998             * queue now, and if not enter the Blocked state to wait for data. */
1999             if( prvIsQueueEmpty( pxQueue ) != pdFALSE )
2000             {
2001                 traceBLOCKING_ON_QUEUE_PEEK( pxQueue );
2002                 vTaskPlaceOnEventList( &( pxQueue->xTasksWaitingToReceive ), xTicksToWait );
2003                 prvUnlockQueue( pxQueue );
2004
2005                 if( xTaskResumeAll() == pdFALSE )
2006                 {
2007                     taskYIELD_WITHIN_API();
2008                 }
2009                 else
2010                 {
2011                     mtCOVERAGE_TEST_MARKER();
2012                 }
2013             }
2014             else
2015             {
2016                 /* There is data in the queue now, so don't enter the blocked
2017                  * state, instead return to try and obtain the data. */
2018                 prvUnlockQueue( pxQueue );
2019                 ( void ) xTaskResumeAll();
2020             }
2021         }
2022         else
2023         {
2024             /* The timeout has expired.  If there is still no data in the queue
2025              * exit, otherwise go back and try to read the data again. */
2026             prvUnlockQueue( pxQueue );
2027             ( void ) xTaskResumeAll();
2028
2029             if( prvIsQueueEmpty( pxQueue ) != pdFALSE )
2030             {
2031                 traceQUEUE_PEEK_FAILED( pxQueue );
2032                 traceRETURN_xQueuePeek( errQUEUE_EMPTY );
2033
2034                 return errQUEUE_EMPTY;
2035             }
2036             else
2037             {
2038                 mtCOVERAGE_TEST_MARKER();
2039             }
2040         }
2041     }
2042 }
2043 /*-----------------------------------------------------------*/
2044
2045 BaseType_t xQueueReceiveFromISR( QueueHandle_t xQueue,
2046                                  void * const pvBuffer,
2047                                  BaseType_t * const pxHigherPriorityTaskWoken )
2048 {
2049     BaseType_t xReturn;
2050     UBaseType_t uxSavedInterruptStatus;
2051     Queue_t * const pxQueue = xQueue;
2052
2053     traceENTER_xQueueReceiveFromISR( xQueue, pvBuffer, pxHigherPriorityTaskWoken );
2054
2055     configASSERT( pxQueue );
2056     configASSERT( !( ( pvBuffer == NULL ) && ( pxQueue->uxItemSize != ( UBaseType_t ) 0U ) ) );
2057
2058     /* RTOS ports that support interrupt nesting have the concept of a maximum
2059      * system call (or maximum API call) interrupt priority.  Interrupts that are
2060      * above the maximum system call priority are kept permanently enabled, even
2061      * when the RTOS kernel is in a critical section, but cannot make any calls to
2062      * FreeRTOS API functions.  If configASSERT() is defined in FreeRTOSConfig.h
2063      * then portASSERT_IF_INTERRUPT_PRIORITY_INVALID() will result in an assertion
2064      * failure if a FreeRTOS API function is called from an interrupt that has been
2065      * assigned a priority above the configured maximum system call priority.
2066      * Only FreeRTOS functions that end in FromISR can be called from interrupts
2067      * that have been assigned a priority at or (logically) below the maximum
2068      * system call interrupt priority.  FreeRTOS maintains a separate interrupt
2069      * safe API to ensure interrupt entry is as fast and as simple as possible.
2070      * More information (albeit Cortex-M specific) is provided on the following
2071      * link: https://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html */
2072     portASSERT_IF_INTERRUPT_PRIORITY_INVALID();
2073
2074     /* MISRA Ref 4.7.1 [Return value shall be checked] */
2075     /* More details at: https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/MISRA.md#dir-47 */
2076     /* coverity[misra_c_2012_directive_4_7_violation] */
2077     uxSavedInterruptStatus = ( UBaseType_t ) taskENTER_CRITICAL_FROM_ISR();
2078     {
2079         const UBaseType_t uxMessagesWaiting = pxQueue->uxMessagesWaiting;
2080
2081         /* Cannot block in an ISR, so check there is data available. */
2082         if( uxMessagesWaiting > ( UBaseType_t ) 0 )
2083         {
2084             const int8_t cRxLock = pxQueue->cRxLock;
2085
2086             traceQUEUE_RECEIVE_FROM_ISR( pxQueue );
2087
2088             prvCopyDataFromQueue( pxQueue, pvBuffer );
2089             pxQueue->uxMessagesWaiting = ( UBaseType_t ) ( uxMessagesWaiting - ( UBaseType_t ) 1 );
2090
2091             /* If the queue is locked the event list will not be modified.
2092              * Instead update the lock count so the task that unlocks the queue
2093              * will know that an ISR has removed data while the queue was
2094              * locked. */
2095             if( cRxLock == queueUNLOCKED )
2096             {
2097                 if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) == pdFALSE )
2098                 {
2099                     if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) != pdFALSE )
2100                     {
2101                         /* The task waiting has a higher priority than us so
2102                          * force a context switch. */
2103                         if( pxHigherPriorityTaskWoken != NULL )
2104                         {
2105                             *pxHigherPriorityTaskWoken = pdTRUE;
2106                         }
2107                         else
2108                         {
2109                             mtCOVERAGE_TEST_MARKER();
2110                         }
2111                     }
2112                     else
2113                     {
2114                         mtCOVERAGE_TEST_MARKER();
2115                     }
2116                 }
2117                 else
2118                 {
2119                     mtCOVERAGE_TEST_MARKER();
2120                 }
2121             }
2122             else
2123             {
2124                 /* Increment the lock count so the task that unlocks the queue
2125                  * knows that data was removed while it was locked. */
2126                 prvIncrementQueueRxLock( pxQueue, cRxLock );
2127             }
2128
2129             xReturn = pdPASS;
2130         }
2131         else
2132         {
2133             xReturn = pdFAIL;
2134             traceQUEUE_RECEIVE_FROM_ISR_FAILED( pxQueue );
2135         }
2136     }
2137     taskEXIT_CRITICAL_FROM_ISR( uxSavedInterruptStatus );
2138
2139     traceRETURN_xQueueReceiveFromISR( xReturn );
2140
2141     return xReturn;
2142 }
2143 /*-----------------------------------------------------------*/
2144
2145 BaseType_t xQueuePeekFromISR( QueueHandle_t xQueue,
2146                               void * const pvBuffer )
2147 {
2148     BaseType_t xReturn;
2149     UBaseType_t uxSavedInterruptStatus;
2150     int8_t * pcOriginalReadPosition;
2151     Queue_t * const pxQueue = xQueue;
2152
2153     traceENTER_xQueuePeekFromISR( xQueue, pvBuffer );
2154
2155     configASSERT( pxQueue );
2156     configASSERT( !( ( pvBuffer == NULL ) && ( pxQueue->uxItemSize != ( UBaseType_t ) 0U ) ) );
2157     configASSERT( pxQueue->uxItemSize != 0 ); /* Can't peek a semaphore. */
2158
2159     /* RTOS ports that support interrupt nesting have the concept of a maximum
2160      * system call (or maximum API call) interrupt priority.  Interrupts that are
2161      * above the maximum system call priority are kept permanently enabled, even
2162      * when the RTOS kernel is in a critical section, but cannot make any calls to
2163      * FreeRTOS API functions.  If configASSERT() is defined in FreeRTOSConfig.h
2164      * then portASSERT_IF_INTERRUPT_PRIORITY_INVALID() will result in an assertion
2165      * failure if a FreeRTOS API function is called from an interrupt that has been
2166      * assigned a priority above the configured maximum system call priority.
2167      * Only FreeRTOS functions that end in FromISR can be called from interrupts
2168      * that have been assigned a priority at or (logically) below the maximum
2169      * system call interrupt priority.  FreeRTOS maintains a separate interrupt
2170      * safe API to ensure interrupt entry is as fast and as simple as possible.
2171      * More information (albeit Cortex-M specific) is provided on the following
2172      * link: https://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html */
2173     portASSERT_IF_INTERRUPT_PRIORITY_INVALID();
2174
2175     /* MISRA Ref 4.7.1 [Return value shall be checked] */
2176     /* More details at: https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/MISRA.md#dir-47 */
2177     /* coverity[misra_c_2012_directive_4_7_violation] */
2178     uxSavedInterruptStatus = ( UBaseType_t ) taskENTER_CRITICAL_FROM_ISR();
2179     {
2180         /* Cannot block in an ISR, so check there is data available. */
2181         if( pxQueue->uxMessagesWaiting > ( UBaseType_t ) 0 )
2182         {
2183             traceQUEUE_PEEK_FROM_ISR( pxQueue );
2184
2185             /* Remember the read position so it can be reset as nothing is
2186              * actually being removed from the queue. */
2187             pcOriginalReadPosition = pxQueue->u.xQueue.pcReadFrom;
2188             prvCopyDataFromQueue( pxQueue, pvBuffer );
2189             pxQueue->u.xQueue.pcReadFrom = pcOriginalReadPosition;
2190
2191             xReturn = pdPASS;
2192         }
2193         else
2194         {
2195             xReturn = pdFAIL;
2196             traceQUEUE_PEEK_FROM_ISR_FAILED( pxQueue );
2197         }
2198     }
2199     taskEXIT_CRITICAL_FROM_ISR( uxSavedInterruptStatus );
2200
2201     traceRETURN_xQueuePeekFromISR( xReturn );
2202
2203     return xReturn;
2204 }
2205 /*-----------------------------------------------------------*/
2206
2207 UBaseType_t uxQueueMessagesWaiting( const QueueHandle_t xQueue )
2208 {
2209     UBaseType_t uxReturn;
2210
2211     traceENTER_uxQueueMessagesWaiting( xQueue );
2212
2213     configASSERT( xQueue );
2214
2215     portBASE_TYPE_ENTER_CRITICAL();
2216     {
2217         uxReturn = ( ( Queue_t * ) xQueue )->uxMessagesWaiting;
2218     }
2219     portBASE_TYPE_EXIT_CRITICAL();
2220
2221     traceRETURN_uxQueueMessagesWaiting( uxReturn );
2222
2223     return uxReturn;
2224 }
2225 /*-----------------------------------------------------------*/
2226
2227 UBaseType_t uxQueueSpacesAvailable( const QueueHandle_t xQueue )
2228 {
2229     UBaseType_t uxReturn;
2230     Queue_t * const pxQueue = xQueue;
2231
2232     traceENTER_uxQueueSpacesAvailable( xQueue );
2233
2234     configASSERT( pxQueue );
2235
2236     portBASE_TYPE_ENTER_CRITICAL();
2237     {
2238         uxReturn = ( UBaseType_t ) ( pxQueue->uxLength - pxQueue->uxMessagesWaiting );
2239     }
2240     portBASE_TYPE_EXIT_CRITICAL();
2241
2242     traceRETURN_uxQueueSpacesAvailable( uxReturn );
2243
2244     return uxReturn;
2245 }
2246 /*-----------------------------------------------------------*/
2247
2248 UBaseType_t uxQueueMessagesWaitingFromISR( const QueueHandle_t xQueue )
2249 {
2250     UBaseType_t uxReturn;
2251     Queue_t * const pxQueue = xQueue;
2252
2253     traceENTER_uxQueueMessagesWaitingFromISR( xQueue );
2254
2255     configASSERT( pxQueue );
2256     uxReturn = pxQueue->uxMessagesWaiting;
2257
2258     traceRETURN_uxQueueMessagesWaitingFromISR( uxReturn );
2259
2260     return uxReturn;
2261 }
2262 /*-----------------------------------------------------------*/
2263
2264 void vQueueDelete( QueueHandle_t xQueue )
2265 {
2266     Queue_t * const pxQueue = xQueue;
2267
2268     traceENTER_vQueueDelete( xQueue );
2269
2270     configASSERT( pxQueue );
2271     traceQUEUE_DELETE( pxQueue );
2272
2273     #if ( configQUEUE_REGISTRY_SIZE > 0 )
2274     {
2275         vQueueUnregisterQueue( pxQueue );
2276     }
2277     #endif
2278
2279     #if ( ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 0 ) )
2280     {
2281         /* The queue can only have been allocated dynamically - free it
2282          * again. */
2283         vPortFree( pxQueue );
2284     }
2285     #elif ( ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 1 ) )
2286     {
2287         /* The queue could have been allocated statically or dynamically, so
2288          * check before attempting to free the memory. */
2289         if( pxQueue->ucStaticallyAllocated == ( uint8_t ) pdFALSE )
2290         {
2291             vPortFree( pxQueue );
2292         }
2293         else
2294         {
2295             mtCOVERAGE_TEST_MARKER();
2296         }
2297     }
2298     #else /* if ( ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 0 ) ) */
2299     {
2300         /* The queue must have been statically allocated, so is not going to be
2301          * deleted.  Avoid compiler warnings about the unused parameter. */
2302         ( void ) pxQueue;
2303     }
2304     #endif /* configSUPPORT_DYNAMIC_ALLOCATION */
2305
2306     traceRETURN_vQueueDelete();
2307 }
2308 /*-----------------------------------------------------------*/
2309
2310 #if ( configUSE_TRACE_FACILITY == 1 )
2311
2312     UBaseType_t uxQueueGetQueueNumber( QueueHandle_t xQueue )
2313     {
2314         traceENTER_uxQueueGetQueueNumber( xQueue );
2315
2316         traceRETURN_uxQueueGetQueueNumber( ( ( Queue_t * ) xQueue )->uxQueueNumber );
2317
2318         return ( ( Queue_t * ) xQueue )->uxQueueNumber;
2319     }
2320
2321 #endif /* configUSE_TRACE_FACILITY */
2322 /*-----------------------------------------------------------*/
2323
2324 #if ( configUSE_TRACE_FACILITY == 1 )
2325
2326     void vQueueSetQueueNumber( QueueHandle_t xQueue,
2327                                UBaseType_t uxQueueNumber )
2328     {
2329         traceENTER_vQueueSetQueueNumber( xQueue, uxQueueNumber );
2330
2331         ( ( Queue_t * ) xQueue )->uxQueueNumber = uxQueueNumber;
2332
2333         traceRETURN_vQueueSetQueueNumber();
2334     }
2335
2336 #endif /* configUSE_TRACE_FACILITY */
2337 /*-----------------------------------------------------------*/
2338
2339 #if ( configUSE_TRACE_FACILITY == 1 )
2340
2341     uint8_t ucQueueGetQueueType( QueueHandle_t xQueue )
2342     {
2343         traceENTER_ucQueueGetQueueType( xQueue );
2344
2345         traceRETURN_ucQueueGetQueueType( ( ( Queue_t * ) xQueue )->ucQueueType );
2346
2347         return ( ( Queue_t * ) xQueue )->ucQueueType;
2348     }
2349
2350 #endif /* configUSE_TRACE_FACILITY */
2351 /*-----------------------------------------------------------*/
2352
2353 UBaseType_t uxQueueGetQueueItemSize( QueueHandle_t xQueue ) /* PRIVILEGED_FUNCTION */
2354 {
2355     traceENTER_uxQueueGetQueueItemSize( xQueue );
2356
2357     traceRETURN_uxQueueGetQueueItemSize( ( ( Queue_t * ) xQueue )->uxItemSize );
2358
2359     return ( ( Queue_t * ) xQueue )->uxItemSize;
2360 }
2361 /*-----------------------------------------------------------*/
2362
2363 UBaseType_t uxQueueGetQueueLength( QueueHandle_t xQueue ) /* PRIVILEGED_FUNCTION */
2364 {
2365     traceENTER_uxQueueGetQueueLength( xQueue );
2366
2367     traceRETURN_uxQueueGetQueueLength( ( ( Queue_t * ) xQueue )->uxLength );
2368
2369     return ( ( Queue_t * ) xQueue )->uxLength;
2370 }
2371 /*-----------------------------------------------------------*/
2372
2373 #if ( configUSE_MUTEXES == 1 )
2374
2375     static UBaseType_t prvGetHighestPriorityOfWaitToReceiveList( const Queue_t * const pxQueue )
2376     {
2377         UBaseType_t uxHighestPriorityOfWaitingTasks;
2378
2379         /* If a task waiting for a mutex causes the mutex holder to inherit a
2380          * priority, but the waiting task times out, then the holder should
2381          * disinherit the priority - but only down to the highest priority of any
2382          * other tasks that are waiting for the same mutex.  For this purpose,
2383          * return the priority of the highest priority task that is waiting for the
2384          * mutex. */
2385         if( listCURRENT_LIST_LENGTH( &( pxQueue->xTasksWaitingToReceive ) ) > 0U )
2386         {
2387             uxHighestPriorityOfWaitingTasks = ( UBaseType_t ) ( ( UBaseType_t ) configMAX_PRIORITIES - ( UBaseType_t ) listGET_ITEM_VALUE_OF_HEAD_ENTRY( &( pxQueue->xTasksWaitingToReceive ) ) );
2388         }
2389         else
2390         {
2391             uxHighestPriorityOfWaitingTasks = tskIDLE_PRIORITY;
2392         }
2393
2394         return uxHighestPriorityOfWaitingTasks;
2395     }
2396
2397 #endif /* configUSE_MUTEXES */
2398 /*-----------------------------------------------------------*/
2399
2400 static BaseType_t prvCopyDataToQueue( Queue_t * const pxQueue,
2401                                       const void * pvItemToQueue,
2402                                       const BaseType_t xPosition )
2403 {
2404     BaseType_t xReturn = pdFALSE;
2405     UBaseType_t uxMessagesWaiting;
2406
2407     /* This function is called from a critical section. */
2408
2409     uxMessagesWaiting = pxQueue->uxMessagesWaiting;
2410
2411     if( pxQueue->uxItemSize == ( UBaseType_t ) 0 )
2412     {
2413         #if ( configUSE_MUTEXES == 1 )
2414         {
2415             if( pxQueue->uxQueueType == queueQUEUE_IS_MUTEX )
2416             {
2417                 /* The mutex is no longer being held. */
2418                 xReturn = xTaskPriorityDisinherit( pxQueue->u.xSemaphore.xMutexHolder );
2419                 pxQueue->u.xSemaphore.xMutexHolder = NULL;
2420             }
2421             else
2422             {
2423                 mtCOVERAGE_TEST_MARKER();
2424             }
2425         }
2426         #endif /* configUSE_MUTEXES */
2427     }
2428     else if( xPosition == queueSEND_TO_BACK )
2429     {
2430         ( void ) memcpy( ( void * ) pxQueue->pcWriteTo, pvItemToQueue, ( size_t ) pxQueue->uxItemSize );
2431         pxQueue->pcWriteTo += pxQueue->uxItemSize;
2432
2433         if( pxQueue->pcWriteTo >= pxQueue->u.xQueue.pcTail )
2434         {
2435             pxQueue->pcWriteTo = pxQueue->pcHead;
2436         }
2437         else
2438         {
2439             mtCOVERAGE_TEST_MARKER();
2440         }
2441     }
2442     else
2443     {
2444         ( void ) memcpy( ( void * ) pxQueue->u.xQueue.pcReadFrom, pvItemToQueue, ( size_t ) pxQueue->uxItemSize );
2445         pxQueue->u.xQueue.pcReadFrom -= pxQueue->uxItemSize;
2446
2447         if( pxQueue->u.xQueue.pcReadFrom < pxQueue->pcHead )
2448         {
2449             pxQueue->u.xQueue.pcReadFrom = ( pxQueue->u.xQueue.pcTail - pxQueue->uxItemSize );
2450         }
2451         else
2452         {
2453             mtCOVERAGE_TEST_MARKER();
2454         }
2455
2456         if( xPosition == queueOVERWRITE )
2457         {
2458             if( uxMessagesWaiting > ( UBaseType_t ) 0 )
2459             {
2460                 /* An item is not being added but overwritten, so subtract
2461                  * one from the recorded number of items in the queue so when
2462                  * one is added again below the number of recorded items remains
2463                  * correct. */
2464                 --uxMessagesWaiting;
2465             }
2466             else
2467             {
2468                 mtCOVERAGE_TEST_MARKER();
2469             }
2470         }
2471         else
2472         {
2473             mtCOVERAGE_TEST_MARKER();
2474         }
2475     }
2476
2477     pxQueue->uxMessagesWaiting = ( UBaseType_t ) ( uxMessagesWaiting + ( UBaseType_t ) 1 );
2478
2479     return xReturn;
2480 }
2481 /*-----------------------------------------------------------*/
2482
2483 static void prvCopyDataFromQueue( Queue_t * const pxQueue,
2484                                   void * const pvBuffer )
2485 {
2486     if( pxQueue->uxItemSize != ( UBaseType_t ) 0 )
2487     {
2488         pxQueue->u.xQueue.pcReadFrom += pxQueue->uxItemSize;
2489
2490         if( pxQueue->u.xQueue.pcReadFrom >= pxQueue->u.xQueue.pcTail )
2491         {
2492             pxQueue->u.xQueue.pcReadFrom = pxQueue->pcHead;
2493         }
2494         else
2495         {
2496             mtCOVERAGE_TEST_MARKER();
2497         }
2498
2499         ( void ) memcpy( ( void * ) pvBuffer, ( void * ) pxQueue->u.xQueue.pcReadFrom, ( size_t ) pxQueue->uxItemSize );
2500     }
2501 }
2502 /*-----------------------------------------------------------*/
2503
2504 static void prvUnlockQueue( Queue_t * const pxQueue )
2505 {
2506     /* THIS FUNCTION MUST BE CALLED WITH THE SCHEDULER SUSPENDED. */
2507
2508     /* The lock counts contains the number of extra data items placed or
2509      * removed from the queue while the queue was locked.  When a queue is
2510      * locked items can be added or removed, but the event lists cannot be
2511      * updated. */
2512     taskENTER_CRITICAL();
2513     {
2514         int8_t cTxLock = pxQueue->cTxLock;
2515
2516         /* See if data was added to the queue while it was locked. */
2517         while( cTxLock > queueLOCKED_UNMODIFIED )
2518         {
2519             /* Data was posted while the queue was locked.  Are any tasks
2520              * blocked waiting for data to become available? */
2521             #if ( configUSE_QUEUE_SETS == 1 )
2522             {
2523                 if( pxQueue->pxQueueSetContainer != NULL )
2524                 {
2525                     if( prvNotifyQueueSetContainer( pxQueue ) != pdFALSE )
2526                     {
2527                         /* The queue is a member of a queue set, and posting to
2528                          * the queue set caused a higher priority task to unblock.
2529                          * A context switch is required. */
2530                         vTaskMissedYield();
2531                     }
2532                     else
2533                     {
2534                         mtCOVERAGE_TEST_MARKER();
2535                     }
2536                 }
2537                 else
2538                 {
2539                     /* Tasks that are removed from the event list will get
2540                      * added to the pending ready list as the scheduler is still
2541                      * suspended. */
2542                     if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE )
2543                     {
2544                         if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE )
2545                         {
2546                             /* The task waiting has a higher priority so record that a
2547                              * context switch is required. */
2548                             vTaskMissedYield();
2549                         }
2550                         else
2551                         {
2552                             mtCOVERAGE_TEST_MARKER();
2553                         }
2554                     }
2555                     else
2556                     {
2557                         break;
2558                     }
2559                 }
2560             }
2561             #else /* configUSE_QUEUE_SETS */
2562             {
2563                 /* Tasks that are removed from the event list will get added to
2564                  * the pending ready list as the scheduler is still suspended. */
2565                 if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE )
2566                 {
2567                     if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE )
2568                     {
2569                         /* The task waiting has a higher priority so record that
2570                          * a context switch is required. */
2571                         vTaskMissedYield();
2572                     }
2573                     else
2574                     {
2575                         mtCOVERAGE_TEST_MARKER();
2576                     }
2577                 }
2578                 else
2579                 {
2580                     break;
2581                 }
2582             }
2583             #endif /* configUSE_QUEUE_SETS */
2584
2585             --cTxLock;
2586         }
2587
2588         pxQueue->cTxLock = queueUNLOCKED;
2589     }
2590     taskEXIT_CRITICAL();
2591
2592     /* Do the same for the Rx lock. */
2593     taskENTER_CRITICAL();
2594     {
2595         int8_t cRxLock = pxQueue->cRxLock;
2596
2597         while( cRxLock > queueLOCKED_UNMODIFIED )
2598         {
2599             if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) == pdFALSE )
2600             {
2601                 if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) != pdFALSE )
2602                 {
2603                     vTaskMissedYield();
2604                 }
2605                 else
2606                 {
2607                     mtCOVERAGE_TEST_MARKER();
2608                 }
2609
2610                 --cRxLock;
2611             }
2612             else
2613             {
2614                 break;
2615             }
2616         }
2617
2618         pxQueue->cRxLock = queueUNLOCKED;
2619     }
2620     taskEXIT_CRITICAL();
2621 }
2622 /*-----------------------------------------------------------*/
2623
2624 static BaseType_t prvIsQueueEmpty( const Queue_t * pxQueue )
2625 {
2626     BaseType_t xReturn;
2627
2628     taskENTER_CRITICAL();
2629     {
2630         if( pxQueue->uxMessagesWaiting == ( UBaseType_t ) 0 )
2631         {
2632             xReturn = pdTRUE;
2633         }
2634         else
2635         {
2636             xReturn = pdFALSE;
2637         }
2638     }
2639     taskEXIT_CRITICAL();
2640
2641     return xReturn;
2642 }
2643 /*-----------------------------------------------------------*/
2644
2645 BaseType_t xQueueIsQueueEmptyFromISR( const QueueHandle_t xQueue )
2646 {
2647     BaseType_t xReturn;
2648     Queue_t * const pxQueue = xQueue;
2649
2650     traceENTER_xQueueIsQueueEmptyFromISR( xQueue );
2651
2652     configASSERT( pxQueue );
2653
2654     if( pxQueue->uxMessagesWaiting == ( UBaseType_t ) 0 )
2655     {
2656         xReturn = pdTRUE;
2657     }
2658     else
2659     {
2660         xReturn = pdFALSE;
2661     }
2662
2663     traceRETURN_xQueueIsQueueEmptyFromISR( xReturn );
2664
2665     return xReturn;
2666 }
2667 /*-----------------------------------------------------------*/
2668
2669 static BaseType_t prvIsQueueFull( const Queue_t * pxQueue )
2670 {
2671     BaseType_t xReturn;
2672
2673     taskENTER_CRITICAL();
2674     {
2675         if( pxQueue->uxMessagesWaiting == pxQueue->uxLength )
2676         {
2677             xReturn = pdTRUE;
2678         }
2679         else
2680         {
2681             xReturn = pdFALSE;
2682         }
2683     }
2684     taskEXIT_CRITICAL();
2685
2686     return xReturn;
2687 }
2688 /*-----------------------------------------------------------*/
2689
2690 BaseType_t xQueueIsQueueFullFromISR( const QueueHandle_t xQueue )
2691 {
2692     BaseType_t xReturn;
2693     Queue_t * const pxQueue = xQueue;
2694
2695     traceENTER_xQueueIsQueueFullFromISR( xQueue );
2696
2697     configASSERT( pxQueue );
2698
2699     if( pxQueue->uxMessagesWaiting == pxQueue->uxLength )
2700     {
2701         xReturn = pdTRUE;
2702     }
2703     else
2704     {
2705         xReturn = pdFALSE;
2706     }
2707
2708     traceRETURN_xQueueIsQueueFullFromISR( xReturn );
2709
2710     return xReturn;
2711 }
2712 /*-----------------------------------------------------------*/
2713
2714 #if ( configUSE_CO_ROUTINES == 1 )
2715
2716     BaseType_t xQueueCRSend( QueueHandle_t xQueue,
2717                              const void * pvItemToQueue,
2718                              TickType_t xTicksToWait )
2719     {
2720         BaseType_t xReturn;
2721         Queue_t * const pxQueue = xQueue;
2722
2723         traceENTER_xQueueCRSend( xQueue, pvItemToQueue, xTicksToWait );
2724
2725         /* If the queue is already full we may have to block.  A critical section
2726          * is required to prevent an interrupt removing something from the queue
2727          * between the check to see if the queue is full and blocking on the queue. */
2728         portDISABLE_INTERRUPTS();
2729         {
2730             if( prvIsQueueFull( pxQueue ) != pdFALSE )
2731             {
2732                 /* The queue is full - do we want to block or just leave without
2733                  * posting? */
2734                 if( xTicksToWait > ( TickType_t ) 0 )
2735                 {
2736                     /* As this is called from a coroutine we cannot block directly, but
2737                      * return indicating that we need to block. */
2738                     vCoRoutineAddToDelayedList( xTicksToWait, &( pxQueue->xTasksWaitingToSend ) );
2739                     portENABLE_INTERRUPTS();
2740                     return errQUEUE_BLOCKED;
2741                 }
2742                 else
2743                 {
2744                     portENABLE_INTERRUPTS();
2745                     return errQUEUE_FULL;
2746                 }
2747             }
2748         }
2749         portENABLE_INTERRUPTS();
2750
2751         portDISABLE_INTERRUPTS();
2752         {
2753             if( pxQueue->uxMessagesWaiting < pxQueue->uxLength )
2754             {
2755                 /* There is room in the queue, copy the data into the queue. */
2756                 prvCopyDataToQueue( pxQueue, pvItemToQueue, queueSEND_TO_BACK );
2757                 xReturn = pdPASS;
2758
2759                 /* Were any co-routines waiting for data to become available? */
2760                 if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE )
2761                 {
2762                     /* In this instance the co-routine could be placed directly
2763                      * into the ready list as we are within a critical section.
2764                      * Instead the same pending ready list mechanism is used as if
2765                      * the event were caused from within an interrupt. */
2766                     if( xCoRoutineRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE )
2767                     {
2768                         /* The co-routine waiting has a higher priority so record
2769                          * that a yield might be appropriate. */
2770                         xReturn = errQUEUE_YIELD;
2771                     }
2772                     else
2773                     {
2774                         mtCOVERAGE_TEST_MARKER();
2775                     }
2776                 }
2777                 else
2778                 {
2779                     mtCOVERAGE_TEST_MARKER();
2780                 }
2781             }
2782             else
2783             {
2784                 xReturn = errQUEUE_FULL;
2785             }
2786         }
2787         portENABLE_INTERRUPTS();
2788
2789         traceRETURN_xQueueCRSend( xReturn );
2790
2791         return xReturn;
2792     }
2793
2794 #endif /* configUSE_CO_ROUTINES */
2795 /*-----------------------------------------------------------*/
2796
2797 #if ( configUSE_CO_ROUTINES == 1 )
2798
2799     BaseType_t xQueueCRReceive( QueueHandle_t xQueue,
2800                                 void * pvBuffer,
2801                                 TickType_t xTicksToWait )
2802     {
2803         BaseType_t xReturn;
2804         Queue_t * const pxQueue = xQueue;
2805
2806         traceENTER_xQueueCRReceive( xQueue, pvBuffer, xTicksToWait );
2807
2808         /* If the queue is already empty we may have to block.  A critical section
2809          * is required to prevent an interrupt adding something to the queue
2810          * between the check to see if the queue is empty and blocking on the queue. */
2811         portDISABLE_INTERRUPTS();
2812         {
2813             if( pxQueue->uxMessagesWaiting == ( UBaseType_t ) 0 )
2814             {
2815                 /* There are no messages in the queue, do we want to block or just
2816                  * leave with nothing? */
2817                 if( xTicksToWait > ( TickType_t ) 0 )
2818                 {
2819                     /* As this is a co-routine we cannot block directly, but return
2820                      * indicating that we need to block. */
2821                     vCoRoutineAddToDelayedList( xTicksToWait, &( pxQueue->xTasksWaitingToReceive ) );
2822                     portENABLE_INTERRUPTS();
2823                     return errQUEUE_BLOCKED;
2824                 }
2825                 else
2826                 {
2827                     portENABLE_INTERRUPTS();
2828                     return errQUEUE_FULL;
2829                 }
2830             }
2831             else
2832             {
2833                 mtCOVERAGE_TEST_MARKER();
2834             }
2835         }
2836         portENABLE_INTERRUPTS();
2837
2838         portDISABLE_INTERRUPTS();
2839         {
2840             if( pxQueue->uxMessagesWaiting > ( UBaseType_t ) 0 )
2841             {
2842                 /* Data is available from the queue. */
2843                 pxQueue->u.xQueue.pcReadFrom += pxQueue->uxItemSize;
2844
2845                 if( pxQueue->u.xQueue.pcReadFrom >= pxQueue->u.xQueue.pcTail )
2846                 {
2847                     pxQueue->u.xQueue.pcReadFrom = pxQueue->pcHead;
2848                 }
2849                 else
2850                 {
2851                     mtCOVERAGE_TEST_MARKER();
2852                 }
2853
2854                 --( pxQueue->uxMessagesWaiting );
2855                 ( void ) memcpy( ( void * ) pvBuffer, ( void * ) pxQueue->u.xQueue.pcReadFrom, ( unsigned ) pxQueue->uxItemSize );
2856
2857                 xReturn = pdPASS;
2858
2859                 /* Were any co-routines waiting for space to become available? */
2860                 if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) == pdFALSE )
2861                 {
2862                     /* In this instance the co-routine could be placed directly
2863                      * into the ready list as we are within a critical section.
2864                      * Instead the same pending ready list mechanism is used as if
2865                      * the event were caused from within an interrupt. */
2866                     if( xCoRoutineRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) != pdFALSE )
2867                     {
2868                         xReturn = errQUEUE_YIELD;
2869                     }
2870                     else
2871                     {
2872                         mtCOVERAGE_TEST_MARKER();
2873                     }
2874                 }
2875                 else
2876                 {
2877                     mtCOVERAGE_TEST_MARKER();
2878                 }
2879             }
2880             else
2881             {
2882                 xReturn = pdFAIL;
2883             }
2884         }
2885         portENABLE_INTERRUPTS();
2886
2887         traceRETURN_xQueueCRReceive( xReturn );
2888
2889         return xReturn;
2890     }
2891
2892 #endif /* configUSE_CO_ROUTINES */
2893 /*-----------------------------------------------------------*/
2894
2895 #if ( configUSE_CO_ROUTINES == 1 )
2896
2897     BaseType_t xQueueCRSendFromISR( QueueHandle_t xQueue,
2898                                     const void * pvItemToQueue,
2899                                     BaseType_t xCoRoutinePreviouslyWoken )
2900     {
2901         Queue_t * const pxQueue = xQueue;
2902
2903         traceENTER_xQueueCRSendFromISR( xQueue, pvItemToQueue, xCoRoutinePreviouslyWoken );
2904
2905         /* Cannot block within an ISR so if there is no space on the queue then
2906          * exit without doing anything. */
2907         if( pxQueue->uxMessagesWaiting < pxQueue->uxLength )
2908         {
2909             prvCopyDataToQueue( pxQueue, pvItemToQueue, queueSEND_TO_BACK );
2910
2911             /* We only want to wake one co-routine per ISR, so check that a
2912              * co-routine has not already been woken. */
2913             if( xCoRoutinePreviouslyWoken == pdFALSE )
2914             {
2915                 if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE )
2916                 {
2917                     if( xCoRoutineRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE )
2918                     {
2919                         return pdTRUE;
2920                     }
2921                     else
2922                     {
2923                         mtCOVERAGE_TEST_MARKER();
2924                     }
2925                 }
2926                 else
2927                 {
2928                     mtCOVERAGE_TEST_MARKER();
2929                 }
2930             }
2931             else
2932             {
2933                 mtCOVERAGE_TEST_MARKER();
2934             }
2935         }
2936         else
2937         {
2938             mtCOVERAGE_TEST_MARKER();
2939         }
2940
2941         traceRETURN_xQueueCRSendFromISR( xCoRoutinePreviouslyWoken );
2942
2943         return xCoRoutinePreviouslyWoken;
2944     }
2945
2946 #endif /* configUSE_CO_ROUTINES */
2947 /*-----------------------------------------------------------*/
2948
2949 #if ( configUSE_CO_ROUTINES == 1 )
2950
2951     BaseType_t xQueueCRReceiveFromISR( QueueHandle_t xQueue,
2952                                        void * pvBuffer,
2953                                        BaseType_t * pxCoRoutineWoken )
2954     {
2955         BaseType_t xReturn;
2956         Queue_t * const pxQueue = xQueue;
2957
2958         traceENTER_xQueueCRReceiveFromISR( xQueue, pvBuffer, pxCoRoutineWoken );
2959
2960         /* We cannot block from an ISR, so check there is data available. If
2961          * not then just leave without doing anything. */
2962         if( pxQueue->uxMessagesWaiting > ( UBaseType_t ) 0 )
2963         {
2964             /* Copy the data from the queue. */
2965             pxQueue->u.xQueue.pcReadFrom += pxQueue->uxItemSize;
2966
2967             if( pxQueue->u.xQueue.pcReadFrom >= pxQueue->u.xQueue.pcTail )
2968             {
2969                 pxQueue->u.xQueue.pcReadFrom = pxQueue->pcHead;
2970             }
2971             else
2972             {
2973                 mtCOVERAGE_TEST_MARKER();
2974             }
2975
2976             --( pxQueue->uxMessagesWaiting );
2977             ( void ) memcpy( ( void * ) pvBuffer, ( void * ) pxQueue->u.xQueue.pcReadFrom, ( unsigned ) pxQueue->uxItemSize );
2978
2979             if( ( *pxCoRoutineWoken ) == pdFALSE )
2980             {
2981                 if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) == pdFALSE )
2982                 {
2983                     if( xCoRoutineRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) != pdFALSE )
2984                     {
2985                         *pxCoRoutineWoken = pdTRUE;
2986                     }
2987                     else
2988                     {
2989                         mtCOVERAGE_TEST_MARKER();
2990                     }
2991                 }
2992                 else
2993                 {
2994                     mtCOVERAGE_TEST_MARKER();
2995                 }
2996             }
2997             else
2998             {
2999                 mtCOVERAGE_TEST_MARKER();
3000             }
3001
3002             xReturn = pdPASS;
3003         }
3004         else
3005         {
3006             xReturn = pdFAIL;
3007         }
3008
3009         traceRETURN_xQueueCRReceiveFromISR( xReturn );
3010
3011         return xReturn;
3012     }
3013
3014 #endif /* configUSE_CO_ROUTINES */
3015 /*-----------------------------------------------------------*/
3016
3017 #if ( configQUEUE_REGISTRY_SIZE > 0 )
3018
3019     void vQueueAddToRegistry( QueueHandle_t xQueue,
3020                               const char * pcQueueName )
3021     {
3022         UBaseType_t ux;
3023         QueueRegistryItem_t * pxEntryToWrite = NULL;
3024
3025         traceENTER_vQueueAddToRegistry( xQueue, pcQueueName );
3026
3027         configASSERT( xQueue );
3028
3029         if( pcQueueName != NULL )
3030         {
3031             /* See if there is an empty space in the registry.  A NULL name denotes
3032              * a free slot. */
3033             for( ux = ( UBaseType_t ) 0U; ux < ( UBaseType_t ) configQUEUE_REGISTRY_SIZE; ux++ )
3034             {
3035                 /* Replace an existing entry if the queue is already in the registry. */
3036                 if( xQueue == xQueueRegistry[ ux ].xHandle )
3037                 {
3038                     pxEntryToWrite = &( xQueueRegistry[ ux ] );
3039                     break;
3040                 }
3041                 /* Otherwise, store in the next empty location */
3042                 else if( ( pxEntryToWrite == NULL ) && ( xQueueRegistry[ ux ].pcQueueName == NULL ) )
3043                 {
3044                     pxEntryToWrite = &( xQueueRegistry[ ux ] );
3045                 }
3046                 else
3047                 {
3048                     mtCOVERAGE_TEST_MARKER();
3049                 }
3050             }
3051         }
3052
3053         if( pxEntryToWrite != NULL )
3054         {
3055             /* Store the information on this queue. */
3056             pxEntryToWrite->pcQueueName = pcQueueName;
3057             pxEntryToWrite->xHandle = xQueue;
3058
3059             traceQUEUE_REGISTRY_ADD( xQueue, pcQueueName );
3060         }
3061
3062         traceRETURN_vQueueAddToRegistry();
3063     }
3064
3065 #endif /* configQUEUE_REGISTRY_SIZE */
3066 /*-----------------------------------------------------------*/
3067
3068 #if ( configQUEUE_REGISTRY_SIZE > 0 )
3069
3070     const char * pcQueueGetName( QueueHandle_t xQueue )
3071     {
3072         UBaseType_t ux;
3073         const char * pcReturn = NULL;
3074
3075         traceENTER_pcQueueGetName( xQueue );
3076
3077         configASSERT( xQueue );
3078
3079         /* Note there is nothing here to protect against another task adding or
3080          * removing entries from the registry while it is being searched. */
3081
3082         for( ux = ( UBaseType_t ) 0U; ux < ( UBaseType_t ) configQUEUE_REGISTRY_SIZE; ux++ )
3083         {
3084             if( xQueueRegistry[ ux ].xHandle == xQueue )
3085             {
3086                 pcReturn = xQueueRegistry[ ux ].pcQueueName;
3087                 break;
3088             }
3089             else
3090             {
3091                 mtCOVERAGE_TEST_MARKER();
3092             }
3093         }
3094
3095         traceRETURN_pcQueueGetName( pcReturn );
3096
3097         return pcReturn;
3098     }
3099
3100 #endif /* configQUEUE_REGISTRY_SIZE */
3101 /*-----------------------------------------------------------*/
3102
3103 #if ( configQUEUE_REGISTRY_SIZE > 0 )
3104
3105     void vQueueUnregisterQueue( QueueHandle_t xQueue )
3106     {
3107         UBaseType_t ux;
3108
3109         traceENTER_vQueueUnregisterQueue( xQueue );
3110
3111         configASSERT( xQueue );
3112
3113         /* See if the handle of the queue being unregistered in actually in the
3114          * registry. */
3115         for( ux = ( UBaseType_t ) 0U; ux < ( UBaseType_t ) configQUEUE_REGISTRY_SIZE; ux++ )
3116         {
3117             if( xQueueRegistry[ ux ].xHandle == xQueue )
3118             {
3119                 /* Set the name to NULL to show that this slot if free again. */
3120                 xQueueRegistry[ ux ].pcQueueName = NULL;
3121
3122                 /* Set the handle to NULL to ensure the same queue handle cannot
3123                  * appear in the registry twice if it is added, removed, then
3124                  * added again. */
3125                 xQueueRegistry[ ux ].xHandle = ( QueueHandle_t ) 0;
3126                 break;
3127             }
3128             else
3129             {
3130                 mtCOVERAGE_TEST_MARKER();
3131             }
3132         }
3133
3134         traceRETURN_vQueueUnregisterQueue();
3135     }
3136
3137 #endif /* configQUEUE_REGISTRY_SIZE */
3138 /*-----------------------------------------------------------*/
3139
3140 #if ( configUSE_TIMERS == 1 )
3141
3142     void vQueueWaitForMessageRestricted( QueueHandle_t xQueue,
3143                                          TickType_t xTicksToWait,
3144                                          const BaseType_t xWaitIndefinitely )
3145     {
3146         Queue_t * const pxQueue = xQueue;
3147
3148         traceENTER_vQueueWaitForMessageRestricted( xQueue, xTicksToWait, xWaitIndefinitely );
3149
3150         /* This function should not be called by application code hence the
3151          * 'Restricted' in its name.  It is not part of the public API.  It is
3152          * designed for use by kernel code, and has special calling requirements.
3153          * It can result in vListInsert() being called on a list that can only
3154          * possibly ever have one item in it, so the list will be fast, but even
3155          * so it should be called with the scheduler locked and not from a critical
3156          * section. */
3157
3158         /* Only do anything if there are no messages in the queue.  This function
3159          *  will not actually cause the task to block, just place it on a blocked
3160          *  list.  It will not block until the scheduler is unlocked - at which
3161          *  time a yield will be performed.  If an item is added to the queue while
3162          *  the queue is locked, and the calling task blocks on the queue, then the
3163          *  calling task will be immediately unblocked when the queue is unlocked. */
3164         prvLockQueue( pxQueue );
3165
3166         if( pxQueue->uxMessagesWaiting == ( UBaseType_t ) 0U )
3167         {
3168             /* There is nothing in the queue, block for the specified period. */
3169             vTaskPlaceOnEventListRestricted( &( pxQueue->xTasksWaitingToReceive ), xTicksToWait, xWaitIndefinitely );
3170         }
3171         else
3172         {
3173             mtCOVERAGE_TEST_MARKER();
3174         }
3175
3176         prvUnlockQueue( pxQueue );
3177
3178         traceRETURN_vQueueWaitForMessageRestricted();
3179     }
3180
3181 #endif /* configUSE_TIMERS */
3182 /*-----------------------------------------------------------*/
3183
3184 #if ( ( configUSE_QUEUE_SETS == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) )
3185
3186     QueueSetHandle_t xQueueCreateSet( const UBaseType_t uxEventQueueLength )
3187     {
3188         QueueSetHandle_t pxQueue;
3189
3190         traceENTER_xQueueCreateSet( uxEventQueueLength );
3191
3192         pxQueue = xQueueGenericCreate( uxEventQueueLength, ( UBaseType_t ) sizeof( Queue_t * ), queueQUEUE_TYPE_SET );
3193
3194         traceRETURN_xQueueCreateSet( pxQueue );
3195
3196         return pxQueue;
3197     }
3198
3199 #endif /* #if ( ( configUSE_QUEUE_SETS == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) ) */
3200 /*-----------------------------------------------------------*/
3201
3202 #if ( ( configUSE_QUEUE_SETS == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 1 ) )
3203
3204     QueueSetHandle_t xQueueCreateSetStatic( const UBaseType_t uxEventQueueLength,
3205                                             uint8_t * pucQueueStorage,
3206                                             StaticQueue_t * pxStaticQueue )
3207     {
3208         QueueSetHandle_t pxQueue;
3209
3210         traceENTER_xQueueCreateSetStatic( uxEventQueueLength );
3211
3212         pxQueue = xQueueGenericCreateStatic( uxEventQueueLength, ( UBaseType_t ) sizeof( Queue_t * ), pucQueueStorage, pxStaticQueue, queueQUEUE_TYPE_SET );
3213
3214         traceRETURN_xQueueCreateSetStatic( pxQueue );
3215
3216         return pxQueue;
3217     }
3218
3219 #endif /* #if ( ( configUSE_QUEUE_SETS == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 1 ) ) */
3220 /*-----------------------------------------------------------*/
3221
3222 #if ( configUSE_QUEUE_SETS == 1 )
3223
3224     BaseType_t xQueueAddToSet( QueueSetMemberHandle_t xQueueOrSemaphore,
3225                                QueueSetHandle_t xQueueSet )
3226     {
3227         BaseType_t xReturn;
3228
3229         traceENTER_xQueueAddToSet( xQueueOrSemaphore, xQueueSet );
3230
3231         taskENTER_CRITICAL();
3232         {
3233             if( ( ( Queue_t * ) xQueueOrSemaphore )->pxQueueSetContainer != NULL )
3234             {
3235                 /* Cannot add a queue/semaphore to more than one queue set. */
3236                 xReturn = pdFAIL;
3237             }
3238             else if( ( ( Queue_t * ) xQueueOrSemaphore )->uxMessagesWaiting != ( UBaseType_t ) 0 )
3239             {
3240                 /* Cannot add a queue/semaphore to a queue set if there are already
3241                  * items in the queue/semaphore. */
3242                 xReturn = pdFAIL;
3243             }
3244             else
3245             {
3246                 ( ( Queue_t * ) xQueueOrSemaphore )->pxQueueSetContainer = xQueueSet;
3247                 xReturn = pdPASS;
3248             }
3249         }
3250         taskEXIT_CRITICAL();
3251
3252         traceRETURN_xQueueAddToSet( xReturn );
3253
3254         return xReturn;
3255     }
3256
3257 #endif /* configUSE_QUEUE_SETS */
3258 /*-----------------------------------------------------------*/
3259
3260 #if ( configUSE_QUEUE_SETS == 1 )
3261
3262     BaseType_t xQueueRemoveFromSet( QueueSetMemberHandle_t xQueueOrSemaphore,
3263                                     QueueSetHandle_t xQueueSet )
3264     {
3265         BaseType_t xReturn;
3266         Queue_t * const pxQueueOrSemaphore = ( Queue_t * ) xQueueOrSemaphore;
3267
3268         traceENTER_xQueueRemoveFromSet( xQueueOrSemaphore, xQueueSet );
3269
3270         if( pxQueueOrSemaphore->pxQueueSetContainer != xQueueSet )
3271         {
3272             /* The queue was not a member of the set. */
3273             xReturn = pdFAIL;
3274         }
3275         else if( pxQueueOrSemaphore->uxMessagesWaiting != ( UBaseType_t ) 0 )
3276         {
3277             /* It is dangerous to remove a queue from a set when the queue is
3278              * not empty because the queue set will still hold pending events for
3279              * the queue. */
3280             xReturn = pdFAIL;
3281         }
3282         else
3283         {
3284             taskENTER_CRITICAL();
3285             {
3286                 /* The queue is no longer contained in the set. */
3287                 pxQueueOrSemaphore->pxQueueSetContainer = NULL;
3288             }
3289             taskEXIT_CRITICAL();
3290             xReturn = pdPASS;
3291         }
3292
3293         traceRETURN_xQueueRemoveFromSet( xReturn );
3294
3295         return xReturn;
3296     }
3297
3298 #endif /* configUSE_QUEUE_SETS */
3299 /*-----------------------------------------------------------*/
3300
3301 #if ( configUSE_QUEUE_SETS == 1 )
3302
3303     QueueSetMemberHandle_t xQueueSelectFromSet( QueueSetHandle_t xQueueSet,
3304                                                 TickType_t const xTicksToWait )
3305     {
3306         QueueSetMemberHandle_t xReturn = NULL;
3307
3308         traceENTER_xQueueSelectFromSet( xQueueSet, xTicksToWait );
3309
3310         ( void ) xQueueReceive( ( QueueHandle_t ) xQueueSet, &xReturn, xTicksToWait );
3311
3312         traceRETURN_xQueueSelectFromSet( xReturn );
3313
3314         return xReturn;
3315     }
3316
3317 #endif /* configUSE_QUEUE_SETS */
3318 /*-----------------------------------------------------------*/
3319
3320 #if ( configUSE_QUEUE_SETS == 1 )
3321
3322     QueueSetMemberHandle_t xQueueSelectFromSetFromISR( QueueSetHandle_t xQueueSet )
3323     {
3324         QueueSetMemberHandle_t xReturn = NULL;
3325
3326         traceENTER_xQueueSelectFromSetFromISR( xQueueSet );
3327
3328         ( void ) xQueueReceiveFromISR( ( QueueHandle_t ) xQueueSet, &xReturn, NULL );
3329
3330         traceRETURN_xQueueSelectFromSetFromISR( xReturn );
3331
3332         return xReturn;
3333     }
3334
3335 #endif /* configUSE_QUEUE_SETS */
3336 /*-----------------------------------------------------------*/
3337
3338 #if ( configUSE_QUEUE_SETS == 1 )
3339
3340     static BaseType_t prvNotifyQueueSetContainer( const Queue_t * const pxQueue )
3341     {
3342         Queue_t * pxQueueSetContainer = pxQueue->pxQueueSetContainer;
3343         BaseType_t xReturn = pdFALSE;
3344
3345         /* This function must be called form a critical section. */
3346
3347         /* The following line is not reachable in unit tests because every call
3348          * to prvNotifyQueueSetContainer is preceded by a check that
3349          * pxQueueSetContainer != NULL */
3350         configASSERT( pxQueueSetContainer ); /* LCOV_EXCL_BR_LINE */
3351         configASSERT( pxQueueSetContainer->uxMessagesWaiting < pxQueueSetContainer->uxLength );
3352
3353         if( pxQueueSetContainer->uxMessagesWaiting < pxQueueSetContainer->uxLength )
3354         {
3355             const int8_t cTxLock = pxQueueSetContainer->cTxLock;
3356
3357             traceQUEUE_SET_SEND( pxQueueSetContainer );
3358
3359             /* The data copied is the handle of the queue that contains data. */
3360             xReturn = prvCopyDataToQueue( pxQueueSetContainer, &pxQueue, queueSEND_TO_BACK );
3361
3362             if( cTxLock == queueUNLOCKED )
3363             {
3364                 if( listLIST_IS_EMPTY( &( pxQueueSetContainer->xTasksWaitingToReceive ) ) == pdFALSE )
3365                 {
3366                     if( xTaskRemoveFromEventList( &( pxQueueSetContainer->xTasksWaitingToReceive ) ) != pdFALSE )
3367                     {
3368                         /* The task waiting has a higher priority. */
3369                         xReturn = pdTRUE;
3370                     }
3371                     else
3372                     {
3373                         mtCOVERAGE_TEST_MARKER();
3374                     }
3375                 }
3376                 else
3377                 {
3378                     mtCOVERAGE_TEST_MARKER();
3379                 }
3380             }
3381             else
3382             {
3383                 prvIncrementQueueTxLock( pxQueueSetContainer, cTxLock );
3384             }
3385         }
3386         else
3387         {
3388             mtCOVERAGE_TEST_MARKER();
3389         }
3390
3391         return xReturn;
3392     }
3393
3394 #endif /* configUSE_QUEUE_SETS */