]> git.sur5r.net Git - freertos/blobdiff - Source/queue.c
Tidy up the RL78 port layer.
[freertos] / Source / queue.c
index 80b014966ff70ccbd6e068427ac3097bded876f1..c2197b7c2e1188331db814ea94716cc6143d4a5c 100644 (file)
 /*\r
-       FreeRTOS.org V4.7.0 - Copyright (C) 2003-2007 Richard Barry.\r
-\r
-       This file is part of the FreeRTOS.org distribution.\r
-\r
-       FreeRTOS.org is free software; you can redistribute it and/or modify\r
-       it under the terms of the GNU General Public License as published by\r
-       the Free Software Foundation; either version 2 of the License, or\r
-       (at your option) any later version.\r
-\r
-       FreeRTOS.org is distributed in the hope that it will be useful,\r
-       but WITHOUT ANY WARRANTY; without even the implied warranty of\r
-       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
-       GNU General Public License for more details.\r
-\r
-       You should have received a copy of the GNU General Public License\r
-       along with FreeRTOS.org; if not, write to the Free Software\r
-       Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\r
-\r
-       A special exception to the GPL can be applied should you wish to distribute\r
-       a combined work that includes FreeRTOS.org, without being obliged to provide\r
-       the source code for any proprietary components.  See the licensing section\r
-       of http://www.FreeRTOS.org for full details of how and when the exception\r
-       can be applied.\r
-\r
-       ***************************************************************************\r
-       See http://www.FreeRTOS.org for documentation, latest information, license\r
-       and contact details.  Please ensure to read the configuration and relevant\r
-       port sections of the online documentation.\r
-\r
-       Also see http://www.SafeRTOS.com a version that has been certified for use\r
-       in safety critical systems, plus commercial licensing, development and\r
-       support options.\r
-       ***************************************************************************\r
+    FreeRTOS V7.0.1 - Copyright (C) 2011 Real Time Engineers Ltd.\r
+       \r
+\r
+       FreeRTOS supports many tools and architectures. V7.0.0 is sponsored by:\r
+       Atollic AB - Atollic provides professional embedded systems development \r
+       tools for C/C++ development, code analysis and test automation.  \r
+       See http://www.atollic.com\r
+       \r
+\r
+    ***************************************************************************\r
+     *                                                                       *\r
+     *    FreeRTOS tutorial books are available in pdf and paperback.        *\r
+     *    Complete, revised, and edited pdf reference manuals are also       *\r
+     *    available.                                                         *\r
+     *                                                                       *\r
+     *    Purchasing FreeRTOS documentation will not only help you, by       *\r
+     *    ensuring you get running as quickly as possible and with an        *\r
+     *    in-depth knowledge of how to use FreeRTOS, it will also help       *\r
+     *    the FreeRTOS project to continue with its mission of providing     *\r
+     *    professional grade, cross platform, de facto standard solutions    *\r
+     *    for microcontrollers - completely free of charge!                  *\r
+     *                                                                       *\r
+     *    >>> See http://www.FreeRTOS.org/Documentation for details. <<<     *\r
+     *                                                                       *\r
+     *    Thank you for using FreeRTOS, and thank you for your support!      *\r
+     *                                                                       *\r
+    ***************************************************************************\r
+\r
+\r
+    This file is part of the FreeRTOS distribution.\r
+\r
+    FreeRTOS is free software; you can redistribute it and/or modify it under\r
+    the terms of the GNU General Public License (version 2) as published by the\r
+    Free Software Foundation AND MODIFIED BY the FreeRTOS exception.\r
+    >>>NOTE<<< The modification to the GPL is included to allow you to\r
+    distribute a combined work that includes FreeRTOS without being obliged to\r
+    provide the source code for proprietary components outside of the FreeRTOS\r
+    kernel.  FreeRTOS is distributed in the hope that it will be useful, but\r
+    WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\r
+    or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for\r
+    more details. You should have received a copy of the GNU General Public\r
+    License and the FreeRTOS license exception along with FreeRTOS; if not it\r
+    can be viewed here: http://www.freertos.org/a00114.html and also obtained\r
+    by writing to Richard Barry, contact details for whom are available on the\r
+    FreeRTOS WEB site.\r
+\r
+    1 tab == 4 spaces!\r
+\r
+    http://www.FreeRTOS.org - Documentation, latest information, license and\r
+    contact details.\r
+\r
+    http://www.SafeRTOS.com - A version that is certified for use in safety\r
+    critical systems.\r
+\r
+    http://www.OpenRTOS.com - Commercial support, development, porting,\r
+    licensing and training services.\r
 */\r
 \r
 #include <stdlib.h>\r
 #include <string.h>\r
+\r
+/* Defining MPU_WRAPPERS_INCLUDED_FROM_API_FILE prevents task.h from redefining\r
+all the API functions to use the MPU wrappers.  That should only be done when\r
+task.h is included from an application file. */\r
+#define MPU_WRAPPERS_INCLUDED_FROM_API_FILE\r
+\r
 #include "FreeRTOS.h"\r
 #include "task.h"\r
-#include "croutine.h"\r
+\r
+#if ( configUSE_CO_ROUTINES == 1 )\r
+       #include "croutine.h"\r
+#endif\r
+\r
+#undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE\r
 \r
 /*-----------------------------------------------------------\r
  * PUBLIC LIST API documented in list.h\r
  *----------------------------------------------------------*/\r
 \r
 /* Constants used with the cRxLock and cTxLock structure members. */\r
-#define queueUNLOCKED  ( ( signed portBASE_TYPE ) -1 )\r
-#define queueERRONEOUS_UNBLOCK                                 ( -1 )\r
+#define queueUNLOCKED                                  ( ( signed portBASE_TYPE ) -1 )\r
+#define queueLOCKED_UNMODIFIED                 ( ( signed portBASE_TYPE ) 0 )\r
+\r
+#define queueERRONEOUS_UNBLOCK                 ( -1 )\r
 \r
 /* For internal use only. */\r
-#define        queueSEND_TO_BACK       ( 0 )\r
-#define        queueSEND_TO_FRONT      ( 1 )\r
+#define        queueSEND_TO_BACK                               ( 0 )\r
+#define        queueSEND_TO_FRONT                              ( 1 )\r
 \r
 /* Effectively make a union out of the xQUEUE structure. */\r
-#define pxMutexHolder                          pcTail\r
-#define uxQueueType                                    pcHead\r
-#define queueQUEUE_IS_MUTEX                    NULL\r
+#define pxMutexHolder                                  pcTail\r
+#define uxQueueType                                            pcHead\r
+#define uxRecursiveCallCount                   pcReadFrom\r
+#define queueQUEUE_IS_MUTEX                            NULL\r
 \r
 /* Semaphores do not actually store or copy data, so have an items size of\r
 zero. */\r
-#define queueSEMAPHORE_QUEUE_ITEM_LENGTH ( 0 )\r
-#define queueDONT_BLOCK                                         ( ( portTickType ) 0 )\r
+#define queueSEMAPHORE_QUEUE_ITEM_LENGTH ( ( unsigned portBASE_TYPE ) 0 )\r
+#define queueDONT_BLOCK                                         ( ( portTickType ) 0U )\r
+#define queueMUTEX_GIVE_BLOCK_TIME              ( ( portTickType ) 0U )\r
 \r
 /*\r
  * Definition of the queue used by the scheduler.\r
@@ -68,11 +106,11 @@ zero. */
  */\r
 typedef struct QueueDefinition\r
 {\r
-       signed portCHAR *pcHead;                                /*< Points to the beginning of the queue storage area. */\r
-       signed portCHAR *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
+       signed char *pcHead;                            /*< Points to the beginning of the queue storage area. */\r
+       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
 \r
-       signed portCHAR *pcWriteTo;                             /*< Points to the free next place in the storage area. */\r
-       signed portCHAR *pcReadFrom;                    /*< Points to the last place that a queued item was read from. */\r
+       signed char *pcWriteTo;                         /*< Points to the free next place in the storage area. */\r
+       signed char *pcReadFrom;                        /*< Points to the last place that a queued item was read from. */\r
 \r
        xList xTasksWaitingToSend;                              /*< List of tasks that are blocked waiting to post onto this queue.  Stored in priority order. */\r
        xList xTasksWaitingToReceive;                   /*< List of tasks that are blocked waiting to read from this queue.  Stored in priority order. */\r
@@ -83,6 +121,7 @@ typedef struct QueueDefinition
 \r
        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
        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
+\r
 } xQUEUE;\r
 /*-----------------------------------------------------------*/\r
 \r
@@ -98,23 +137,59 @@ typedef xQUEUE * xQueueHandle;
  * include the API header file (as it defines xQueueHandle differently).  These\r
  * functions are documented in the API header file.\r
  */\r
