]> git.sur5r.net Git - freertos/blob - Source/queue.c
c2197b7c2e1188331db814ea94716cc6143d4a5c
[freertos] / Source / queue.c
1 /*\r
2     FreeRTOS V7.0.1 - Copyright (C) 2011 Real Time Engineers Ltd.\r
3         \r
4 \r
5         FreeRTOS supports many tools and architectures. V7.0.0 is sponsored by:\r
6         Atollic AB - Atollic provides professional embedded systems development \r
7         tools for C/C++ development, code analysis and test automation.  \r
8         See http://www.atollic.com\r
9         \r
10 \r
11     ***************************************************************************\r
12      *                                                                       *\r
13      *    FreeRTOS tutorial books are available in pdf and paperback.        *\r
14      *    Complete, revised, and edited pdf reference manuals are also       *\r
15      *    available.                                                         *\r
16      *                                                                       *\r
17      *    Purchasing FreeRTOS documentation will not only help you, by       *\r
18      *    ensuring you get running as quickly as possible and with an        *\r
19      *    in-depth knowledge of how to use FreeRTOS, it will also help       *\r
20      *    the FreeRTOS project to continue with its mission of providing     *\r
21      *    professional grade, cross platform, de facto standard solutions    *\r
22      *    for microcontrollers - completely free of charge!                  *\r
23      *                                                                       *\r
24      *    >>> See http://www.FreeRTOS.org/Documentation for details. <<<     *\r
25      *                                                                       *\r
26      *    Thank you for using FreeRTOS, and thank you for your support!      *\r
27      *                                                                       *\r
28     ***************************************************************************\r
29 \r
30 \r
31     This file is part of the FreeRTOS distribution.\r
32 \r
33     FreeRTOS is free software; you can redistribute it and/or modify it under\r
34     the terms of the GNU General Public License (version 2) as published by the\r
35     Free Software Foundation AND MODIFIED BY the FreeRTOS exception.\r
36     >>>NOTE<<< The modification to the GPL is included to allow you to\r
37     distribute a combined work that includes FreeRTOS without being obliged to\r
38     provide the source code for proprietary components outside of the FreeRTOS\r
39     kernel.  FreeRTOS is distributed in the hope that it will be useful, but\r
40     WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\r
41     or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for\r
42     more details. You should have received a copy of the GNU General Public\r
43     License and the FreeRTOS license exception along with FreeRTOS; if not it\r
44     can be viewed here: http://www.freertos.org/a00114.html and also obtained\r
45     by writing to Richard Barry, contact details for whom are available on the\r
46     FreeRTOS WEB site.\r
47 \r
48     1 tab == 4 spaces!\r
49 \r
50     http://www.FreeRTOS.org - Documentation, latest information, license and\r
51     contact details.\r
52 \r
53     http://www.SafeRTOS.com - A version that is certified for use in safety\r
54     critical systems.\r
55 \r
56     http://www.OpenRTOS.com - Commercial support, development, porting,\r
57     licensing and training services.\r
58 */\r
59 \r
60 #include <stdlib.h>\r
61 #include <string.h>\r
62 \r
63 /* Defining MPU_WRAPPERS_INCLUDED_FROM_API_FILE prevents task.h from redefining\r
64 all the API functions to use the MPU wrappers.  That should only be done when\r
65 task.h is included from an application file. */\r
66 #define MPU_WRAPPERS_INCLUDED_FROM_API_FILE\r
67 \r
68 #include "FreeRTOS.h"\r
69 #include "task.h"\r
70 \r
71 #if ( configUSE_CO_ROUTINES == 1 )\r
72         #include "croutine.h"\r
73 #endif\r
74 \r
75 #undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE\r
76 \r
77 /*-----------------------------------------------------------\r
78  * PUBLIC LIST API documented in list.h\r
79  *----------------------------------------------------------*/\r
80 \r
81 /* Constants used with the cRxLock and cTxLock structure members. */\r
82 #define queueUNLOCKED                                   ( ( signed portBASE_TYPE ) -1 )\r
83 #define queueLOCKED_UNMODIFIED                  ( ( signed portBASE_TYPE ) 0 )\r
84 \r
85 #define queueERRONEOUS_UNBLOCK                  ( -1 )\r
86 \r
87 /* For internal use only. */\r
88 #define queueSEND_TO_BACK                               ( 0 )\r
89 #define queueSEND_TO_FRONT                              ( 1 )\r
90 \r
91 /* Effectively make a union out of the xQUEUE structure. */\r
92 #define pxMutexHolder                                   pcTail\r
93 #define uxQueueType                                             pcHead\r
94 #define uxRecursiveCallCount                    pcReadFrom\r
95 #define queueQUEUE_IS_MUTEX                             NULL\r
96 \r
97 /* Semaphores do not actually store or copy data, so have an items size of\r
98 zero. */\r
99 #define queueSEMAPHORE_QUEUE_ITEM_LENGTH ( ( unsigned portBASE_TYPE ) 0 )\r
100 #define queueDONT_BLOCK                                  ( ( portTickType ) 0U )\r
101 #define queueMUTEX_GIVE_BLOCK_TIME               ( ( portTickType ) 0U )\r
102 \r
103 /*\r
104  * Definition of the queue used by the scheduler.\r
105  * Items are queued by copy, not reference.\r
106  */\r
107 typedef struct QueueDefinition\r
108 {\r
109         signed char *pcHead;                            /*< Points to the beginning of the queue storage area. */\r
110         signed char *pcTail;                            /*< Points to the byte at the end of the queue storage area.  Once more byte is allocated than necessary to store the queue items, this is used as a marker. */\r
111 \r
112         signed char *pcWriteTo;                         /*< Points to the free next place in the storage area. */\r
113         signed char *pcReadFrom;                        /*< Points to the last place that a queued item was read from. */\r
114 \r
115         xList xTasksWaitingToSend;                              /*< List of tasks that are blocked waiting to post onto this queue.  Stored in priority order. */\r
116         xList xTasksWaitingToReceive;                   /*< List of tasks that are blocked waiting to read from this queue.  Stored in priority order. */\r
117 \r
118         volatile unsigned portBASE_TYPE uxMessagesWaiting;/*< The number of items currently in the queue. */\r
119         unsigned portBASE_TYPE uxLength;                /*< The length of the queue defined as the number of items it will hold, not the number of bytes. */\r
120         unsigned portBASE_TYPE uxItemSize;              /*< The size of each items that the queue will hold. */\r
121 \r
122         signed portBASE_TYPE xRxLock;                   /*< Stores the number of items received from the queue (removed from the queue) while the queue was locked.  Set to queueUNLOCKED when the queue is not locked. */\r
123         signed portBASE_TYPE xTxLock;                   /*< Stores the number of items transmitted to the queue (added to the queue) while the queue was locked.  Set to queueUNLOCKED when the queue is not locked. */\r
124 \r
125 } xQUEUE;\r
126 /*-----------------------------------------------------------*/\r
127 \r
128 /*\r
129  * Inside this file xQueueHandle is a pointer to a xQUEUE structure.\r
130  * To keep the definition private the API header file defines it as a\r
131  * pointer to void.\r
132  */\r
133 typedef xQUEUE * xQueueHandle;\r
134 \r
135 /*\r
136  * Prototypes for public functions are included here so we don't have to\r
137  * include the API header file (as it defines xQueueHandle differently).  These\r
138  * functions are documented in the API header file.\r
139  */\r
140 xQueueHandle xQueueCreate( unsigned portBASE_TYPE uxQueueLength, unsigned portBASE_TYPE uxItemSize ) PRIVILEGED_FUNCTION;\r
141 signed portBASE_TYPE xQueueGenericSend( xQueueHandle xQueue, const void * const pvItemToQueue, portTickType xTicksToWait, portBASE_TYPE xCopyPosition ) PRIVILEGED_FUNCTION;\r
142 unsigned portBASE_TYPE uxQueueMessagesWaiting( const xQueueHandle pxQueue ) PRIVILEGED_FUNCTION;\r
143 void vQueueDelete( xQueueHandle xQueue ) PRIVILEGED_FUNCTION;\r
144 signed portBASE_TYPE xQueueGenericSendFromISR( xQueueHandle pxQueue, const void * const pvItemToQueue, signed portBASE_TYPE *pxHigherPriorityTaskWoken, portBASE_TYPE xCopyPosition ) PRIVILEGED_FUNCTION;\r
145 signed portBASE_TYPE xQueueGenericReceive( xQueueHandle pxQueue, void * const pvBuffer, portTickType xTicksToWait, portBASE_TYPE xJustPeeking ) PRIVILEGED_FUNCTION;\r
146 signed portBASE_TYPE xQueueReceiveFromISR( xQueueHandle pxQueue, void * const pvBuffer, signed portBASE_TYPE *pxTaskWoken ) PRIVILEGED_FUNCTION;\r
147 xQueueHandle xQueueCreateMutex( void ) PRIVILEGED_FUNCTION;\r
148 xQueueHandle xQueueCreateCountingSemaphore( unsigned portBASE_TYPE uxCountValue, unsigned portBASE_TYPE uxInitialCount ) PRIVILEGED_FUNCTION;\r
149 portBASE_TYPE xQueueTakeMutexRecursive( xQueueHandle xMutex, portTickType xBlockTime ) PRIVILEGED_FUNCTION;\r
150 portBASE_TYPE xQueueGiveMutexRecursive( xQueueHandle xMutex ) PRIVILEGED_FUNCTION;\r
151 signed portBASE_TYPE xQueueAltGenericSend( xQueueHandle pxQueue, const void * const pvItemToQueue, portTickType xTicksToWait, portBASE_TYPE xCopyPosition ) PRIVILEGED_FUNCTION;\r
152 signed portBASE_TYPE xQueueAltGenericReceive( xQueueHandle pxQueue, void * const pvBuffer, portTickType xTicksToWait, portBASE_TYPE xJustPeeking ) PRIVILEGED_FUNCTION;\r
153 signed portBASE_TYPE xQueueIsQueueEmptyFromISR( const xQueueHandle pxQueue ) PRIVILEGED_FUNCTION;\r
154 signed portBASE_TYPE xQueueIsQueueFullFromISR( const xQueueHandle pxQueue ) PRIVILEGED_FUNCTION;\r
155 unsigned portBASE_TYPE uxQueueMessagesWaitingFromISR( const xQueueHandle pxQueue ) PRIVILEGED_FUNCTION;\r
156 void vQueueWaitForMessageRestricted( xQueueHandle pxQueue, portTickType xTicksToWait ) PRIVILEGED_FUNCTION;\r
157 \r
158 /*\r
159  * Co-routine queue functions differ from task queue functions.  Co-routines are\r
160  * an optional component.\r
161  */\r
162 #if configUSE_CO_ROUTINES == 1\r
163         signed portBASE_TYPE xQueueCRSendFromISR( xQueueHandle pxQueue, const void *pvItemToQueue, signed portBASE_TYPE xCoRoutinePreviouslyWoken ) PRIVILEGED_FUNCTION;\r
164         signed portBASE_TYPE xQueueCRReceiveFromISR( xQueueHandle pxQueue, void *pvBuffer, signed portBASE_TYPE *pxTaskWoken ) PRIVILEGED_FUNCTION;\r
165         signed portBASE_TYPE xQueueCRSend( xQueueHandle pxQueue, const void *pvItemToQueue, portTickType xTicksToWait ) PRIVILEGED_FUNCTION;\r
166         signed portBASE_TYPE xQueueCRReceive( xQueueHandle pxQueue, void *pvBuffer, portTickType xTicksToWait ) PRIVILEGED_FUNCTION;\r
167 #endif\r
168 \r
169 /*\r
170  * The queue registry is just a means for kernel aware debuggers to locate\r
171  * queue structures.  It has no other purpose so is an optional component.\r
172  */\r
173 #if configQUEUE_REGISTRY_SIZE > 0\r
174 \r
175         /* The type stored within the queue registry array.  This allows a name\r
176         to be assigned to each queue making kernel aware debugging a little\r
177         more user friendly. */\r
178         typedef struct QUEUE_REGISTRY_ITEM\r
179         {\r
180                 signed char *pcQueueName;\r
181                 xQueueHandle xHandle;\r
182         } xQueueRegistryItem;\r
183 \r
184         /* The queue registry is simply an array of xQueueRegistryItem structures.\r
185         The pcQueueName member of a structure being NULL is indicative of the\r
186         array position being vacant. */\r
187         xQueueRegistryItem xQueueRegistry[ configQUEUE_REGISTRY_SIZE ];\r
188 \r
189         /* Removes a queue from the registry by simply setting the pcQueueName\r
190         member to NULL. */\r
191         static void vQueueUnregisterQueue( xQueueHandle xQueue ) PRIVILEGED_FUNCTION;\r
192         void vQueueAddToRegistry( xQueueHandle xQueue, signed char *pcQueueName ) PRIVILEGED_FUNCTION;\r
193 #endif\r
194 \r
195 /*\r
196  * Unlocks a queue locked by a call to prvLockQueue.  Locking a queue does not\r
197  * prevent an ISR from adding or removing items to the queue, but does prevent\r
198  * an ISR from removing tasks from the queue event lists.  If an ISR finds a\r
199  * queue is locked it will instead increment the appropriate queue lock count\r
200  * to indicate that a task may require unblocking.  When the queue in unlocked\r
201  * these lock counts are inspected, and the appropriate action taken.\r
202  */\r
203 static void prvUnlockQueue( xQueueHandle pxQueue ) PRIVILEGED_FUNCTION;\r
204 \r
205 /*\r
206  * Uses a critical section to determine if there is any data in a queue.\r
207  *\r
208  * @return pdTRUE if the queue contains no items, otherwise pdFALSE.\r
209  */\r
210 static signed portBASE_TYPE prvIsQueueEmpty( const xQueueHandle pxQueue ) PRIVILEGED_FUNCTION;\r
211 \r
212 /*\r
213  * Uses a critical section to determine if there is any space in a queue.\r
214  *\r
215  * @return pdTRUE if there is no space, otherwise pdFALSE;\r
216  */\r
217 static signed portBASE_TYPE prvIsQueueFull( const xQueueHandle pxQueue ) PRIVILEGED_FUNCTION;\r
218 \r
219 /*\r
220  * Copies an item into the queue, either at the front of the queue or the\r
221  * back of the queue.\r
222  */\r
223 static void prvCopyDataToQueue( xQUEUE *pxQueue, const void *pvItemToQueue, portBASE_TYPE xPosition ) PRIVILEGED_FUNCTION;\r
224 \r
225 /*\r
226  * Copies an item out of a queue.\r
227  */\r
228 static void prvCopyDataFromQueue( xQUEUE * const pxQueue, const void *pvBuffer ) PRIVILEGED_FUNCTION;\r
229 /*-----------------------------------------------------------*/\r
230 \r
231 /*\r
232  * Macro to mark a queue as locked.  Locking a queue prevents an ISR from\r
233  * accessing the queue event lists.\r
234  */\r
235 #define prvLockQueue( pxQueue )                                                         \\r
236         taskENTER_CRITICAL();                                                                   \\r
237         {                                                                                                               \\r
238                 if( ( pxQueue )->xRxLock == queueUNLOCKED )                     \\r
239                 {                                                                                                       \\r
240                         ( pxQueue )->xRxLock = queueLOCKED_UNMODIFIED;  \\r
241                 }                                                                                                       \\r
242                 if( ( pxQueue )->xTxLock == queueUNLOCKED )                     \\r
243                 {                                                                                                       \\r
244                         ( pxQueue )->xTxLock = queueLOCKED_UNMODIFIED;  \\r
245                 }                                                                                                       \\r
246         }                                                                                                               \\r
247         taskEXIT_CRITICAL()\r
248 /*-----------------------------------------------------------*/\r
249 \r
250 \r
251 /*-----------------------------------------------------------\r
252  * PUBLIC QUEUE MANAGEMENT API documented in queue.h\r
253  *----------------------------------------------------------*/\r
254 \r
255 xQueueHandle xQueueCreate( unsigned portBASE_TYPE uxQueueLength, unsigned portBASE_TYPE uxItemSize )\r
256 {\r
257 xQUEUE *pxNewQueue;\r
258 size_t xQueueSizeInBytes;\r
259 xQueueHandle xReturn = NULL;\r
260 \r
261         /* Allocate the new queue structure. */\r
262         if( uxQueueLength > ( unsigned portBASE_TYPE ) 0 )\r
263         {\r
264                 pxNewQueue = ( xQUEUE * ) pvPortMalloc( sizeof( xQUEUE ) );\r
265                 if( pxNewQueue != NULL )\r
266                 {\r
267                         /* Create the list of pointers to queue items.  The queue is one byte\r
268                         longer than asked for to make wrap checking easier/faster. */\r
269                         xQueueSizeInBytes = ( size_t ) ( uxQueueLength * uxItemSize ) + ( size_t ) 1;\r
270 \r
271                         pxNewQueue->pcHead = ( signed char * ) pvPortMalloc( xQueueSizeInBytes );\r
272                         if( pxNewQueue->pcHead != NULL )\r
273                         {\r
274                                 /* Initialise the queue members as described above where the\r
275                                 queue type is defined. */\r
276                                 pxNewQueue->pcTail = pxNewQueue->pcHead + ( uxQueueLength * uxItemSize );\r
277                                 pxNewQueue->uxMessagesWaiting = ( unsigned portBASE_TYPE ) 0U;\r
278                                 pxNewQueue->pcWriteTo = pxNewQueue->pcHead;\r
279                                 pxNewQueue->pcReadFrom = pxNewQueue->pcHead + ( ( uxQueueLength - ( unsigned portBASE_TYPE ) 1U ) * uxItemSize );\r
280                                 pxNewQueue->uxLength = uxQueueLength;\r
281                                 pxNewQueue->uxItemSize = uxItemSize;\r
282                                 pxNewQueue->xRxLock = queueUNLOCKED;\r
283                                 pxNewQueue->xTxLock = queueUNLOCKED;\r
284 \r
285                                 /* Likewise ensure the event queues start with the correct state. */\r
286                                 vListInitialise( &( pxNewQueue->xTasksWaitingToSend ) );\r
287                                 vListInitialise( &( pxNewQueue->xTasksWaitingToReceive ) );\r
288 \r
289                                 traceQUEUE_CREATE( pxNewQueue );\r
290                                 xReturn = pxNewQueue;\r
291                         }\r
292                         else\r
293                         {\r
294                                 traceQUEUE_CREATE_FAILED();\r
295                                 vPortFree( pxNewQueue );\r
296                         }\r
297                 }\r
298         }\r
299 \r
300         configASSERT( xReturn );\r
301 \r
302         return xReturn;\r
303 }\r
304 /*-----------------------------------------------------------*/\r
305 \r
306 #if ( configUSE_MUTEXES == 1 )\r
307 \r
308         xQueueHandle xQueueCreateMutex( void )\r
309         {\r
310         xQUEUE *pxNewQueue;\r
311 \r
312                 /* Allocate the new queue structure. */\r
313                 pxNewQueue = ( xQUEUE * ) pvPortMalloc( sizeof( xQUEUE ) );\r
314                 if( pxNewQueue != NULL )\r
315                 {\r
316                         /* Information required for priority inheritance. */\r
317                         pxNewQueue->pxMutexHolder = NULL;\r
318                         pxNewQueue->uxQueueType = queueQUEUE_IS_MUTEX;\r
319 \r
320                         /* Queues used as a mutex no data is actually copied into or out\r
321                         of the queue. */\r
322                         pxNewQueue->pcWriteTo = NULL;\r
323                         pxNewQueue->pcReadFrom = NULL;\r
324 \r
325                         /* Each mutex has a length of 1 (like a binary semaphore) and\r
326                         an item size of 0 as nothing is actually copied into or out\r
327                         of the mutex. */\r
328                         pxNewQueue->uxMessagesWaiting = ( unsigned portBASE_TYPE ) 0U;\r
329                         pxNewQueue->uxLength = ( unsigned portBASE_TYPE ) 1U;\r
330                         pxNewQueue->uxItemSize = ( unsigned portBASE_TYPE ) 0U;\r
331                         pxNewQueue->xRxLock = queueUNLOCKED;\r
332                         pxNewQueue->xTxLock = queueUNLOCKED;\r
333 \r
334                         /* Ensure the event queues start with the correct state. */\r
335                         vListInitialise( &( pxNewQueue->xTasksWaitingToSend ) );\r
336                         vListInitialise( &( pxNewQueue->xTasksWaitingToReceive ) );\r
337 \r
338                         /* Start with the semaphore in the expected state. */\r
339                         xQueueGenericSend( pxNewQueue, NULL, ( portTickType ) 0U, queueSEND_TO_BACK );\r
340 \r
341                         traceCREATE_MUTEX( pxNewQueue );\r
342                 }\r
343                 else\r
344                 {\r
345                         traceCREATE_MUTEX_FAILED();\r
346                 }\r
347 \r
348                 configASSERT( pxNewQueue );\r
349                 return pxNewQueue;\r
350         }\r
351 \r
352 #endif /* configUSE_MUTEXES */\r
353 /*-----------------------------------------------------------*/\r
354 \r
355 #if configUSE_RECURSIVE_MUTEXES == 1\r
356 \r
357         portBASE_TYPE xQueueGiveMutexRecursive( xQueueHandle pxMutex )\r
358         {\r
359         portBASE_TYPE xReturn;\r
360 \r
361                 configASSERT( pxMutex );\r
362 \r
363                 /* If this is the task that holds the mutex then pxMutexHolder will not\r
364                 change outside of this task.  If this task does not hold the mutex then\r
365                 pxMutexHolder can never coincidentally equal the tasks handle, and as\r
366                 this is the only condition we are interested in it does not matter if\r
367                 pxMutexHolder is accessed simultaneously by another task.  Therefore no\r
368                 mutual exclusion is required to test the pxMutexHolder variable. */\r
369                 if( pxMutex->pxMutexHolder == xTaskGetCurrentTaskHandle() )\r
370                 {\r
371                         traceGIVE_MUTEX_RECURSIVE( pxMutex );\r
372 \r
373                         /* uxRecursiveCallCount cannot be zero if pxMutexHolder is equal to\r
374                         the task handle, therefore no underflow check is required.  Also,\r
375                         uxRecursiveCallCount is only modified by the mutex holder, and as\r
376                         there can only be one, no mutual exclusion is required to modify the\r
377                         uxRecursiveCallCount member. */\r
378                         ( pxMutex->uxRecursiveCallCount )--;\r
379 \r
380                         /* Have we unwound the call count? */\r
381                         if( pxMutex->uxRecursiveCallCount == 0 )\r
382                         {\r
383                                 /* Return the mutex.  This will automatically unblock any other\r
384                                 task that might be waiting to access the mutex. */\r
385                                 xQueueGenericSend( pxMutex, NULL, queueMUTEX_GIVE_BLOCK_TIME, queueSEND_TO_BACK );\r
386                         }\r
387 \r
388                         xReturn = pdPASS;\r
389                 }\r
390                 else\r
391                 {\r
392                         /* We cannot give the mutex because we are not the holder. */\r
393                         xReturn = pdFAIL;\r
394 \r
395                         traceGIVE_MUTEX_RECURSIVE_FAILED( pxMutex );\r
396                 }\r
397 \r
398                 return xReturn;\r
399         }\r
400 \r
401 #endif /* configUSE_RECURSIVE_MUTEXES */\r
402 /*-----------------------------------------------------------*/\r
403 \r
404 #if configUSE_RECURSIVE_MUTEXES == 1\r
405 \r
406         portBASE_TYPE xQueueTakeMutexRecursive( xQueueHandle pxMutex, portTickType xBlockTime )\r
407         {\r
408         portBASE_TYPE xReturn;\r
409 \r
410                 configASSERT( pxMutex );\r
411 \r
412                 /* Comments regarding mutual exclusion as per those within\r
413                 xQueueGiveMutexRecursive(). */\r
414 \r
415                 traceTAKE_MUTEX_RECURSIVE( pxMutex );\r
416 \r
417                 if( pxMutex->pxMutexHolder == xTaskGetCurrentTaskHandle() )\r
418                 {\r
419                         ( pxMutex->uxRecursiveCallCount )++;\r
420                         xReturn = pdPASS;\r
421                 }\r
422                 else\r
423                 {\r
424                         xReturn = xQueueGenericReceive( pxMutex, NULL, xBlockTime, pdFALSE );\r
425 \r
426                         /* pdPASS will only be returned if we successfully obtained the mutex,\r
427                         we may have blocked to reach here. */\r
428                         if( xReturn == pdPASS )\r
429                         {\r
430                                 ( pxMutex->uxRecursiveCallCount )++;\r
431                         }\r
432                         else\r
433                         {\r
434                                 traceTAKE_MUTEX_RECURSIVE_FAILED( pxMutex );\r
435                         }\r
436                 }\r
437 \r
438                 return xReturn;\r
439         }\r
440 \r
441 #endif /* configUSE_RECURSIVE_MUTEXES */\r
442 /*-----------------------------------------------------------*/\r
443 \r
444 #if configUSE_COUNTING_SEMAPHORES == 1\r
445 \r
446         xQueueHandle xQueueCreateCountingSemaphore( unsigned portBASE_TYPE uxCountValue, unsigned portBASE_TYPE uxInitialCount )\r
447         {\r
448         xQueueHandle pxHandle;\r
449 \r
450                 pxHandle = xQueueCreate( ( unsigned portBASE_TYPE ) uxCountValue, queueSEMAPHORE_QUEUE_ITEM_LENGTH );\r
451 \r
452                 if( pxHandle != NULL )\r
453                 {\r
454                         pxHandle->uxMessagesWaiting = uxInitialCount;\r
455 \r
456                         traceCREATE_COUNTING_SEMAPHORE();\r
457                 }\r
458                 else\r
459                 {\r
460                         traceCREATE_COUNTING_SEMAPHORE_FAILED();\r
461                 }\r
462 \r
463                 configASSERT( pxHandle );\r
464                 return pxHandle;\r
465         }\r
466 \r
467 #endif /* configUSE_COUNTING_SEMAPHORES */\r
468 /*-----------------------------------------------------------*/\r
469 \r
470 signed portBASE_TYPE xQueueGenericSend( xQueueHandle pxQueue, const void * const pvItemToQueue, portTickType xTicksToWait, portBASE_TYPE xCopyPosition )\r
471 {\r
472 signed portBASE_TYPE xEntryTimeSet = pdFALSE;\r
473 xTimeOutType xTimeOut;\r
474 \r
475         configASSERT( pxQueue );\r
476         configASSERT( !( ( pvItemToQueue == NULL ) && ( pxQueue->uxItemSize != ( unsigned portBASE_TYPE ) 0U ) ) );\r
477 \r
478         /* This function relaxes the coding standard somewhat to allow return\r
479         statements within the function itself.  This is done in the interest\r
480         of execution time efficiency. */\r
481         for( ;; )\r
482         {\r
483                 taskENTER_CRITICAL();\r
484                 {\r
485                         /* Is there room on the queue now?  To be running we must be\r
486                         the highest priority task wanting to access the queue. */\r
487                         if( pxQueue->uxMessagesWaiting < pxQueue->uxLength )\r
488                         {\r
489                                 traceQUEUE_SEND( pxQueue );\r
490                                 prvCopyDataToQueue( pxQueue, pvItemToQueue, xCopyPosition );\r
491 \r
492                                 /* If there was a task waiting for data to arrive on the\r
493                                 queue then unblock it now. */\r
494                                 if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE )\r
495                                 {\r
496                                         if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) == pdTRUE )\r
497                                         {\r
498                                                 /* The unblocked task has a priority higher than\r
499                                                 our own so yield immediately.  Yes it is ok to do\r
500                                                 this from within the critical section - the kernel\r
501                                                 takes care of that. */\r
502                                                 portYIELD_WITHIN_API();\r
503                                         }\r
504                                 }\r
505 \r
506                                 taskEXIT_CRITICAL();\r
507 \r
508                                 /* Return to the original privilege level before exiting the\r
509                                 function. */\r
510                                 return pdPASS;\r
511                         }\r
512                         else\r
513                         {\r
514                                 if( xTicksToWait == ( portTickType ) 0 )\r
515                                 {\r
516                                         /* The queue was full and no block time is specified (or\r
517                                         the block time has expired) so leave now. */\r
518                                         taskEXIT_CRITICAL();\r
519 \r
520                                         /* Return to the original privilege level before exiting\r
521                                         the function. */\r
522                                         traceQUEUE_SEND_FAILED( pxQueue );\r
523                                         return errQUEUE_FULL;\r
524                                 }\r
525                                 else if( xEntryTimeSet == pdFALSE )\r
526                                 {\r
527                                         /* The queue was full and a block time was specified so\r
528                                         configure the timeout structure. */\r
529                                         vTaskSetTimeOutState( &xTimeOut );\r
530                                         xEntryTimeSet = pdTRUE;\r
531                                 }\r
532                         }\r
533                 }\r
534                 taskEXIT_CRITICAL();\r
535 \r
536                 /* Interrupts and other tasks can send to and receive from the queue\r
537                 now the critical section has been exited. */\r
538 \r
539                 vTaskSuspendAll();\r
540                 prvLockQueue( pxQueue );\r
541 \r
542                 /* Update the timeout state to see if it has expired yet. */\r
543                 if( xTaskCheckForTimeOut( &xTimeOut, &xTicksToWait ) == pdFALSE )\r
544                 {\r
545                         if( prvIsQueueFull( pxQueue ) != pdFALSE )\r
546                         {\r
547                                 traceBLOCKING_ON_QUEUE_SEND( pxQueue );\r
548                                 vTaskPlaceOnEventList( &( pxQueue->xTasksWaitingToSend ), xTicksToWait );\r
549 \r
550                                 /* Unlocking the queue means queue events can effect the\r
551                                 event list.  It is possible     that interrupts occurring now\r
552                                 remove this task from the event list again - but as the\r
553                                 scheduler is suspended the task will go onto the pending\r
554                                 ready last instead of the actual ready list. */\r
555                                 prvUnlockQueue( pxQueue );\r
556 \r
557                                 /* Resuming the scheduler will move tasks from the pending\r
558                                 ready list into the ready list - so it is feasible that this\r
559                                 task is already in a ready list before it yields - in which\r
560                                 case the yield will not cause a context switch unless there\r
561                                 is also a higher priority task in the pending ready list. */\r
562                                 if( xTaskResumeAll() == pdFALSE )\r
563                                 {\r
564                                         portYIELD_WITHIN_API();\r
565                                 }\r
566                         }\r
567                         else\r
568                         {\r
569                                 /* Try again. */\r
570                                 prvUnlockQueue( pxQueue );\r
571                                 ( void ) xTaskResumeAll();\r
572                         }\r
573                 }\r
574                 else\r
575                 {\r
576                         /* The timeout has expired. */\r
577                         prvUnlockQueue( pxQueue );\r
578                         ( void ) xTaskResumeAll();\r
579 \r
580                         /* Return to the original privilege level before exiting the\r
581                         function. */\r
582                         traceQUEUE_SEND_FAILED( pxQueue );\r
583                         return errQUEUE_FULL;\r
584                 }\r
585         }\r
586 }\r
587 /*-----------------------------------------------------------*/\r
588 \r
589 #if configUSE_ALTERNATIVE_API == 1\r
590 \r
591         signed portBASE_TYPE xQueueAltGenericSend( xQueueHandle pxQueue, const void * const pvItemToQueue, portTickType xTicksToWait, portBASE_TYPE xCopyPosition )\r
592         {\r
593         signed portBASE_TYPE xEntryTimeSet = pdFALSE;\r
594         xTimeOutType xTimeOut;\r
595 \r
596                 configASSERT( pxQueue );\r
597                 configASSERT( !( ( pvItemToQueue == NULL ) && ( pxQueue->uxItemSize != ( unsigned portBASE_TYPE ) 0U ) ) );\r
598 \r
599                 for( ;; )\r
600                 {\r
601                         taskENTER_CRITICAL();\r
602                         {\r
603                                 /* Is there room on the queue now?  To be running we must be\r
604                                 the highest priority task wanting to access the queue. */\r
605                                 if( pxQueue->uxMessagesWaiting < pxQueue->uxLength )\r
606                                 {\r
607                                         traceQUEUE_SEND( pxQueue );\r
608                                         prvCopyDataToQueue( pxQueue, pvItemToQueue, xCopyPosition );\r
609 \r
610                                         /* If there was a task waiting for data to arrive on the\r
611                                         queue then unblock it now. */\r
612                                         if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE )\r
613                                         {\r
614                                                 if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) == pdTRUE )\r
615                                                 {\r
616                                                         /* The unblocked task has a priority higher than\r
617                                                         our own so yield immediately. */\r
618                                                         portYIELD_WITHIN_API();\r
619                                                 }\r
620                                         }\r
621 \r
622                                         taskEXIT_CRITICAL();\r
623                                         return pdPASS;\r
624                                 }\r
625                                 else\r
626                                 {\r
627                                         if( xTicksToWait == ( portTickType ) 0 )\r
628                                         {\r
629                                                 taskEXIT_CRITICAL();\r
630                                                 return errQUEUE_FULL;\r
631                                         }\r
632                                         else if( xEntryTimeSet == pdFALSE )\r
633                                         {\r
634                                                 vTaskSetTimeOutState( &xTimeOut );\r
635                                                 xEntryTimeSet = pdTRUE;\r
636                                         }\r
637                                 }\r
638                         }\r
639                         taskEXIT_CRITICAL();\r
640 \r
641                         taskENTER_CRITICAL();\r
642                         {\r
643                                 if( xTaskCheckForTimeOut( &xTimeOut, &xTicksToWait ) == pdFALSE )\r
644                                 {\r
645                                         if( prvIsQueueFull( pxQueue ) != pdFALSE )\r
646                                         {\r
647                                                 traceBLOCKING_ON_QUEUE_SEND( pxQueue );\r
648                                                 vTaskPlaceOnEventList( &( pxQueue->xTasksWaitingToSend ), xTicksToWait );\r
649                                                 portYIELD_WITHIN_API();\r
650                                         }\r
651                                 }\r
652                                 else\r
653                                 {\r
654                                         taskEXIT_CRITICAL();\r
655                                         traceQUEUE_SEND_FAILED( pxQueue );\r
656                                         return errQUEUE_FULL;\r
657                                 }\r
658                         }\r
659                         taskEXIT_CRITICAL();\r
660                 }\r
661         }\r
662 \r
663 #endif /* configUSE_ALTERNATIVE_API */\r
664 /*-----------------------------------------------------------*/\r
665 \r
666 #if configUSE_ALTERNATIVE_API == 1\r
667 \r
668         signed portBASE_TYPE xQueueAltGenericReceive( xQueueHandle pxQueue, void * const pvBuffer, portTickType xTicksToWait, portBASE_TYPE xJustPeeking )\r
669         {\r
670         signed portBASE_TYPE xEntryTimeSet = pdFALSE;\r
671         xTimeOutType xTimeOut;\r
672         signed char *pcOriginalReadPosition;\r
673 \r
674                 configASSERT( pxQueue );\r
675                 configASSERT( !( ( pvBuffer == NULL ) && ( pxQueue->uxItemSize != ( unsigned portBASE_TYPE ) 0U ) ) );\r
676 \r
677                 for( ;; )\r
678                 {\r
679                         taskENTER_CRITICAL();\r
680                         {\r
681                                 if( pxQueue->uxMessagesWaiting > ( unsigned portBASE_TYPE ) 0 )\r
682                                 {\r
683                                         /* Remember our read position in case we are just peeking. */\r
684                                         pcOriginalReadPosition = pxQueue->pcReadFrom;\r
685 \r
686                                         prvCopyDataFromQueue( pxQueue, pvBuffer );\r
687 \r
688                                         if( xJustPeeking == pdFALSE )\r
689                                         {\r
690                                                 traceQUEUE_RECEIVE( pxQueue );\r
691 \r
692                                                 /* We are actually removing data. */\r
693                                                 --( pxQueue->uxMessagesWaiting );\r
694 \r
695                                                 #if ( configUSE_MUTEXES == 1 )\r
696                                                 {\r
697                                                         if( pxQueue->uxQueueType == queueQUEUE_IS_MUTEX )\r
698                                                         {\r
699                                                                 /* Record the information required to implement\r
700                                                                 priority inheritance should it become necessary. */\r
701                                                                 pxQueue->pxMutexHolder = xTaskGetCurrentTaskHandle();\r
702                                                         }\r
703                                                 }\r
704                                                 #endif\r
705 \r
706                                                 if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) == pdFALSE )\r
707                                                 {\r
708                                                         if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) == pdTRUE )\r
709                                                         {\r
710                                                                 portYIELD_WITHIN_API();\r
711                                                         }\r
712                                                 }\r
713                                         }\r
714                                         else\r
715                                         {\r
716                                                 traceQUEUE_PEEK( pxQueue );\r
717 \r
718                                                 /* We are not removing the data, so reset our read\r
719                                                 pointer. */\r
720                                                 pxQueue->pcReadFrom = pcOriginalReadPosition;\r
721 \r
722                                                 /* The data is being left in the queue, so see if there are\r
723                                                 any other tasks waiting for the data. */\r
724                                                 if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE )\r
725                                                 {\r
726                                                         /* Tasks that are removed from the event list will get added to\r
727                                                         the pending ready list as the scheduler is still suspended. */\r
728                                                         if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE )\r
729                                                         {\r
730                                                                 /* The task waiting has a higher priority than this task. */\r
731                                                                 portYIELD_WITHIN_API();\r
732                                                         }\r
733                                                 }\r
734 \r
735                                         }\r
736 \r
737                                         taskEXIT_CRITICAL();\r
738                                         return pdPASS;\r
739                                 }\r
740                                 else\r
741                                 {\r
742                                         if( xTicksToWait == ( portTickType ) 0 )\r
743                                         {\r
744                                                 taskEXIT_CRITICAL();\r
745                                                 traceQUEUE_RECEIVE_FAILED( pxQueue );\r
746                                                 return errQUEUE_EMPTY;\r
747                                         }\r
748                                         else if( xEntryTimeSet == pdFALSE )\r
749                                         {\r
750                                                 vTaskSetTimeOutState( &xTimeOut );\r
751                                                 xEntryTimeSet = pdTRUE;\r
752                                         }\r
753                                 }\r
754                         }\r
755                         taskEXIT_CRITICAL();\r
756 \r
757                         taskENTER_CRITICAL();\r
758                         {\r
759                                 if( xTaskCheckForTimeOut( &xTimeOut, &xTicksToWait ) == pdFALSE )\r
760                                 {\r
761                                         if( prvIsQueueEmpty( pxQueue ) != pdFALSE )\r
762                                         {\r
763                                                 traceBLOCKING_ON_QUEUE_RECEIVE( pxQueue );\r
764 \r
765                                                 #if ( configUSE_MUTEXES == 1 )\r
766                                                 {\r
767                                                         if( pxQueue->uxQueueType == queueQUEUE_IS_MUTEX )\r
768                                                         {\r
769                                                                 portENTER_CRITICAL();\r
770                                                                         vTaskPriorityInherit( ( void * ) pxQueue->pxMutexHolder );\r
771                                                                 portEXIT_CRITICAL();\r
772                                                         }\r
773                                                 }\r
774                                                 #endif\r
775 \r
776                                                 vTaskPlaceOnEventList( &( pxQueue->xTasksWaitingToReceive ), xTicksToWait );\r
777                                                 portYIELD_WITHIN_API();\r
778                                         }\r
779                                 }\r
780                                 else\r
781                                 {\r
782                                         taskEXIT_CRITICAL();\r
783                                         traceQUEUE_RECEIVE_FAILED( pxQueue );\r
784                                         return errQUEUE_EMPTY;\r
785                                 }\r
786                         }\r
787                         taskEXIT_CRITICAL();\r
788                 }\r
789         }\r
790 \r
791 \r
792 #endif /* configUSE_ALTERNATIVE_API */\r
793 /*-----------------------------------------------------------*/\r
794 \r
795 signed portBASE_TYPE xQueueGenericSendFromISR( xQueueHandle pxQueue, const void * const pvItemToQueue, signed portBASE_TYPE *pxHigherPriorityTaskWoken, portBASE_TYPE xCopyPosition )\r
796 {\r
797 signed portBASE_TYPE xReturn;\r
798 unsigned portBASE_TYPE uxSavedInterruptStatus;\r
799 \r
800         configASSERT( pxQueue );\r
801         configASSERT( pxHigherPriorityTaskWoken );\r
802         configASSERT( !( ( pvItemToQueue == NULL ) && ( pxQueue->uxItemSize != ( unsigned portBASE_TYPE ) 0U ) ) );\r
803 \r
804         /* Similar to xQueueGenericSend, except we don't block if there is no room\r
805         in the queue.  Also we don't directly wake a task that was blocked on a\r
806         queue read, instead we return a flag to say whether a context switch is\r
807         required or not (i.e. has a task with a higher priority than us been woken\r
808         by this post). */\r
809         uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR();\r
810         {\r
811                 if( pxQueue->uxMessagesWaiting < pxQueue->uxLength )\r
812                 {\r
813                         traceQUEUE_SEND_FROM_ISR( pxQueue );\r
814 \r
815                         prvCopyDataToQueue( pxQueue, pvItemToQueue, xCopyPosition );\r
816 \r
817                         /* If the queue is locked we do not alter the event list.  This will\r
818                         be done when the queue is unlocked later. */\r
819                         if( pxQueue->xTxLock == queueUNLOCKED )\r
820                         {\r
821                                 if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE )\r
822                                 {\r
823                                         if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE )\r
824                                         {\r
825                                                 /* The task waiting has a higher priority so record that a\r
826                                                 context switch is required. */\r
827                                                 *pxHigherPriorityTaskWoken = pdTRUE;\r
828                                         }\r
829                                 }\r
830                         }\r
831                         else\r
832                         {\r
833                                 /* Increment the lock count so the task that unlocks the queue\r
834                                 knows that data was posted while it was locked. */\r
835                                 ++( pxQueue->xTxLock );\r
836                         }\r
837 \r
838                         xReturn = pdPASS;\r
839                 }\r
840                 else\r
841                 {\r
842                         traceQUEUE_SEND_FROM_ISR_FAILED( pxQueue );\r
843                         xReturn = errQUEUE_FULL;\r
844                 }\r
845         }\r
846         portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus );\r
847 \r
848         return xReturn;\r
849 }\r
850 /*-----------------------------------------------------------*/\r
851 \r
852 signed portBASE_TYPE xQueueGenericReceive( xQueueHandle pxQueue, void * const pvBuffer, portTickType xTicksToWait, portBASE_TYPE xJustPeeking )\r
853 {\r
854 signed portBASE_TYPE xEntryTimeSet = pdFALSE;\r
855 xTimeOutType xTimeOut;\r
856 signed char *pcOriginalReadPosition;\r
857 \r
858         configASSERT( pxQueue );\r
859         configASSERT( !( ( pvBuffer == NULL ) && ( pxQueue->uxItemSize != ( unsigned portBASE_TYPE ) 0U ) ) );\r
860 \r
861         /* This function relaxes the coding standard somewhat to allow return\r
862         statements within the function itself.  This is done in the interest\r
863         of execution time efficiency. */\r
864 \r
865         for( ;; )\r
866         {\r
867                 taskENTER_CRITICAL();\r
868                 {\r
869                         /* Is there data in the queue now?  To be running we must be\r
870                         the highest priority task wanting to access the queue. */\r
871                         if( pxQueue->uxMessagesWaiting > ( unsigned portBASE_TYPE ) 0 )\r
872                         {\r
873                                 /* Remember our read position in case we are just peeking. */\r
874                                 pcOriginalReadPosition = pxQueue->pcReadFrom;\r
875 \r
876                                 prvCopyDataFromQueue( pxQueue, pvBuffer );\r
877 \r
878                                 if( xJustPeeking == pdFALSE )\r
879                                 {\r
880                                         traceQUEUE_RECEIVE( pxQueue );\r
881 \r
882                                         /* We are actually removing data. */\r
883                                         --( pxQueue->uxMessagesWaiting );\r
884 \r
885                                         #if ( configUSE_MUTEXES == 1 )\r
886                                         {\r
887                                                 if( pxQueue->uxQueueType == queueQUEUE_IS_MUTEX )\r
888                                                 {\r
889                                                         /* Record the information required to implement\r
890                                                         priority inheritance should it become necessary. */\r
891                                                         pxQueue->pxMutexHolder = xTaskGetCurrentTaskHandle();\r
892                                                 }\r
893                                         }\r
894                                         #endif\r
895 \r
896                                         if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) == pdFALSE )\r
897                                         {\r
898                                                 if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) == pdTRUE )\r
899                                                 {\r
900                                                         portYIELD_WITHIN_API();\r
901                                                 }\r
902                                         }\r
903                                 }\r
904                                 else\r
905                                 {\r
906                                         traceQUEUE_PEEK( pxQueue );\r
907 \r
908                                         /* We are not removing the data, so reset our read\r
909                                         pointer. */\r
910                                         pxQueue->pcReadFrom = pcOriginalReadPosition;\r
911 \r
912                                         /* The data is being left in the queue, so see if there are\r
913                                         any other tasks waiting for the data. */\r
914                                         if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE )\r
915                                         {\r
916                                                 /* Tasks that are removed from the event list will get added to\r
917                                                 the pending ready list as the scheduler is still suspended. */\r
918                                                 if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE )\r
919                                                 {\r
920                                                         /* The task waiting has a higher priority than this task. */\r
921                                                         portYIELD_WITHIN_API();\r
922                                                 }\r
923                                         }\r
924 \r
925                                 }\r
926 \r
927                                 taskEXIT_CRITICAL();\r
928                                 return pdPASS;\r
929                         }\r
930                         else\r
931                         {\r
932                                 if( xTicksToWait == ( portTickType ) 0 )\r
933                                 {\r
934                                         /* The queue was empty and no block time is specified (or\r
935                                         the block time has expired) so leave now. */\r
936                                         taskEXIT_CRITICAL();\r
937                                         traceQUEUE_RECEIVE_FAILED( pxQueue );\r
938                                         return errQUEUE_EMPTY;\r
939                                 }\r
940                                 else if( xEntryTimeSet == pdFALSE )\r
941                                 {\r
942                                         /* The queue was empty and a block time was specified so\r
943                                         configure the timeout structure. */\r
944                                         vTaskSetTimeOutState( &xTimeOut );\r
945                                         xEntryTimeSet = pdTRUE;\r
946                                 }\r
947                         }\r
948                 }\r
949                 taskEXIT_CRITICAL();\r
950 \r
951                 /* Interrupts and other tasks can send to and receive from the queue\r
952                 now the critical section has been exited. */\r
953 \r
954                 vTaskSuspendAll();\r
955                 prvLockQueue( pxQueue );\r
956 \r
957                 /* Update the timeout state to see if it has expired yet. */\r
958                 if( xTaskCheckForTimeOut( &xTimeOut, &xTicksToWait ) == pdFALSE )\r
959                 {\r
960                         if( prvIsQueueEmpty( pxQueue ) != pdFALSE )\r
961                         {\r
962                                 traceBLOCKING_ON_QUEUE_RECEIVE( pxQueue );\r
963 \r
964                                 #if ( configUSE_MUTEXES == 1 )\r
965                                 {\r
966                                         if( pxQueue->uxQueueType == queueQUEUE_IS_MUTEX )\r
967                                         {\r
968                                                 portENTER_CRITICAL();\r
969                                                 {\r
970                                                         vTaskPriorityInherit( ( void * ) pxQueue->pxMutexHolder );\r
971                                                 }\r
972                                                 portEXIT_CRITICAL();\r
973                                         }\r
974                                 }\r
975                                 #endif\r
976 \r
977                                 vTaskPlaceOnEventList( &( pxQueue->xTasksWaitingToReceive ), xTicksToWait );\r
978                                 prvUnlockQueue( pxQueue );\r
979                                 if( xTaskResumeAll() == pdFALSE )\r
980                                 {\r
981                                         portYIELD_WITHIN_API();\r
982                                 }\r
983                         }\r
984                         else\r
985                         {\r
986                                 /* Try again. */\r
987                                 prvUnlockQueue( pxQueue );\r
988                                 ( void ) xTaskResumeAll();\r
989                         }\r
990                 }\r
991                 else\r
992                 {\r
993                         prvUnlockQueue( pxQueue );\r
994                         ( void ) xTaskResumeAll();\r
995                         traceQUEUE_RECEIVE_FAILED( pxQueue );\r
996                         return errQUEUE_EMPTY;\r
997                 }\r
998         }\r
999 }\r
1000 /*-----------------------------------------------------------*/\r
1001 \r
1002 signed portBASE_TYPE xQueueReceiveFromISR( xQueueHandle pxQueue, void * const pvBuffer, signed portBASE_TYPE *pxTaskWoken )\r
1003 {\r
1004 signed portBASE_TYPE xReturn;\r
1005 unsigned portBASE_TYPE uxSavedInterruptStatus;\r
1006 \r
1007         configASSERT( pxQueue );\r
1008         configASSERT( pxTaskWoken );\r
1009         configASSERT( !( ( pvBuffer == NULL ) && ( pxQueue->uxItemSize != ( unsigned portBASE_TYPE ) 0U ) ) );\r
1010 \r
1011         uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR();\r
1012         {\r
1013                 /* We cannot block from an ISR, so check there is data available. */\r
1014                 if( pxQueue->uxMessagesWaiting > ( unsigned portBASE_TYPE ) 0 )\r
1015                 {\r
1016                         traceQUEUE_RECEIVE_FROM_ISR( pxQueue );\r
1017 \r
1018                         prvCopyDataFromQueue( pxQueue, pvBuffer );\r
1019                         --( pxQueue->uxMessagesWaiting );\r
1020 \r
1021                         /* If the queue is locked we will not modify the event list.  Instead\r
1022                         we update the lock count so the task that unlocks the queue will know\r
1023                         that an ISR has removed data while the queue was locked. */\r
1024                         if( pxQueue->xRxLock == queueUNLOCKED )\r
1025                         {\r
1026                                 if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) == pdFALSE )\r
1027                                 {\r
1028                                         if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) != pdFALSE )\r
1029                                         {\r
1030                                                 /* The task waiting has a higher priority than us so\r
1031                                                 force a context switch. */\r
1032                                                 *pxTaskWoken = pdTRUE;\r
1033                                         }\r
1034                                 }\r
1035                         }\r
1036                         else\r
1037                         {\r
1038                                 /* Increment the lock count so the task that unlocks the queue\r
1039                                 knows that data was removed while it was locked. */\r
1040                                 ++( pxQueue->xRxLock );\r
1041                         }\r
1042 \r
1043                         xReturn = pdPASS;\r
1044                 }\r
1045                 else\r
1046                 {\r
1047                         xReturn = pdFAIL;\r
1048                         traceQUEUE_RECEIVE_FROM_ISR_FAILED( pxQueue );\r
1049                 }\r
1050         }\r
1051         portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus );\r
1052 \r
1053         return xReturn;\r
1054 }\r
1055 /*-----------------------------------------------------------*/\r
1056 \r
1057 unsigned portBASE_TYPE uxQueueMessagesWaiting( const xQueueHandle pxQueue )\r
1058 {\r
1059 unsigned portBASE_TYPE uxReturn;\r
1060 \r
1061         configASSERT( pxQueue );\r
1062 \r
1063         taskENTER_CRITICAL();\r
1064                 uxReturn = pxQueue->uxMessagesWaiting;\r
1065         taskEXIT_CRITICAL();\r
1066 \r
1067         return uxReturn;\r
1068 }\r
1069 /*-----------------------------------------------------------*/\r
1070 \r
1071 unsigned portBASE_TYPE uxQueueMessagesWaitingFromISR( const xQueueHandle pxQueue )\r
1072 {\r
1073 unsigned portBASE_TYPE uxReturn;\r
1074 \r
1075         configASSERT( pxQueue );\r
1076 \r
1077         uxReturn = pxQueue->uxMessagesWaiting;\r
1078 \r
1079         return uxReturn;\r
1080 }\r
1081 /*-----------------------------------------------------------*/\r
1082 \r
1083 void vQueueDelete( xQueueHandle pxQueue )\r
1084 {\r
1085         configASSERT( pxQueue );\r
1086 \r
1087         traceQUEUE_DELETE( pxQueue );\r
1088         vQueueUnregisterQueue( pxQueue );\r
1089         vPortFree( pxQueue->pcHead );\r
1090         vPortFree( pxQueue );\r
1091 }\r
1092 /*-----------------------------------------------------------*/\r
1093 \r
1094 static void prvCopyDataToQueue( xQUEUE *pxQueue, const void *pvItemToQueue, portBASE_TYPE xPosition )\r
1095 {\r
1096         if( pxQueue->uxItemSize == ( unsigned portBASE_TYPE ) 0 )\r
1097         {\r
1098                 #if ( configUSE_MUTEXES == 1 )\r
1099                 {\r
1100                         if( pxQueue->uxQueueType == queueQUEUE_IS_MUTEX )\r
1101                         {\r
1102                                 /* The mutex is no longer being held. */\r
1103                                 vTaskPriorityDisinherit( ( void * ) pxQueue->pxMutexHolder );\r
1104                                 pxQueue->pxMutexHolder = NULL;\r
1105                         }\r
1106                 }\r
1107                 #endif\r
1108         }\r
1109         else if( xPosition == queueSEND_TO_BACK )\r
1110         {\r
1111                 memcpy( ( void * ) pxQueue->pcWriteTo, pvItemToQueue, ( unsigned ) pxQueue->uxItemSize );\r
1112                 pxQueue->pcWriteTo += pxQueue->uxItemSize;\r
1113                 if( pxQueue->pcWriteTo >= pxQueue->pcTail )\r
1114                 {\r
1115                         pxQueue->pcWriteTo = pxQueue->pcHead;\r
1116                 }\r
1117         }\r
1118         else\r
1119         {\r
1120                 memcpy( ( void * ) pxQueue->pcReadFrom, pvItemToQueue, ( unsigned ) pxQueue->uxItemSize );\r
1121                 pxQueue->pcReadFrom -= pxQueue->uxItemSize;\r
1122                 if( pxQueue->pcReadFrom < pxQueue->pcHead )\r
1123                 {\r
1124                         pxQueue->pcReadFrom = ( pxQueue->pcTail - pxQueue->uxItemSize );\r
1125                 }\r
1126         }\r
1127 \r
1128         ++( pxQueue->uxMessagesWaiting );\r
1129 }\r
1130 /*-----------------------------------------------------------*/\r
1131 \r
1132 static void prvCopyDataFromQueue( xQUEUE * const pxQueue, const void *pvBuffer )\r
1133 {\r
1134         if( pxQueue->uxQueueType != queueQUEUE_IS_MUTEX )\r
1135         {\r
1136                 pxQueue->pcReadFrom += pxQueue->uxItemSize;\r
1137                 if( pxQueue->pcReadFrom >= pxQueue->pcTail )\r
1138                 {\r
1139                         pxQueue->pcReadFrom = pxQueue->pcHead;\r
1140                 }\r
1141                 memcpy( ( void * ) pvBuffer, ( void * ) pxQueue->pcReadFrom, ( unsigned ) pxQueue->uxItemSize );\r
1142         }\r
1143 }\r
1144 /*-----------------------------------------------------------*/\r
1145 \r
1146 static void prvUnlockQueue( xQueueHandle pxQueue )\r
1147 {\r
1148         /* THIS FUNCTION MUST BE CALLED WITH THE SCHEDULER SUSPENDED. */\r
1149 \r
1150         /* The lock counts contains the number of extra data items placed or\r
1151         removed from the queue while the queue was locked.  When a queue is\r
1152         locked items can be added or removed, but the event lists cannot be\r
1153         updated. */\r
1154         taskENTER_CRITICAL();\r
1155         {\r
1156                 /* See if data was added to the queue while it was locked. */\r
1157                 while( pxQueue->xTxLock > queueLOCKED_UNMODIFIED )\r
1158                 {\r
1159                         /* Data was posted while the queue was locked.  Are any tasks\r
1160                         blocked waiting for data to become available? */\r
1161                         if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE )\r
1162                         {\r
1163                                 /* Tasks that are removed from the event list will get added to\r
1164                                 the pending ready list as the scheduler is still suspended. */\r
1165                                 if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE )\r
1166                                 {\r
1167                                         /* The task waiting has a higher priority so record that a\r
1168                                         context switch is required. */\r
1169                                         vTaskMissedYield();\r
1170                                 }\r
1171 \r
1172                                 --( pxQueue->xTxLock );\r
1173                         }\r
1174                         else\r
1175                         {\r
1176                                 break;\r
1177                         }\r
1178                 }\r
1179 \r
1180                 pxQueue->xTxLock = queueUNLOCKED;\r
1181         }\r
1182         taskEXIT_CRITICAL();\r
1183 \r
1184         /* Do the same for the Rx lock. */\r
1185         taskENTER_CRITICAL();\r
1186         {\r
1187                 while( pxQueue->xRxLock > queueLOCKED_UNMODIFIED )\r
1188                 {\r
1189                         if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) == pdFALSE )\r
1190                         {\r
1191                                 if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) != pdFALSE )\r
1192                                 {\r
1193                                         vTaskMissedYield();\r
1194                                 }\r
1195 \r
1196                                 --( pxQueue->xRxLock );\r
1197                         }\r
1198                         else\r
1199                         {\r
1200                                 break;\r
1201                         }\r
1202                 }\r
1203 \r
1204                 pxQueue->xRxLock = queueUNLOCKED;\r
1205         }\r
1206         taskEXIT_CRITICAL();\r
1207 }\r
1208 /*-----------------------------------------------------------*/\r
1209 \r
1210 static signed portBASE_TYPE prvIsQueueEmpty( const xQueueHandle pxQueue )\r
1211 {\r
1212 signed portBASE_TYPE xReturn;\r
1213 \r
1214         taskENTER_CRITICAL();\r
1215                 xReturn = ( pxQueue->uxMessagesWaiting == ( unsigned portBASE_TYPE ) 0 );\r
1216         taskEXIT_CRITICAL();\r
1217 \r
1218         return xReturn;\r
1219 }\r
1220 /*-----------------------------------------------------------*/\r
1221 \r
1222 signed portBASE_TYPE xQueueIsQueueEmptyFromISR( const xQueueHandle pxQueue )\r
1223 {\r
1224 signed portBASE_TYPE xReturn;\r
1225 \r
1226         configASSERT( pxQueue );\r
1227         xReturn = ( pxQueue->uxMessagesWaiting == ( unsigned portBASE_TYPE ) 0 );\r
1228 \r
1229         return xReturn;\r
1230 }\r
1231 /*-----------------------------------------------------------*/\r
1232 \r
1233 static signed portBASE_TYPE prvIsQueueFull( const xQueueHandle pxQueue )\r
1234 {\r
1235 signed portBASE_TYPE xReturn;\r
1236 \r
1237         taskENTER_CRITICAL();\r
1238                 xReturn = ( pxQueue->uxMessagesWaiting == pxQueue->uxLength );\r
1239         taskEXIT_CRITICAL();\r
1240 \r
1241         return xReturn;\r
1242 }\r
1243 /*-----------------------------------------------------------*/\r
1244 \r
1245 signed portBASE_TYPE xQueueIsQueueFullFromISR( const xQueueHandle pxQueue )\r
1246 {\r
1247 signed portBASE_TYPE xReturn;\r
1248 \r
1249         configASSERT( pxQueue );\r
1250         xReturn = ( pxQueue->uxMessagesWaiting == pxQueue->uxLength );\r
1251 \r
1252         return xReturn;\r
1253 }\r
1254 /*-----------------------------------------------------------*/\r
1255 \r
1256 #if configUSE_CO_ROUTINES == 1\r
1257 signed portBASE_TYPE xQueueCRSend( xQueueHandle pxQueue, const void *pvItemToQueue, portTickType xTicksToWait )\r
1258 {\r
1259 signed portBASE_TYPE xReturn;\r
1260 \r
1261         /* If the queue is already full we may have to block.  A critical section\r
1262         is required to prevent an interrupt removing something from the queue\r
1263         between the check to see if the queue is full and blocking on the queue. */\r
1264         portDISABLE_INTERRUPTS();\r
1265         {\r
1266                 if( prvIsQueueFull( pxQueue ) != pdFALSE )\r
1267                 {\r
1268                         /* The queue is full - do we want to block or just leave without\r
1269                         posting? */\r
1270                         if( xTicksToWait > ( portTickType ) 0 )\r
1271                         {\r
1272                                 /* As this is called from a coroutine we cannot block directly, but\r
1273                                 return indicating that we need to block. */\r
1274                                 vCoRoutineAddToDelayedList( xTicksToWait, &( pxQueue->xTasksWaitingToSend ) );\r
1275                                 portENABLE_INTERRUPTS();\r
1276                                 return errQUEUE_BLOCKED;\r
1277                         }\r
1278                         else\r
1279                         {\r
1280                                 portENABLE_INTERRUPTS();\r
1281                                 return errQUEUE_FULL;\r
1282                         }\r
1283                 }\r
1284         }\r
1285         portENABLE_INTERRUPTS();\r
1286 \r
1287         portNOP();\r
1288 \r
1289         portDISABLE_INTERRUPTS();\r
1290         {\r
1291                 if( pxQueue->uxMessagesWaiting < pxQueue->uxLength )\r
1292                 {\r
1293                         /* There is room in the queue, copy the data into the queue. */\r
1294                         prvCopyDataToQueue( pxQueue, pvItemToQueue, queueSEND_TO_BACK );\r
1295                         xReturn = pdPASS;\r
1296 \r
1297                         /* Were any co-routines waiting for data to become available? */\r
1298                         if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE )\r
1299                         {\r
1300                                 /* In this instance the co-routine could be placed directly\r
1301                                 into the ready list as we are within a critical section.\r
1302                                 Instead the same pending ready list mechanism is used as if\r
1303                                 the event were caused from within an interrupt. */\r
1304                                 if( xCoRoutineRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE )\r
1305                                 {\r
1306                                         /* The co-routine waiting has a higher priority so record\r
1307                                         that a yield might be appropriate. */\r
1308                                         xReturn = errQUEUE_YIELD;\r
1309                                 }\r
1310                         }\r
1311                 }\r
1312                 else\r
1313                 {\r
1314                         xReturn = errQUEUE_FULL;\r
1315                 }\r
1316         }\r
1317         portENABLE_INTERRUPTS();\r
1318 \r
1319         return xReturn;\r
1320 }\r
1321 #endif\r
1322 /*-----------------------------------------------------------*/\r
1323 \r
1324 #if configUSE_CO_ROUTINES == 1\r
1325 signed portBASE_TYPE xQueueCRReceive( xQueueHandle pxQueue, void *pvBuffer, portTickType xTicksToWait )\r
1326 {\r
1327 signed portBASE_TYPE xReturn;\r
1328 \r
1329         /* If the queue is already empty we may have to block.  A critical section\r
1330         is required to prevent an interrupt adding something to the queue\r
1331         between the check to see if the queue is empty and blocking on the queue. */\r
1332         portDISABLE_INTERRUPTS();\r
1333         {\r
1334                 if( pxQueue->uxMessagesWaiting == ( unsigned portBASE_TYPE ) 0 )\r
1335                 {\r
1336                         /* There are no messages in the queue, do we want to block or just\r
1337                         leave with nothing? */\r
1338                         if( xTicksToWait > ( portTickType ) 0 )\r
1339                         {\r
1340                                 /* As this is a co-routine we cannot block directly, but return\r
1341                                 indicating that we need to block. */\r
1342                                 vCoRoutineAddToDelayedList( xTicksToWait, &( pxQueue->xTasksWaitingToReceive ) );\r
1343                                 portENABLE_INTERRUPTS();\r
1344                                 return errQUEUE_BLOCKED;\r
1345                         }\r
1346                         else\r
1347                         {\r
1348                                 portENABLE_INTERRUPTS();\r
1349                                 return errQUEUE_FULL;\r
1350                         }\r
1351                 }\r
1352         }\r
1353         portENABLE_INTERRUPTS();\r
1354 \r
1355         portNOP();\r
1356 \r
1357         portDISABLE_INTERRUPTS();\r
1358         {\r
1359                 if( pxQueue->uxMessagesWaiting > ( unsigned portBASE_TYPE ) 0 )\r
1360                 {\r
1361                         /* Data is available from the queue. */\r
1362                         pxQueue->pcReadFrom += pxQueue->uxItemSize;\r
1363                         if( pxQueue->pcReadFrom >= pxQueue->pcTail )\r
1364                         {\r
1365                                 pxQueue->pcReadFrom = pxQueue->pcHead;\r
1366                         }\r
1367                         --( pxQueue->uxMessagesWaiting );\r
1368                         memcpy( ( void * ) pvBuffer, ( void * ) pxQueue->pcReadFrom, ( unsigned ) pxQueue->uxItemSize );\r
1369 \r
1370                         xReturn = pdPASS;\r
1371 \r
1372                         /* Were any co-routines waiting for space to become available? */\r
1373                         if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) == pdFALSE )\r
1374                         {\r
1375                                 /* In this instance the co-routine could be placed directly\r
1376                                 into the ready list as we are within a critical section.\r
1377                                 Instead the same pending ready list mechanism is used as if\r
1378                                 the event were caused from within an interrupt. */\r
1379                                 if( xCoRoutineRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) != pdFALSE )\r
1380                                 {\r
1381                                         xReturn = errQUEUE_YIELD;\r
1382                                 }\r
1383                         }\r
1384                 }\r
1385                 else\r
1386                 {\r
1387                         xReturn = pdFAIL;\r
1388                 }\r
1389         }\r
1390         portENABLE_INTERRUPTS();\r
1391 \r
1392         return xReturn;\r
1393 }\r
1394 #endif\r
1395 /*-----------------------------------------------------------*/\r
1396 \r
1397 \r
1398 \r
1399 #if configUSE_CO_ROUTINES == 1\r
1400 signed portBASE_TYPE xQueueCRSendFromISR( xQueueHandle pxQueue, const void *pvItemToQueue, signed portBASE_TYPE xCoRoutinePreviouslyWoken )\r
1401 {\r
1402         /* Cannot block within an ISR so if there is no space on the queue then\r
1403         exit without doing anything. */\r
1404         if( pxQueue->uxMessagesWaiting < pxQueue->uxLength )\r
1405         {\r
1406                 prvCopyDataToQueue( pxQueue, pvItemToQueue, queueSEND_TO_BACK );\r
1407 \r
1408                 /* We only want to wake one co-routine per ISR, so check that a\r
1409                 co-routine has not already been woken. */\r
1410                 if( xCoRoutinePreviouslyWoken == pdFALSE )\r
1411                 {\r
1412                         if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE )\r
1413                         {\r
1414                                 if( xCoRoutineRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE )\r
1415                                 {\r
1416                                         return pdTRUE;\r
1417                                 }\r
1418                         }\r
1419                 }\r
1420         }\r
1421 \r
1422         return xCoRoutinePreviouslyWoken;\r
1423 }\r
1424 #endif\r
1425 /*-----------------------------------------------------------*/\r
1426 \r
1427 #if configUSE_CO_ROUTINES == 1\r
1428 signed portBASE_TYPE xQueueCRReceiveFromISR( xQueueHandle pxQueue, void *pvBuffer, signed portBASE_TYPE *pxCoRoutineWoken )\r
1429 {\r
1430 signed portBASE_TYPE xReturn;\r
1431 \r
1432         /* We cannot block from an ISR, so check there is data available. If\r
1433         not then just leave without doing anything. */\r
1434         if( pxQueue->uxMessagesWaiting > ( unsigned portBASE_TYPE ) 0 )\r
1435         {\r
1436                 /* Copy the data from the queue. */\r
1437                 pxQueue->pcReadFrom += pxQueue->uxItemSize;\r
1438                 if( pxQueue->pcReadFrom >= pxQueue->pcTail )\r
1439                 {\r
1440                         pxQueue->pcReadFrom = pxQueue->pcHead;\r
1441                 }\r
1442                 --( pxQueue->uxMessagesWaiting );\r
1443                 memcpy( ( void * ) pvBuffer, ( void * ) pxQueue->pcReadFrom, ( unsigned ) pxQueue->uxItemSize );\r
1444 \r
1445                 if( ( *pxCoRoutineWoken ) == pdFALSE )\r
1446                 {\r
1447                         if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) == pdFALSE )\r
1448                         {\r
1449                                 if( xCoRoutineRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) != pdFALSE )\r
1450                                 {\r
1451                                         *pxCoRoutineWoken = pdTRUE;\r
1452                                 }\r
1453                         }\r
1454                 }\r
1455 \r
1456                 xReturn = pdPASS;\r
1457         }\r
1458         else\r
1459         {\r
1460                 xReturn = pdFAIL;\r
1461         }\r
1462 \r
1463         return xReturn;\r
1464 }\r
1465 #endif\r
1466 /*-----------------------------------------------------------*/\r
1467 \r
1468 #if configQUEUE_REGISTRY_SIZE > 0\r
1469 \r
1470         void vQueueAddToRegistry( xQueueHandle xQueue, signed char *pcQueueName )\r
1471         {\r
1472         unsigned portBASE_TYPE ux;\r
1473 \r
1474                 /* See if there is an empty space in the registry.  A NULL name denotes\r
1475                 a free slot. */\r
1476                 for( ux = ( unsigned portBASE_TYPE ) 0U; ux < ( unsigned portBASE_TYPE ) configQUEUE_REGISTRY_SIZE; ux++ )\r
1477                 {\r
1478                         if( xQueueRegistry[ ux ].pcQueueName == NULL )\r
1479                         {\r
1480                                 /* Store the information on this queue. */\r
1481                                 xQueueRegistry[ ux ].pcQueueName = pcQueueName;\r
1482                                 xQueueRegistry[ ux ].xHandle = xQueue;\r
1483                                 break;\r
1484                         }\r
1485                 }\r
1486         }\r
1487 \r
1488 #endif\r
1489 /*-----------------------------------------------------------*/\r
1490 \r
1491 #if configQUEUE_REGISTRY_SIZE > 0\r
1492 \r
1493         static void vQueueUnregisterQueue( xQueueHandle xQueue )\r
1494         {\r
1495         unsigned portBASE_TYPE ux;\r
1496 \r
1497                 /* See if the handle of the queue being unregistered in actually in the\r
1498                 registry. */\r
1499                 for( ux = ( unsigned portBASE_TYPE ) 0U; ux < ( unsigned portBASE_TYPE ) configQUEUE_REGISTRY_SIZE; ux++ )\r
1500                 {\r
1501                         if( xQueueRegistry[ ux ].xHandle == xQueue )\r
1502                         {\r
1503                                 /* Set the name to NULL to show that this slot if free again. */\r
1504                                 xQueueRegistry[ ux ].pcQueueName = NULL;\r
1505                                 break;\r
1506                         }\r
1507                 }\r
1508 \r
1509         }\r
1510 \r
1511 #endif\r
1512 /*-----------------------------------------------------------*/\r
1513 \r
1514 #if configUSE_TIMERS == 1\r
1515 \r
1516         void vQueueWaitForMessageRestricted( xQueueHandle pxQueue, portTickType xTicksToWait )\r
1517         {\r
1518                 /* This function should not be called by application code hence the\r
1519                 'Restricted' in its name.  It is not part of the public API.  It is\r
1520                 designed for use by kernel code, and has special calling requirements.\r
1521                 It can result in vListInsert() being called on a list that can only\r
1522                 possibly ever have one item in it, so the list will be fast, but even\r
1523                 so it should be called with the scheduler locked and not from a critical\r
1524                 section. */\r
1525 \r
1526                 /* Only do anything if there are no messages in the queue.  This function\r
1527                 will not actually cause the task to block, just place it on a blocked\r
1528                 list.  It will not block until the scheduler is unlocked - at which\r
1529                 time a yield will be performed.  If an item is added to the queue while\r
1530                 the queue is locked, and the calling task blocks on the queue, then the\r
1531                 calling task will be immediately unblocked when the queue is unlocked. */\r
1532                 prvLockQueue( pxQueue );\r
1533                 if( pxQueue->uxMessagesWaiting == ( unsigned portBASE_TYPE ) 0U )\r
1534                 {\r
1535                         /* There is nothing in the queue, block for the specified period. */\r
1536                         vTaskPlaceOnEventListRestricted( &( pxQueue->xTasksWaitingToReceive ), xTicksToWait );\r
1537                 }\r
1538                 prvUnlockQueue( pxQueue );\r
1539         }\r
1540 \r
1541 #endif\r
1542 \r