]> git.sur5r.net Git - freertos/blobdiff - Source/queue.c
Remove .bak files.
[freertos] / Source / queue.c
index 9bb773414c3abaa4039d20ef59ac0116d1fb4d96..67e24e9c31d3ad25044240a91ca5eb9531017172 100644 (file)
@@ -1,5 +1,5 @@
 /*\r
-       FreeRTOS.org V4.0.5 - Copyright (C) 2003-2006 Richard Barry.\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
        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
-*/\r
-\r
-/*\r
-Changes from V1.01\r
-\r
-       + More use of 8bit data types.\r
-       + Function name prefixes changed where the data type returned has changed.\r
-\r
-Changed from V2.0.0\r
-\r
-       + Added the queue locking mechanism and make more use of the scheduler\r
-         suspension feature to minimise the time interrupts have to be disabled\r
-         when accessing a queue.\r
-\r
-Changed from V2.2.0\r
-\r
-       + Explicit use of 'signed' qualifier on portCHAR types added.\r
-\r
-Changes from V3.0.0\r
-\r
-       + API changes as described on the FreeRTOS.org WEB site.\r
-\r
-Changes from V3.2.3\r
-\r
-       + Added the queue functions that can be used from co-routines.\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
 */\r
 \r
 #include <stdlib.h>\r
@@ -68,6 +46,21 @@ Changes from V3.2.3
 \r
 /* Constants used with the cRxLock and cTxLock structure members. */\r
 #define queueUNLOCKED  ( ( signed portBASE_TYPE ) -1 )\r
+#define queueERRONEOUS_UNBLOCK                                 ( -1 )\r
+\r
+/* For internal use only. */\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
+\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
 \r
 /*\r
  * Definition of the queue used by the scheduler.\r
@@ -84,12 +77,12 @@ typedef struct QueueDefinition
        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
 \r
-       unsigned portBASE_TYPE uxMessagesWaiting;/*< The number of items currently in the queue. */\r
+       volatile unsigned portBASE_TYPE uxMessagesWaiting;/*< The number of items currently in the queue. */\r
        unsigned portBASE_TYPE uxLength;                /*< The length of the queue defined as the number of items it will hold, not the number of bytes. */\r
        unsigned portBASE_TYPE uxItemSize;              /*< The size of each items that the queue will hold. */\r
 \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
+       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
 } xQUEUE;\r
 /*-----------------------------------------------------------*/\r
 \r
@@ -106,12 +99,16 @@ typedef xQUEUE * xQueueHandle;
  * functions are documented in the API header file.\r
  */\r
 xQueueHandle xQueueCreate( unsigned portBASE_TYPE uxQueueLength, unsigned portBASE_TYPE uxItemSize );\r
-signed portBASE_TYPE xQueueSend( xQueueHandle xQueue, const void * pvItemToQueue, portTickType xTicksToWait );\r
-unsigned portBASE_TYPE uxQueueMessagesWaiting( xQueueHandle pxQueue );\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 xQueueSendFromISR( xQueueHandle pxQueue, const void *pvItemToQueue, signed portBASE_TYPE xTaskPreviouslyWoken );\r
-signed portBASE_TYPE xQueueReceive( xQueueHandle pxQueue, void *pvBuffer, portTickType xTicksToWait );\r
-signed portBASE_TYPE xQueueReceiveFromISR( xQueueHandle pxQueue, void *pvBuffer, signed portBASE_TYPE *pxTaskWoken );\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
 \r
 #if configUSE_CO_ROUTINES == 1\r
        signed portBASE_TYPE xQueueCRSendFromISR( xQueueHandle pxQueue, const void *pvItemToQueue, signed portBASE_TYPE xCoRoutinePreviouslyWoken );\r