-xQueueHandle xQueueCreate( unsigned portBASE_TYPE uxQueueLength, unsigned portBASE_TYPE uxItemSize );\r
-signed portBASE_TYPE xQueueGenericSend( xQueueHandle xQueue, const void * const pvItemToQueue, portTickType xTicksToWait, portBASE_TYPE xCopyPosition );\r
-unsigned portBASE_TYPE uxQueueMessagesWaiting( const xQueueHandle pxQueue );\r
-void vQueueDelete( xQueueHandle xQueue );\r
-signed portBASE_TYPE xQueueGenericSendFromISR( xQueueHandle pxQueue, const void * const pvItemToQueue, signed portBASE_TYPE xTaskPreviouslyWoken, portBASE_TYPE xCopyPosition );\r
-signed portBASE_TYPE xQueueGenericReceive( xQueueHandle pxQueue, const void * const pvBuffer, portTickType xTicksToWait, portBASE_TYPE xJustPeeking );\r
-signed portBASE_TYPE xQueueReceiveFromISR( xQueueHandle pxQueue, const void * const pvBuffer, signed portBASE_TYPE *pxTaskWoken );\r
-xQueueHandle xQueueCreateMutex( void );\r
-xQueueHandle xQueueCreateCountingSemaphore( unsigned portBASE_TYPE uxCountValue, unsigned portBASE_TYPE uxInitialCount );\r
-signed portBASE_TYPE xQueueAltGenericSend( xQueueHandle pxQueue, const void * const pvItemToQueue, portTickType xTicksToWait, portBASE_TYPE xCopyPosition );\r
-signed portBASE_TYPE xQueueAltGenericReceive( xQueueHandle pxQueue, const void * const pvBuffer, portTickType xTicksToWait, portBASE_TYPE xJustPeeking );\r
+xQueueHandle xQueueCreate( unsigned portBASE_TYPE uxQueueLength, unsigned portBASE_TYPE uxItemSize ) PRIVILEGED_FUNCTION;\r
+signed portBASE_TYPE xQueueGenericSend( xQueueHandle xQueue, const void * const pvItemToQueue, portTickType xTicksToWait, portBASE_TYPE xCopyPosition ) PRIVILEGED_FUNCTION;\r
+unsigned portBASE_TYPE uxQueueMessagesWaiting( const xQueueHandle pxQueue ) PRIVILEGED_FUNCTION;\r
+void vQueueDelete( xQueueHandle xQueue ) PRIVILEGED_FUNCTION;\r
+signed portBASE_TYPE xQueueGenericSendFromISR( xQueueHandle pxQueue, const void * const pvItemToQueue, signed portBASE_TYPE *pxHigherPriorityTaskWoken, portBASE_TYPE xCopyPosition ) PRIVILEGED_FUNCTION;\r
+signed portBASE_TYPE xQueueGenericReceive( xQueueHandle pxQueue, void * const pvBuffer, portTickType xTicksToWait, portBASE_TYPE xJustPeeking ) PRIVILEGED_FUNCTION;\r
+signed portBASE_TYPE xQueueReceiveFromISR( xQueueHandle pxQueue, void * const pvBuffer, signed portBASE_TYPE *pxTaskWoken ) PRIVILEGED_FUNCTION;\r
+xQueueHandle xQueueCreateMutex( void ) PRIVILEGED_FUNCTION;\r
+xQueueHandle xQueueCreateCountingSemaphore( unsigned portBASE_TYPE uxCountValue, unsigned portBASE_TYPE uxInitialCount ) PRIVILEGED_FUNCTION;\r
+portBASE_TYPE xQueueTakeMutexRecursive( xQueueHandle xMutex, portTickType xBlockTime ) PRIVILEGED_FUNCTION;\r
+portBASE_TYPE xQueueGiveMutexRecursive( xQueueHandle xMutex ) PRIVILEGED_FUNCTION;\r
+signed portBASE_TYPE xQueueAltGenericSend( xQueueHandle pxQueue, const void * const pvItemToQueue, portTickType xTicksToWait, portBASE_TYPE xCopyPosition ) PRIVILEGED_FUNCTION;\r
+signed portBASE_TYPE xQueueAltGenericReceive( xQueueHandle pxQueue, void * const pvBuffer, portTickType xTicksToWait, portBASE_TYPE xJustPeeking ) PRIVILEGED_FUNCTION;\r
+signed portBASE_TYPE xQueueIsQueueEmptyFromISR( const xQueueHandle pxQueue ) PRIVILEGED_FUNCTION;\r
+signed portBASE_TYPE xQueueIsQueueFullFromISR( const xQueueHandle pxQueue ) PRIVILEGED_FUNCTION;\r
+unsigned portBASE_TYPE uxQueueMessagesWaitingFromISR( const xQueueHandle pxQueue ) PRIVILEGED_FUNCTION;\r
+void vQueueWaitForMessageRestricted( xQueueHandle pxQueue, portTickType xTicksToWait ) PRIVILEGED_FUNCTION;\r
 \r
+/*\r
+ * Co-routine queue functions differ from task queue functions.  Co-routines are\r
+ * an optional component.\r
+ */\r
 #if configUSE_CO_ROUTINES == 1\r
-       signed portBASE_TYPE xQueueCRSendFromISR( xQueueHandle pxQueue, const void *pvItemToQueue, signed portBASE_TYPE xCoRoutinePreviouslyWoken );\r
-       signed portBASE_TYPE xQueueCRReceiveFromISR( xQueueHandle pxQueue, void *pvBuffer, signed portBASE_TYPE *pxTaskWoken );\r
-       signed portBASE_TYPE xQueueCRSend( xQueueHandle pxQueue, const void *pvItemToQueue, portTickType xTicksToWait );\r
-       signed portBASE_TYPE xQueueCRReceive( xQueueHandle pxQueue, void *pvBuffer, portTickType xTicksToWait );\r
+       signed portBASE_TYPE xQueueCRSendFromISR( xQueueHandle pxQueue, const void *pvItemToQueue, signed portBASE_TYPE xCoRoutinePreviouslyWoken ) PRIVILEGED_FUNCTION;\r
+       signed portBASE_TYPE xQueueCRReceiveFromISR( xQueueHandle pxQueue, void *pvBuffer, signed portBASE_TYPE *pxTaskWoken ) PRIVILEGED_FUNCTION;\r
+       signed portBASE_TYPE xQueueCRSend( xQueueHandle pxQueue, const void *pvItemToQueue, portTickType xTicksToWait ) PRIVILEGED_FUNCTION;\r
+       signed portBASE_TYPE xQueueCRReceive( xQueueHandle pxQueue, void *pvBuffer, portTickType xTicksToWait ) PRIVILEGED_FUNCTION;\r
+#endif\r
+\r
+/*\r
+ * The queue registry is just a means for kernel aware debuggers to locate\r
+ * queue structures.  It has no other purpose so is an optional component.\r
+ */\r
+#if configQUEUE_REGISTRY_SIZE > 0\r
+\r
+       /* The type stored within the queue registry array.  This allows a name\r
+       to be assigned to each queue making kernel aware debugging a little\r
+       more user friendly. */\r
+       typedef struct QUEUE_REGISTRY_ITEM\r
+       {\r
+               signed char *pcQueueName;\r
+               xQueueHandle xHandle;\r
+       } xQueueRegistryItem;\r
+\r
+       /* The queue registry is simply an array of xQueueRegistryItem structures.\r
+       The pcQueueName member of a structure being NULL is indicative of the\r
+       array position being vacant. */\r
+       xQueueRegistryItem xQueueRegistry[ configQUEUE_REGISTRY_SIZE ];\r
+\r
+       /* Removes a queue from the registry by simply setting the pcQueueName\r
+       member to NULL. */\r
+       static void vQueueUnregisterQueue( xQueueHandle xQueue ) PRIVILEGED_FUNCTION;\r
+       void vQueueAddToRegistry( xQueueHandle xQueue, signed char *pcQueueName ) PRIVILEGED_FUNCTION;\r
 #endif\r
 \r
 /*\r
@@ -125,45 +200,51 @@ signed portBASE_TYPE xQueueAltGenericReceive( xQueueHandle pxQueue, const void *
  * to indicate that a task may require unblocking.  When the queue in unlocked\r
  * these lock counts are inspected, and the appropriate action taken.\r
  */\r
-static void prvUnlockQueue( xQueueHandle pxQueue );\r
+static void prvUnlockQueue( xQueueHandle pxQueue ) PRIVILEGED_FUNCTION;\r
 \r
 /*\r
  * Uses a critical section to determine if there is any data in a queue.\r
  *\r
  * @return pdTRUE if the queue contains no items, otherwise pdFALSE.\r
  */\r
-static signed portBASE_TYPE prvIsQueueEmpty( const xQueueHandle pxQueue );\r
+static signed portBASE_TYPE prvIsQueueEmpty( const xQueueHandle pxQueue ) PRIVILEGED_FUNCTION;\r
 \r
 /*\r
  * Uses a critical section to determine if there is any space in a queue.\r
  *\r
  * @return pdTRUE if there is no space, otherwise pdFALSE;\r
  */\r
-static signed portBASE_TYPE prvIsQueueFull( const xQueueHandle pxQueue );\r
+static signed portBASE_TYPE prvIsQueueFull( const xQueueHandle pxQueue ) PRIVILEGED_FUNCTION;\r
 \r
 /*\r
  * Copies an item into the queue, either at the front of the queue or the\r
  * back of the queue.\r
  */\r
-static void prvCopyDataToQueue( xQUEUE *pxQueue, const void *pvItemToQueue, portBASE_TYPE xPosition );\r
+static void prvCopyDataToQueue( xQUEUE *pxQueue, const void *pvItemToQueue, portBASE_TYPE xPosition ) PRIVILEGED_FUNCTION;\r
 \r
 /*\r
  * Copies an item out of a queue.\r
  */\r
-static void prvCopyDataFromQueue( xQUEUE * const pxQueue, const void *pvBuffer );\r
+static void prvCopyDataFromQueue( xQUEUE * const pxQueue, const void *pvBuffer ) PRIVILEGED_FUNCTION;\r
 /*-----------------------------------------------------------*/\r
 \r
 /*\r
  * Macro to mark a queue as locked.  Locking a queue prevents an ISR from\r
  * accessing the queue event lists.\r
  */\r
-#define prvLockQueue( pxQueue )                        \\r
-{                                                                              \\r
-       taskENTER_CRITICAL();                           \\r
-               ++( pxQueue->xRxLock );                 \\r
-               ++( pxQueue->xTxLock );                 \\r
-       taskEXIT_CRITICAL();                            \\r
-}\r
+#define prvLockQueue( pxQueue )                                                                \\r
+       taskENTER_CRITICAL();                                                                   \\r
+       {                                                                                                               \\r
+               if( ( pxQueue )->xRxLock == queueUNLOCKED )                     \\r
+               {                                                                                                       \\r
+                       ( pxQueue )->xRxLock = queueLOCKED_UNMODIFIED;  \\r
+               }                                                                                                       \\r
+               if( ( pxQueue )->xTxLock == queueUNLOCKED )                     \\r
+               {                                                                                                       \\r
+                       ( pxQueue )->xTxLock = queueLOCKED_UNMODIFIED;  \\r
+               }                                                                                                       \\r
+       }                                                                                                               \\r
+       taskEXIT_CRITICAL()\r
 /*-----------------------------------------------------------*/\r
 \r
 \r
@@ -175,6 +256,7 @@ xQueueHandle xQueueCreate( unsigned portBASE_TYPE uxQueueLength, unsigned portBA
 {\r
 xQUEUE *pxNewQueue;\r
 size_t xQueueSizeInBytes;\r
+xQueueHandle xReturn = NULL;\r
 \r
        /* Allocate the new queue structure. */\r
        if( uxQueueLength > ( unsigned portBASE_TYPE ) 0 )\r
@@ -186,15 +268,15 @@ size_t xQueueSizeInBytes;
                        longer than asked for to make wrap checking easier/faster. */\r
                        xQueueSizeInBytes = ( size_t ) ( uxQueueLength * uxItemSize ) + ( size_t ) 1;\r
 \r
-                       pxNewQueue->pcHead = ( signed portCHAR * ) pvPortMalloc( xQueueSizeInBytes );\r
+                       pxNewQueue->pcHead = ( signed char * ) pvPortMalloc( xQueueSizeInBytes );\r
                        if( pxNewQueue->pcHead != NULL )\r
                        {\r
                                /* Initialise the queue members as described above where the\r
                                queue type is defined. */\r
                                pxNewQueue->pcTail = pxNewQueue->pcHead + ( uxQueueLength * uxItemSize );\r
-                               pxNewQueue->uxMessagesWaiting = 0;\r
+                               pxNewQueue->uxMessagesWaiting = ( unsigned portBASE_TYPE ) 0U;\r
                                pxNewQueue->pcWriteTo = pxNewQueue->pcHead;\r
-                               pxNewQueue->pcReadFrom = pxNewQueue->pcHead + ( ( uxQueueLength - 1 ) * uxItemSize );\r
+                               pxNewQueue->pcReadFrom = pxNewQueue->pcHead + ( ( uxQueueLength - ( unsigned portBASE_TYPE ) 1U ) * uxItemSize );\r
                                pxNewQueue->uxLength = uxQueueLength;\r
                                pxNewQueue->uxItemSize = uxItemSize;\r
                                pxNewQueue->xRxLock = queueUNLOCKED;\r
@@ -204,18 +286,20 @@ size_t xQueueSizeInBytes;
                                vListInitialise( &( pxNewQueue->xTasksWaitingToSend ) );\r
                                vListInitialise( &( pxNewQueue->xTasksWaitingToReceive ) );\r
 \r
-                               return  pxNewQueue;\r
+                               traceQUEUE_CREATE( pxNewQueue );\r
+                               xReturn = pxNewQueue;\r
                        }\r
                        else\r
                        {\r
+                               traceQUEUE_CREATE_FAILED();\r
                                vPortFree( pxNewQueue );\r
                        }\r
                }\r
        }\r
 \r
