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