@@ -128,7 +125,7 @@ signed portBASE_TYPE xQueueReceiveFromISR( xQueueHandle pxQueue, void *pvBuffer,
  * 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 signed portBASE_TYPE prvUnlockQueue( xQueueHandle pxQueue );\r
+static void prvUnlockQueue( xQueueHandle pxQueue );\r
 \r
 /*\r
  * Uses a critical section to determine if there is any data in a queue.\r
@@ -145,20 +142,15 @@ static signed portBASE_TYPE prvIsQueueEmpty( const xQueueHandle pxQueue );
 static signed portBASE_TYPE prvIsQueueFull( const xQueueHandle pxQueue );\r
 \r
 /*\r
- * Macro that copies an item into the queue.  This is done by copying the item\r
- * byte for byte, not by reference.  Updates the queue state to ensure it's\r
- * integrity after the copy.\r
+ * Copies an item into the queue, either at the front of the queue or the\r
+ * back of the queue.\r
  */\r
-#define prvCopyQueueData( pxQueue, pvItemToQueue )                                                                                             \\r
-{                                                                                                                                                                                              \\r
-       memcpy( ( void * ) pxQueue->pcWriteTo, pvItemToQueue, ( unsigned ) pxQueue->uxItemSize );       \\r
-       ++( pxQueue->uxMessagesWaiting );                                                                                                                       \\r
-       pxQueue->pcWriteTo += pxQueue->uxItemSize;                                                                                                      \\r
-       if( pxQueue->pcWriteTo >= pxQueue->pcTail )                                                                                                     \\r
-       {                                                                                                                                                                                       \\r
-               pxQueue->pcWriteTo = pxQueue->pcHead;                                                                                                   \\r
-       }                                                                                                                                                                                       \\r
-}\r
+static void prvCopyDataToQueue( xQUEUE *pxQueue, const void *pvItemToQueue, portBASE_TYPE xPosition );\r
+\r
+/*\r
+ * Copies an item out of a queue.\r
+ */\r
+static void prvCopyDataFromQueue( xQUEUE * const pxQueue, const void *pvBuffer );\r
 /*-----------------------------------------------------------*/\r
 \r
 /*\r
@@ -227,13 +219,78 @@ size_t xQueueSizeInBytes;
 }\r
 /*-----------------------------------------------------------*/\r
 \r
-signed portBASE_TYPE xQueueSend( xQueueHandle pxQueue, const void *pvItemToQueue, portTickType xTicksToWait )\r
+#if ( configUSE_MUTEXES == 1 )\r
+\r
+       xQueueHandle xQueueCreateMutex( void )\r
+       {\r
+       xQUEUE *pxNewQueue;\r
+       \r
+               /* Allocate the new queue structure. */\r
+               pxNewQueue = ( xQUEUE * ) pvPortMalloc( sizeof( xQUEUE ) );\r
+               if( pxNewQueue != NULL )\r
+               {\r
+                       /* Information required for priority inheritance. */\r
+                       pxNewQueue->pxMutexHolder = NULL;\r
+                       pxNewQueue->uxQueueType = queueQUEUE_IS_MUTEX;\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
+                       /* 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->xRxLock = queueUNLOCKED;\r
+                       pxNewQueue->xTxLock = queueUNLOCKED;\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
+               }\r
+       \r
+               return pxNewQueue;\r
+       }\r
+\r
+#endif /* configUSE_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
+               pxHandle = xQueueCreate( ( unsigned portBASE_TYPE ) uxCountValue, queueSEMAPHORE_QUEUE_ITEM_LENGTH );\r
+\r
+               if( pxHandle != NULL )\r
+               {\r
+                       pxHandle->uxMessagesWaiting = uxInitialCount;\r
+               }\r
+\r
+               return pxHandle;\r
+       }\r
+\r
+#endif /* configUSE_COUNTING_SEMAPHORES */\r
+/*-----------------------------------------------------------*/\r
+\r
+signed portBASE_TYPE xQueueGenericSend( xQueueHandle pxQueue, const void * const pvItemToQueue, portTickType xTicksToWait, portBASE_TYPE xCopyPosition )\r
 {\r
-signed portBASE_TYPE xReturn;\r
+signed portBASE_TYPE xReturn = pdPASS;\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
@@ -260,135 +317,348 @@ signed portBASE_TYPE xReturn;
        queue being modified here.  Places where the event list is modified\r
        include:\r
 \r
-               + xQueueSendFromISR().  This checks the lock on the queue to see if\r
-                 it has access.  If the queue is locked then the Tx lock count is\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 xQueueSendFromISR().\r
+               + xQueueReceiveFromISR().  As per xQueueGenericSendFromISR().\r
        */\r
                \r
        /* If the queue is already full we may have to block. */\r
-       if( prvIsQueueFull( pxQueue ) )\r
+       do\r
        {\r
-               /* The queue is full - do we want to block or just leave without\r
-               posting? */\r
-               if( xTicksToWait > ( portTickType ) 0 )\r
+               if( prvIsQueueFull( pxQueue ) )\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
+                       /* 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 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
+\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
+                                       {\r
+                                               /* We unblocked but there is no space in the queue,\r
+                                               we probably timed out. */\r
+                                               xReturn = errQUEUE_FULL;\r
+                                       }\r
+       \r
+                                       /* Before leaving the critical section we have to ensure\r
+                                       exclusive access again. */\r
+                                       vTaskSuspendAll();\r
+                                       prvLockQueue( pxQueue );                                \r
+                               }\r
+                               taskEXIT_CRITICAL();\r
+                       }\r
+               }\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
+               /* 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
                        {\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
+                               if( pxQueue->uxMessagesWaiting < pxQueue->uxLength )\r
                                {\r
-                                       taskYIELD();\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
+                               }\r
+                               else\r
+                               {\r
+                                       xReturn = errQUEUE_FULL;\r
                                }\r
-\r
-                               /* Before leaving the critical section we have to ensure\r
-                               exclusive access again. */\r
-                               vTaskSuspendAll();\r
-                               prvLockQueue( pxQueue );                                \r
                        }\r
                        taskEXIT_CRITICAL();\r
                }\r
