]> git.sur5r.net Git - freertos/blob - FreeRTOS/Source/queue.c
Update version number in readiness for V10.3.0 release. Sync SVN with reviewed releas...
[freertos] / FreeRTOS / Source / queue.c
1 /*\r
2  * FreeRTOS Kernel V10.3.0\r
3  * Copyright (C) 2020 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                         const UBaseType_t uxPreviousMessagesWaiting = pxQueue->uxMessagesWaiting;\r
987 \r
988                         traceQUEUE_SEND_FROM_ISR( pxQueue );\r
989 \r
990                         /* Semaphores use xQueueGiveFromISR(), so pxQueue will not be a\r
991                         semaphore or mutex.  That means prvCopyDataToQueue() cannot result\r
992                         in a task disinheriting a priority and prvCopyDataToQueue() can be\r
993                         called here even though the disinherit function does not check if\r
994                         the scheduler is suspended before accessing the ready lists. */\r
995                         ( void ) prvCopyDataToQueue( pxQueue, pvItemToQueue, xCopyPosition );\r
996 \r
997                         /* The event list is not altered if the queue is locked.  This will\r
998                         be done when the queue is unlocked later. */\r
999                         if( cTxLock == queueUNLOCKED )\r
1000                         {\r
1001                                 #if ( configUSE_QUEUE_SETS == 1 )\r
1002                                 {\r
1003                                         if( pxQueue->pxQueueSetContainer != NULL )\r
1004                                         {\r
1005                                                 if( ( xCopyPosition == queueOVERWRITE ) && ( uxPreviousMessagesWaiting != ( UBaseType_t ) 0 ) )\r
1006                                                 {\r
1007                                                         /* Do not notify the queue set as an existing item\r
1008                                                         was overwritten in the queue so the number of items\r
1009                                                         in the queue has not changed. */\r
1010                                                         mtCOVERAGE_TEST_MARKER();\r
1011                                                 }\r
1012                                                 else if( prvNotifyQueueSetContainer( pxQueue ) != pdFALSE )\r
1013                                                 {\r
1014                                                         /* The queue is a member of a queue set, and posting\r
1015                                                         to the queue set caused a higher priority task to\r
1016                                                         unblock.  A context switch is required. */\r
1017                                                         if( pxHigherPriorityTaskWoken != NULL )\r
1018                                                         {\r
1019                                                                 *pxHigherPriorityTaskWoken = pdTRUE;\r
1020                                                         }\r
1021                                                         else\r
1022                                                         {\r
1023                                                                 mtCOVERAGE_TEST_MARKER();\r
1024                                                         }\r
1025                                                 }\r
1026                                                 else\r
1027                                                 {\r
1028                                                         mtCOVERAGE_TEST_MARKER();\r
1029                                                 }\r
1030                                         }\r
1031                                         else\r
1032                                         {\r
1033                                                 if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE )\r
1034                                                 {\r
1035                                                         if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE )\r
1036                                                         {\r
1037                                                                 /* The task waiting has a higher priority so\r
1038                                                                 record that a context switch is required. */\r
1039                                                                 if( pxHigherPriorityTaskWoken != NULL )\r
1040                                                                 {\r
1041                                                                         *pxHigherPriorityTaskWoken = pdTRUE;\r
1042                                                                 }\r
1043                                                                 else\r
1044                                                                 {\r
1045                                                                         mtCOVERAGE_TEST_MARKER();\r
1046                                                                 }\r
1047                                                         }\r
1048                                                         else\r
1049                                                         {\r
1050                                                                 mtCOVERAGE_TEST_MARKER();\r
1051                                                         }\r
1052                                                 }\r
1053                                                 else\r
1054                                                 {\r
1055                                                         mtCOVERAGE_TEST_MARKER();\r
1056                                                 }\r
1057                                         }\r
1058                                 }\r
1059                                 #else /* configUSE_QUEUE_SETS */\r
1060                                 {\r
1061                                         if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE )\r
1062                                         {\r
1063                                                 if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE )\r
1064                                                 {\r
1065                                                         /* The task waiting has a higher priority so record that a\r
1066                                                         context switch is required. */\r
1067                                                         if( pxHigherPriorityTaskWoken != NULL )\r
1068                                                         {\r
1069                                                                 *pxHigherPriorityTaskWoken = pdTRUE;\r
1070                                                         }\r
1071                                                         else\r
1072                                                         {\r
1073                                                                 mtCOVERAGE_TEST_MARKER();\r
1074                                                         }\r
1075                                                 }\r
1076                                                 else\r
1077                                                 {\r
1078                                                         mtCOVERAGE_TEST_MARKER();\r
1079                                                 }\r
1080                                         }\r
1081                                         else\r
1082                                         {\r
1083                                                 mtCOVERAGE_TEST_MARKER();\r
1084                                         }\r
1085                                         \r
1086                                         /* Not used in this path. */\r
1087                                         ( void ) uxPreviousMessagesWaiting;\r
1088                                 }\r
1089                                 #endif /* configUSE_QUEUE_SETS */\r
1090                         }\r
1091                         else\r
1092                         {\r
1093                                 /* Increment the lock count so the task that unlocks the queue\r
1094                                 knows that data was posted while it was locked. */\r
1095                                 pxQueue->cTxLock = ( int8_t ) ( cTxLock + 1 );\r
1096                         }\r
1097 \r
1098                         xReturn = pdPASS;\r
1099                 }\r
1100                 else\r
1101                 {\r
1102                         traceQUEUE_SEND_FROM_ISR_FAILED( pxQueue );\r
1103                         xReturn = errQUEUE_FULL;\r
1104                 }\r
1105         }\r
1106         portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus );\r
1107 \r
1108         return xReturn;\r
1109 }\r
1110 /*-----------------------------------------------------------*/\r
1111 \r
1112 BaseType_t xQueueGiveFromISR( QueueHandle_t xQueue, BaseType_t * const pxHigherPriorityTaskWoken )\r
1113 {\r
1114 BaseType_t xReturn;\r
1115 UBaseType_t uxSavedInterruptStatus;\r
1116 Queue_t * const pxQueue = xQueue;\r
1117 \r
1118         /* Similar to xQueueGenericSendFromISR() but used with semaphores where the\r
1119         item size is 0.  Don't directly wake a task that was blocked on a queue\r
1120         read, instead return a flag to say whether a context switch is required or\r
1121         not (i.e. has a task with a higher priority than us been woken by this\r
1122         post). */\r
1123 \r
1124         configASSERT( pxQueue );\r
1125 \r
1126         /* xQueueGenericSendFromISR() should be used instead of xQueueGiveFromISR()\r
1127         if the item size is not 0. */\r
1128         configASSERT( pxQueue->uxItemSize == 0 );\r
1129 \r
1130         /* Normally a mutex would not be given from an interrupt, especially if\r
1131         there is a mutex holder, as priority inheritance makes no sense for an\r
1132         interrupts, only tasks. */\r
1133         configASSERT( !( ( pxQueue->uxQueueType == queueQUEUE_IS_MUTEX ) && ( pxQueue->u.xSemaphore.xMutexHolder != NULL ) ) );\r
1134 \r
1135         /* RTOS ports that support interrupt nesting have the concept of a maximum\r
1136         system call (or maximum API call) interrupt priority.  Interrupts that are\r
1137         above the maximum system call priority are kept permanently enabled, even\r
1138         when the RTOS kernel is in a critical section, but cannot make any calls to\r
1139         FreeRTOS API functions.  If configASSERT() is defined in FreeRTOSConfig.h\r
1140         then portASSERT_IF_INTERRUPT_PRIORITY_INVALID() will result in an assertion\r
1141         failure if a FreeRTOS API function is called from an interrupt that has been\r
1142         assigned a priority above the configured maximum system call priority.\r
1143         Only FreeRTOS functions that end in FromISR can be called from interrupts\r
1144         that have been assigned a priority at or (logically) below the maximum\r
1145         system call     interrupt priority.  FreeRTOS maintains a separate interrupt\r
1146         safe API to ensure interrupt entry is as fast and as simple as possible.\r
1147         More information (albeit Cortex-M specific) is provided on the following\r
1148         link: http://www.freertos.org/RTOS-Cortex-M3-M4.html */\r
1149         portASSERT_IF_INTERRUPT_PRIORITY_INVALID();\r
1150 \r
1151         uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR();\r
1152         {\r
1153                 const UBaseType_t uxMessagesWaiting = pxQueue->uxMessagesWaiting;\r
1154 \r
1155                 /* When the queue is used to implement a semaphore no data is ever\r
1156                 moved through the queue but it is still valid to see if the queue 'has\r
1157                 space'. */\r
1158                 if( uxMessagesWaiting < pxQueue->uxLength )\r
1159                 {\r
1160                         const int8_t cTxLock = pxQueue->cTxLock;\r
1161 \r
1162                         traceQUEUE_SEND_FROM_ISR( pxQueue );\r
1163 \r
1164                         /* A task can only have an inherited priority if it is a mutex\r
1165                         holder - and if there is a mutex holder then the mutex cannot be\r
1166                         given from an ISR.  As this is the ISR version of the function it\r
1167                         can be assumed there is no mutex holder and no need to determine if\r
1168                         priority disinheritance is needed.  Simply increase the count of\r
1169                         messages (semaphores) available. */\r
1170                         pxQueue->uxMessagesWaiting = uxMessagesWaiting + ( UBaseType_t ) 1;\r
1171 \r
1172                         /* The event list is not altered if the queue is locked.  This will\r
1173                         be done when the queue is unlocked later. */\r
1174                         if( cTxLock == queueUNLOCKED )\r
1175                         {\r
1176                                 #if ( configUSE_QUEUE_SETS == 1 )\r
1177                                 {\r
1178                                         if( pxQueue->pxQueueSetContainer != NULL )\r
1179                                         {\r
1180                                                 if( prvNotifyQueueSetContainer( pxQueue ) != pdFALSE )\r
1181                                                 {\r
1182                                                         /* The semaphore is a member of a queue set, and\r
1183                                                         posting to the queue set caused a higher priority\r
1184                                                         task to unblock.  A context switch is required. */\r
1185                                                         if( pxHigherPriorityTaskWoken != NULL )\r
1186                                                         {\r
1187                                                                 *pxHigherPriorityTaskWoken = pdTRUE;\r
1188                                                         }\r
1189                                                         else\r
1190                                                         {\r
1191                                                                 mtCOVERAGE_TEST_MARKER();\r
1192                                                         }\r
1193                                                 }\r
1194                                                 else\r
1195                                                 {\r
1196                                                         mtCOVERAGE_TEST_MARKER();\r
1197                                                 }\r
1198                                         }\r
1199                                         else\r
1200                                         {\r
1201                                                 if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE )\r
1202                                                 {\r
1203                                                         if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE )\r
1204                                                         {\r
1205                                                                 /* The task waiting has a higher priority so\r
1206                                                                 record that a context switch is required. */\r
1207                                                                 if( pxHigherPriorityTaskWoken != NULL )\r
1208                                                                 {\r
1209                                                                         *pxHigherPriorityTaskWoken = pdTRUE;\r
1210                                                                 }\r
1211                                                                 else\r
1212                                                                 {\r
1213                                                                         mtCOVERAGE_TEST_MARKER();\r
1214                                                                 }\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                                 }\r
1227                                 #else /* configUSE_QUEUE_SETS */\r
1228                                 {\r
1229                                         if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE )\r
1230                                         {\r
1231                                                 if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE )\r
1232                                                 {\r
1233                                                         /* The task waiting has a higher priority so record that a\r
1234                                                         context switch is required. */\r
1235                                                         if( pxHigherPriorityTaskWoken != NULL )\r
1236                                                         {\r
1237                                                                 *pxHigherPriorityTaskWoken = pdTRUE;\r
1238                                                         }\r
1239                                                         else\r
1240                                                         {\r
1241                                                                 mtCOVERAGE_TEST_MARKER();\r
1242                                                         }\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                                 #endif /* configUSE_QUEUE_SETS */\r
1255                         }\r
1256                         else\r
1257                         {\r
1258                                 /* Increment the lock count so the task that unlocks the queue\r
1259                                 knows that data was posted while it was locked. */\r
1260                                 pxQueue->cTxLock = ( int8_t ) ( cTxLock + 1 );\r
1261                         }\r
1262 \r
1263                         xReturn = pdPASS;\r
1264                 }\r
1265                 else\r
1266                 {\r
1267                         traceQUEUE_SEND_FROM_ISR_FAILED( pxQueue );\r
1268                         xReturn = errQUEUE_FULL;\r
1269                 }\r
1270         }\r
1271         portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus );\r
1272 \r
1273         return xReturn;\r
1274 }\r
1275 /*-----------------------------------------------------------*/\r
1276 \r
1277 BaseType_t xQueueReceive( QueueHandle_t xQueue, void * const pvBuffer, TickType_t xTicksToWait )\r
1278 {\r
1279 BaseType_t xEntryTimeSet = pdFALSE;\r
1280 TimeOut_t xTimeOut;\r
1281 Queue_t * const pxQueue = xQueue;\r
1282 \r
1283         /* Check the pointer is not NULL. */\r
1284         configASSERT( ( pxQueue ) );\r
1285 \r
1286         /* The buffer into which data is received can only be NULL if the data size\r
1287         is zero (so no data is copied into the buffer. */\r
1288         configASSERT( !( ( ( pvBuffer ) == NULL ) && ( ( pxQueue )->uxItemSize != ( UBaseType_t ) 0U ) ) );\r
1289 \r
1290         /* Cannot block if the scheduler is suspended. */\r
1291         #if ( ( INCLUDE_xTaskGetSchedulerState == 1 ) || ( configUSE_TIMERS == 1 ) )\r
1292         {\r
1293                 configASSERT( !( ( xTaskGetSchedulerState() == taskSCHEDULER_SUSPENDED ) && ( xTicksToWait != 0 ) ) );\r
1294         }\r
1295         #endif\r
1296 \r
1297 \r
1298         /*lint -save -e904  This function relaxes the coding standard somewhat to\r
1299         allow return statements within the function itself.  This is done in the\r
1300         interest of execution time efficiency. */\r
1301         for( ;; )\r
1302         {\r
1303                 taskENTER_CRITICAL();\r
1304                 {\r
1305                         const UBaseType_t uxMessagesWaiting = pxQueue->uxMessagesWaiting;\r
1306 \r
1307                         /* Is there data in the queue now?  To be running the calling task\r
1308                         must be the highest priority task wanting to access the queue. */\r
1309                         if( uxMessagesWaiting > ( UBaseType_t ) 0 )\r
1310                         {\r
1311                                 /* Data available, remove one item. */\r
1312                                 prvCopyDataFromQueue( pxQueue, pvBuffer );\r
1313                                 traceQUEUE_RECEIVE( pxQueue );\r
1314                                 pxQueue->uxMessagesWaiting = uxMessagesWaiting - ( UBaseType_t ) 1;\r
1315 \r
1316                                 /* There is now space in the queue, were any tasks waiting to\r
1317                                 post to the queue?  If so, unblock the highest priority waiting\r
1318                                 task. */\r
1319                                 if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) == pdFALSE )\r
1320                                 {\r
1321                                         if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) != pdFALSE )\r
1322                                         {\r
1323                                                 queueYIELD_IF_USING_PREEMPTION();\r
1324                                         }\r
1325                                         else\r
1326                                         {\r
1327                                                 mtCOVERAGE_TEST_MARKER();\r
1328                                         }\r
1329                                 }\r
1330                                 else\r
1331                                 {\r
1332                                         mtCOVERAGE_TEST_MARKER();\r
1333                                 }\r
1334 \r
1335                                 taskEXIT_CRITICAL();\r
1336                                 return pdPASS;\r
1337                         }\r
1338                         else\r
1339                         {\r
1340                                 if( xTicksToWait == ( TickType_t ) 0 )\r
1341                                 {\r
1342                                         /* The queue was empty and no block time is specified (or\r
1343                                         the block time has expired) so leave now. */\r
1344                                         taskEXIT_CRITICAL();\r
1345                                         traceQUEUE_RECEIVE_FAILED( pxQueue );\r
1346                                         return errQUEUE_EMPTY;\r
1347                                 }\r
1348                                 else if( xEntryTimeSet == pdFALSE )\r
1349                                 {\r
1350                                         /* The queue was empty and a block time was specified so\r
1351                                         configure the timeout structure. */\r
1352                                         vTaskInternalSetTimeOutState( &xTimeOut );\r
1353                                         xEntryTimeSet = pdTRUE;\r
1354                                 }\r
1355                                 else\r
1356                                 {\r
1357                                         /* Entry time was already set. */\r
1358                                         mtCOVERAGE_TEST_MARKER();\r
1359                                 }\r
1360                         }\r
1361                 }\r
1362                 taskEXIT_CRITICAL();\r
1363 \r
1364                 /* Interrupts and other tasks can send to and receive from the queue\r
1365                 now the critical section has been exited. */\r
1366 \r
1367                 vTaskSuspendAll();\r
1368                 prvLockQueue( pxQueue );\r
1369 \r
1370                 /* Update the timeout state to see if it has expired yet. */\r
1371                 if( xTaskCheckForTimeOut( &xTimeOut, &xTicksToWait ) == pdFALSE )\r
1372                 {\r
1373                         /* The timeout has not expired.  If the queue is still empty place\r
1374                         the task on the list of tasks waiting to receive from the queue. */\r
1375                         if( prvIsQueueEmpty( pxQueue ) != pdFALSE )\r
1376                         {\r
1377                                 traceBLOCKING_ON_QUEUE_RECEIVE( pxQueue );\r
1378                                 vTaskPlaceOnEventList( &( pxQueue->xTasksWaitingToReceive ), xTicksToWait );\r
1379                                 prvUnlockQueue( pxQueue );\r
1380                                 if( xTaskResumeAll() == pdFALSE )\r
1381                                 {\r
1382                                         portYIELD_WITHIN_API();\r
1383                                 }\r
1384                                 else\r
1385                                 {\r
1386                                         mtCOVERAGE_TEST_MARKER();\r
1387                                 }\r
1388                         }\r
1389                         else\r
1390                         {\r
1391                                 /* The queue contains data again.  Loop back to try and read the\r
1392                                 data. */\r
1393                                 prvUnlockQueue( pxQueue );\r
1394                                 ( void ) xTaskResumeAll();\r
1395                         }\r
1396                 }\r
1397                 else\r
1398                 {\r
1399                         /* Timed out.  If there is no data in the queue exit, otherwise loop\r
1400                         back and attempt to read the data. */\r
1401                         prvUnlockQueue( pxQueue );\r
1402                         ( void ) xTaskResumeAll();\r
1403 \r
1404                         if( prvIsQueueEmpty( pxQueue ) != pdFALSE )\r
1405                         {\r
1406                                 traceQUEUE_RECEIVE_FAILED( pxQueue );\r
1407                                 return errQUEUE_EMPTY;\r
1408                         }\r
1409                         else\r
1410                         {\r
1411                                 mtCOVERAGE_TEST_MARKER();\r
1412                         }\r
1413                 }\r
1414         } /*lint -restore */\r
1415 }\r
1416 /*-----------------------------------------------------------*/\r
1417 \r
1418 BaseType_t xQueueSemaphoreTake( QueueHandle_t xQueue, TickType_t xTicksToWait )\r
1419 {\r
1420 BaseType_t xEntryTimeSet = pdFALSE;\r
1421 TimeOut_t xTimeOut;\r
1422 Queue_t * const pxQueue = xQueue;\r
1423 \r
1424 #if( configUSE_MUTEXES == 1 )\r
1425         BaseType_t xInheritanceOccurred = pdFALSE;\r
1426 #endif\r
1427 \r
1428         /* Check the queue pointer is not NULL. */\r
1429         configASSERT( ( pxQueue ) );\r
1430 \r
1431         /* Check this really is a semaphore, in which case the item size will be\r
1432         0. */\r
1433         configASSERT( pxQueue->uxItemSize == 0 );\r
1434 \r
1435         /* Cannot block if the scheduler is suspended. */\r
1436         #if ( ( INCLUDE_xTaskGetSchedulerState == 1 ) || ( configUSE_TIMERS == 1 ) )\r
1437         {\r
1438                 configASSERT( !( ( xTaskGetSchedulerState() == taskSCHEDULER_SUSPENDED ) && ( xTicksToWait != 0 ) ) );\r
1439         }\r
1440         #endif\r
1441 \r
1442 \r
1443         /*lint -save -e904 This function relaxes the coding standard somewhat to allow return\r
1444         statements within the function itself.  This is done in the interest\r
1445         of execution time efficiency. */\r
1446         for( ;; )\r
1447         {\r
1448                 taskENTER_CRITICAL();\r
1449                 {\r
1450                         /* Semaphores are queues with an item size of 0, and where the\r
1451                         number of messages in the queue is the semaphore's count value. */\r
1452                         const UBaseType_t uxSemaphoreCount = pxQueue->uxMessagesWaiting;\r
1453 \r
1454                         /* Is there data in the queue now?  To be running the calling task\r
1455                         must be the highest priority task wanting to access the queue. */\r
1456                         if( uxSemaphoreCount > ( UBaseType_t ) 0 )\r
1457                         {\r
1458                                 traceQUEUE_RECEIVE( pxQueue );\r
1459 \r
1460                                 /* Semaphores are queues with a data size of zero and where the\r
1461                                 messages waiting is the semaphore's count.  Reduce the count. */\r
1462                                 pxQueue->uxMessagesWaiting = uxSemaphoreCount - ( UBaseType_t ) 1;\r
1463 \r
1464                                 #if ( configUSE_MUTEXES == 1 )\r
1465                                 {\r
1466                                         if( pxQueue->uxQueueType == queueQUEUE_IS_MUTEX )\r
1467                                         {\r
1468                                                 /* Record the information required to implement\r
1469                                                 priority inheritance should it become necessary. */\r
1470                                                 pxQueue->u.xSemaphore.xMutexHolder = pvTaskIncrementMutexHeldCount();\r
1471                                         }\r
1472                                         else\r
1473                                         {\r
1474                                                 mtCOVERAGE_TEST_MARKER();\r
1475                                         }\r
1476                                 }\r
1477                                 #endif /* configUSE_MUTEXES */\r
1478 \r
1479                                 /* Check to see if other tasks are blocked waiting to give the\r
1480                                 semaphore, and if so, unblock the highest priority such task. */\r
1481                                 if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) == pdFALSE )\r
1482                                 {\r
1483                                         if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) != pdFALSE )\r
1484                                         {\r
1485                                                 queueYIELD_IF_USING_PREEMPTION();\r
1486                                         }\r
1487                                         else\r
1488                                         {\r
1489                                                 mtCOVERAGE_TEST_MARKER();\r
1490                                         }\r
1491                                 }\r
1492                                 else\r
1493                                 {\r
1494                                         mtCOVERAGE_TEST_MARKER();\r
1495                                 }\r
1496 \r
1497                                 taskEXIT_CRITICAL();\r
1498                                 return pdPASS;\r
1499                         }\r
1500                         else\r
1501                         {\r
1502                                 if( xTicksToWait == ( TickType_t ) 0 )\r
1503                                 {\r
1504                                         /* For inheritance to have occurred there must have been an\r
1505                                         initial timeout, and an adjusted timeout cannot become 0, as\r
1506                                         if it were 0 the function would have exited. */\r
1507                                         #if( configUSE_MUTEXES == 1 )\r
1508                                         {\r
1509                                                 configASSERT( xInheritanceOccurred == pdFALSE );\r
1510                                         }\r
1511                                         #endif /* configUSE_MUTEXES */\r
1512 \r
1513                                         /* The semaphore count was 0 and no block time is specified\r
1514                                         (or the block time has expired) so exit now. */\r
1515                                         taskEXIT_CRITICAL();\r
1516                                         traceQUEUE_RECEIVE_FAILED( pxQueue );\r
1517                                         return errQUEUE_EMPTY;\r
1518                                 }\r
1519                                 else if( xEntryTimeSet == pdFALSE )\r
1520                                 {\r
1521                                         /* The semaphore count was 0 and a block time was specified\r
1522                                         so configure the timeout structure ready to block. */\r
1523                                         vTaskInternalSetTimeOutState( &xTimeOut );\r
1524                                         xEntryTimeSet = pdTRUE;\r
1525                                 }\r
1526                                 else\r
1527                                 {\r
1528                                         /* Entry time was already set. */\r
1529                                         mtCOVERAGE_TEST_MARKER();\r
1530                                 }\r
1531                         }\r
1532                 }\r
1533                 taskEXIT_CRITICAL();\r
1534 \r
1535                 /* Interrupts and other tasks can give to and take from the semaphore\r
1536                 now the critical section has been exited. */\r
1537 \r
1538                 vTaskSuspendAll();\r
1539                 prvLockQueue( pxQueue );\r
1540 \r
1541                 /* Update the timeout state to see if it has expired yet. */\r
1542                 if( xTaskCheckForTimeOut( &xTimeOut, &xTicksToWait ) == pdFALSE )\r
1543                 {\r
1544                         /* A block time is specified and not expired.  If the semaphore\r
1545                         count is 0 then enter the Blocked state to wait for a semaphore to\r
1546                         become available.  As semaphores are implemented with queues the\r
1547                         queue being empty is equivalent to the semaphore count being 0. */\r
1548                         if( prvIsQueueEmpty( pxQueue ) != pdFALSE )\r
1549                         {\r
1550                                 traceBLOCKING_ON_QUEUE_RECEIVE( pxQueue );\r
1551 \r
1552                                 #if ( configUSE_MUTEXES == 1 )\r
1553                                 {\r
1554                                         if( pxQueue->uxQueueType == queueQUEUE_IS_MUTEX )\r
1555                                         {\r
1556                                                 taskENTER_CRITICAL();\r
1557                                                 {\r
1558                                                         xInheritanceOccurred = xTaskPriorityInherit( pxQueue->u.xSemaphore.xMutexHolder );\r
1559                                                 }\r
1560                                                 taskEXIT_CRITICAL();\r
1561                                         }\r
1562                                         else\r
1563                                         {\r
1564                                                 mtCOVERAGE_TEST_MARKER();\r
1565                                         }\r
1566                                 }\r
1567                                 #endif\r
1568 \r
1569                                 vTaskPlaceOnEventList( &( pxQueue->xTasksWaitingToReceive ), xTicksToWait );\r
1570                                 prvUnlockQueue( pxQueue );\r
1571                                 if( xTaskResumeAll() == pdFALSE )\r
1572                                 {\r
1573                                         portYIELD_WITHIN_API();\r
1574                                 }\r
1575                                 else\r
1576                                 {\r
1577                                         mtCOVERAGE_TEST_MARKER();\r
1578                                 }\r
1579                         }\r
1580                         else\r
1581                         {\r
1582                                 /* There was no timeout and the semaphore count was not 0, so\r
1583                                 attempt to take the semaphore again. */\r
1584                                 prvUnlockQueue( pxQueue );\r
1585                                 ( void ) xTaskResumeAll();\r
1586                         }\r
1587                 }\r
1588                 else\r
1589                 {\r
1590                         /* Timed out. */\r
1591                         prvUnlockQueue( pxQueue );\r
1592                         ( void ) xTaskResumeAll();\r
1593 \r
1594                         /* If the semaphore count is 0 exit now as the timeout has\r
1595                         expired.  Otherwise return to attempt to take the semaphore that is\r
1596                         known to be available.  As semaphores are implemented by queues the\r
1597                         queue being empty is equivalent to the semaphore count being 0. */\r
1598                         if( prvIsQueueEmpty( pxQueue ) != pdFALSE )\r
1599                         {\r
1600                                 #if ( configUSE_MUTEXES == 1 )\r
1601                                 {\r
1602                                         /* xInheritanceOccurred could only have be set if\r
1603                                         pxQueue->uxQueueType == queueQUEUE_IS_MUTEX so no need to\r
1604                                         test the mutex type again to check it is actually a mutex. */\r
1605                                         if( xInheritanceOccurred != pdFALSE )\r
1606                                         {\r
1607                                                 taskENTER_CRITICAL();\r
1608                                                 {\r
1609                                                         UBaseType_t uxHighestWaitingPriority;\r
1610 \r
1611                                                         /* This task blocking on the mutex caused another\r
1612                                                         task to inherit this task's priority.  Now this task\r
1613                                                         has timed out the priority should be disinherited\r
1614                                                         again, but only as low as the next highest priority\r
1615                                                         task that is waiting for the same mutex. */\r
1616                                                         uxHighestWaitingPriority = prvGetDisinheritPriorityAfterTimeout( pxQueue );\r
1617                                                         vTaskPriorityDisinheritAfterTimeout( pxQueue->u.xSemaphore.xMutexHolder, uxHighestWaitingPriority );\r
1618                                                 }\r
1619                                                 taskEXIT_CRITICAL();\r
1620                                         }\r
1621                                 }\r
1622                                 #endif /* configUSE_MUTEXES */\r
1623 \r
1624                                 traceQUEUE_RECEIVE_FAILED( pxQueue );\r
1625                                 return errQUEUE_EMPTY;\r
1626                         }\r
1627                         else\r
1628                         {\r
1629                                 mtCOVERAGE_TEST_MARKER();\r
1630                         }\r
1631                 }\r
1632         } /*lint -restore */\r
1633 }\r
1634 /*-----------------------------------------------------------*/\r
1635 \r
1636 BaseType_t xQueuePeek( QueueHandle_t xQueue, void * const pvBuffer, TickType_t xTicksToWait )\r
1637 {\r
1638 BaseType_t xEntryTimeSet = pdFALSE;\r
1639 TimeOut_t xTimeOut;\r
1640 int8_t *pcOriginalReadPosition;\r
1641 Queue_t * const pxQueue = xQueue;\r
1642 \r
1643         /* Check the pointer is not NULL. */\r
1644         configASSERT( ( pxQueue ) );\r
1645 \r
1646         /* The buffer into which data is received can only be NULL if the data size\r
1647         is zero (so no data is copied into the buffer. */\r
1648         configASSERT( !( ( ( pvBuffer ) == NULL ) && ( ( pxQueue )->uxItemSize != ( UBaseType_t ) 0U ) ) );\r
1649 \r
1650         /* Cannot block if the scheduler is suspended. */\r
1651         #if ( ( INCLUDE_xTaskGetSchedulerState == 1 ) || ( configUSE_TIMERS == 1 ) )\r
1652         {\r
1653                 configASSERT( !( ( xTaskGetSchedulerState() == taskSCHEDULER_SUSPENDED ) && ( xTicksToWait != 0 ) ) );\r
1654         }\r
1655         #endif\r
1656 \r
1657 \r
1658         /*lint -save -e904  This function relaxes the coding standard somewhat to\r
1659         allow return statements within the function itself.  This is done in the\r
1660         interest of execution time efficiency. */\r
1661         for( ;; )\r
1662         {\r
1663                 taskENTER_CRITICAL();\r
1664                 {\r
1665                         const UBaseType_t uxMessagesWaiting = pxQueue->uxMessagesWaiting;\r
1666 \r
1667                         /* Is there data in the queue now?  To be running the calling task\r
1668                         must be the highest priority task wanting to access the queue. */\r
1669                         if( uxMessagesWaiting > ( UBaseType_t ) 0 )\r
1670                         {\r
1671                                 /* Remember the read position so it can be reset after the data\r
1672                                 is read from the queue as this function is only peeking the\r
1673                                 data, not removing it. */\r
1674                                 pcOriginalReadPosition = pxQueue->u.xQueue.pcReadFrom;\r
1675 \r
1676                                 prvCopyDataFromQueue( pxQueue, pvBuffer );\r
1677                                 traceQUEUE_PEEK( pxQueue );\r
1678 \r
1679                                 /* The data is not being removed, so reset the read pointer. */\r
1680                                 pxQueue->u.xQueue.pcReadFrom = pcOriginalReadPosition;\r
1681 \r
1682                                 /* The data is being left in the queue, so see if there are\r
1683                                 any other tasks waiting for the data. */\r
1684                                 if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE )\r
1685                                 {\r
1686                                         if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE )\r
1687                                         {\r
1688                                                 /* The task waiting has a higher priority than this task. */\r
1689                                                 queueYIELD_IF_USING_PREEMPTION();\r
1690                                         }\r
1691                                         else\r
1692                                         {\r
1693                                                 mtCOVERAGE_TEST_MARKER();\r
1694                                         }\r
1695                                 }\r
1696                                 else\r
1697                                 {\r
1698                                         mtCOVERAGE_TEST_MARKER();\r
1699                                 }\r
1700 \r
1701                                 taskEXIT_CRITICAL();\r
1702                                 return pdPASS;\r
1703                         }\r
1704                         else\r
1705                         {\r
1706                                 if( xTicksToWait == ( TickType_t ) 0 )\r
1707                                 {\r
1708                                         /* The queue was empty and no block time is specified (or\r
1709                                         the block time has expired) so leave now. */\r
1710                                         taskEXIT_CRITICAL();\r
1711                                         traceQUEUE_PEEK_FAILED( pxQueue );\r
1712                                         return errQUEUE_EMPTY;\r
1713                                 }\r
1714                                 else if( xEntryTimeSet == pdFALSE )\r
1715                                 {\r
1716                                         /* The queue was empty and a block time was specified so\r
1717                                         configure the timeout structure ready to enter the blocked\r
1718                                         state. */\r
1719                                         vTaskInternalSetTimeOutState( &xTimeOut );\r
1720                                         xEntryTimeSet = pdTRUE;\r
1721                                 }\r
1722                                 else\r
1723                                 {\r
1724                                         /* Entry time was already set. */\r
1725                                         mtCOVERAGE_TEST_MARKER();\r
1726                                 }\r
1727                         }\r
1728                 }\r
1729                 taskEXIT_CRITICAL();\r
1730 \r
1731                 /* Interrupts and other tasks can send to and receive from the queue\r
1732                 now the critical section has been exited. */\r
1733 \r
1734                 vTaskSuspendAll();\r
1735                 prvLockQueue( pxQueue );\r
1736 \r
1737                 /* Update the timeout state to see if it has expired yet. */\r
1738                 if( xTaskCheckForTimeOut( &xTimeOut, &xTicksToWait ) == pdFALSE )\r
1739                 {\r
1740                         /* Timeout has not expired yet, check to see if there is data in the\r
1741                         queue now, and if not enter the Blocked state to wait for data. */\r
1742                         if( prvIsQueueEmpty( pxQueue ) != pdFALSE )\r
1743                         {\r
1744                                 traceBLOCKING_ON_QUEUE_PEEK( pxQueue );\r
1745                                 vTaskPlaceOnEventList( &( pxQueue->xTasksWaitingToReceive ), xTicksToWait );\r
1746                                 prvUnlockQueue( pxQueue );\r
1747                                 if( xTaskResumeAll() == pdFALSE )\r
1748                                 {\r
1749                                         portYIELD_WITHIN_API();\r
1750                                 }\r
1751                                 else\r
1752                                 {\r
1753                                         mtCOVERAGE_TEST_MARKER();\r
1754                                 }\r
1755                         }\r
1756                         else\r
1757                         {\r
1758                                 /* There is data in the queue now, so don't enter the blocked\r
1759                                 state, instead return to try and obtain the data. */\r
1760                                 prvUnlockQueue( pxQueue );\r
1761                                 ( void ) xTaskResumeAll();\r
1762                         }\r
1763                 }\r
1764                 else\r
1765                 {\r
1766                         /* The timeout has expired.  If there is still no data in the queue\r
1767                         exit, otherwise go back and try to read the data again. */\r
1768                         prvUnlockQueue( pxQueue );\r
1769                         ( void ) xTaskResumeAll();\r
1770 \r
1771                         if( prvIsQueueEmpty( pxQueue ) != pdFALSE )\r
1772                         {\r
1773                                 traceQUEUE_PEEK_FAILED( pxQueue );\r
1774                                 return errQUEUE_EMPTY;\r
1775                         }\r
1776                         else\r
1777                         {\r
1778                                 mtCOVERAGE_TEST_MARKER();\r
1779                         }\r
1780                 }\r
1781         } /*lint -restore */\r
1782 }\r
1783 /*-----------------------------------------------------------*/\r
1784 \r
1785 BaseType_t xQueueReceiveFromISR( QueueHandle_t xQueue, void * const pvBuffer, BaseType_t * const pxHigherPriorityTaskWoken )\r
1786 {\r
1787 BaseType_t xReturn;\r
1788 UBaseType_t uxSavedInterruptStatus;\r
1789 Queue_t * const pxQueue = xQueue;\r
1790 \r
1791         configASSERT( pxQueue );\r
1792         configASSERT( !( ( pvBuffer == NULL ) && ( pxQueue->uxItemSize != ( UBaseType_t ) 0U ) ) );\r
1793 \r
1794         /* RTOS ports that support interrupt nesting have the concept of a maximum\r
1795         system call (or maximum API call) interrupt priority.  Interrupts that are\r
1796         above the maximum system call priority are kept permanently enabled, even\r
1797         when the RTOS kernel is in a critical section, but cannot make any calls to\r
1798         FreeRTOS API functions.  If configASSERT() is defined in FreeRTOSConfig.h\r
1799         then portASSERT_IF_INTERRUPT_PRIORITY_INVALID() will result in an assertion\r
1800         failure if a FreeRTOS API function is called from an interrupt that has been\r
1801         assigned a priority above the configured maximum system call priority.\r
1802         Only FreeRTOS functions that end in FromISR can be called from interrupts\r
1803         that have been assigned a priority at or (logically) below the maximum\r
1804         system call     interrupt priority.  FreeRTOS maintains a separate interrupt\r
1805         safe API to ensure interrupt entry is as fast and as simple as possible.\r
1806         More information (albeit Cortex-M specific) is provided on the following\r
1807         link: http://www.freertos.org/RTOS-Cortex-M3-M4.html */\r
1808         portASSERT_IF_INTERRUPT_PRIORITY_INVALID();\r
1809 \r
1810         uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR();\r
1811         {\r
1812                 const UBaseType_t uxMessagesWaiting = pxQueue->uxMessagesWaiting;\r
1813 \r
1814                 /* Cannot block in an ISR, so check there is data available. */\r
1815                 if( uxMessagesWaiting > ( UBaseType_t ) 0 )\r
1816                 {\r
1817                         const int8_t cRxLock = pxQueue->cRxLock;\r
1818 \r
1819                         traceQUEUE_RECEIVE_FROM_ISR( pxQueue );\r
1820 \r
1821                         prvCopyDataFromQueue( pxQueue, pvBuffer );\r
1822                         pxQueue->uxMessagesWaiting = uxMessagesWaiting - ( UBaseType_t ) 1;\r
1823 \r
1824                         /* If the queue is locked the event list will not be modified.\r
1825                         Instead update the lock count so the task that unlocks the queue\r
1826                         will know that an ISR has removed data while the queue was\r
1827                         locked. */\r
1828                         if( cRxLock == queueUNLOCKED )\r
1829                         {\r
1830                                 if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) == pdFALSE )\r
1831                                 {\r
1832                                         if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) != pdFALSE )\r
1833                                         {\r
1834                                                 /* The task waiting has a higher priority than us so\r
1835                                                 force a context switch. */\r
1836                                                 if( pxHigherPriorityTaskWoken != NULL )\r
1837                                                 {\r
1838                                                         *pxHigherPriorityTaskWoken = pdTRUE;\r
1839                                                 }\r
1840                                                 else\r
1841                                                 {\r
1842                                                         mtCOVERAGE_TEST_MARKER();\r
1843                                                 }\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                                 /* Increment the lock count so the task that unlocks the queue\r
1858                                 knows that data was removed while it was locked. */\r
1859                                 pxQueue->cRxLock = ( int8_t ) ( cRxLock + 1 );\r
1860                         }\r
1861 \r
1862                         xReturn = pdPASS;\r
1863                 }\r
1864                 else\r
1865                 {\r
1866                         xReturn = pdFAIL;\r
1867                         traceQUEUE_RECEIVE_FROM_ISR_FAILED( pxQueue );\r
1868                 }\r
1869         }\r
1870         portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus );\r
1871 \r
1872         return xReturn;\r
1873 }\r
1874 /*-----------------------------------------------------------*/\r
1875 \r
1876 BaseType_t xQueuePeekFromISR( QueueHandle_t xQueue,  void * const pvBuffer )\r
1877 {\r
1878 BaseType_t xReturn;\r
1879 UBaseType_t uxSavedInterruptStatus;\r
1880 int8_t *pcOriginalReadPosition;\r
1881 Queue_t * const pxQueue = xQueue;\r
1882 \r
1883         configASSERT( pxQueue );\r
1884         configASSERT( !( ( pvBuffer == NULL ) && ( pxQueue->uxItemSize != ( UBaseType_t ) 0U ) ) );\r
1885         configASSERT( pxQueue->uxItemSize != 0 ); /* Can't peek a semaphore. */\r
1886 \r
1887         /* RTOS ports that support interrupt nesting have the concept of a maximum\r
1888         system call (or maximum API call) interrupt priority.  Interrupts that are\r
1889         above the maximum system call priority are kept permanently enabled, even\r
1890         when the RTOS kernel is in a critical section, but cannot make any calls to\r
1891         FreeRTOS API functions.  If configASSERT() is defined in FreeRTOSConfig.h\r
1892         then portASSERT_IF_INTERRUPT_PRIORITY_INVALID() will result in an assertion\r
1893         failure if a FreeRTOS API function is called from an interrupt that has been\r
1894         assigned a priority above the configured maximum system call priority.\r
1895         Only FreeRTOS functions that end in FromISR can be called from interrupts\r
1896         that have been assigned a priority at or (logically) below the maximum\r
1897         system call     interrupt priority.  FreeRTOS maintains a separate interrupt\r
1898         safe API to ensure interrupt entry is as fast and as simple as possible.\r
1899         More information (albeit Cortex-M specific) is provided on the following\r
1900         link: http://www.freertos.org/RTOS-Cortex-M3-M4.html */\r
1901         portASSERT_IF_INTERRUPT_PRIORITY_INVALID();\r
1902 \r
1903         uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR();\r
1904         {\r
1905                 /* Cannot block in an ISR, so check there is data available. */\r
1906                 if( pxQueue->uxMessagesWaiting > ( UBaseType_t ) 0 )\r
1907                 {\r
1908                         traceQUEUE_PEEK_FROM_ISR( pxQueue );\r
1909 \r
1910                         /* Remember the read position so it can be reset as nothing is\r
1911                         actually being removed from the queue. */\r
1912                         pcOriginalReadPosition = pxQueue->u.xQueue.pcReadFrom;\r
1913                         prvCopyDataFromQueue( pxQueue, pvBuffer );\r
1914                         pxQueue->u.xQueue.pcReadFrom = pcOriginalReadPosition;\r
1915 \r
1916                         xReturn = pdPASS;\r
1917                 }\r
1918                 else\r
1919                 {\r
1920                         xReturn = pdFAIL;\r
1921                         traceQUEUE_PEEK_FROM_ISR_FAILED( pxQueue );\r
1922                 }\r
1923         }\r
1924         portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus );\r
1925 \r
1926         return xReturn;\r
1927 }\r
1928 /*-----------------------------------------------------------*/\r
1929 \r
1930 UBaseType_t uxQueueMessagesWaiting( const QueueHandle_t xQueue )\r
1931 {\r
1932 UBaseType_t uxReturn;\r
1933 \r
1934         configASSERT( xQueue );\r
1935 \r
1936         taskENTER_CRITICAL();\r
1937         {\r
1938                 uxReturn = ( ( Queue_t * ) xQueue )->uxMessagesWaiting;\r
1939         }\r
1940         taskEXIT_CRITICAL();\r
1941 \r
1942         return uxReturn;\r
1943 } /*lint !e818 Pointer cannot be declared const as xQueue is a typedef not pointer. */\r
1944 /*-----------------------------------------------------------*/\r
1945 \r
1946 UBaseType_t uxQueueSpacesAvailable( const QueueHandle_t xQueue )\r
1947 {\r
1948 UBaseType_t uxReturn;\r
1949 Queue_t * const pxQueue = xQueue;\r
1950 \r
1951         configASSERT( pxQueue );\r
1952 \r
1953         taskENTER_CRITICAL();\r
1954         {\r
1955                 uxReturn = pxQueue->uxLength - pxQueue->uxMessagesWaiting;\r
1956         }\r
1957         taskEXIT_CRITICAL();\r
1958 \r
1959         return uxReturn;\r
1960 } /*lint !e818 Pointer cannot be declared const as xQueue is a typedef not pointer. */\r
1961 /*-----------------------------------------------------------*/\r
1962 \r
1963 UBaseType_t uxQueueMessagesWaitingFromISR( const QueueHandle_t xQueue )\r
1964 {\r
1965 UBaseType_t uxReturn;\r
1966 Queue_t * const pxQueue = xQueue;\r
1967 \r
1968         configASSERT( pxQueue );\r
1969         uxReturn = pxQueue->uxMessagesWaiting;\r
1970 \r
1971         return uxReturn;\r
1972 } /*lint !e818 Pointer cannot be declared const as xQueue is a typedef not pointer. */\r
1973 /*-----------------------------------------------------------*/\r
1974 \r
1975 void vQueueDelete( QueueHandle_t xQueue )\r
1976 {\r
1977 Queue_t * const pxQueue = xQueue;\r
1978 \r
1979         configASSERT( pxQueue );\r
1980         traceQUEUE_DELETE( pxQueue );\r
1981 \r
1982         #if ( configQUEUE_REGISTRY_SIZE > 0 )\r
1983         {\r
1984                 vQueueUnregisterQueue( pxQueue );\r
1985         }\r
1986         #endif\r
1987 \r
1988         #if( ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 0 ) )\r
1989         {\r
1990                 /* The queue can only have been allocated dynamically - free it\r
1991                 again. */\r
1992                 vPortFree( pxQueue );\r
1993         }\r
1994         #elif( ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 1 ) )\r
1995         {\r
1996                 /* The queue could have been allocated statically or dynamically, so\r
1997                 check before attempting to free the memory. */\r
1998                 if( pxQueue->ucStaticallyAllocated == ( uint8_t ) pdFALSE )\r
1999                 {\r
2000                         vPortFree( pxQueue );\r
2001                 }\r
2002                 else\r
2003                 {\r
2004                         mtCOVERAGE_TEST_MARKER();\r
2005                 }\r
2006         }\r
2007         #else\r
2008         {\r
2009                 /* The queue must have been statically allocated, so is not going to be\r
2010                 deleted.  Avoid compiler warnings about the unused parameter. */\r
2011                 ( void ) pxQueue;\r
2012         }\r
2013         #endif /* configSUPPORT_DYNAMIC_ALLOCATION */\r
2014 }\r
2015 /*-----------------------------------------------------------*/\r
2016 \r
2017 #if ( configUSE_TRACE_FACILITY == 1 )\r
2018 \r
2019         UBaseType_t uxQueueGetQueueNumber( QueueHandle_t xQueue )\r
2020         {\r
2021                 return ( ( Queue_t * ) xQueue )->uxQueueNumber;\r
2022         }\r
2023 \r
2024 #endif /* configUSE_TRACE_FACILITY */\r
2025 /*-----------------------------------------------------------*/\r
2026 \r
2027 #if ( configUSE_TRACE_FACILITY == 1 )\r
2028 \r
2029         void vQueueSetQueueNumber( QueueHandle_t xQueue, UBaseType_t uxQueueNumber )\r
2030         {\r
2031                 ( ( Queue_t * ) xQueue )->uxQueueNumber = uxQueueNumber;\r
2032         }\r
2033 \r
2034 #endif /* configUSE_TRACE_FACILITY */\r
2035 /*-----------------------------------------------------------*/\r
2036 \r
2037 #if ( configUSE_TRACE_FACILITY == 1 )\r
2038 \r
2039         uint8_t ucQueueGetQueueType( QueueHandle_t xQueue )\r
2040         {\r
2041                 return ( ( Queue_t * ) xQueue )->ucQueueType;\r
2042         }\r
2043 \r
2044 #endif /* configUSE_TRACE_FACILITY */\r
2045 /*-----------------------------------------------------------*/\r
2046 \r
2047 #if( configUSE_MUTEXES == 1 )\r
2048 \r
2049         static UBaseType_t prvGetDisinheritPriorityAfterTimeout( const Queue_t * const pxQueue )\r
2050         {\r
2051         UBaseType_t uxHighestPriorityOfWaitingTasks;\r
2052 \r
2053                 /* If a task waiting for a mutex causes the mutex holder to inherit a\r
2054                 priority, but the waiting task times out, then the holder should\r
2055                 disinherit the priority - but only down to the highest priority of any\r
2056                 other tasks that are waiting for the same mutex.  For this purpose,\r
2057                 return the priority of the highest priority task that is waiting for the\r
2058                 mutex. */\r
2059                 if( listCURRENT_LIST_LENGTH( &( pxQueue->xTasksWaitingToReceive ) ) > 0U )\r
2060                 {\r
2061                         uxHighestPriorityOfWaitingTasks = ( UBaseType_t ) configMAX_PRIORITIES - ( UBaseType_t ) listGET_ITEM_VALUE_OF_HEAD_ENTRY( &( pxQueue->xTasksWaitingToReceive ) );\r
2062                 }\r
2063                 else\r
2064                 {\r
2065                         uxHighestPriorityOfWaitingTasks = tskIDLE_PRIORITY;\r
2066                 }\r
2067 \r
2068                 return uxHighestPriorityOfWaitingTasks;\r
2069         }\r
2070 \r
2071 #endif /* configUSE_MUTEXES */\r
2072 /*-----------------------------------------------------------*/\r
2073 \r
2074 static BaseType_t prvCopyDataToQueue( Queue_t * const pxQueue, const void *pvItemToQueue, const BaseType_t xPosition )\r
2075 {\r
2076 BaseType_t xReturn = pdFALSE;\r
2077 UBaseType_t uxMessagesWaiting;\r
2078 \r
2079         /* This function is called from a critical section. */\r
2080 \r
2081         uxMessagesWaiting = pxQueue->uxMessagesWaiting;\r
2082 \r
2083         if( pxQueue->uxItemSize == ( UBaseType_t ) 0 )\r
2084         {\r
2085                 #if ( configUSE_MUTEXES == 1 )\r
2086                 {\r
2087                         if( pxQueue->uxQueueType == queueQUEUE_IS_MUTEX )\r
2088                         {\r
2089                                 /* The mutex is no longer being held. */\r
2090                                 xReturn = xTaskPriorityDisinherit( pxQueue->u.xSemaphore.xMutexHolder );\r
2091                                 pxQueue->u.xSemaphore.xMutexHolder = NULL;\r
2092                         }\r
2093                         else\r
2094                         {\r
2095                                 mtCOVERAGE_TEST_MARKER();\r
2096                         }\r
2097                 }\r
2098                 #endif /* configUSE_MUTEXES */\r
2099         }\r
2100         else if( xPosition == queueSEND_TO_BACK )\r
2101         {\r
2102                 ( 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
2103                 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
2104                 if( pxQueue->pcWriteTo >= pxQueue->u.xQueue.pcTail ) /*lint !e946 MISRA exception justified as comparison of pointers is the cleanest solution. */\r
2105                 {\r
2106                         pxQueue->pcWriteTo = pxQueue->pcHead;\r
2107                 }\r
2108                 else\r
2109                 {\r
2110                         mtCOVERAGE_TEST_MARKER();\r
2111                 }\r
2112         }\r
2113         else\r
2114         {\r
2115                 ( 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
2116                 pxQueue->u.xQueue.pcReadFrom -= pxQueue->uxItemSize;\r
2117                 if( pxQueue->u.xQueue.pcReadFrom < pxQueue->pcHead ) /*lint !e946 MISRA exception justified as comparison of pointers is the cleanest solution. */\r
2118                 {\r
2119                         pxQueue->u.xQueue.pcReadFrom = ( pxQueue->u.xQueue.pcTail - pxQueue->uxItemSize );\r
2120                 }\r
2121                 else\r
2122                 {\r
2123                         mtCOVERAGE_TEST_MARKER();\r
2124                 }\r
2125 \r
2126                 if( xPosition == queueOVERWRITE )\r
2127                 {\r
2128                         if( uxMessagesWaiting > ( UBaseType_t ) 0 )\r
2129                         {\r
2130                                 /* An item is not being added but overwritten, so subtract\r
2131                                 one from the recorded number of items in the queue so when\r
2132                                 one is added again below the number of recorded items remains\r
2133                                 correct. */\r
2134                                 --uxMessagesWaiting;\r
2135                         }\r
2136                         else\r
2137                         {\r
2138                                 mtCOVERAGE_TEST_MARKER();\r
2139                         }\r
2140                 }\r
2141                 else\r
2142                 {\r
2143                         mtCOVERAGE_TEST_MARKER();\r
2144                 }\r
2145         }\r
2146 \r
2147         pxQueue->uxMessagesWaiting = uxMessagesWaiting + ( UBaseType_t ) 1;\r
2148 \r
2149         return xReturn;\r
2150 }\r
2151 /*-----------------------------------------------------------*/\r
2152 \r
2153 static void prvCopyDataFromQueue( Queue_t * const pxQueue, void * const pvBuffer )\r
2154 {\r
2155         if( pxQueue->uxItemSize != ( UBaseType_t ) 0 )\r
2156         {\r
2157                 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
2158                 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
2159                 {\r
2160                         pxQueue->u.xQueue.pcReadFrom = pxQueue->pcHead;\r
2161                 }\r
2162                 else\r
2163                 {\r
2164                         mtCOVERAGE_TEST_MARKER();\r
2165                 }\r
2166                 ( 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
2167         }\r
2168 }\r
2169 /*-----------------------------------------------------------*/\r
2170 \r
2171 static void prvUnlockQueue( Queue_t * const pxQueue )\r
2172 {\r
2173         /* THIS FUNCTION MUST BE CALLED WITH THE SCHEDULER SUSPENDED. */\r
2174 \r
2175         /* The lock counts contains the number of extra data items placed or\r
2176         removed from the queue while the queue was locked.  When a queue is\r
2177         locked items can be added or removed, but the event lists cannot be\r
2178         updated. */\r
2179         taskENTER_CRITICAL();\r
2180         {\r
2181                 int8_t cTxLock = pxQueue->cTxLock;\r
2182 \r
2183                 /* See if data was added to the queue while it was locked. */\r
2184                 while( cTxLock > queueLOCKED_UNMODIFIED )\r
2185                 {\r
2186                         /* Data was posted while the queue was locked.  Are any tasks\r
2187                         blocked waiting for data to become available? */\r
2188                         #if ( configUSE_QUEUE_SETS == 1 )\r
2189                         {\r
2190                                 if( pxQueue->pxQueueSetContainer != NULL )\r
2191                                 {\r
2192                                         if( prvNotifyQueueSetContainer( pxQueue ) != pdFALSE )\r
2193                                         {\r
2194                                                 /* The queue is a member of a queue set, and posting to\r
2195                                                 the queue set caused a higher priority task to unblock.\r
2196                                                 A context switch is required. */\r
2197                                                 vTaskMissedYield();\r
2198                                         }\r
2199                                         else\r
2200                                         {\r
2201                                                 mtCOVERAGE_TEST_MARKER();\r
2202                                         }\r
2203                                 }\r
2204                                 else\r
2205                                 {\r
2206                                         /* Tasks that are removed from the event list will get\r
2207                                         added to the pending ready list as the scheduler is still\r
2208                                         suspended. */\r
2209                                         if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE )\r
2210                                         {\r
2211                                                 if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE )\r
2212                                                 {\r
2213                                                         /* The task waiting has a higher priority so record that a\r
2214                                                         context switch is required. */\r
2215                                                         vTaskMissedYield();\r
2216                                                 }\r
2217                                                 else\r
2218                                                 {\r
2219                                                         mtCOVERAGE_TEST_MARKER();\r
2220                                                 }\r
2221                                         }\r
2222                                         else\r
2223                                         {\r
2224                                                 break;\r
2225                                         }\r
2226                                 }\r
2227                         }\r
2228                         #else /* configUSE_QUEUE_SETS */\r
2229                         {\r
2230                                 /* Tasks that are removed from the event list will get added to\r
2231                                 the pending ready list as the scheduler is still suspended. */\r
2232                                 if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE )\r
2233                                 {\r
2234                                         if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE )\r
2235                                         {\r
2236                                                 /* The task waiting has a higher priority so record that\r
2237                                                 a context switch is required. */\r
2238                                                 vTaskMissedYield();\r
2239                                         }\r
2240                                         else\r
2241                                         {\r
2242                                                 mtCOVERAGE_TEST_MARKER();\r
2243                                         }\r
2244                                 }\r
2245                                 else\r
2246                                 {\r
2247                                         break;\r
2248                                 }\r
2249                         }\r
2250                         #endif /* configUSE_QUEUE_SETS */\r
2251 \r
2252                         --cTxLock;\r
2253                 }\r
2254 \r
2255                 pxQueue->cTxLock = queueUNLOCKED;\r
2256         }\r
2257         taskEXIT_CRITICAL();\r
2258 \r
2259         /* Do the same for the Rx lock. */\r
2260         taskENTER_CRITICAL();\r
2261         {\r
2262                 int8_t cRxLock = pxQueue->cRxLock;\r
2263 \r
2264                 while( cRxLock > queueLOCKED_UNMODIFIED )\r
2265                 {\r
2266                         if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) == pdFALSE )\r
2267                         {\r
2268                                 if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) != pdFALSE )\r
2269                                 {\r
2270                                         vTaskMissedYield();\r
2271                                 }\r
2272                                 else\r
2273                                 {\r
2274                                         mtCOVERAGE_TEST_MARKER();\r
2275                                 }\r
2276 \r
2277                                 --cRxLock;\r
2278                         }\r
2279                         else\r
2280                         {\r
2281                                 break;\r
2282                         }\r
2283                 }\r
2284 \r
2285                 pxQueue->cRxLock = queueUNLOCKED;\r
2286         }\r
2287         taskEXIT_CRITICAL();\r
2288 }\r
2289 /*-----------------------------------------------------------*/\r
2290 \r
2291 static BaseType_t prvIsQueueEmpty( const Queue_t *pxQueue )\r
2292 {\r
2293 BaseType_t xReturn;\r
2294 \r
2295         taskENTER_CRITICAL();\r
2296         {\r
2297                 if( pxQueue->uxMessagesWaiting == ( UBaseType_t )  0 )\r
2298                 {\r
2299                         xReturn = pdTRUE;\r
2300                 }\r
2301                 else\r
2302                 {\r
2303                         xReturn = pdFALSE;\r
2304                 }\r
2305         }\r
2306         taskEXIT_CRITICAL();\r
2307 \r
2308         return xReturn;\r
2309 }\r
2310 /*-----------------------------------------------------------*/\r
2311 \r
2312 BaseType_t xQueueIsQueueEmptyFromISR( const QueueHandle_t xQueue )\r
2313 {\r
2314 BaseType_t xReturn;\r
2315 Queue_t * const pxQueue = xQueue;\r
2316 \r
2317         configASSERT( pxQueue );\r
2318         if( pxQueue->uxMessagesWaiting == ( UBaseType_t ) 0 )\r
2319         {\r
2320                 xReturn = pdTRUE;\r
2321         }\r
2322         else\r
2323         {\r
2324                 xReturn = pdFALSE;\r
2325         }\r
2326 \r
2327         return xReturn;\r
2328 } /*lint !e818 xQueue could not be pointer to const because it is a typedef. */\r
2329 /*-----------------------------------------------------------*/\r
2330 \r
2331 static BaseType_t prvIsQueueFull( const Queue_t *pxQueue )\r
2332 {\r
2333 BaseType_t xReturn;\r
2334 \r
2335         taskENTER_CRITICAL();\r
2336         {\r
2337                 if( pxQueue->uxMessagesWaiting == pxQueue->uxLength )\r
2338                 {\r
2339                         xReturn = pdTRUE;\r
2340                 }\r
2341                 else\r
2342                 {\r
2343                         xReturn = pdFALSE;\r
2344                 }\r
2345         }\r
2346         taskEXIT_CRITICAL();\r
2347 \r
2348         return xReturn;\r
2349 }\r
2350 /*-----------------------------------------------------------*/\r
2351 \r
2352 BaseType_t xQueueIsQueueFullFromISR( const QueueHandle_t xQueue )\r
2353 {\r
2354 BaseType_t xReturn;\r
2355 Queue_t * const pxQueue = xQueue;\r
2356 \r
2357         configASSERT( pxQueue );\r
2358         if( pxQueue->uxMessagesWaiting == pxQueue->uxLength )\r
2359         {\r
2360                 xReturn = pdTRUE;\r
2361         }\r
2362         else\r
2363         {\r
2364                 xReturn = pdFALSE;\r
2365         }\r
2366 \r
2367         return xReturn;\r
2368 } /*lint !e818 xQueue could not be pointer to const because it is a typedef. */\r
2369 /*-----------------------------------------------------------*/\r
2370 \r
2371 #if ( configUSE_CO_ROUTINES == 1 )\r
2372 \r
2373         BaseType_t xQueueCRSend( QueueHandle_t xQueue, const void *pvItemToQueue, TickType_t xTicksToWait )\r
2374         {\r
2375         BaseType_t xReturn;\r
2376         Queue_t * const pxQueue = xQueue;\r
2377 \r
2378                 /* If the queue is already full we may have to block.  A critical section\r
2379                 is required to prevent an interrupt removing something from the queue\r
2380                 between the check to see if the queue is full and blocking on the queue. */\r
2381                 portDISABLE_INTERRUPTS();\r
2382                 {\r
2383                         if( prvIsQueueFull( pxQueue ) != pdFALSE )\r
2384                         {\r
2385                                 /* The queue is full - do we want to block or just leave without\r
2386                                 posting? */\r
2387                                 if( xTicksToWait > ( TickType_t ) 0 )\r
2388                                 {\r
2389                                         /* As this is called from a coroutine we cannot block directly, but\r
2390                                         return indicating that we need to block. */\r
2391                                         vCoRoutineAddToDelayedList( xTicksToWait, &( pxQueue->xTasksWaitingToSend ) );\r
2392                                         portENABLE_INTERRUPTS();\r
2393                                         return errQUEUE_BLOCKED;\r
2394                                 }\r
2395                                 else\r
2396                                 {\r
2397                                         portENABLE_INTERRUPTS();\r
2398                                         return errQUEUE_FULL;\r
2399                                 }\r
2400                         }\r
2401                 }\r
2402                 portENABLE_INTERRUPTS();\r
2403 \r
2404                 portDISABLE_INTERRUPTS();\r
2405                 {\r
2406                         if( pxQueue->uxMessagesWaiting < pxQueue->uxLength )\r
2407                         {\r
2408                                 /* There is room in the queue, copy the data into the queue. */\r
2409                                 prvCopyDataToQueue( pxQueue, pvItemToQueue, queueSEND_TO_BACK );\r
2410                                 xReturn = pdPASS;\r
2411 \r
2412                                 /* Were any co-routines waiting for data to become available? */\r
2413                                 if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE )\r
2414                                 {\r
2415                                         /* In this instance the co-routine could be placed directly\r
2416                                         into the ready list as we are within a critical section.\r
2417                                         Instead the same pending ready list mechanism is used as if\r
2418                                         the event were caused from within an interrupt. */\r
2419                                         if( xCoRoutineRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE )\r
2420                                         {\r
2421                                                 /* The co-routine waiting has a higher priority so record\r
2422                                                 that a yield might be appropriate. */\r
2423                                                 xReturn = errQUEUE_YIELD;\r
2424                                         }\r
2425                                         else\r
2426                                         {\r
2427                                                 mtCOVERAGE_TEST_MARKER();\r
2428                                         }\r
2429                                 }\r
2430                                 else\r
2431                                 {\r
2432                                         mtCOVERAGE_TEST_MARKER();\r
2433                                 }\r
2434                         }\r
2435                         else\r
2436                         {\r
2437                                 xReturn = errQUEUE_FULL;\r
2438                         }\r
2439                 }\r
2440                 portENABLE_INTERRUPTS();\r
2441 \r
2442                 return xReturn;\r
2443         }\r
2444 \r
2445 #endif /* configUSE_CO_ROUTINES */\r
2446 /*-----------------------------------------------------------*/\r
2447 \r
2448 #if ( configUSE_CO_ROUTINES == 1 )\r
2449 \r
2450         BaseType_t xQueueCRReceive( QueueHandle_t xQueue, void *pvBuffer, TickType_t xTicksToWait )\r
2451         {\r
2452         BaseType_t xReturn;\r
2453         Queue_t * const pxQueue = xQueue;\r
2454 \r
2455                 /* If the queue is already empty we may have to block.  A critical section\r
2456                 is required to prevent an interrupt adding something to the queue\r
2457                 between the check to see if the queue is empty and blocking on the queue. */\r
2458                 portDISABLE_INTERRUPTS();\r
2459                 {\r
2460                         if( pxQueue->uxMessagesWaiting == ( UBaseType_t ) 0 )\r
2461                         {\r
2462                                 /* There are no messages in the queue, do we want to block or just\r
2463                                 leave with nothing? */\r
2464                                 if( xTicksToWait > ( TickType_t ) 0 )\r
2465                                 {\r
2466                                         /* As this is a co-routine we cannot block directly, but return\r
2467                                         indicating that we need to block. */\r
2468                                         vCoRoutineAddToDelayedList( xTicksToWait, &( pxQueue->xTasksWaitingToReceive ) );\r
2469                                         portENABLE_INTERRUPTS();\r
2470                                         return errQUEUE_BLOCKED;\r
2471                                 }\r
2472                                 else\r
2473                                 {\r
2474                                         portENABLE_INTERRUPTS();\r
2475                                         return errQUEUE_FULL;\r
2476                                 }\r
2477                         }\r
2478                         else\r
2479                         {\r
2480                                 mtCOVERAGE_TEST_MARKER();\r
2481                         }\r
2482                 }\r
2483                 portENABLE_INTERRUPTS();\r
2484 \r
2485                 portDISABLE_INTERRUPTS();\r
2486                 {\r
2487                         if( pxQueue->uxMessagesWaiting > ( UBaseType_t ) 0 )\r
2488                         {\r
2489                                 /* Data is available from the queue. */\r
2490                                 pxQueue->u.xQueue.pcReadFrom += pxQueue->uxItemSize;\r
2491                                 if( pxQueue->u.xQueue.pcReadFrom >= pxQueue->u.xQueue.pcTail )\r
2492                                 {\r
2493                                         pxQueue->u.xQueue.pcReadFrom = pxQueue->pcHead;\r
2494                                 }\r
2495                                 else\r
2496                                 {\r
2497                                         mtCOVERAGE_TEST_MARKER();\r
2498                                 }\r
2499                                 --( pxQueue->uxMessagesWaiting );\r
2500                                 ( void ) memcpy( ( void * ) pvBuffer, ( void * ) pxQueue->u.xQueue.pcReadFrom, ( unsigned ) pxQueue->uxItemSize );\r
2501 \r
2502                                 xReturn = pdPASS;\r
2503 \r
2504                                 /* Were any co-routines waiting for space to become available? */\r
2505                                 if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) == pdFALSE )\r
2506                                 {\r
2507                                         /* In this instance the co-routine could be placed directly\r
2508                                         into the ready list as we are within a critical section.\r
2509                                         Instead the same pending ready list mechanism is used as if\r
2510                                         the event were caused from within an interrupt. */\r
2511                                         if( xCoRoutineRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) != pdFALSE )\r
2512                                         {\r
2513                                                 xReturn = errQUEUE_YIELD;\r
2514                                         }\r
2515                                         else\r
2516                                         {\r
2517                                                 mtCOVERAGE_TEST_MARKER();\r
2518                                         }\r
2519                                 }\r
2520                                 else\r
2521                                 {\r
2522                                         mtCOVERAGE_TEST_MARKER();\r
2523                                 }\r
2524                         }\r
2525                         else\r
2526                         {\r
2527                                 xReturn = pdFAIL;\r
2528                         }\r
2529                 }\r
2530                 portENABLE_INTERRUPTS();\r
2531 \r
2532                 return xReturn;\r
2533         }\r
2534 \r
2535 #endif /* configUSE_CO_ROUTINES */\r
2536 /*-----------------------------------------------------------*/\r
2537 \r
2538 #if ( configUSE_CO_ROUTINES == 1 )\r
2539 \r
2540         BaseType_t xQueueCRSendFromISR( QueueHandle_t xQueue, const void *pvItemToQueue, BaseType_t xCoRoutinePreviouslyWoken )\r
2541         {\r
2542         Queue_t * const pxQueue = xQueue;\r
2543 \r
2544                 /* Cannot block within an ISR so if there is no space on the queue then\r
2545                 exit without doing anything. */\r
2546                 if( pxQueue->uxMessagesWaiting < pxQueue->uxLength )\r
2547                 {\r
2548                         prvCopyDataToQueue( pxQueue, pvItemToQueue, queueSEND_TO_BACK );\r
2549 \r
2550                         /* We only want to wake one co-routine per ISR, so check that a\r
2551                         co-routine has not already been woken. */\r
2552                         if( xCoRoutinePreviouslyWoken == pdFALSE )\r
2553                         {\r
2554                                 if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE )\r
2555                                 {\r
2556                                         if( xCoRoutineRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE )\r
2557                                         {\r
2558                                                 return pdTRUE;\r
2559                                         }\r
2560                                         else\r
2561                                         {\r
2562                                                 mtCOVERAGE_TEST_MARKER();\r
2563                                         }\r
2564                                 }\r
2565                                 else\r
2566                                 {\r
2567                                         mtCOVERAGE_TEST_MARKER();\r
2568                                 }\r
2569                         }\r
2570                         else\r
2571                         {\r
2572                                 mtCOVERAGE_TEST_MARKER();\r
2573                         }\r
2574                 }\r
2575                 else\r
2576                 {\r
2577                         mtCOVERAGE_TEST_MARKER();\r
2578                 }\r
2579 \r
2580                 return xCoRoutinePreviouslyWoken;\r
2581         }\r
2582 \r
2583 #endif /* configUSE_CO_ROUTINES */\r
2584 /*-----------------------------------------------------------*/\r
2585 \r
2586 #if ( configUSE_CO_ROUTINES == 1 )\r
2587 \r
2588         BaseType_t xQueueCRReceiveFromISR( QueueHandle_t xQueue, void *pvBuffer, BaseType_t *pxCoRoutineWoken )\r
2589         {\r
2590         BaseType_t xReturn;\r
2591         Queue_t * const pxQueue = xQueue;\r
2592 \r
2593                 /* We cannot block from an ISR, so check there is data available. If\r
2594                 not then just leave without doing anything. */\r
2595                 if( pxQueue->uxMessagesWaiting > ( UBaseType_t ) 0 )\r
2596                 {\r
2597                         /* Copy the data from the queue. */\r
2598                         pxQueue->u.xQueue.pcReadFrom += pxQueue->uxItemSize;\r
2599                         if( pxQueue->u.xQueue.pcReadFrom >= pxQueue->u.xQueue.pcTail )\r
2600                         {\r
2601                                 pxQueue->u.xQueue.pcReadFrom = pxQueue->pcHead;\r
2602                         }\r
2603                         else\r
2604                         {\r
2605                                 mtCOVERAGE_TEST_MARKER();\r
2606                         }\r
2607                         --( pxQueue->uxMessagesWaiting );\r
2608                         ( void ) memcpy( ( void * ) pvBuffer, ( void * ) pxQueue->u.xQueue.pcReadFrom, ( unsigned ) pxQueue->uxItemSize );\r
2609 \r
2610                         if( ( *pxCoRoutineWoken ) == pdFALSE )\r
2611                         {\r
2612                                 if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) == pdFALSE )\r
2613                                 {\r
2614                                         if( xCoRoutineRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) != pdFALSE )\r
2615                                         {\r
2616                                                 *pxCoRoutineWoken = pdTRUE;\r
2617                                         }\r
2618                                         else\r
2619                                         {\r
2620                                                 mtCOVERAGE_TEST_MARKER();\r
2621                                         }\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                         xReturn = pdPASS;\r
2634                 }\r
2635                 else\r
2636                 {\r
2637                         xReturn = pdFAIL;\r
2638                 }\r
2639 \r
2640                 return xReturn;\r
2641         }\r
2642 \r
2643 #endif /* configUSE_CO_ROUTINES */\r
2644 /*-----------------------------------------------------------*/\r
2645 \r
2646 #if ( configQUEUE_REGISTRY_SIZE > 0 )\r
2647 \r
2648         void vQueueAddToRegistry( QueueHandle_t xQueue, const char *pcQueueName ) /*lint !e971 Unqualified char types are allowed for strings and single characters only. */\r
2649         {\r
2650         UBaseType_t ux;\r
2651 \r
2652                 /* See if there is an empty space in the registry.  A NULL name denotes\r
2653                 a free slot. */\r
2654                 for( ux = ( UBaseType_t ) 0U; ux < ( UBaseType_t ) configQUEUE_REGISTRY_SIZE; ux++ )\r
2655                 {\r
2656                         if( xQueueRegistry[ ux ].pcQueueName == NULL )\r
2657                         {\r
2658                                 /* Store the information on this queue. */\r
2659                                 xQueueRegistry[ ux ].pcQueueName = pcQueueName;\r
2660                                 xQueueRegistry[ ux ].xHandle = xQueue;\r
2661 \r
2662                                 traceQUEUE_REGISTRY_ADD( xQueue, pcQueueName );\r
2663                                 break;\r
2664                         }\r
2665                         else\r
2666                         {\r
2667                                 mtCOVERAGE_TEST_MARKER();\r
2668                         }\r
2669                 }\r
2670         }\r
2671 \r
2672 #endif /* configQUEUE_REGISTRY_SIZE */\r
2673 /*-----------------------------------------------------------*/\r
2674 \r
2675 #if ( configQUEUE_REGISTRY_SIZE > 0 )\r
2676 \r
2677         const char *pcQueueGetName( QueueHandle_t xQueue ) /*lint !e971 Unqualified char types are allowed for strings and single characters only. */\r
2678         {\r
2679         UBaseType_t ux;\r
2680         const char *pcReturn = NULL; /*lint !e971 Unqualified char types are allowed for strings and single characters only. */\r
2681 \r
2682                 /* Note there is nothing here to protect against another task adding or\r
2683                 removing entries from the registry while it is being searched. */\r
2684                 for( ux = ( UBaseType_t ) 0U; ux < ( UBaseType_t ) configQUEUE_REGISTRY_SIZE; ux++ )\r
2685                 {\r
2686                         if( xQueueRegistry[ ux ].xHandle == xQueue )\r
2687                         {\r
2688                                 pcReturn = xQueueRegistry[ ux ].pcQueueName;\r
2689                                 break;\r
2690                         }\r
2691                         else\r
2692                         {\r
2693                                 mtCOVERAGE_TEST_MARKER();\r
2694                         }\r
2695                 }\r
2696 \r
2697                 return pcReturn;\r
2698         } /*lint !e818 xQueue cannot be a pointer to const because it is a typedef. */\r
2699 \r
2700 #endif /* configQUEUE_REGISTRY_SIZE */\r
2701 /*-----------------------------------------------------------*/\r
2702 \r
2703 #if ( configQUEUE_REGISTRY_SIZE > 0 )\r
2704 \r
2705         void vQueueUnregisterQueue( QueueHandle_t xQueue )\r
2706         {\r
2707         UBaseType_t ux;\r
2708 \r
2709                 /* See if the handle of the queue being unregistered in actually in the\r
2710                 registry. */\r
2711                 for( ux = ( UBaseType_t ) 0U; ux < ( UBaseType_t ) configQUEUE_REGISTRY_SIZE; ux++ )\r
2712                 {\r
2713                         if( xQueueRegistry[ ux ].xHandle == xQueue )\r
2714                         {\r
2715                                 /* Set the name to NULL to show that this slot if free again. */\r
2716                                 xQueueRegistry[ ux ].pcQueueName = NULL;\r
2717 \r
2718                                 /* Set the handle to NULL to ensure the same queue handle cannot\r
2719                                 appear in the registry twice if it is added, removed, then\r
2720                                 added again. */\r
2721                                 xQueueRegistry[ ux ].xHandle = ( QueueHandle_t ) 0;\r
2722                                 break;\r
2723                         }\r
2724                         else\r
2725                         {\r
2726                                 mtCOVERAGE_TEST_MARKER();\r
2727                         }\r
2728                 }\r
2729 \r
2730         } /*lint !e818 xQueue could not be pointer to const because it is a typedef. */\r
2731 \r
2732 #endif /* configQUEUE_REGISTRY_SIZE */\r
2733 /*-----------------------------------------------------------*/\r
2734 \r
2735 #if ( configUSE_TIMERS == 1 )\r
2736 \r
2737         void vQueueWaitForMessageRestricted( QueueHandle_t xQueue, TickType_t xTicksToWait, const BaseType_t xWaitIndefinitely )\r
2738         {\r
2739         Queue_t * const pxQueue = xQueue;\r
2740 \r
2741                 /* This function should not be called by application code hence the\r
2742                 'Restricted' in its name.  It is not part of the public API.  It is\r
2743                 designed for use by kernel code, and has special calling requirements.\r
2744                 It can result in vListInsert() being called on a list that can only\r
2745                 possibly ever have one item in it, so the list will be fast, but even\r
2746                 so it should be called with the scheduler locked and not from a critical\r
2747                 section. */\r
2748 \r
2749                 /* Only do anything if there are no messages in the queue.  This function\r
2750                 will not actually cause the task to block, just place it on a blocked\r
2751                 list.  It will not block until the scheduler is unlocked - at which\r
2752                 time a yield will be performed.  If an item is added to the queue while\r
2753                 the queue is locked, and the calling task blocks on the queue, then the\r
2754                 calling task will be immediately unblocked when the queue is unlocked. */\r
2755                 prvLockQueue( pxQueue );\r
2756                 if( pxQueue->uxMessagesWaiting == ( UBaseType_t ) 0U )\r
2757                 {\r
2758                         /* There is nothing in the queue, block for the specified period. */\r
2759                         vTaskPlaceOnEventListRestricted( &( pxQueue->xTasksWaitingToReceive ), xTicksToWait, xWaitIndefinitely );\r
2760                 }\r
2761                 else\r
2762                 {\r
2763                         mtCOVERAGE_TEST_MARKER();\r
2764                 }\r
2765                 prvUnlockQueue( pxQueue );\r
2766         }\r
2767 \r
2768 #endif /* configUSE_TIMERS */\r
2769 /*-----------------------------------------------------------*/\r
2770 \r
2771 #if( ( configUSE_QUEUE_SETS == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) )\r
2772 \r
2773         QueueSetHandle_t xQueueCreateSet( const UBaseType_t uxEventQueueLength )\r
2774         {\r
2775         QueueSetHandle_t pxQueue;\r
2776 \r
2777                 pxQueue = xQueueGenericCreate( uxEventQueueLength, ( UBaseType_t ) sizeof( Queue_t * ), queueQUEUE_TYPE_SET );\r
2778 \r
2779                 return pxQueue;\r
2780         }\r
2781 \r
2782 #endif /* configUSE_QUEUE_SETS */\r
2783 /*-----------------------------------------------------------*/\r
2784 \r
2785 #if ( configUSE_QUEUE_SETS == 1 )\r
2786 \r
2787         BaseType_t xQueueAddToSet( QueueSetMemberHandle_t xQueueOrSemaphore, QueueSetHandle_t xQueueSet )\r
2788         {\r
2789         BaseType_t xReturn;\r
2790 \r
2791                 taskENTER_CRITICAL();\r
2792                 {\r
2793                         if( ( ( Queue_t * ) xQueueOrSemaphore )->pxQueueSetContainer != NULL )\r
2794                         {\r
2795                                 /* Cannot add a queue/semaphore to more than one queue set. */\r
2796                                 xReturn = pdFAIL;\r
2797                         }\r
2798                         else if( ( ( Queue_t * ) xQueueOrSemaphore )->uxMessagesWaiting != ( UBaseType_t ) 0 )\r
2799                         {\r
2800                                 /* Cannot add a queue/semaphore to a queue set if there are already\r
2801                                 items in the queue/semaphore. */\r
2802                                 xReturn = pdFAIL;\r
2803                         }\r
2804                         else\r
2805                         {\r
2806                                 ( ( Queue_t * ) xQueueOrSemaphore )->pxQueueSetContainer = xQueueSet;\r
2807                                 xReturn = pdPASS;\r
2808                         }\r
2809                 }\r
2810                 taskEXIT_CRITICAL();\r
2811 \r
2812                 return xReturn;\r
2813         }\r
2814 \r
2815 #endif /* configUSE_QUEUE_SETS */\r
2816 /*-----------------------------------------------------------*/\r
2817 \r
2818 #if ( configUSE_QUEUE_SETS == 1 )\r
2819 \r
2820         BaseType_t xQueueRemoveFromSet( QueueSetMemberHandle_t xQueueOrSemaphore, QueueSetHandle_t xQueueSet )\r
2821         {\r
2822         BaseType_t xReturn;\r
2823         Queue_t * const pxQueueOrSemaphore = ( Queue_t * ) xQueueOrSemaphore;\r
2824 \r
2825                 if( pxQueueOrSemaphore->pxQueueSetContainer != xQueueSet )\r
2826                 {\r
2827                         /* The queue was not a member of the set. */\r
2828                         xReturn = pdFAIL;\r
2829                 }\r
2830                 else if( pxQueueOrSemaphore->uxMessagesWaiting != ( UBaseType_t ) 0 )\r
2831                 {\r
2832                         /* It is dangerous to remove a queue from a set when the queue is\r
2833                         not empty because the queue set will still hold pending events for\r
2834                         the queue. */\r
2835                         xReturn = pdFAIL;\r
2836                 }\r
2837                 else\r
2838                 {\r
2839                         taskENTER_CRITICAL();\r
2840                         {\r
2841                                 /* The queue is no longer contained in the set. */\r
2842                                 pxQueueOrSemaphore->pxQueueSetContainer = NULL;\r
2843                         }\r
2844                         taskEXIT_CRITICAL();\r
2845                         xReturn = pdPASS;\r
2846                 }\r
2847 \r
2848                 return xReturn;\r
2849         } /*lint !e818 xQueueSet could not be declared as pointing to const as it is a typedef. */\r
2850 \r
2851 #endif /* configUSE_QUEUE_SETS */\r
2852 /*-----------------------------------------------------------*/\r
2853 \r
2854 #if ( configUSE_QUEUE_SETS == 1 )\r
2855 \r
2856         QueueSetMemberHandle_t xQueueSelectFromSet( QueueSetHandle_t xQueueSet, TickType_t const xTicksToWait )\r
2857         {\r
2858         QueueSetMemberHandle_t xReturn = NULL;\r
2859 \r
2860                 ( void ) xQueueReceive( ( QueueHandle_t ) xQueueSet, &xReturn, xTicksToWait ); /*lint !e961 Casting from one typedef to another is not redundant. */\r
2861                 return xReturn;\r
2862         }\r
2863 \r
2864 #endif /* configUSE_QUEUE_SETS */\r
2865 /*-----------------------------------------------------------*/\r
2866 \r
2867 #if ( configUSE_QUEUE_SETS == 1 )\r
2868 \r
2869         QueueSetMemberHandle_t xQueueSelectFromSetFromISR( QueueSetHandle_t xQueueSet )\r
2870         {\r
2871         QueueSetMemberHandle_t xReturn = NULL;\r
2872 \r
2873                 ( void ) xQueueReceiveFromISR( ( QueueHandle_t ) xQueueSet, &xReturn, NULL ); /*lint !e961 Casting from one typedef to another is not redundant. */\r
2874                 return xReturn;\r
2875         }\r
2876 \r
2877 #endif /* configUSE_QUEUE_SETS */\r
2878 /*-----------------------------------------------------------*/\r
2879 \r
2880 #if ( configUSE_QUEUE_SETS == 1 )\r
2881 \r
2882         static BaseType_t prvNotifyQueueSetContainer( const Queue_t * const pxQueue )\r
2883         {\r
2884         Queue_t *pxQueueSetContainer = pxQueue->pxQueueSetContainer;\r
2885         BaseType_t xReturn = pdFALSE;\r
2886 \r
2887                 /* This function must be called form a critical section. */\r
2888 \r
2889                 configASSERT( pxQueueSetContainer );\r
2890                 configASSERT( pxQueueSetContainer->uxMessagesWaiting < pxQueueSetContainer->uxLength );\r
2891 \r
2892                 if( pxQueueSetContainer->uxMessagesWaiting < pxQueueSetContainer->uxLength )\r
2893                 {\r
2894                         const int8_t cTxLock = pxQueueSetContainer->cTxLock;\r
2895 \r
2896                         traceQUEUE_SEND( pxQueueSetContainer );\r
2897 \r
2898                         /* The data copied is the handle of the queue that contains data. */\r
2899                         xReturn = prvCopyDataToQueue( pxQueueSetContainer, &pxQueue, queueSEND_TO_BACK );\r
2900 \r
2901                         if( cTxLock == queueUNLOCKED )\r
2902                         {\r
2903                                 if( listLIST_IS_EMPTY( &( pxQueueSetContainer->xTasksWaitingToReceive ) ) == pdFALSE )\r
2904                                 {\r
2905                                         if( xTaskRemoveFromEventList( &( pxQueueSetContainer->xTasksWaitingToReceive ) ) != pdFALSE )\r
2906                                         {\r
2907                                                 /* The task waiting has a higher priority. */\r
2908                                                 xReturn = pdTRUE;\r
2909                                         }\r
2910                                         else\r
2911                                         {\r
2912                                                 mtCOVERAGE_TEST_MARKER();\r
2913                                         }\r
2914                                 }\r
2915                                 else\r
2916                                 {\r
2917                                         mtCOVERAGE_TEST_MARKER();\r
2918                                 }\r
2919                         }\r
2920                         else\r
2921                         {\r
2922                                 pxQueueSetContainer->cTxLock = ( int8_t ) ( cTxLock + 1 );\r
2923                         }\r
2924                 }\r
2925                 else\r
2926                 {\r
2927                         mtCOVERAGE_TEST_MARKER();\r
2928                 }\r
2929 \r
2930                 return xReturn;\r
2931         }\r
2932 \r
2933 #endif /* configUSE_QUEUE_SETS */\r
2934 \r
2935 \r
2936 \r
2937 \r
2938 \r
2939 \r
2940 \r
2941 \r
2942 \r
2943 \r
2944 \r
2945 \r