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