-       }\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
-       {\r
-               if( pxQueue->uxMessagesWaiting < pxQueue->uxLength )\r
-               {\r
-                       /* There is room in the queue, copy the data into the queue. */                 \r
-                       prvCopyQueueData( pxQueue, pvItemToQueue );             \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
-               }\r
-               else\r
+               if( xReturn == errQUEUE_FULL )\r
                {\r
-                       xReturn = errQUEUE_FULL;\r
+                       if( xTicksToWait > 0 )\r
+                       {\r
+                               if( xTaskCheckForTimeOut( &xTimeOut, &xTicksToWait ) == pdFALSE )\r
+                               {\r
+                                       xReturn = queueERRONEOUS_UNBLOCK;\r
+                               }\r
+                       }\r
                }\r
        }\r
-       taskEXIT_CRITICAL();\r
+       while( xReturn == queueERRONEOUS_UNBLOCK );\r
 \r
-       /* We no longer require exclusive access to the queue.  prvUnlockQueue\r
-       will remove any tasks suspended on a receive if either this function\r
-       or an ISR has posted onto the queue. */\r
-       if( prvUnlockQueue( pxQueue ) )\r
+       prvUnlockQueue( pxQueue );\r
+       xTaskResumeAll();\r
+\r
+       return xReturn;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+#if configUSE_ALTERNATIVE_API == 1\r
+\r
+       signed portBASE_TYPE xQueueAltGenericSend( xQueueHandle pxQueue, const void * const pvItemToQueue, portTickType xTicksToWait, portBASE_TYPE xCopyPosition )\r
        {\r
-               /* Resume the scheduler - making ready any tasks that were woken\r
-               by an event while the scheduler was locked.  Resuming the\r
-               scheduler may cause a yield, in which case there is no point\r
-               yielding again here. */\r
-               if( !xTaskResumeAll() )\r
+       signed portBASE_TYPE xReturn;\r
+       xTimeOutType xTimeOut;\r
+\r
+               /* The source code that implements the alternative (Alt) 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
+               preferred fully featured API too.  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 alternative API sacrifices interrupt \r
+               responsiveness to gain execution speed, whereas the fully featured API\r
+               sacrifices execution speed to ensure better interrupt responsiveness.  */\r
+\r
+               taskENTER_CRITICAL();\r
                {\r
-                       taskYIELD();\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
+                       {\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
+                               if( pxQueue->uxMessagesWaiting < pxQueue->uxLength )\r
+                               {\r
+                                       /* There is room in the queue, copy the data into the queue. */                 \r
+                                       prvCopyDataToQueue( pxQueue, pvItemToQueue, xCopyPosition );\r
+                                       xReturn = pdPASS;\r
+\r
+                                       if( !listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) )\r
+                                       {\r
+                                               if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE )\r
+                                               {\r
+                                                       /* The task waiting has a higher priority. */\r
+                                                       taskYIELD();\r
+                                               }\r
+                                       }                       \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
+                                       }\r
+                               }\r
+                       }\r
+                       while( xReturn == queueERRONEOUS_UNBLOCK );\r
                }\r
+               taskEXIT_CRITICAL();\r
+\r
+               return xReturn;\r
        }\r