-       /* Will only reach here if we could not allocate enough memory or no memory\r
-       was required. */\r
-       return NULL;\r
+       configASSERT( xReturn );\r
+\r
+       return xReturn;\r
 }\r
 /*-----------------------------------------------------------*/\r
 \r
@@ -224,7 +308,7 @@ size_t xQueueSizeInBytes;
        xQueueHandle xQueueCreateMutex( void )\r
        {\r
        xQUEUE *pxNewQueue;\r
-       \r
+\r
                /* Allocate the new queue structure. */\r
                pxNewQueue = ( xQUEUE * ) pvPortMalloc( sizeof( xQUEUE ) );\r
                if( pxNewQueue != NULL )\r
@@ -232,48 +316,151 @@ size_t xQueueSizeInBytes;
                        /* Information required for priority inheritance. */\r
                        pxNewQueue->pxMutexHolder = NULL;\r
                        pxNewQueue->uxQueueType = queueQUEUE_IS_MUTEX;\r
-       \r
+\r
                        /* Queues used as a mutex no data is actually copied into or out\r
                        of the queue. */\r
                        pxNewQueue->pcWriteTo = NULL;\r
                        pxNewQueue->pcReadFrom = NULL;\r
-                       \r
+\r
                        /* Each mutex has a length of 1 (like a binary semaphore) and\r
                        an item size of 0 as nothing is actually copied into or out\r
                        of the mutex. */\r
-                       pxNewQueue->uxMessagesWaiting = 0;\r
-                       pxNewQueue->uxLength = 1;\r
-                       pxNewQueue->uxItemSize = 0;\r
+                       pxNewQueue->uxMessagesWaiting = ( unsigned portBASE_TYPE ) 0U;\r
+                       pxNewQueue->uxLength = ( unsigned portBASE_TYPE ) 1U;\r
+                       pxNewQueue->uxItemSize = ( unsigned portBASE_TYPE ) 0U;\r
                        pxNewQueue->xRxLock = queueUNLOCKED;\r
                        pxNewQueue->xTxLock = queueUNLOCKED;\r
-       \r
+\r
                        /* Ensure the event queues start with the correct state. */\r
                        vListInitialise( &( pxNewQueue->xTasksWaitingToSend ) );\r
                        vListInitialise( &( pxNewQueue->xTasksWaitingToReceive ) );\r
 \r
                        /* Start with the semaphore in the expected state. */\r
-                       xQueueGenericSend( pxNewQueue, NULL, 0, queueSEND_TO_BACK );\r
+                       xQueueGenericSend( pxNewQueue, NULL, ( portTickType ) 0U, queueSEND_TO_BACK );\r
+\r
+                       traceCREATE_MUTEX( pxNewQueue );\r
                }\r
-       \r
+               else\r
+               {\r
+                       traceCREATE_MUTEX_FAILED();\r
+               }\r
+\r
+               configASSERT( pxNewQueue );\r
                return pxNewQueue;\r
        }\r
 \r
 #endif /* configUSE_MUTEXES */\r
 /*-----------------------------------------------------------*/\r
 \r
+#if configUSE_RECURSIVE_MUTEXES == 1\r
+\r
+       portBASE_TYPE xQueueGiveMutexRecursive( xQueueHandle pxMutex )\r
+       {\r
+       portBASE_TYPE xReturn;\r
+\r
+               configASSERT( pxMutex );\r
+\r
+               /* If this is the task that holds the mutex then pxMutexHolder will not\r
+               change outside of this task.  If this task does not hold the mutex then\r
+               pxMutexHolder can never coincidentally equal the tasks handle, and as\r
+               this is the only condition we are interested in it does not matter if\r
+               pxMutexHolder is accessed simultaneously by another task.  Therefore no\r
+               mutual exclusion is required to test the pxMutexHolder variable. */\r
+               if( pxMutex->pxMutexHolder == xTaskGetCurrentTaskHandle() )\r
+               {\r
+                       traceGIVE_MUTEX_RECURSIVE( pxMutex );\r
+\r
+                       /* uxRecursiveCallCount cannot be zero if pxMutexHolder is equal to\r
+                       the task handle, therefore no underflow check is required.  Also,\r
+                       uxRecursiveCallCount is only modified by the mutex holder, and as\r
+                       there can only be one, no mutual exclusion is required to modify the\r
+                       uxRecursiveCallCount member. */\r
+                       ( pxMutex->uxRecursiveCallCount )--;\r
+\r
+                       /* Have we unwound the call count? */\r
+                       if( pxMutex->uxRecursiveCallCount == 0 )\r
+                       {\r
+                               /* Return the mutex.  This will automatically unblock any other\r
+                               task that might be waiting to access the mutex. */\r
+                               xQueueGenericSend( pxMutex, NULL, queueMUTEX_GIVE_BLOCK_TIME, queueSEND_TO_BACK );\r
+                       }\r
+\r
+                       xReturn = pdPASS;\r
+               }\r
+               else\r
+               {\r
+                       /* We cannot give the mutex because we are not the holder. */\r
+                       xReturn = pdFAIL;\r
+\r
+                       traceGIVE_MUTEX_RECURSIVE_FAILED( pxMutex );\r
+               }\r
+\r
+               return xReturn;\r
+       }\r
+\r
+#endif /* configUSE_RECURSIVE_MUTEXES */\r
+/*-----------------------------------------------------------*/\r
+\r
+#if configUSE_RECURSIVE_MUTEXES == 1\r
+\r
+       portBASE_TYPE xQueueTakeMutexRecursive( xQueueHandle pxMutex, portTickType xBlockTime )\r
+       {\r
+       portBASE_TYPE xReturn;\r
+\r
+               configASSERT( pxMutex );\r
+\r
+               /* Comments regarding mutual exclusion as per those within\r
+               xQueueGiveMutexRecursive(). */\r
+\r
+               traceTAKE_MUTEX_RECURSIVE( pxMutex );\r
+\r
+               if( pxMutex->pxMutexHolder == xTaskGetCurrentTaskHandle() )\r
+               {\r
+                       ( pxMutex->uxRecursiveCallCount )++;\r
+                       xReturn = pdPASS;\r
+               }\r
+               else\r
+               {\r
+                       xReturn = xQueueGenericReceive( pxMutex, NULL, xBlockTime, pdFALSE );\r
+\r
+                       /* pdPASS will only be returned if we successfully obtained the mutex,\r
+                       we may have blocked to reach here. */\r
+                       if( xReturn == pdPASS )\r
+                       {\r
+                               ( pxMutex->uxRecursiveCallCount )++;\r
+                       }\r
+                       else\r
+                       {\r
+                               traceTAKE_MUTEX_RECURSIVE_FAILED( pxMutex );\r
+                       }\r
+               }\r
+\r
+               return xReturn;\r
+       }\r
+\r
+#endif /* configUSE_RECURSIVE_MUTEXES */\r
+/*-----------------------------------------------------------*/\r
+\r
 #if configUSE_COUNTING_SEMAPHORES == 1\r
 \r
        xQueueHandle xQueueCreateCountingSemaphore( unsigned portBASE_TYPE uxCountValue, unsigned portBASE_TYPE uxInitialCount )\r
        {\r
        xQueueHandle pxHandle;\r
-       \r
+\r
                pxHandle = xQueueCreate( ( unsigned portBASE_TYPE ) uxCountValue, queueSEMAPHORE_QUEUE_ITEM_LENGTH );\r
 \r
                if( pxHandle != NULL )\r
                {\r
                        pxHandle->uxMessagesWaiting = uxInitialCount;\r
+\r
+                       traceCREATE_COUNTING_SEMAPHORE();\r
+               }\r
+               else\r
+               {\r
+                       traceCREATE_COUNTING_SEMAPHORE_FAILED();\r
                }\r
 \r
+               configASSERT( pxHandle );\r
                return pxHandle;\r
        }\r
 \r
