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