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