@@ -282,178 +469,120 @@ size_t xQueueSizeInBytes;
 \r
 signed portBASE_TYPE xQueueGenericSend( xQueueHandle pxQueue, const void * const pvItemToQueue, portTickType xTicksToWait, portBASE_TYPE xCopyPosition )\r
 {\r
-signed portBASE_TYPE xReturn = pdPASS;\r
+signed portBASE_TYPE xEntryTimeSet = pdFALSE;\r
 xTimeOutType xTimeOut;\r
 \r
-       /* Make sure other tasks do not access the queue. */\r
-       vTaskSuspendAll();\r
-\r
-       /* Capture the current time status for future reference. */\r
-       vTaskSetTimeOutState( &xTimeOut );\r
-\r
-       /* It is important that this is the only thread/ISR that modifies the\r
-       ready or delayed lists until xTaskResumeAll() is called.  Places where\r
-       the ready/delayed lists are modified include:\r
-\r
-               + vTaskDelay() -  Nothing can call vTaskDelay as the scheduler is\r
-                 suspended, vTaskDelay() cannot be called from an ISR.\r
-               + vTaskPrioritySet() - Has a critical section around the access.\r
-               + vTaskSwitchContext() - This will not get executed while the scheduler\r
-                 is suspended.\r
-               + prvCheckDelayedTasks() - This will not get executed while the\r
-                 scheduler is suspended.\r
-               + xTaskCreate() - Has a critical section around the access.\r
-               + vTaskResume() - Has a critical section around the access.\r
-               + xTaskResumeAll() - Has a critical section around the access.\r
-               + xTaskRemoveFromEventList - Checks to see if the scheduler is\r
-                 suspended.  If so then the TCB being removed from the event is\r
-                 removed from the event and added to the xPendingReadyList.\r
-       */\r
-\r
-       /* Make sure interrupts do not access the queue event list. */\r
-       prvLockQueue( pxQueue );\r
-\r
-       /* It is important that interrupts to not access the event list of the\r
-       queue being modified here.  Places where the event list is modified\r
-       include:\r
-\r
-               + xQueueGenericSendFromISR().  This checks the lock on the queue to see\r
-                 if it has access.  If the queue is locked then the Tx lock count is\r
-                 incremented to signify that a task waiting for data can be made ready\r
-                 once the queue lock is removed.  If the queue is not locked then\r
-                 a task can be moved from the event list, but will not be removed\r
-                 from the delayed list or placed in the ready list until the scheduler\r
-                 is unlocked.\r
-\r
-               + xQueueReceiveFromISR().  As per xQueueGenericSendFromISR().\r
-       */\r
-               \r
-       /* If the queue is already full we may have to block. */\r
-       do\r
+       configASSERT( pxQueue );\r
+       configASSERT( !( ( pvItemToQueue == NULL ) && ( pxQueue->uxItemSize != ( unsigned portBASE_TYPE ) 0U ) ) );\r
+\r
+       /* This function relaxes the coding standard somewhat to allow return\r
+       statements within the function itself.  This is done in the interest\r
+       of execution time efficiency. */\r
+       for( ;; )\r
        {\r
-               if( prvIsQueueFull( pxQueue ) )\r
+               taskENTER_CRITICAL();\r
                {\r
-                       /* The queue is full - do we want to block or just leave without\r
-                       posting? */\r
-                       if( xTicksToWait > ( portTickType ) 0 )\r
+                       /* Is there room on the queue now?  To be running we must be\r
+                       the highest priority task wanting to access the queue. */\r
+                       if( pxQueue->uxMessagesWaiting < pxQueue->uxLength )\r
                        {\r
-                               /* We are going to place ourselves on the xTasksWaitingToSend event\r
-                               list, and will get woken should the delay expire, or space become\r
-                               available on the queue.\r
-                               \r
-                               As detailed above we do not require mutual exclusion on the event\r
-                               list as nothing else can modify it or the ready lists while we\r
-                               have the scheduler suspended and queue locked.\r
-                               \r
-                               It is possible that an ISR has removed data from the queue since we\r
-                               checked if any was available.  If this is the case then the data\r
-                               will have been copied from the queue, and the queue variables\r
-                               updated, but the event list will not yet have been checked to see if\r
-                               anything is waiting as the queue is locked. */\r
-                               vTaskPlaceOnEventList( &( pxQueue->xTasksWaitingToSend ), xTicksToWait );\r
-       \r
-                               /* Force a context switch now as we are blocked.  We can do\r
-                               this from within a critical section as the task we are\r
-                               switching to has its own context.  When we return here (i.e. we\r
-                               unblock) we will leave the critical section as normal.\r
-                               \r
-                               It is possible that an ISR has caused an event on an unrelated and\r
-                               unlocked queue.  If this was the case then the event list for that\r
-                               queue will have been updated but the ready lists left unchanged -\r
-                               instead the readied task will have been added to the pending ready\r
-                               list. */\r
-                               taskENTER_CRITICAL();\r
-                               {\r
-                                       /* We can safely unlock the queue and scheduler here as\r
-                                       interrupts are disabled.  We must not yield with anything\r
-                                       locked, but we can yield from within a critical section.\r
-                                       \r
-                                       Tasks that have been placed on the pending ready list cannot\r
-                                       be tasks that are waiting for events on this queue.  See\r
-                                       in comment xTaskRemoveFromEventList(). */\r
-                                       prvUnlockQueue( pxQueue );\r
-       \r
-                                       /* Resuming the scheduler may cause a yield.  If so then there\r
-                                       is no point yielding again here. */\r
-                                       if( !xTaskResumeAll() )\r
-                                       {\r
-                                               taskYIELD();\r
-                                       }\r
+                               traceQUEUE_SEND( pxQueue );\r
+                               prvCopyDataToQueue( pxQueue, pvItemToQueue, xCopyPosition );\r
 \r
-                                       /* We want to check to see if the queue is still full\r
-                                       before leaving the critical section.  This is to prevent\r
-                                       this task placing an item into the queue due to an\r
-                                       interrupt making space on the queue between critical\r
-                                       sections (when there might be a higher priority task\r
-                                       blocked on the queue that cannot run yet because the\r
-                                       scheduler gets suspended). */\r
-                                       if( pxQueue->uxMessagesWaiting == pxQueue->uxLength )\r
+                               /* If there was a task waiting for data to arrive on the\r
+                               queue then unblock it now. */\r
+                               if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE )\r
+                               {\r
+                                       if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) == pdTRUE )\r
                                        {\r
-                                               /* We unblocked but there is no space in the queue,\r
-                                               we probably timed out. */\r
-                                               xReturn = errQUEUE_FULL;\r
+                                               /* The unblocked task has a priority higher than\r
+                                               our own so yield immediately.  Yes it is ok to do\r
+                                               this from within the critical section - the kernel\r
+                                               takes care of that. */\r
+                                               portYIELD_WITHIN_API();\r
                                        }\r
-       \r
-                                       /* Before leaving the critical section we have to ensure\r
-                                       exclusive access again. */\r
-                                       vTaskSuspendAll();\r
-                                       prvLockQueue( pxQueue );                                \r
                                }\r
+\r
                                taskEXIT_CRITICAL();\r
+\r
+                               /* Return to the original privilege level before exiting the\r
+                               function. */\r
+                               return pdPASS;\r
                        }\r
-               }\r
-                       \r
-               /* If xReturn is errQUEUE_FULL then we unblocked when the queue\r
-               was still full.  Don't check it again now as it is possible that\r
-               an interrupt has removed an item from the queue since we left the\r
-               critical section and we don't want to write to the queue in case\r
-               there is a task of higher priority blocked waiting for space to\r
-               be available on the queue.  If this is the case the higher priority\r
-               task will execute when the scheduler is unsupended. */\r
-               if( xReturn != errQUEUE_FULL )\r
-               {\r
-                       /* When we are here it is possible that we unblocked as space became\r
-                       available on the queue.  It is also possible that an ISR posted to the\r
-                       queue since we left the critical section, so it may be that again there\r
-                       is no space.  This would only happen if a task and ISR post onto the\r
-                       same queue. */\r
-                       taskENTER_CRITICAL();\r
+                       else\r
                        {\r
-                               if( pxQueue->uxMessagesWaiting < pxQueue->uxLength )\r
+                               if( xTicksToWait == ( portTickType ) 0 )\r
                                {\r
-                                       /* There is room in the queue, copy the data into the queue. */                 \r
-                                       prvCopyDataToQueue( pxQueue, pvItemToQueue, xCopyPosition );\r
-                                       xReturn = pdPASS;\r
-               \r
-                                       /* Update the TxLock count so prvUnlockQueue knows to check for\r
-                                       tasks waiting for data to become available in the queue. */\r
-                                       ++( pxQueue->xTxLock );\r
+                                       /* The queue was full and no block time is specified (or\r
+                                       the block time has expired) so leave now. */\r
+                                       taskEXIT_CRITICAL();\r
+\r
+                                       /* Return to the original privilege level before exiting\r
+                                       the function. */\r
+                                       traceQUEUE_SEND_FAILED( pxQueue );\r
+                                       return errQUEUE_FULL;\r
                                }\r
-                               else\r
+                               else if( xEntryTimeSet == pdFALSE )\r
                                {\r
-                                       xReturn = errQUEUE_FULL;\r
+                                       /* The queue was full and a block time was specified so\r
+                                       configure the timeout structure. */\r
+                                       vTaskSetTimeOutState( &xTimeOut );\r
+                                       xEntryTimeSet = pdTRUE;\r
                                }\r
                        }\r
-                       taskEXIT_CRITICAL();\r
                }\r
+               taskEXIT_CRITICAL();\r
+\r
+               /* Interrupts and other tasks can send to and receive from the queue\r
+               now the critical section has been exited. */\r
 \r
-               if( xReturn == errQUEUE_FULL )\r
+               vTaskSuspendAll();\r
+               prvLockQueue( pxQueue );\r
+\r
+               /* Update the timeout state to see if it has expired yet. */\r
+               if( xTaskCheckForTimeOut( &xTimeOut, &xTicksToWait ) == pdFALSE )\r
                {\r
-                       if( xTicksToWait > 0 )\r
+                       if( prvIsQueueFull( pxQueue ) != pdFALSE )\r
                        {\r
-                               if( xTaskCheckForTimeOut( &xTimeOut, &xTicksToWait ) == pdFALSE )\r
+                               traceBLOCKING_ON_QUEUE_SEND( pxQueue );\r
+                               vTaskPlaceOnEventList( &( pxQueue->xTasksWaitingToSend ), xTicksToWait );\r
+\r
+                               /* Unlocking the queue means queue events can effect the\r
+                               event list.  It is possible     that interrupts occurring now\r
+                               remove this task from the event list again - but as the\r
+                               scheduler is suspended the task will go onto the pending\r
+                               ready last instead of the actual ready list. */\r
+                               prvUnlockQueue( pxQueue );\r
+\r
+                               /* Resuming the scheduler will move tasks from the pending\r
+                               ready list into the ready list - so it is feasible that this\r
+                               task is already in a ready list before it yields - in which\r
+                               case the yield will not cause a context switch unless there\r
+                               is also a higher priority task in the pending ready list. */\r
+                               if( xTaskResumeAll() == pdFALSE )\r
                                {\r
-                                       xReturn = queueERRONEOUS_UNBLOCK;\r
+                                       portYIELD_WITHIN_API();\r
                                }\r
                        }\r
+                       else\r
+                       {\r
+                               /* Try again. */\r
+                               prvUnlockQueue( pxQueue );\r
+                               ( void ) xTaskResumeAll();\r
+                       }\r
+               }\r
+               else\r
+               {\r
+                       /* The timeout has expired. */\r
+                       prvUnlockQueue( pxQueue );\r
+                       ( void ) xTaskResumeAll();\r
+\r
+                       /* Return to the original privilege level before exiting the\r
+                       function. */\r
+                       traceQUEUE_SEND_FAILED( pxQueue );\r
+                       return errQUEUE_FULL;\r
                }\r
        }\r
-       while( xReturn == queueERRONEOUS_UNBLOCK );\r
-\r
-       prvUnlockQueue( pxQueue );\r
-       xTaskResumeAll();\r
-\r
-       return xReturn;\r
 }\r
 /*-----------------------------------------------------------*/\r
 \r
