\r
signed portBASE_TYPE xQueueGenericSend( xQueueHandle pxQueue, const void * const pvItemToQueue, portTickType xTicksToWait, portBASE_TYPE xCopyPosition )\r
{\r
-signed portBASE_TYPE xReturn = pdTRUE;\r
+signed portBASE_TYPE xEntryTimeSet = pdFALSE;\r
xTimeOutType xTimeOut;\r
\r
- do\r
+ for( ;; )\r
{\r
- /* If xTicksToWait is zero then we are not going to block even\r
- if there is no room in the queue to post. */\r
- if( xTicksToWait > ( portTickType ) 0 )\r
- {\r
- vTaskSuspendAll();\r
- prvLockQueue( pxQueue );\r
-\r
- if( xReturn == pdTRUE )\r
- {\r
- /* This is the first time through - we need to capture the\r
- time while the scheduler is locked to ensure we attempt to\r
- block at least once. */\r
- vTaskSetTimeOutState( &xTimeOut );\r
- }\r
-\r
- if( prvIsQueueFull( pxQueue ) )\r
- {\r
- /* Need to call xTaskCheckForTimeout again as time could\r
- have passed since it was last called if this is not the\r
- first time around this loop. */\r
- if( xTaskCheckForTimeOut( &xTimeOut, &xTicksToWait ) == pdFALSE )\r
- {\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() )\r
- {\r
- taskYIELD();\r
- }\r
- }\r
- else\r
- {\r
- prvUnlockQueue( pxQueue );\r
- ( void ) xTaskResumeAll();\r
- }\r
- }\r
- else\r
- {\r
- /* The queue was not full so we can just unlock the\r
- scheduler and queue again before carrying on. */\r
- prvUnlockQueue( pxQueue );\r
- ( void ) xTaskResumeAll();\r
- }\r
- }\r
-\r
- /* Higher priority tasks and interrupts can execute during\r
- this time and could possible refill the queue - even if we\r
- unblocked because space became available. */\r
-\r
taskENTER_CRITICAL();\r
{\r
/* Is there room on the queue now? To be running we must be\r
{\r
traceQUEUE_SEND( pxQueue );\r
prvCopyDataToQueue( pxQueue, pvItemToQueue, xCopyPosition );\r
- xReturn = pdPASS;\r
\r
/* If there was a task waiting for data to arrive on the\r
queue then unblock it now. */\r
{\r
if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) == pdTRUE )\r
{\r
- /* The unblocked task has a priority higher than\r
- our own so yield immediately. */\r
- taskYIELD();\r
+ /* The unblocked task has a priority higher than\r
+ our own so yield immediately. */\r
+ taskYIELD();\r
}\r
}\r
+\r
+ taskEXIT_CRITICAL();\r
+ return pdPASS;\r
}\r
else\r
{\r
- /* Setting xReturn to errQUEUE_FULL will force its timeout\r
- to be re-evaluated. This is necessary in case interrupts\r
- and higher priority tasks accessed the queue between this\r
- task being unblocked and subsequently attempting to write\r
- to the queue. */\r
- xReturn = errQUEUE_FULL;\r
+ if( xTicksToWait == ( portTickType ) 0 )\r
+ {\r
+ taskEXIT_CRITICAL();\r
+ return errQUEUE_FULL;\r
+ }\r
+ else if( xEntryTimeSet == pdFALSE )\r
+ {\r
+ vTaskSetTimeOutState( &xTimeOut );\r
+ xEntryTimeSet = pdTRUE;\r
+ }\r
}\r
}\r
- taskEXIT_CRITICAL();\r
+ taskEXIT_CRITICAL(); \r
+\r
+ vTaskSuspendAll();\r
+ prvLockQueue( pxQueue );\r
\r
- if( xReturn == errQUEUE_FULL )\r
+ if( prvIsQueueFull( pxQueue ) )\r
{\r
- if( xTicksToWait > ( portTickType ) 0 )\r
+ /* Need to call xTaskCheckForTimeout again as time could\r
+ have passed since it was last called if this is not the\r
+ first time around this loop. */\r
+ if( xTaskCheckForTimeOut( &xTimeOut, &xTicksToWait ) == pdFALSE )\r
{\r
- if( xTaskCheckForTimeOut( &xTimeOut, &xTicksToWait ) == pdFALSE )\r
- {\r
- xReturn = queueERRONEOUS_UNBLOCK;\r
- }\r
- else\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() )\r
{\r
- traceQUEUE_SEND_FAILED( pxQueue );\r
+ taskYIELD();\r
}\r
}\r
else\r
{\r
- traceQUEUE_SEND_FAILED( pxQueue );\r
+ prvUnlockQueue( pxQueue );\r
+ ( void ) xTaskResumeAll();\r
+ return errQUEUE_FULL;\r
}\r
}\r
+ else\r
+ {\r
+ prvUnlockQueue( pxQueue );\r
+ ( void ) xTaskResumeAll();\r
+ }\r
}\r
- while( xReturn == queueERRONEOUS_UNBLOCK );\r
-\r
- return xReturn;\r
}\r
/*-----------------------------------------------------------*/\r
\r
\r
signed portBASE_TYPE xQueueAltGenericSend( 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
- /* The source code that implements the alternative (Alt) API is\r
- simpler because it makes more use of critical sections. This is\r
- 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 less use of\r
- critical sections. */\r
-\r
- do\r
+ for( ;; )\r
{\r
- /* If xTicksToWait is zero then we are not going to block even\r
- if there is no room in the queue to post. */\r
- if( xTicksToWait > ( portTickType ) 0 )\r
- {\r
- portENTER_CRITICAL();\r
- {\r
- if( xReturn == pdPASS )\r
- {\r
- /* This is the first time through - capture the time\r
- inside the critical section to ensure we attempt to\r
- block at least once. */\r
- vTaskSetTimeOutState( &xTimeOut );\r
- }\r
-\r
- if( prvIsQueueFull( pxQueue ) )\r
- {\r
- /* Need to call xTaskCheckForTimeout again as time could\r
- have passed since it was last called if this is not the\r
- first time around this loop. */\r
- if( xTaskCheckForTimeOut( &xTimeOut, &xTicksToWait ) == pdFALSE )\r
- {\r
- traceBLOCKING_ON_QUEUE_SEND( pxQueue );\r
- vTaskPlaceOnEventList( &( pxQueue->xTasksWaitingToSend ), xTicksToWait );\r
-\r
- /* This will exit the critical section, then re-enter when\r
- the task next runs. */\r
- taskYIELD();\r
- }\r
- }\r
- }\r
- portEXIT_CRITICAL();\r
- }\r
-\r
- /* Higher priority tasks and interrupts can execute during\r
- this time and could possible refill the queue - even if we\r
- unblocked because space became available. */\r
-\r
taskENTER_CRITICAL();\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
+ /* 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
traceQUEUE_SEND( pxQueue );\r
prvCopyDataToQueue( pxQueue, pvItemToQueue, xCopyPosition );\r
- xReturn = pdPASS;\r
\r
/* If there was a task waiting for data to arrive on the\r
queue then unblock it now. */\r
taskYIELD();\r
}\r
}\r
+\r
+ taskEXIT_CRITICAL();\r
+ return pdPASS;\r
}\r
else\r
{\r
- /* Setting xReturn to errQUEUE_FULL will force its timeout\r
- to be re-evaluated. This is necessary in case interrupts\r
- and higher priority tasks accessed the queue between this\r
- task being unblocked and subsequently attempting to write\r
- to the queue. */\r
- xReturn = errQUEUE_FULL;\r
+ if( xTicksToWait == ( portTickType ) 0 )\r
+ {\r
+ taskEXIT_CRITICAL();\r
+ return errQUEUE_FULL;\r
+ }\r
+ else if( xEntryTimeSet == pdFALSE )\r
+ {\r
+ vTaskSetTimeOutState( &xTimeOut );\r
+ xEntryTimeSet = pdTRUE;\r
+ }\r
}\r
}\r
- taskEXIT_CRITICAL();\r
+ taskEXIT_CRITICAL(); \r
\r
- if( xReturn == errQUEUE_FULL )\r
+ taskENTER_CRITICAL();\r
{\r
- if( xTicksToWait > ( portTickType ) 0 )\r
+ if( prvIsQueueFull( pxQueue ) )\r
{\r
+ /* Need to call xTaskCheckForTimeout again as time could\r
+ have passed since it was last called if this is not the\r
+ first time around this loop. */\r
if( xTaskCheckForTimeOut( &xTimeOut, &xTicksToWait ) == pdFALSE )\r
{\r
- xReturn = queueERRONEOUS_UNBLOCK;\r
+ traceBLOCKING_ON_QUEUE_SEND( pxQueue );\r
+ vTaskPlaceOnEventList( &( pxQueue->xTasksWaitingToSend ), xTicksToWait );\r
+ taskYIELD();\r
}\r
else\r
{\r
- traceQUEUE_SEND_FAILED( pxQueue );\r
+ taskEXIT_CRITICAL();\r
+ return errQUEUE_FULL;\r
}\r
}\r
- else\r
- {\r
- traceQUEUE_SEND_FAILED( pxQueue );\r
- }\r
}\r
+ taskEXIT_CRITICAL();\r
}\r
- while( xReturn == queueERRONEOUS_UNBLOCK );\r
-\r
- return xReturn;\r
}\r
\r
#endif /* configUSE_ALTERNATIVE_API */\r
\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
\r
- /* The source code that implements the alternative (Alt) API is\r
- simpler because it makes more use of critical sections. This is\r
- 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 less use of\r
- critical sections. */\r
-\r
- do\r
+ for( ;; )\r
{\r
- /* If there are no messages in the queue we may have to block. */\r
- if( xTicksToWait > ( portTickType ) 0 )\r
- {\r
- portENTER_CRITICAL();\r
- {\r
- if( xReturn == pdPASS )\r
- {\r
- /* This is the first time through - capture the time\r
- inside the critical section to ensure we attempt to\r
- block at least once. */\r
- vTaskSetTimeOutState( &xTimeOut );\r
- }\r
-\r
- if( prvIsQueueEmpty( pxQueue ) )\r
- {\r
- /* Need to call xTaskCheckForTimeout again as time could\r
- have passed since it was last called if this is not the\r
- first time around this loop. */\r
- if( xTaskCheckForTimeOut( &xTimeOut, &xTicksToWait ) == pdFALSE )\r
- {\r
- traceBLOCKING_ON_QUEUE_RECEIVE( pxQueue );\r
-\r
- #if ( configUSE_MUTEXES == 1 )\r
- {\r
- if( pxQueue->uxQueueType == queueQUEUE_IS_MUTEX )\r
- {\r
- vTaskPriorityInherit( ( void * ) pxQueue->pxMutexHolder );\r
- }\r
- }\r
- #endif\r
-\r
- vTaskPlaceOnEventList( &( pxQueue->xTasksWaitingToReceive ), xTicksToWait );\r
- taskYIELD();\r
- }\r
- }\r
- }\r
- portEXIT_CRITICAL();\r
- }\r
-\r
taskENTER_CRITICAL();\r
{\r
if( pxQueue->uxMessagesWaiting > ( unsigned portBASE_TYPE ) 0 )\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 that this task. */\r
+ /* The task waiting has a higher priority than this task. */\r
taskYIELD();\r
}\r
}\r
\r
}\r
\r
- xReturn = pdPASS;\r
+ taskEXIT_CRITICAL();\r
+ return pdPASS;\r
}\r
else\r
{\r
- xReturn = errQUEUE_EMPTY;\r
+ if( xTicksToWait == ( portTickType ) 0 )\r
+ {\r
+ taskEXIT_CRITICAL();\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( xReturn == errQUEUE_EMPTY )\r
+ taskENTER_CRITICAL();\r
{\r
- if( xTicksToWait > ( portTickType ) 0 )\r
+ if( prvIsQueueEmpty( pxQueue ) )\r
{\r
+ /* Need to call xTaskCheckForTimeout again as time could\r
+ have passed since it was last called if this is not the\r
+ first time around this loop. */\r
if( xTaskCheckForTimeOut( &xTimeOut, &xTicksToWait ) == pdFALSE )\r
{\r
- xReturn = queueERRONEOUS_UNBLOCK;\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
+ vTaskPriorityInherit( ( void * ) pxQueue->pxMutexHolder );\r
+ portEXIT_CRITICAL();\r
+ }\r
+ }\r
+ #endif\r
+\r
+ vTaskPlaceOnEventList( &( pxQueue->xTasksWaitingToReceive ), xTicksToWait );\r
+ taskYIELD();\r
}\r
else\r
{\r
- traceQUEUE_RECEIVE_FAILED( pxQueue );\r
+ taskEXIT_CRITICAL();\r
+ return errQUEUE_EMPTY;\r
}\r
}\r
- else\r
- {\r
- traceQUEUE_RECEIVE_FAILED( pxQueue );\r
- }\r
}\r
- } while( xReturn == queueERRONEOUS_UNBLOCK );\r
-\r
- return xReturn;\r
+ taskEXIT_CRITICAL();\r
+ }\r
}\r
\r
\r
\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
\r
- do\r
+ for( ;; )\r
{\r
- /* If there are no messages in the queue we may have to block. */\r
- if( xTicksToWait > ( portTickType ) 0 )\r
- {\r
- vTaskSuspendAll();\r
- prvLockQueue( pxQueue );\r
-\r
- if( xReturn == pdTRUE )\r
- {\r
- /* This is the first time through - we need to capture the\r
- time while the scheduler is locked to ensure we attempt to\r
- block at least once. */\r
- vTaskSetTimeOutState( &xTimeOut );\r
- }\r
-\r
- if( prvIsQueueEmpty( pxQueue ) )\r
- {\r
- /* Need to call xTaskCheckForTimeout again as time could\r
- have passed since it was last called if this is not the\r
- first time around this loop. */\r
- if( xTaskCheckForTimeOut( &xTimeOut, &xTicksToWait ) == pdFALSE )\r
- {\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
- vTaskPriorityInherit( ( void * ) pxQueue->pxMutexHolder );\r
- portEXIT_CRITICAL();\r
- }\r
- }\r
- #endif\r
-\r
- vTaskPlaceOnEventList( &( pxQueue->xTasksWaitingToReceive ), xTicksToWait );\r
- prvUnlockQueue( pxQueue );\r
- if( !xTaskResumeAll() )\r
- {\r
- taskYIELD();\r
- }\r
- }\r
- else\r
- {\r
- prvUnlockQueue( pxQueue );\r
- ( void ) xTaskResumeAll();\r
- }\r
- }\r
- else\r
- {\r
- prvUnlockQueue( pxQueue );\r
- ( void ) xTaskResumeAll();\r
- }\r
- }\r
-\r
taskENTER_CRITICAL();\r
{\r
if( pxQueue->uxMessagesWaiting > ( unsigned portBASE_TYPE ) 0 )\r
\r
}\r
\r
- xReturn = pdPASS;\r
+ taskEXIT_CRITICAL();\r
+ return pdPASS;\r
}\r
else\r
{\r
- xReturn = errQUEUE_EMPTY;\r
+ if( xTicksToWait == ( portTickType ) 0 )\r
+ {\r
+ taskEXIT_CRITICAL();\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( xReturn == errQUEUE_EMPTY )\r
+ vTaskSuspendAll();\r
+ prvLockQueue( pxQueue );\r
+\r
+ if( prvIsQueueEmpty( pxQueue ) )\r
{\r
- if( xTicksToWait > ( portTickType ) 0 )\r
+ /* Need to call xTaskCheckForTimeout again as time could\r
+ have passed since it was last called if this is not the\r
+ first time around this loop. */\r
+ if( xTaskCheckForTimeOut( &xTimeOut, &xTicksToWait ) == 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
- else\r
+ #endif\r
+\r
+ vTaskPlaceOnEventList( &( pxQueue->xTasksWaitingToReceive ), xTicksToWait );\r
+ prvUnlockQueue( pxQueue );\r
+ if( !xTaskResumeAll() )\r
{\r
- traceQUEUE_RECEIVE_FAILED( pxQueue );\r
+ taskYIELD();\r
}\r
}\r
else\r
{\r
- traceQUEUE_RECEIVE_FAILED( pxQueue );\r
+ prvUnlockQueue( pxQueue );\r
+ ( void ) xTaskResumeAll();\r
+ return errQUEUE_EMPTY;\r
}\r
}\r
-\r
- } while( xReturn == queueERRONEOUS_UNBLOCK );\r
-\r
- return xReturn;\r
+ else\r
+ {\r
+ prvUnlockQueue( pxQueue );\r
+ ( void ) xTaskResumeAll();\r
+ }\r
+ }\r
}\r
/*-----------------------------------------------------------*/\r
\r