-       else\r
+\r
+#endif /* configUSE_ALTERNATIVE_API */\r
+/*-----------------------------------------------------------*/\r
+\r
+#if configUSE_ALTERNATIVE_API == 1\r
+\r
+       signed portBASE_TYPE xQueueAltGenericReceive( xQueueHandle pxQueue, const void * const pvBuffer, portTickType xTicksToWait, portBASE_TYPE xJustPeeking )\r
        {\r
-               /* Resume the scheduler - making ready any tasks that were woken\r
-               by an event while the scheduler was locked. */\r
-               xTaskResumeAll();\r
+       signed portBASE_TYPE xReturn = pdTRUE;\r
+       xTimeOutType xTimeOut;\r
+       signed portCHAR *pcOriginalReadPosition;\r
+\r
+               /* The source code that implements the alternative (Alt) 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
+               preferred fully featured API too.  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 alternative API sacrifices interrupt \r
+               responsiveness to gain execution speed, whereas the fully featured API\r
+               sacrifices execution speed to ensure better interrupt responsiveness.  */\r
+\r
+               taskENTER_CRITICAL();\r
+               {\r
+                       /* Capture the current time status for future reference. */\r
+                       vTaskSetTimeOutState( &xTimeOut );\r
+\r
+                       do\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
+                                       pcOriginalReadPosition = pxQueue->pcReadFrom;\r
+\r
+                                       prvCopyDataFromQueue( pxQueue, pvBuffer );\r
+\r
+                                       if( xJustPeeking == pdFALSE )\r
+                                       {\r
+                                               /* We are actually removing data. */\r
+                                               --( pxQueue->uxMessagesWaiting );\r
+                                                       \r
+                                               #if ( configUSE_MUTEXES == 1 )\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
+                                               }\r
+                                               #endif\r
+\r
+                                               if( !listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) )\r
+                                               {\r
+                                                       if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) != pdFALSE )\r
+                                                       {\r
+                                                               /* The task waiting has a higher priority. */\r
+                                                               taskYIELD();\r
+                                                       }\r
+                                               }\r
+                                       }\r
+                                       else\r
+                                       {\r
+                                               /* We are not removing the data, so reset our read\r
+                                               pointer. */\r
+                                               pxQueue->pcReadFrom = pcOriginalReadPosition;\r
+                                       }\r
+                                       \r
+                                       xReturn = pdPASS;                                       \r
+                               }\r
+                               else\r
+                               {\r
+                                       xReturn = errQUEUE_EMPTY;\r
+\r
+                                       if( xTicksToWait > 0 )\r
+                                       {\r
+                                               if( xTaskCheckForTimeOut( &xTimeOut, &xTicksToWait ) == pdFALSE )\r
+                                               {\r
+                                                       xReturn = queueERRONEOUS_UNBLOCK;\r
+                                               }\r
+                                       }\r
+                               }\r
+\r
+                       } while( xReturn == queueERRONEOUS_UNBLOCK );\r
+               }\r
+               taskEXIT_CRITICAL();\r
+\r
+               return xReturn;\r
        }\r
 \r
-       return xReturn;\r
-}\r
+#endif /* configUSE_ALTERNATIVE_API */\r
 /*-----------------------------------------------------------*/\r
 \r