@@ -461,84 +590,74 @@ xTimeOutType xTimeOut;
 \r
        signed portBASE_TYPE xQueueAltGenericSend( xQueueHandle pxQueue, const void * const pvItemToQueue, portTickType xTicksToWait, portBASE_TYPE xCopyPosition )\r
        {\r
-       signed portBASE_TYPE xReturn;\r
+       signed portBASE_TYPE xEntryTimeSet = pdFALSE;\r
        xTimeOutType xTimeOut;\r
 \r
-               /* The source code that implements the light weight (fast) API is much \r
-               simpler because it executes everything from within a critical section.  \r
-               This is the approach taken by many other RTOSes, but FreeRTOS.org has the \r
-               fully featured API as an alternative.  The fully featured API has more \r
-               complex code that takes longer to execute, but makes much less use of \r
-               critical sections.  Therefore the light weight API sacrifices interrupt \r
-               responsiveness to gain execution speed, whereas the fully featured API\r
-               sacrifices execution speed to ensure better interrupt responsiveness.  */\r
+               configASSERT( pxQueue );\r
+               configASSERT( !( ( pvItemToQueue == NULL ) && ( pxQueue->uxItemSize != ( unsigned portBASE_TYPE ) 0U ) ) );\r
 \r
-               taskENTER_CRITICAL();\r
+               for( ;; )\r
                {\r
-                       /* Capture the current time status for future reference. */\r
-                       vTaskSetTimeOutState( &xTimeOut );\r
-\r
-                       /* If the queue is already full we may have to block. */\r
-                       do\r
+                       taskENTER_CRITICAL();\r
                        {\r
-                               if( pxQueue->uxMessagesWaiting == pxQueue->uxLength )\r
-                               {\r
-                                       /* The queue is full - do we want to block or just leave without\r
-                                       posting? */\r
-                                       if( xTicksToWait > ( portTickType ) 0 )\r
-                                       {\r
-                                               /* We are going to place ourselves on the xTasksWaitingToSend \r
-                                               event list, and will get woken should the delay expire, or \r
-                                               space become available on the queue. */\r
-                                               vTaskPlaceOnEventList( &( pxQueue->xTasksWaitingToSend ), xTicksToWait );\r
-                       \r
-                                               /* Force a context switch now as we are blocked.  We can do\r
-                                               this from within a critical section as the task we are\r
-                                               switching to has its own context.  When we return here (i.e.\r
-                                               we unblock) we will leave the critical section as normal. */\r
-                                               taskYIELD();\r
-                                       }\r
-                               }\r
-                                       \r
+                               /* Is there room on the queue now?  To be running we must be\r
+                               the highest priority task wanting to access the queue. */\r
                                if( pxQueue->uxMessagesWaiting < pxQueue->uxLength )\r
                                {\r
-                                       /* There is room in the queue, copy the data into the queue. */                 \r
+                                       traceQUEUE_SEND( pxQueue );\r
                                        prvCopyDataToQueue( pxQueue, pvItemToQueue, xCopyPosition );\r
-                                       xReturn = pdPASS;\r
 \r
-                                       if( !listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) )\r
+                                       /* If there was a task waiting for data to arrive on the\r
+                                       queue then unblock it now. */\r
+                                       if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE )\r
                                        {\r
-                                               if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE )\r
+                                               if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) == pdTRUE )\r
                                                {\r
-                                                       /* The task waiting has a higher priority. */\r
-                                                       taskYIELD();\r
+                                                       /* The unblocked task has a priority higher than\r
+                                                       our own so yield immediately. */\r
+                                                       portYIELD_WITHIN_API();\r
                                                }\r
-                                       }                       \r
+                                       }\r
+\r
+                                       taskEXIT_CRITICAL();\r
+                                       return pdPASS;\r
                                }\r
                                else\r
                                {\r
-                                       xReturn = errQUEUE_FULL;\r
-\r
-                                       if( xTicksToWait > 0 )\r
-                                       {                                       \r
-                                               if( xTaskCheckForTimeOut( &xTimeOut, &xTicksToWait ) == pdFALSE )\r
-                                               {\r
-                                                       /* Another task must have accessed the queue between \r
-                                                       this task unblocking and actually executing. */\r
-                                                       xReturn = queueERRONEOUS_UNBLOCK;\r
-                                               }\r
+                                       if( xTicksToWait == ( portTickType ) 0 )\r
+                                       {\r
+                                               taskEXIT_CRITICAL();\r
+                                               return errQUEUE_FULL;\r
                                        }\r
-                                       else\r
+                                       else if( xEntryTimeSet == pdFALSE )\r
                                        {\r
-                                               \r
+                                               vTaskSetTimeOutState( &xTimeOut );\r
+                                               xEntryTimeSet = pdTRUE;\r
                                        }\r
                                }\r
                        }\r
-                       while( xReturn == queueERRONEOUS_UNBLOCK );\r
-               }\r
-               taskEXIT_CRITICAL();\r
+                       taskEXIT_CRITICAL();\r
 \r
-               return xReturn;\r
+                       taskENTER_CRITICAL();\r
+                       {\r
+                               if( xTaskCheckForTimeOut( &xTimeOut, &xTicksToWait ) == pdFALSE )\r
+                               {\r
+                                       if( prvIsQueueFull( pxQueue ) != pdFALSE )\r
+                                       {\r
+                                               traceBLOCKING_ON_QUEUE_SEND( pxQueue );\r
+                                               vTaskPlaceOnEventList( &( pxQueue->xTasksWaitingToSend ), xTicksToWait );\r
+                                               portYIELD_WITHIN_API();\r
+                                       }\r
+                               }\r
+                               else\r
+                               {\r
+                                       taskEXIT_CRITICAL();\r
+                                       traceQUEUE_SEND_FAILED( pxQueue );\r
+                                       return errQUEUE_FULL;\r
+                               }\r
+                       }\r
+                       taskEXIT_CRITICAL();\r
+               }\r
        }\r
 \r
 #endif /* configUSE_ALTERNATIVE_API */\r
@@ -546,49 +665,19 @@ xTimeOutType xTimeOut;
 \r
 #if configUSE_ALTERNATIVE_API == 1\r
 \r
-       signed portBASE_TYPE xQueueAltGenericReceive( xQueueHandle pxQueue, const void * const pvBuffer, portTickType xTicksToWait, portBASE_TYPE xJustPeeking )\r
+       signed portBASE_TYPE xQueueAltGenericReceive( xQueueHandle pxQueue, void * const pvBuffer, portTickType xTicksToWait, portBASE_TYPE xJustPeeking )\r
        {\r
-       signed portBASE_TYPE xReturn = pdTRUE;\r
+       signed portBASE_TYPE xEntryTimeSet = pdFALSE;\r
        xTimeOutType xTimeOut;\r
-       signed portCHAR *pcOriginalReadPosition;\r
+       signed char *pcOriginalReadPosition;\r
 \r
-               /* The source code that implements the light weight (fast) API is much \r
-               simpler because it executes everything from within a critical section.  \r
-               This is the approach taken by many other RTOSes, but FreeRTOS.org has the \r
-               fully featured API as an alternative.  The fully featured API has more \r
-               complex code that takes longer to execute, but makes much less use of \r
-               critical sections.  Therefore the light weight API sacrifices interrupt \r
-               responsiveness to gain execution speed, whereas the fully featured API\r
-               sacrifices execution speed to ensure better interrupt responsiveness.  */\r
+               configASSERT( pxQueue );\r
+               configASSERT( !( ( pvBuffer == NULL ) && ( pxQueue->uxItemSize != ( unsigned portBASE_TYPE ) 0U ) ) );\r
 \r
-               taskENTER_CRITICAL();\r
+               for( ;; )\r
                {\r
-                       /* Capture the current time status for future reference. */\r
-                       vTaskSetTimeOutState( &xTimeOut );\r
-\r
-                       do\r
+                       taskENTER_CRITICAL();\r
                        {\r
-                               /* If there are no messages in the queue we may have to block. */\r
-                               if( pxQueue->uxMessagesWaiting == ( unsigned portBASE_TYPE ) 0 )\r
-                               {\r
-                                       /* There are no messages in the queue, do we want to block or just\r
-                                       leave with nothing? */                  \r
-                                       if( xTicksToWait > ( portTickType ) 0 )\r
-                                       {\r
-                                               #if ( configUSE_MUTEXES == 1 )\r
-                                               {\r
-                                                       if( pxQueue->uxQueueType == queueQUEUE_IS_MUTEX )\r
-                                                       {\r
-                                                               vTaskPriorityInherit( ( void * const ) pxQueue->pxMutexHolder );\r
-                                                       }\r
-                                               }\r
-                                               #endif\r
-                                               \r
-                                               vTaskPlaceOnEventList( &( pxQueue->xTasksWaitingToReceive ), xTicksToWait );\r
-                                               taskYIELD();\r
-                                       }\r
-                               }\r
-                       \r
                                if( pxQueue->uxMessagesWaiting > ( unsigned portBASE_TYPE ) 0 )\r
                                {\r
                                        /* Remember our read position in case we are just peeking. */\r
@@ -598,9 +687,11 @@ xTimeOutType xTimeOut;
 \r
                                        if( xJustPeeking == pdFALSE )\r
                                        {\r
+                                               traceQUEUE_RECEIVE( pxQueue );\r
+\r
                                                /* We are actually removing data. */\r
                                                --( pxQueue->uxMessagesWaiting );\r
-                                                       \r
+\r
                                                #if ( configUSE_MUTEXES == 1 )\r
                                                {\r
                                                        if( pxQueue->uxQueueType == queueQUEUE_IS_MUTEX )\r
@@ -612,243 +703,327 @@ xTimeOutType xTimeOut;
                                                }\r
                                                #endif\r
 \r
-                                               if( !listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) )\r
+                                               if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) == pdFALSE )\r
                                                {\r
-                                                       if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) != pdFALSE )\r
+                                                       if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) == pdTRUE )\r
                                                        {\r
-                                                               /* The task waiting has a higher priority. */\r
-                                                               taskYIELD();\r
+                                                               portYIELD_WITHIN_API();\r
                                                        }\r
                                                }\r
                                        }\r
                                        else\r
                                        {\r
+                                               traceQUEUE_PEEK( pxQueue );\r
+\r
                                                /* We are not removing the data, so reset our read\r
                                                pointer. */\r
                                                pxQueue->pcReadFrom = pcOriginalReadPosition;\r
+\r
+                                               /* The data is being left in the queue, so see if there are\r
+                                               any other tasks waiting for the data. */\r
+                                               if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE )\r
+                                               {\r
+                                                       /* Tasks that are removed from the event list will get added to\r
+                                                       the pending ready list as the scheduler is still suspended. */\r
+                                                       if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE )\r
+                                                       {\r
+                                                               /* The task waiting has a higher priority than this task. */\r
+                                                               portYIELD_WITHIN_API();\r
+                                                       }\r
+                                               }\r
+\r
                                        }\r
-                                       \r
-                                       xReturn = pdPASS;                                       \r
+\r
+                                       taskEXIT_CRITICAL();\r
+                                       return pdPASS;\r
                                }\r
                                else\r
                                {\r
-                                       xReturn = errQUEUE_EMPTY;\r
+                                       if( xTicksToWait == ( portTickType ) 0 )\r
+                                       {\r
+                                               taskEXIT_CRITICAL();\r
+                                               traceQUEUE_RECEIVE_FAILED( pxQueue );\r
+                                               return errQUEUE_EMPTY;\r
+                                       }\r
+                                       else if( xEntryTimeSet == pdFALSE )\r
+                                       {\r
+                                               vTaskSetTimeOutState( &xTimeOut );\r
+                                               xEntryTimeSet = pdTRUE;\r
+                                       }\r
+                               }\r
+                       }\r
+                       taskEXIT_CRITICAL();\r
 \r
-                                       if( xTicksToWait > 0 )\r
+                       taskENTER_CRITICAL();\r
+                       {\r
+                               if( xTaskCheckForTimeOut( &xTimeOut, &xTicksToWait ) == pdFALSE )\r
+                               {\r
+                                       if( prvIsQueueEmpty( pxQueue ) != pdFALSE )\r
                                        {\r
-                                               if( xTaskCheckForTimeOut( &xTimeOut, &xTicksToWait ) == pdFALSE )\r
+                                               traceBLOCKING_ON_QUEUE_RECEIVE( pxQueue );\r
+\r
+                                               #if ( configUSE_MUTEXES == 1 )\r
                                                {\r
-                                                       xReturn = queueERRONEOUS_UNBLOCK;\r
+                                                       if( pxQueue->uxQueueType == queueQUEUE_IS_MUTEX )\r
+                                                       {\r
+                                                               portENTER_CRITICAL();\r
+                                                                       vTaskPriorityInherit( ( void * ) pxQueue->pxMutexHolder );\r
+                                                               portEXIT_CRITICAL();\r
+                                                       }\r
                                                }\r
+                                               #endif\r
+\r
+                                               vTaskPlaceOnEventList( &( pxQueue->xTasksWaitingToReceive ), xTicksToWait );\r
+                                               portYIELD_WITHIN_API();\r
                                        }\r
                                }\r
-\r
-                       } while( xReturn == queueERRONEOUS_UNBLOCK );\r
+                               else\r
+                               {\r
+                                       taskEXIT_CRITICAL();\r
+                                       traceQUEUE_RECEIVE_FAILED( pxQueue );\r
+                                       return errQUEUE_EMPTY;\r
+                               }\r
+                       }\r
+                       taskEXIT_CRITICAL();\r
                }\r
