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