-signed portBASE_TYPE xQueueSendFromISR( xQueueHandle pxQueue, const void *pvItemToQueue, signed portBASE_TYPE xTaskPreviouslyWoken )\r
+signed portBASE_TYPE xQueueGenericSendFromISR( xQueueHandle pxQueue, const void * const pvItemToQueue, signed portBASE_TYPE xTaskPreviouslyWoken, portBASE_TYPE xCopyPosition )\r
 {\r
-       /* Similar to xQueueSend, except we don't block if there is no room in the\r
-       queue.  Also we don't directly wake a task that was blocked on a queue\r
-       read, instead we return a flag to say whether a context switch is required\r
-       or not (i.e. has a task with a higher priority than us been woken by this\r
-       post). */\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
        {\r
-               prvCopyQueueData( pxQueue, pvItemToQueue );\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
@@ -421,98 +691,149 @@ signed portBASE_TYPE xQueueSendFromISR( xQueueHandle pxQueue, const void *pvItem
 }\r
 /*-----------------------------------------------------------*/\r
 \r
-signed portBASE_TYPE xQueueReceive( xQueueHandle pxQueue, void *pvBuffer, portTickType xTicksToWait )\r
+signed portBASE_TYPE xQueueGenericReceive( xQueueHandle pxQueue, const void * const pvBuffer, portTickType xTicksToWait, portBASE_TYPE xJustPeeking )\r
 {\r
-signed portBASE_TYPE xReturn;\r
+signed portBASE_TYPE xReturn = pdTRUE;\r
+xTimeOutType xTimeOut;\r
+signed portCHAR *pcOriginalReadPosition;\r
 \r
-       /* This function is very similar to xQueueSend().  See comments within\r
-       xQueueSend() for a more detailed explanation.\r
+       /* This function is very similar to xQueueGenericSend().  See comments\r
+       within xQueueGenericSend() for a more detailed explanation.\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
        /* Make sure interrupts do not access the queue. */\r
        prvLockQueue( pxQueue );\r
 \r
-       /* If there are no messages in the queue we may have to block. */\r
-       if( prvIsQueueEmpty( pxQueue ) )\r
+       do\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
+               /* If there are no messages in the queue we may have to block. */\r
+               if( prvIsQueueEmpty( pxQueue ) )\r
                {\r
-                       vTaskPlaceOnEventList( &( pxQueue->xTasksWaitingToReceive ), xTicksToWait );\r
-                       taskENTER_CRITICAL();\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
-                               prvUnlockQueue( pxQueue );\r
-                               if( !xTaskResumeAll() )\r
+                               #if ( configUSE_MUTEXES == 1 )\r
                                {\r
-                                       taskYIELD();\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
+                               {\r
+                                       prvUnlockQueue( pxQueue );\r
+                                       if( !xTaskResumeAll() )\r
+                                       {\r
+                                               taskYIELD();\r
+                                       }\r
 \r
-                               vTaskSuspendAll();\r
-                               prvLockQueue( pxQueue );\r
+                                       if( pxQueue->uxMessagesWaiting == ( unsigned portBASE_TYPE ) 0 )\r
+                                       {\r
+                                               /* We unblocked but the queue is empty.  We probably\r
+                                               timed out. */\r
+                                               xReturn = errQUEUE_EMPTY;\r
+                                       }\r
+       \r
+                                       vTaskSuspendAll();\r
+                                       prvLockQueue( pxQueue );\r
+                               }\r
+                               taskEXIT_CRITICAL();\r
                        }\r
-                       taskEXIT_CRITICAL();\r
                }\r
-       }\r
-\r
-       taskENTER_CRITICAL();\r
-       {\r
-               if( pxQueue->uxMessagesWaiting > ( unsigned portBASE_TYPE ) 0 )\r
+       \r
+               if( xReturn != errQUEUE_EMPTY )\r
                {\r
-                       pxQueue->pcReadFrom += pxQueue->uxItemSize;\r
-                       if( pxQueue->pcReadFrom >= pxQueue->pcTail )\r
+                       taskENTER_CRITICAL();\r
                        {\r
-                               pxQueue->pcReadFrom = pxQueue->pcHead;\r
-                       }\r
-                       --( pxQueue->uxMessagesWaiting );\r
-                       memcpy( ( void * ) pvBuffer, ( void * ) pxQueue->pcReadFrom, ( unsigned ) pxQueue->uxItemSize );\r
+                               if( pxQueue->uxMessagesWaiting > ( unsigned portBASE_TYPE ) 0 )\r
+                               {\r
+                                       /* Remember our read position in case we are just peeking. */\r
+                                       pcOriginalReadPosition = pxQueue->pcReadFrom;\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
-                       xReturn = pdPASS;\r
+                                       prvCopyDataFromQueue( pxQueue, pvBuffer );\r
+\r
+                                       if( xJustPeeking == 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
+                                               {\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
+                                       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
+                                       xReturn = errQUEUE_EMPTY;\r
+                               }\r
+                       }\r
+                       taskEXIT_CRITICAL();\r
                }\r
-               else\r
+\r
+               if( xReturn == errQUEUE_EMPTY )\r
                {\r
-                       xReturn = pdFAIL;\r
+                       if( xTicksToWait > 0 )\r
+                       {\r
+                               if( xTaskCheckForTimeOut( &xTimeOut, &xTicksToWait ) == pdFALSE )\r
+                               {\r
+                                       xReturn = queueERRONEOUS_UNBLOCK;\r
+                               }\r
+                       }\r
                }\r
-       }\r
-       taskEXIT_CRITICAL();\r
+       } while( xReturn == queueERRONEOUS_UNBLOCK );\r
 \r
        /* We no longer require exclusive access to the queue. */\r
-       if( prvUnlockQueue( pxQueue ) )\r
-       {\r
-               if( !xTaskResumeAll() )\r
-               {\r
-                       taskYIELD();\r
-               }\r
-       }\r
-       else\r
-       {\r
-               xTaskResumeAll();\r
-       }\r
+       prvUnlockQueue( pxQueue );\r
+       xTaskResumeAll();\r
 \r
        return xReturn;\r
 }\r
 /*-----------------------------------------------------------*/\r
 \r
-signed portBASE_TYPE xQueueReceiveFromISR( xQueueHandle pxQueue, void *pvBuffer, signed portBASE_TYPE *pxTaskWoken )\r
+signed portBASE_TYPE xQueueReceiveFromISR( xQueueHandle pxQueue, const void * const pvBuffer, signed portBASE_TYPE *pxTaskWoken )\r
 {\r
 signed portBASE_TYPE xReturn;\r
 \r
        /* We cannot block from an ISR, so check there is data available. */\r
        if( pxQueue->uxMessagesWaiting > ( unsigned portBASE_TYPE ) 0 )\r
        {\r
-               /* Copy the data from the queue. */\r
-               pxQueue->pcReadFrom += pxQueue->uxItemSize;\r
-               if( pxQueue->pcReadFrom >= pxQueue->pcTail )\r
-               {\r
-                       pxQueue->pcReadFrom = pxQueue->pcHead;\r
-               }\r
+               prvCopyDataFromQueue( pxQueue, pvBuffer );\r
                --( pxQueue->uxMessagesWaiting );\r
-               memcpy( ( void * ) pvBuffer, ( void * ) pxQueue->pcReadFrom, ( unsigned ) pxQueue->uxItemSize );\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
@@ -552,7 +873,7 @@ signed portBASE_TYPE xReturn;
 }\r
 /*-----------------------------------------------------------*/\r
 \r
-unsigned portBASE_TYPE uxQueueMessagesWaiting( xQueueHandle pxQueue )\r
+unsigned portBASE_TYPE uxQueueMessagesWaiting( const xQueueHandle pxQueue )\r
 {\r
 unsigned portBASE_TYPE uxReturn;\r
 \r
@@ -571,10 +892,59 @@ void vQueueDelete( xQueueHandle pxQueue )
 }\r
 /*-----------------------------------------------------------*/\r
 \r
-static signed portBASE_TYPE prvUnlockQueue( xQueueHandle pxQueue )\r
+static void prvCopyDataToQueue( xQUEUE *pxQueue, const void *pvItemToQueue, portBASE_TYPE xPosition )\r
+{\r
+       if( pxQueue->uxItemSize == 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
+                       }\r
+               }\r
+               #endif\r
+       }\r
+       else if( xPosition == queueSEND_TO_BACK )\r
+       {\r
+               memcpy( ( void * ) pxQueue->pcWriteTo, pvItemToQueue, ( unsigned ) pxQueue->uxItemSize );\r
+               pxQueue->pcWriteTo += pxQueue->uxItemSize;\r
+               if( pxQueue->pcWriteTo >= pxQueue->pcTail )\r
+               {\r
+                       pxQueue->pcWriteTo = pxQueue->pcHead;\r
+               }\r
+       }\r
+       else\r
+       {\r
+               memcpy( ( void * ) pxQueue->pcReadFrom, pvItemToQueue, ( unsigned ) pxQueue->uxItemSize );\r
+               pxQueue->pcReadFrom -= pxQueue->uxItemSize;\r
+               if( pxQueue->pcReadFrom < pxQueue->pcHead )\r
+               {\r
+                       pxQueue->pcReadFrom = ( pxQueue->pcTail - pxQueue->uxItemSize );\r
+               }               \r
+       }\r
+\r
+       ++( pxQueue->uxMessagesWaiting );\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static void prvCopyDataFromQueue( xQUEUE * const pxQueue, const void *pvBuffer )\r
 {\r
-signed portBASE_TYPE xYieldRequired = pdFALSE;\r
+       if( pxQueue->uxQueueType != queueQUEUE_IS_MUTEX )\r
+       {\r
+               pxQueue->pcReadFrom += pxQueue->uxItemSize;\r
+               if( pxQueue->pcReadFrom >= pxQueue->pcTail )\r
+               {\r
+                       pxQueue->pcReadFrom = pxQueue->pcHead;\r
+               }\r
+               memcpy( ( void * ) pvBuffer, ( void * ) pxQueue->pcReadFrom, ( unsigned ) pxQueue->uxItemSize );\r
+       }       \r
+}\r
+/*-----------------------------------------------------------*/\r
 \r
+static void prvUnlockQueue( xQueueHandle pxQueue )\r
+{\r
        /* THIS FUNCTION MUST BE CALLED WITH THE SCHEDULER SUSPENDED. */\r
 \r
        /* The lock counts contains the number of extra data items placed or\r
@@ -600,7 +970,7 @@ signed portBASE_TYPE xYieldRequired = pdFALSE;
                                {\r
                                        /* The task waiting has a higher priority so record that a\r
                                        context switch is required. */\r
-                                       xYieldRequired = pdTRUE;\r
+                                       vTaskMissedYield();\r
                                }\r
                        }                       \r
                }\r