-               taskEXIT_CRITICAL();\r
-\r
-               return xReturn;\r
        }\r
 \r
+\r
 #endif /* configUSE_ALTERNATIVE_API */\r
 /*-----------------------------------------------------------*/\r
 \r
-signed portBASE_TYPE xQueueGenericSendFromISR( xQueueHandle pxQueue, const void * const pvItemToQueue, signed portBASE_TYPE xTaskPreviouslyWoken, portBASE_TYPE xCopyPosition )\r
+signed portBASE_TYPE xQueueGenericSendFromISR( xQueueHandle pxQueue, const void * const pvItemToQueue, signed portBASE_TYPE *pxHigherPriorityTaskWoken, portBASE_TYPE xCopyPosition )\r
 {\r
+signed portBASE_TYPE xReturn;\r
+unsigned portBASE_TYPE uxSavedInterruptStatus;\r
+\r
+       configASSERT( pxQueue );\r
+       configASSERT( pxHigherPriorityTaskWoken );\r
+       configASSERT( !( ( pvItemToQueue == NULL ) && ( pxQueue->uxItemSize != ( unsigned portBASE_TYPE ) 0U ) ) );\r
+\r
        /* Similar to xQueueGenericSend, except we don't block if there is no room\r
        in the queue.  Also we don't directly wake a task that was blocked on a\r
        queue read, instead we return a flag to say whether a context switch is\r
        required or not (i.e. has a task with a higher priority than us been woken\r
        by this post). */\r
-       if( pxQueue->uxMessagesWaiting < pxQueue->uxLength )\r
+       uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR();\r
        {\r
-               prvCopyDataToQueue( pxQueue, pvItemToQueue, xCopyPosition );\r
-\r
-               /* If the queue is locked we do not alter the event list.  This will\r
-               be done when the queue is unlocked later. */\r
-               if( pxQueue->xTxLock == queueUNLOCKED )\r
+               if( pxQueue->uxMessagesWaiting < pxQueue->uxLength )\r
                {\r
-                       /* We only want to wake one task per ISR, so check that a task has\r
-                       not already been woken. */\r
-                       if( !xTaskPreviouslyWoken )             \r
+                       traceQUEUE_SEND_FROM_ISR( pxQueue );\r
+\r
+                       prvCopyDataToQueue( pxQueue, pvItemToQueue, xCopyPosition );\r
+\r
+                       /* If the queue is locked we do not alter the event list.  This will\r
+                       be done when the queue is unlocked later. */\r
+                       if( pxQueue->xTxLock == queueUNLOCKED )\r
                        {\r
-                               if( !listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) )\r
+                               if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE )\r
                                {\r
                                        if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE )\r
                                        {\r
                                                /* The task waiting has a higher priority so record that a\r
                                                context switch is required. */\r
-                                               return pdTRUE;\r
+                                               *pxHigherPriorityTaskWoken = pdTRUE;\r
                                        }\r
                                }\r
                        }\r
+                       else\r
+                       {\r
+                               /* Increment the lock count so the task that unlocks the queue\r
+                               knows that data was posted while it was locked. */\r
+                               ++( pxQueue->xTxLock );\r
+                       }\r
+\r
+                       xReturn = pdPASS;\r
                }\r
                else\r
                {\r
-                       /* Increment the lock count so the task that unlocks the queue\r
-                       knows that data was posted while it was locked. */\r
-                       ++( pxQueue->xTxLock );\r
+                       traceQUEUE_SEND_FROM_ISR_FAILED( pxQueue );\r
+                       xReturn = errQUEUE_FULL;\r
                }\r
        }\r
+       portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus );\r
 \r
-       return xTaskPreviouslyWoken;\r
+       return xReturn;\r
 }\r
 /*-----------------------------------------------------------*/\r
 \r
-signed portBASE_TYPE xQueueGenericReceive( xQueueHandle pxQueue, const void * const pvBuffer, portTickType xTicksToWait, portBASE_TYPE xJustPeeking )\r
+signed portBASE_TYPE xQueueGenericReceive( xQueueHandle pxQueue, void * const pvBuffer, portTickType xTicksToWait, portBASE_TYPE xJustPeeking )\r
 {\r
-signed portBASE_TYPE xReturn = pdTRUE;\r
+signed portBASE_TYPE xEntryTimeSet = pdFALSE;\r
 xTimeOutType xTimeOut;\r
-signed portCHAR *pcOriginalReadPosition;\r
+signed char *pcOriginalReadPosition;\r
 \r
-       /* This function is very similar to xQueueGenericSend().  See comments\r
-       within xQueueGenericSend() for a more detailed explanation.\r
+       configASSERT( pxQueue );\r
+       configASSERT( !( ( pvBuffer == NULL ) && ( pxQueue->uxItemSize != ( unsigned portBASE_TYPE ) 0U ) ) );\r
 \r
-       Make sure other tasks do not access the queue. */\r
-       vTaskSuspendAll();\r
+       /* This function relaxes the coding standard somewhat to allow return\r
+       statements within the function itself.  This is done in the interest\r
+       of execution time efficiency. */\r
 \r
-       /* Capture the current time status for future reference. */\r
-       vTaskSetTimeOutState( &xTimeOut );\r
-\r
-       /* Make sure interrupts do not access the queue. */\r
-       prvLockQueue( pxQueue );\r
-\r
-       do\r
+       for( ;; )\r
        {\r
-               /* If there are no messages in the queue we may have to block. */\r
-               if( prvIsQueueEmpty( pxQueue ) )\r
+               taskENTER_CRITICAL();\r
                {\r
-                       /* There are no messages in the queue, do we want to block or just\r
-                       leave with nothing? */                  \r
-                       if( xTicksToWait > ( portTickType ) 0 )\r
+                       /* Is there data in the queue now?  To be running we must be\r
+                       the highest priority task wanting to access the queue. */\r
+                       if( pxQueue->uxMessagesWaiting > ( unsigned portBASE_TYPE ) 0 )\r
                        {\r
-                               #if ( configUSE_MUTEXES == 1 )\r
-                               {\r
-                                       if( pxQueue->uxQueueType == queueQUEUE_IS_MUTEX )\r
-                                       {\r
-                                               portENTER_CRITICAL();\r
-                                                       vTaskPriorityInherit( ( void * const ) pxQueue->pxMutexHolder );\r
-                                               portEXIT_CRITICAL();\r
-                                       }\r
-                               }\r
-                               #endif\r
-                               \r
-                               vTaskPlaceOnEventList( &( pxQueue->xTasksWaitingToReceive ), xTicksToWait );\r
-                               taskENTER_CRITICAL();\r
+                               /* Remember our read position in case we are just peeking. */\r
+                               pcOriginalReadPosition = pxQueue->pcReadFrom;\r
+\r
+                               prvCopyDataFromQueue( pxQueue, pvBuffer );\r
+\r
+                               if( xJustPeeking == pdFALSE )\r
                                {\r
-                                       prvUnlockQueue( pxQueue );\r
-                                       if( !xTaskResumeAll() )\r
+                                       traceQUEUE_RECEIVE( pxQueue );\r
+\r
+                                       /* We are actually removing data. */\r
+                                       --( pxQueue->uxMessagesWaiting );\r
+\r
+                                       #if ( configUSE_MUTEXES == 1 )\r
                                        {\r
-                                               taskYIELD();\r
+                                               if( pxQueue->uxQueueType == queueQUEUE_IS_MUTEX )\r
+                                               {\r
+                                                       /* Record the information required to implement\r
+                                                       priority inheritance should it become necessary. */\r
+                                                       pxQueue->pxMutexHolder = xTaskGetCurrentTaskHandle();\r
+                                               }\r
                                        }\r
+                                       #endif\r
 \r
-                                       if( pxQueue->uxMessagesWaiting == ( unsigned portBASE_TYPE ) 0 )\r
+                                       if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) == pdFALSE )\r
                                        {\r
-                                               /* We unblocked but the queue is empty.  We probably\r
-                                               timed out. */\r
-                                               xReturn = errQUEUE_EMPTY;\r
+                                               if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) == pdTRUE )\r
+                                               {\r
+                                                       portYIELD_WITHIN_API();\r
+                                               }\r
                                        }\r
-       \r
-                                       vTaskSuspendAll();\r
-                                       prvLockQueue( pxQueue );\r
                                }\r
-                               taskEXIT_CRITICAL();\r
-                       }\r
-               }\r
-       \r
-               if( xReturn != errQUEUE_EMPTY )\r
-               {\r
-                       taskENTER_CRITICAL();\r
-                       {\r
-                               if( pxQueue->uxMessagesWaiting > ( unsigned portBASE_TYPE ) 0 )\r
+                               else\r
                                {\r
-                                       /* Remember our read position in case we are just peeking. */\r
-                                       pcOriginalReadPosition = pxQueue->pcReadFrom;\r
+                                       traceQUEUE_PEEK( pxQueue );\r
 \r
-                                       prvCopyDataFromQueue( pxQueue, pvBuffer );\r
+                                       /* We are not removing the data, so reset our read\r
+                                       pointer. */\r
+                                       pxQueue->pcReadFrom = pcOriginalReadPosition;\r
 \r
-                                       if( xJustPeeking == pdFALSE )\r
+                                       /* The data is being left in the queue, so see if there are\r
+                                       any other tasks waiting for the data. */\r
+                                       if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE )\r
                                        {\r
-                                               /* We are actually removing data. */\r
-                                               --( pxQueue->uxMessagesWaiting );\r
-                                                       \r
-                                               /* Increment the lock count so prvUnlockQueue knows to check for\r
-                                               tasks waiting for space to become available on the queue. */\r
-                                               ++( pxQueue->xRxLock );\r
-                                               \r
-                                               #if ( configUSE_MUTEXES == 1 )\r
+                                               /* Tasks that are removed from the event list will get added to\r
+                                               the pending ready list as the scheduler is still suspended. */\r
+                                               if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE )\r
                                                {\r
-                                                       if( pxQueue->uxQueueType == queueQUEUE_IS_MUTEX )\r
-                                                       {\r
-                                                               /* Record the information required to implement\r
-                                                               priority inheritance should it become necessary. */\r
-                                                               pxQueue->pxMutexHolder = xTaskGetCurrentTaskHandle();\r
-                                                       }\r
+                                                       /* The task waiting has a higher priority than this task. */\r
+                                                       portYIELD_WITHIN_API();\r
                                                }\r
-                                               #endif\r
                                        }\r
-                                       else\r
-                                       {\r
-                                               /* We are not removing the data, so reset our read\r
-                                               pointer. */\r
-                                               pxQueue->pcReadFrom = pcOriginalReadPosition;\r
 \r
-                                               /* The data is being left in the queue, so increment the\r
-                                               lock count so prvUnlockQueue knows to check for other\r
-                                               tasks waiting for the data to be available. */\r
-                                               ++( pxQueue->xTxLock );                                         \r
-                                       }\r
-                                       \r
-                                       xReturn = pdPASS;                                       \r
                                }\r
