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