@@ -620,14 +990,12 @@ signed portBASE_TYPE xYieldRequired = pdFALSE;
                        {\r
                                if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) != pdFALSE )\r
                                {\r
-                                       xYieldRequired = pdTRUE;\r
+                                       vTaskMissedYield();\r
                                }\r
                        }                       \r
                }\r
        }\r
        taskEXIT_CRITICAL();\r
-\r
-       return xYieldRequired;\r
 }\r
 /*-----------------------------------------------------------*/\r
 \r
@@ -661,7 +1029,7 @@ signed portBASE_TYPE xQueueCRSend( xQueueHandle pxQueue, const void *pvItemToQue
 signed portBASE_TYPE xReturn;\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
+       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
@@ -693,19 +1061,19 @@ signed portBASE_TYPE xReturn;
                if( pxQueue->uxMessagesWaiting < pxQueue->uxLength )\r
                {\r
                        /* There is room in the queue, copy the data into the queue. */                 \r
-                       prvCopyQueueData( pxQueue, pvItemToQueue );             \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
                        {\r
-                               /* In this instance the co-routine could be placed directly \r
-                               into the ready list as we are within a critical section.  \r
-                               Instead the same pending ready list mechansim is used as if\r
+                               /* In this instance the co-routine could be placed directly\r
+                               into the ready list as we are within a critical section.\r
+                               Instead the same pending ready list mechanism is used as if\r
                                the event were caused from within an interrupt. */\r
                                if( xCoRoutineRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE )\r
                                {\r
-                                       /* The co-routine waiting has a higher priority so record \r
+                                       /* The co-routine waiting has a higher priority so record\r
                                        that a yield might be appropriate. */\r
                                        xReturn = errQUEUE_YIELD;\r
                                }\r
@@ -729,11 +1097,11 @@ signed portBASE_TYPE xQueueCRReceive( xQueueHandle pxQueue, void *pvBuffer, port
 signed portBASE_TYPE xReturn;\r
 \r
        /* If the queue is already empty we may have to block.  A critical section\r
-       is required to prevent an interrupt adding something to the queue \r
+       is required to prevent an interrupt adding something to the queue\r
        between the check to see if the queue is empty and blocking on the queue. */\r
        portDISABLE_INTERRUPTS();\r
        {\r
-               if( prvIsQueueEmpty( pxQueue ) )\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
@@ -774,9 +1142,9 @@ signed portBASE_TYPE xReturn;
                        /* Were any co-routines waiting for space to become available? */\r
                        if( !listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) )\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
-                               Instead the same pending ready list mechansim is used as if\r
+                               /* In this instance the co-routine could be placed directly\r
+                               into the ready list as we are within a critical section.\r
+                               Instead the same pending ready list mechanism is used as if\r
                                the event were caused from within an interrupt. */\r
                                if( xCoRoutineRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) != pdFALSE )\r
                                {\r
@@ -805,9 +1173,9 @@ signed portBASE_TYPE xQueueCRSendFromISR( xQueueHandle pxQueue, const void *pvIt
        exit without doing anything. */\r
        if( pxQueue->uxMessagesWaiting < pxQueue->uxLength )\r
        {\r
-               prvCopyQueueData( pxQueue, pvItemToQueue );\r
+               prvCopyDataToQueue( pxQueue, pvItemToQueue, queueSEND_TO_BACK );\r
 \r
-               /* We only want to wake one co-routine per ISR, so check that a \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
                {\r