-                               else\r
+\r
+                               taskEXIT_CRITICAL();\r
+                               return pdPASS;\r
+                       }\r
+                       else\r
+                       {\r
+                               if( xTicksToWait == ( portTickType ) 0 )\r
+                               {\r
+                                       /* The queue was empty and no block time is specified (or\r
+                                       the block time has expired) so leave now. */\r
+                                       taskEXIT_CRITICAL();\r
+                                       traceQUEUE_RECEIVE_FAILED( pxQueue );\r
+                                       return errQUEUE_EMPTY;\r
+                               }\r
+                               else if( xEntryTimeSet == pdFALSE )\r
                                {\r
-                                       xReturn = errQUEUE_EMPTY;\r
+                                       /* The queue was empty and a block time was specified so\r
+                                       configure the timeout structure. */\r
+                                       vTaskSetTimeOutState( &xTimeOut );\r
+                                       xEntryTimeSet = pdTRUE;\r
                                }\r
                        }\r
-                       taskEXIT_CRITICAL();\r
                }\r
+               taskEXIT_CRITICAL();\r
+\r
+               /* Interrupts and other tasks can send to and receive from the queue\r
+               now the critical section has been exited. */\r
 \r
-               if( xReturn == errQUEUE_EMPTY )\r
+               vTaskSuspendAll();\r
+               prvLockQueue( pxQueue );\r
+\r
+               /* Update the timeout state to see if it has expired yet. */\r
+               if( xTaskCheckForTimeOut( &xTimeOut, &xTicksToWait ) == pdFALSE )\r
                {\r
-                       if( xTicksToWait > 0 )\r
+                       if( prvIsQueueEmpty( pxQueue ) != pdFALSE )\r
                        {\r
-                               if( xTaskCheckForTimeOut( &xTimeOut, &xTicksToWait ) == pdFALSE )\r
+                               traceBLOCKING_ON_QUEUE_RECEIVE( pxQueue );\r
+\r
+                               #if ( configUSE_MUTEXES == 1 )\r
+                               {\r
+                                       if( pxQueue->uxQueueType == queueQUEUE_IS_MUTEX )\r
+                                       {\r
+                                               portENTER_CRITICAL();\r
+                                               {\r
+                                                       vTaskPriorityInherit( ( void * ) pxQueue->pxMutexHolder );\r
+                                               }\r
+                                               portEXIT_CRITICAL();\r
+                                       }\r
+                               }\r
+                               #endif\r
+\r
+                               vTaskPlaceOnEventList( &( pxQueue->xTasksWaitingToReceive ), xTicksToWait );\r
+                               prvUnlockQueue( pxQueue );\r
+                               if( xTaskResumeAll() == pdFALSE )\r
                                {\r
-                                       xReturn = queueERRONEOUS_UNBLOCK;\r
+                                       portYIELD_WITHIN_API();\r
                                }\r
                        }\r
+                       else\r
+                       {\r
+                               /* Try again. */\r
+                               prvUnlockQueue( pxQueue );\r
+                               ( void ) xTaskResumeAll();\r
+                       }\r
                }\r
-       } while( xReturn == queueERRONEOUS_UNBLOCK );\r
-\r
-       /* We no longer require exclusive access to the queue. */\r
-       prvUnlockQueue( pxQueue );\r
-       xTaskResumeAll();\r
-\r
-       return xReturn;\r
+               else\r
+               {\r
+                       prvUnlockQueue( pxQueue );\r
+                       ( void ) xTaskResumeAll();\r
+                       traceQUEUE_RECEIVE_FAILED( pxQueue );\r
+                       return errQUEUE_EMPTY;\r
+               }\r
+       }\r
 }\r
 /*-----------------------------------------------------------*/\r
 \r
-signed portBASE_TYPE xQueueReceiveFromISR( xQueueHandle pxQueue, const void * const pvBuffer, signed portBASE_TYPE *pxTaskWoken )\r
+signed portBASE_TYPE xQueueReceiveFromISR( xQueueHandle pxQueue, void * const pvBuffer, signed portBASE_TYPE *pxTaskWoken )\r
 {\r
 signed portBASE_TYPE xReturn;\r
+unsigned portBASE_TYPE uxSavedInterruptStatus;\r
 \r
-       /* We cannot block from an ISR, so check there is data available. */\r
-       if( pxQueue->uxMessagesWaiting > ( unsigned portBASE_TYPE ) 0 )\r
-       {\r
-               prvCopyDataFromQueue( pxQueue, pvBuffer );\r
-               --( pxQueue->uxMessagesWaiting );\r
+       configASSERT( pxQueue );\r
+       configASSERT( pxTaskWoken );\r
+       configASSERT( !( ( pvBuffer == NULL ) && ( pxQueue->uxItemSize != ( unsigned portBASE_TYPE ) 0U ) ) );\r
 \r
-               /* If the queue is locked we will not modify the event list.  Instead\r
-               we update the lock count so the task that unlocks the queue will know\r
-               that an ISR has removed data while the queue was locked. */\r
-               if( pxQueue->xRxLock == queueUNLOCKED )\r
+       uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR();\r
+       {\r
+               /* We cannot block from an ISR, so check there is data available. */\r
+               if( pxQueue->uxMessagesWaiting > ( unsigned portBASE_TYPE ) 0 )\r
                {\r
-                       /* We only want to wake one task per ISR, so check that a task has\r
-                       not already been woken. */\r
-                       if( !( *pxTaskWoken ) )\r
+                       traceQUEUE_RECEIVE_FROM_ISR( pxQueue );\r
+\r
+                       prvCopyDataFromQueue( pxQueue, pvBuffer );\r
+                       --( pxQueue->uxMessagesWaiting );\r
+\r
+                       /* If the queue is locked we will not modify the event list.  Instead\r
+                       we update the lock count so the task that unlocks the queue will know\r
+                       that an ISR has removed data while the queue was locked. */\r
+                       if( pxQueue->xRxLock == queueUNLOCKED )\r
                        {\r
-                               if( !listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) )\r
+                               if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) == pdFALSE )\r
                                {\r
                                        if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) != pdFALSE )\r
                                        {\r
@@ -858,20 +1033,22 @@ signed portBASE_TYPE xReturn;
                                        }\r
                                }\r
                        }\r
+                       else\r
+                       {\r
+                               /* Increment the lock count so the task that unlocks the queue\r
+                               knows that data was removed while it was locked. */\r
+                               ++( pxQueue->xRxLock );\r
+                       }\r
+\r
+                       xReturn = pdPASS;\r
                }\r
                else\r
                {\r
-                       /* Increment the lock count so the task that unlocks the queue\r
-                       knows that data was removed while it was locked. */\r
-                       ++( pxQueue->xRxLock );\r
+                       xReturn = pdFAIL;\r
+                       traceQUEUE_RECEIVE_FROM_ISR_FAILED( pxQueue );\r
                }\r
-\r
-               xReturn = pdPASS;\r
-       }\r
-       else\r
-       {\r
-               xReturn = pdFAIL;\r
        }\r
+       portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus );\r
 \r
        return xReturn;\r
 }\r
@@ -881,6 +1058,8 @@ unsigned portBASE_TYPE uxQueueMessagesWaiting( const xQueueHandle pxQueue )
 {\r
 unsigned portBASE_TYPE uxReturn;\r
 \r
+       configASSERT( pxQueue );\r
+\r
        taskENTER_CRITICAL();\r
                uxReturn = pxQueue->uxMessagesWaiting;\r
        taskEXIT_CRITICAL();\r
@@ -889,8 +1068,24 @@ unsigned portBASE_TYPE uxReturn;
 }\r
 /*-----------------------------------------------------------*/\r
 \r
+unsigned portBASE_TYPE uxQueueMessagesWaitingFromISR( const xQueueHandle pxQueue )\r
+{\r
+unsigned portBASE_TYPE uxReturn;\r
+\r
+       configASSERT( pxQueue );\r
+\r
+       uxReturn = pxQueue->uxMessagesWaiting;\r
+\r
+       return uxReturn;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
 void vQueueDelete( xQueueHandle pxQueue )\r
 {\r
+       configASSERT( pxQueue );\r
+\r
+       traceQUEUE_DELETE( pxQueue );\r
+       vQueueUnregisterQueue( pxQueue );\r
        vPortFree( pxQueue->pcHead );\r
        vPortFree( pxQueue );\r
 }\r
@@ -898,14 +1093,15 @@ void vQueueDelete( xQueueHandle pxQueue )
 \r
 static void prvCopyDataToQueue( xQUEUE *pxQueue, const void *pvItemToQueue, portBASE_TYPE xPosition )\r
 {\r
-       if( pxQueue->uxItemSize == 0 )\r
+       if( pxQueue->uxItemSize == ( unsigned portBASE_TYPE ) 0 )\r
        {\r
                #if ( configUSE_MUTEXES == 1 )\r
                {\r
                        if( pxQueue->uxQueueType == queueQUEUE_IS_MUTEX )\r
                        {\r
                                /* The mutex is no longer being held. */\r
-                               vTaskPriorityDisinherit( ( void * const ) pxQueue->pxMutexHolder );\r
+                               vTaskPriorityDisinherit( ( void * ) pxQueue->pxMutexHolder );\r
+                               pxQueue->pxMutexHolder = NULL;\r
                        }\r
                }\r
                #endif\r
@@ -926,7 +1122,7 @@ static void prvCopyDataToQueue( xQUEUE *pxQueue, const void *pvItemToQueue, port
                if( pxQueue->pcReadFrom < pxQueue->pcHead )\r
                {\r
                        pxQueue->pcReadFrom = ( pxQueue->pcTail - pxQueue->uxItemSize );\r
-               }               \r
+               }\r
        }\r
 \r
        ++( pxQueue->uxMessagesWaiting );\r
@@ -943,7 +1139,7 @@ static void prvCopyDataFromQueue( xQUEUE * const pxQueue, const void *pvBuffer )
                        pxQueue->pcReadFrom = pxQueue->pcHead;\r
                }\r
                memcpy( ( void * ) pvBuffer, ( void * ) pxQueue->pcReadFrom, ( unsigned ) pxQueue->uxItemSize );\r
-       }       \r
+       }\r
 }\r
 /*-----------------------------------------------------------*/\r
 \r
