]> git.sur5r.net Git - freertos/blobdiff - Source/queue.c
Remove .bak files.
[freertos] / Source / queue.c
index b2a36379256d29dcc35eccc23c585e7b5ffb1e80..67e24e9c31d3ad25044240a91ca5eb9531017172 100644 (file)
@@ -1,5 +1,5 @@
 /*\r
-       FreeRTOS.org V4.6.1 - Copyright (C) 2003-2007 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
        ***************************************************************************\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
-Changes from V4.0.5\r
-\r
-       + Added a loop within xQueueSend() and xQueueReceive() to prevent the\r
-         functions exiting when a block time remains and the function has\r
-         not completed.\r
-\r
-Changes from V4.1.2:\r
-\r
-       + BUG FIX:  Removed the call to prvIsQueueEmpty from within xQueueCRReceive\r
-         as it exited with interrupts enabled.  Thanks Paul Katz.\r
-\r
-Changes from V4.1.3:\r
-\r
-       + Modified xQueueSend() and xQueueReceive() to handle the (very unlikely)\r
-       case whereby a task unblocking due to a temporal event can remove/send an\r
-       item from/to a queue when a higher priority task is     still blocked on the\r
-       queue.  This modification is a result of the SafeRTOS testing.\r
-*/\r
-\r
 #include <stdlib.h>\r
 #include <string.h>\r
 #include "FreeRTOS.h"\r
@@ -100,6 +57,11 @@ Changes from V4.1.3:
 #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
  * Items are queued by copy, not reference.\r
@@ -115,7 +77,7 @@ 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
@@ -144,6 +106,9 @@ signed portBASE_TYPE xQueueGenericSendFromISR( xQueueHandle pxQueue, const void
 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
@@ -296,6 +261,25 @@ size_t xQueueSizeInBytes;
 #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 = pdPASS;\r
@@ -473,6 +457,198 @@ xTimeOutType xTimeOut;
 }\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
+       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
+                       /* 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
+\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
+       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
+#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
 {\r
        /* Similar to xQueueGenericSend, except we don't block if there is no room\r