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