@@ -957,16 +1153,12 @@ static void prvUnlockQueue( xQueueHandle pxQueue )
        updated. */\r
        taskENTER_CRITICAL();\r
        {\r
-               --( pxQueue->xTxLock );\r
-\r
                /* See if data was added to the queue while it was locked. */\r
-               if( pxQueue->xTxLock > queueUNLOCKED )\r
+               while( pxQueue->xTxLock > queueLOCKED_UNMODIFIED )\r
                {\r
-                       pxQueue->xTxLock = queueUNLOCKED;\r
-\r
                        /* Data was posted while the queue was locked.  Are any tasks\r
                        blocked waiting for data to become available? */\r
-                       if( !listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) )\r
+                       if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE )\r
                        {\r
                                /* Tasks that are removed from the event list will get added to\r
                                the pending ready list as the scheduler is still suspended. */\r
@@ -976,28 +1168,40 @@ static void prvUnlockQueue( xQueueHandle pxQueue )
                                        context switch is required. */\r
                                        vTaskMissedYield();\r
                                }\r
-                       }                       \r
+\r
+                               --( pxQueue->xTxLock );\r
+                       }\r
+                       else\r
+                       {\r
+                               break;\r
+                       }\r
                }\r
+\r
+               pxQueue->xTxLock = queueUNLOCKED;\r
        }\r
        taskEXIT_CRITICAL();\r
 \r
        /* Do the same for the Rx lock. */\r
        taskENTER_CRITICAL();\r
        {\r
-               --( pxQueue->xRxLock );\r
-\r
-               if( pxQueue->xRxLock > queueUNLOCKED )\r
+               while( pxQueue->xRxLock > queueLOCKED_UNMODIFIED )\r
                {\r
-                       pxQueue->xRxLock = queueUNLOCKED;\r
-\r
-                       if( !listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) )\r
+                       if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) == pdFALSE )\r
                        {\r
                                if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) != pdFALSE )\r
                                {\r
                                        vTaskMissedYield();\r
                                }\r
-                       }                       \r
+\r
+                               --( pxQueue->xRxLock );\r
+                       }\r
+                       else\r
+                       {\r
+                               break;\r
+                       }\r
                }\r
+\r
+               pxQueue->xRxLock = queueUNLOCKED;\r
        }\r
        taskEXIT_CRITICAL();\r
 }\r
@@ -1015,6 +1219,17 @@ signed portBASE_TYPE xReturn;
 }\r
 /*-----------------------------------------------------------*/\r
 \r
+signed portBASE_TYPE xQueueIsQueueEmptyFromISR( const xQueueHandle pxQueue )\r
+{\r
+signed portBASE_TYPE xReturn;\r
+\r
+       configASSERT( pxQueue );\r
+       xReturn = ( pxQueue->uxMessagesWaiting == ( unsigned portBASE_TYPE ) 0 );\r
+\r
+       return xReturn;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
 static signed portBASE_TYPE prvIsQueueFull( const xQueueHandle pxQueue )\r
 {\r
 signed portBASE_TYPE xReturn;\r
@@ -1027,17 +1242,28 @@ signed portBASE_TYPE xReturn;
 }\r
 /*-----------------------------------------------------------*/\r
 \r
+signed portBASE_TYPE xQueueIsQueueFullFromISR( const xQueueHandle pxQueue )\r
+{\r
+signed portBASE_TYPE xReturn;\r
+\r
+       configASSERT( pxQueue );\r
+       xReturn = ( pxQueue->uxMessagesWaiting == pxQueue->uxLength );\r
+\r
+       return xReturn;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
 #if configUSE_CO_ROUTINES == 1\r
 signed portBASE_TYPE xQueueCRSend( xQueueHandle pxQueue, const void *pvItemToQueue, portTickType xTicksToWait )\r
 {\r
 signed portBASE_TYPE xReturn;\r
-               \r
+\r
        /* If the queue is already full we may have to block.  A critical section\r
        is required to prevent an interrupt removing something from the queue\r
        between the check to see if the queue is full and blocking on the queue. */\r
        portDISABLE_INTERRUPTS();\r
        {\r
-               if( prvIsQueueFull( pxQueue ) )\r
+               if( prvIsQueueFull( pxQueue ) != pdFALSE )\r
                {\r
                        /* The queue is full - do we want to block or just leave without\r
                        posting? */\r
@@ -1045,7 +1271,7 @@ signed portBASE_TYPE xReturn;
                        {\r
                                /* As this is called from a coroutine we cannot block directly, but\r
                                return indicating that we need to block. */\r
-                               vCoRoutineAddToDelayedList( xTicksToWait, &( pxQueue->xTasksWaitingToSend ) );                          \r
+                               vCoRoutineAddToDelayedList( xTicksToWait, &( pxQueue->xTasksWaitingToSend ) );\r
                                portENABLE_INTERRUPTS();\r
                                return errQUEUE_BLOCKED;\r
                        }\r
@@ -1057,19 +1283,19 @@ signed portBASE_TYPE xReturn;
                }\r
        }\r
        portENABLE_INTERRUPTS();\r
-               \r
+\r
        portNOP();\r
 \r
        portDISABLE_INTERRUPTS();\r
        {\r
                if( pxQueue->uxMessagesWaiting < pxQueue->uxLength )\r
                {\r
-                       /* There is room in the queue, copy the data into the queue. */                 \r
+                       /* There is room in the queue, copy the data into the queue. */\r
                        prvCopyDataToQueue( pxQueue, pvItemToQueue, queueSEND_TO_BACK );\r
                        xReturn = pdPASS;\r
 \r
                        /* Were any co-routines waiting for data to become available? */\r
-                       if( !listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) )\r
+                       if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE )\r
                        {\r
                                /* In this instance the co-routine could be placed directly\r
                                into the ready list as we are within a critical section.\r
@@ -1108,7 +1334,7 @@ signed portBASE_TYPE xReturn;
                if( pxQueue->uxMessagesWaiting == ( unsigned portBASE_TYPE ) 0 )\r
                {\r
                        /* There are no messages in the queue, do we want to block or just\r
-                       leave with nothing? */                  \r
+                       leave with nothing? */\r
                        if( xTicksToWait > ( portTickType ) 0 )\r
                        {\r
                                /* As this is a co-routine we cannot block directly, but return\r
@@ -1144,7 +1370,7 @@ signed portBASE_TYPE xReturn;
                        xReturn = pdPASS;\r
 \r
                        /* Were any co-routines waiting for space to become available? */\r
-                       if( !listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) )\r
+                       if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) == pdFALSE )\r
                        {\r
                                /* In this instance the co-routine could be placed directly\r
                                into the ready list as we are within a critical section.\r
@@ -1154,7 +1380,7 @@ signed portBASE_TYPE xReturn;
                                {\r
                                        xReturn = errQUEUE_YIELD;\r
                                }\r
-                       }       \r
+                       }\r
                }\r
                else\r
                {\r
@@ -1181,9 +1407,9 @@ signed portBASE_TYPE xQueueCRSendFromISR( xQueueHandle pxQueue, const void *pvIt
 \r
                /* We only want to wake one co-routine per ISR, so check that a\r
                co-routine has not already been woken. */\r
-               if( !xCoRoutinePreviouslyWoken )                \r
+               if( xCoRoutinePreviouslyWoken == pdFALSE )\r
                {\r
-                       if( !listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) )\r
+                       if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE )\r
                        {\r
                                if( xCoRoutineRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE )\r
                                {\r
@@ -1216,9 +1442,9 @@ signed portBASE_TYPE xReturn;
                --( pxQueue->uxMessagesWaiting );\r
                memcpy( ( void * ) pvBuffer, ( void * ) pxQueue->pcReadFrom, ( unsigned ) pxQueue->uxItemSize );\r
 \r
-               if( !( *pxCoRoutineWoken ) )\r
+               if( ( *pxCoRoutineWoken ) == pdFALSE )\r
                {\r
-                       if( !listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) )\r
+                       if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) == pdFALSE )\r
                        {\r
                                if( xCoRoutineRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) != pdFALSE )\r
                                {\r
@@ -1239,3 +1465,78 @@ signed portBASE_TYPE xReturn;
 #endif\r
 /*-----------------------------------------------------------*/\r
 \r
+#if configQUEUE_REGISTRY_SIZE > 0\r
+\r
+       void vQueueAddToRegistry( xQueueHandle xQueue, signed char *pcQueueName )\r
+       {\r
+       unsigned portBASE_TYPE ux;\r
+\r
+               /* See if there is an empty space in the registry.  A NULL name denotes\r
+               a free slot. */\r
+               for( ux = ( unsigned portBASE_TYPE ) 0U; ux < ( unsigned portBASE_TYPE ) configQUEUE_REGISTRY_SIZE; ux++ )\r
+               {\r
+                       if( xQueueRegistry[ ux ].pcQueueName == NULL )\r
+                       {\r
+                               /* Store the information on this queue. */\r
+                               xQueueRegistry[ ux ].pcQueueName = pcQueueName;\r
+                               xQueueRegistry[ ux ].xHandle = xQueue;\r
+                               break;\r
+                       }\r
+               }\r
+       }\r
+\r
+#endif\r
+/*-----------------------------------------------------------*/\r
+\r
+#if configQUEUE_REGISTRY_SIZE > 0\r
+\r
+       static void vQueueUnregisterQueue( xQueueHandle xQueue )\r
+       {\r
+       unsigned portBASE_TYPE ux;\r
+\r
+               /* See if the handle of the queue being unregistered in actually in the\r
+               registry. */\r
+               for( ux = ( unsigned portBASE_TYPE ) 0U; ux < ( unsigned portBASE_TYPE ) configQUEUE_REGISTRY_SIZE; ux++ )\r
+               {\r
+                       if( xQueueRegistry[ ux ].xHandle == xQueue )\r
+                       {\r
+                               /* Set the name to NULL to show that this slot if free again. */\r
+                               xQueueRegistry[ ux ].pcQueueName = NULL;\r
+                               break;\r
+                       }\r
+               }\r
+\r
+       }\r
+\r
+#endif\r
+/*-----------------------------------------------------------*/\r
+\r
+#if configUSE_TIMERS == 1\r
+\r
+       void vQueueWaitForMessageRestricted( xQueueHandle pxQueue, portTickType xTicksToWait )\r
+       {\r
+               /* This function should not be called by application code hence the\r
+               'Restricted' in its name.  It is not part of the public API.  It is\r
+               designed for use by kernel code, and has special calling requirements.\r
+               It can result in vListInsert() being called on a list that can only\r
+               possibly ever have one item in it, so the list will be fast, but even\r
+               so it should be called with the scheduler locked and not from a critical\r
+               section. */\r
+\r
+               /* Only do anything if there are no messages in the queue.  This function\r
+               will not actually cause the task to block, just place it on a blocked\r
+               list.  It will not block until the scheduler is unlocked - at which\r
+               time a yield will be performed.  If an item is added to the queue while\r
+               the queue is locked, and the calling task blocks on the queue, then the\r
+               calling task will be immediately unblocked when the queue is unlocked. */\r
+               prvLockQueue( pxQueue );\r
+               if( pxQueue->uxMessagesWaiting == ( unsigned portBASE_TYPE ) 0U )\r
+               {\r
+                       /* There is nothing in the queue, block for the specified period. */\r
+                       vTaskPlaceOnEventListRestricted( &( pxQueue->xTasksWaitingToReceive ), xTicksToWait );\r
+               }\r
+               prvUnlockQueue( pxQueue );\r
+       }\r
+\r
+#endif\r
+\r