summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichardBarry <RichardBarry@1d2547de-c912-0410-9cb9-b8ca96c0e9e2>2009-03-11 10:53:45 +0000
committerRichardBarry <RichardBarry@1d2547de-c912-0410-9cb9-b8ca96c0e9e2>2009-03-11 10:53:45 +0000
commitba4707960248025ca135fa06171adab6746f3a2d (patch)
treea804a35745292d9c7f05f3486a066d280d2dd954
parentaf5eab6cb372c52296d5bfd6dd26614c87bb2c65 (diff)
downloadfreertos-ba4707960248025ca135fa06171adab6746f3a2d.tar.gz
freertos-ba4707960248025ca135fa06171adab6746f3a2d.tar.bz2
freertos-ba4707960248025ca135fa06171adab6746f3a2d.tar.xz
Optimisations - being checked in for backup - not yet complete.
git-svn-id: https://freertos.svn.sourceforge.net/svnroot/freertos/trunk@703 1d2547de-c912-0410-9cb9-b8ca96c0e9e2
-rw-r--r--Source/queue.c450
1 files changed, 166 insertions, 284 deletions
diff --git a/Source/queue.c b/Source/queue.c
index 6bd33505..4f093f29 100644
--- a/Source/queue.c
+++ b/Source/queue.c
@@ -442,72 +442,11 @@ size_t xQueueSizeInBytes;
signed portBASE_TYPE xQueueGenericSend( xQueueHandle pxQueue, const void * const pvItemToQueue, portTickType xTicksToWait, portBASE_TYPE xCopyPosition )
{
-signed portBASE_TYPE xReturn = pdTRUE;
+signed portBASE_TYPE xEntryTimeSet = pdFALSE;
xTimeOutType xTimeOut;
- do
+ for( ;; )
{
- /* If xTicksToWait is zero then we are not going to block even
- if there is no room in the queue to post. */
- if( xTicksToWait > ( portTickType ) 0 )
- {
- vTaskSuspendAll();
- prvLockQueue( pxQueue );
-
- if( xReturn == pdTRUE )
- {
- /* This is the first time through - we need to capture the
- time while the scheduler is locked to ensure we attempt to
- block at least once. */
- vTaskSetTimeOutState( &xTimeOut );
- }
-
- if( prvIsQueueFull( pxQueue ) )
- {
- /* Need to call xTaskCheckForTimeout again as time could
- have passed since it was last called if this is not the
- first time around this loop. */
- if( xTaskCheckForTimeOut( &xTimeOut, &xTicksToWait ) == pdFALSE )
- {
- traceBLOCKING_ON_QUEUE_SEND( pxQueue );
- vTaskPlaceOnEventList( &( pxQueue->xTasksWaitingToSend ), xTicksToWait );
-
- /* Unlocking the queue means queue events can effect the
- event list. It is possible that interrupts occurring now
- remove this task from the event list again - but as the
- scheduler is suspended the task will go onto the pending
- ready last instead of the actual ready list. */
- prvUnlockQueue( pxQueue );
-
- /* Resuming the scheduler will move tasks from the pending
- ready list into the ready list - so it is feasible that this
- task is already in a ready list before it yields - in which
- case the yield will not cause a context switch unless there
- is also a higher priority task in the pending ready list. */
- if( !xTaskResumeAll() )
- {
- taskYIELD();
- }
- }
- else
- {
- prvUnlockQueue( pxQueue );
- ( void ) xTaskResumeAll();
- }
- }
- else
- {
- /* The queue was not full so we can just unlock the
- scheduler and queue again before carrying on. */
- prvUnlockQueue( pxQueue );
- ( void ) xTaskResumeAll();
- }
- }
-
- /* Higher priority tasks and interrupts can execute during
- this time and could possible refill the queue - even if we
- unblocked because space became available. */
-
taskENTER_CRITICAL();
{
/* Is there room on the queue now? To be running we must be
@@ -516,7 +455,6 @@ xTimeOutType xTimeOut;
{
traceQUEUE_SEND( pxQueue );
prvCopyDataToQueue( pxQueue, pvItemToQueue, xCopyPosition );
- xReturn = pdPASS;
/* If there was a task waiting for data to arrive on the
queue then unblock it now. */
@@ -524,46 +462,74 @@ xTimeOutType xTimeOut;
{
if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) == pdTRUE )
{
- /* The unblocked task has a priority higher than
- our own so yield immediately. */
- taskYIELD();
+ /* The unblocked task has a priority higher than
+ our own so yield immediately. */
+ taskYIELD();
}
}
+
+ taskEXIT_CRITICAL();
+ return pdPASS;
}
else
{
- /* Setting xReturn to errQUEUE_FULL will force its timeout
- to be re-evaluated. This is necessary in case interrupts
- and higher priority tasks accessed the queue between this
- task being unblocked and subsequently attempting to write
- to the queue. */
- xReturn = errQUEUE_FULL;
+ if( xTicksToWait == ( portTickType ) 0 )
+ {
+ taskEXIT_CRITICAL();
+ return errQUEUE_FULL;
+ }
+ else if( xEntryTimeSet == pdFALSE )
+ {
+ vTaskSetTimeOutState( &xTimeOut );
+ xEntryTimeSet = pdTRUE;
+ }
}
}
- taskEXIT_CRITICAL();
+ taskEXIT_CRITICAL();
+
+ vTaskSuspendAll();
+ prvLockQueue( pxQueue );
- if( xReturn == errQUEUE_FULL )
+ if( prvIsQueueFull( pxQueue ) )
{
- if( xTicksToWait > ( portTickType ) 0 )
+ /* Need to call xTaskCheckForTimeout again as time could
+ have passed since it was last called if this is not the
+ first time around this loop. */
+ if( xTaskCheckForTimeOut( &xTimeOut, &xTicksToWait ) == pdFALSE )
{
- if( xTaskCheckForTimeOut( &xTimeOut, &xTicksToWait ) == pdFALSE )
- {
- xReturn = queueERRONEOUS_UNBLOCK;
- }
- else
+ traceBLOCKING_ON_QUEUE_SEND( pxQueue );
+ vTaskPlaceOnEventList( &( pxQueue->xTasksWaitingToSend ), xTicksToWait );
+
+ /* Unlocking the queue means queue events can effect the
+ event list. It is possible that interrupts occurring now
+ remove this task from the event list again - but as the
+ scheduler is suspended the task will go onto the pending
+ ready last instead of the actual ready list. */
+ prvUnlockQueue( pxQueue );
+
+ /* Resuming the scheduler will move tasks from the pending
+ ready list into the ready list - so it is feasible that this
+ task is already in a ready list before it yields - in which
+ case the yield will not cause a context switch unless there
+ is also a higher priority task in the pending ready list. */
+ if( !xTaskResumeAll() )
{
- traceQUEUE_SEND_FAILED( pxQueue );
+ taskYIELD();
}
}
else
{
- traceQUEUE_SEND_FAILED( pxQueue );
+ prvUnlockQueue( pxQueue );
+ ( void ) xTaskResumeAll();
+ return errQUEUE_FULL;
}
}
+ else
+ {
+ prvUnlockQueue( pxQueue );
+ ( void ) xTaskResumeAll();
+ }
}
- while( xReturn == queueERRONEOUS_UNBLOCK );
-
- return xReturn;
}
/*-----------------------------------------------------------*/
@@ -571,64 +537,19 @@ xTimeOutType xTimeOut;
signed portBASE_TYPE xQueueAltGenericSend( xQueueHandle pxQueue, const void * const pvItemToQueue, portTickType xTicksToWait, portBASE_TYPE xCopyPosition )
{
- signed portBASE_TYPE xReturn = pdPASS;
+ signed portBASE_TYPE xEntryTimeSet = pdFALSE;
xTimeOutType xTimeOut;
- /* The source code that implements the alternative (Alt) API is
- simpler because it makes more use of critical sections. This is
- the approach taken by many other RTOSes, but FreeRTOS.org has the
- preferred fully featured API too. The fully featured API has more
- complex code that takes longer to execute, but makes less use of
- critical sections. */
-
- do
+ for( ;; )
{
- /* If xTicksToWait is zero then we are not going to block even
- if there is no room in the queue to post. */
- if( xTicksToWait > ( portTickType ) 0 )
- {
- portENTER_CRITICAL();
- {
- if( xReturn == pdPASS )
- {
- /* This is the first time through - capture the time
- inside the critical section to ensure we attempt to
- block at least once. */
- vTaskSetTimeOutState( &xTimeOut );
- }
-
- if( prvIsQueueFull( pxQueue ) )
- {
- /* Need to call xTaskCheckForTimeout again as time could
- have passed since it was last called if this is not the
- first time around this loop. */
- if( xTaskCheckForTimeOut( &xTimeOut, &xTicksToWait ) == pdFALSE )
- {
- traceBLOCKING_ON_QUEUE_SEND( pxQueue );
- vTaskPlaceOnEventList( &( pxQueue->xTasksWaitingToSend ), xTicksToWait );
-
- /* This will exit the critical section, then re-enter when
- the task next runs. */
- taskYIELD();
- }
- }
- }
- portEXIT_CRITICAL();
- }
-
- /* Higher priority tasks and interrupts can execute during
- this time and could possible refill the queue - even if we
- unblocked because space became available. */
-
taskENTER_CRITICAL();
{
- /* Is there room on the queue now? To be running we must be
- the highest priority task wanting to access the queue. */
+ /* Is there room on the queue now? To be running we must be
+ the highest priority task wanting to access the queue. */
if( pxQueue->uxMessagesWaiting < pxQueue->uxLength )
{
traceQUEUE_SEND( pxQueue );
prvCopyDataToQueue( pxQueue, pvItemToQueue, xCopyPosition );
- xReturn = pdPASS;
/* If there was a task waiting for data to arrive on the
queue then unblock it now. */
@@ -641,41 +562,48 @@ xTimeOutType xTimeOut;
taskYIELD();
}
}
+
+ taskEXIT_CRITICAL();
+ return pdPASS;
}
else
{
- /* Setting xReturn to errQUEUE_FULL will force its timeout
- to be re-evaluated. This is necessary in case interrupts
- and higher priority tasks accessed the queue between this
- task being unblocked and subsequently attempting to write
- to the queue. */
- xReturn = errQUEUE_FULL;
+ if( xTicksToWait == ( portTickType ) 0 )
+ {
+ taskEXIT_CRITICAL();
+ return errQUEUE_FULL;
+ }
+ else if( xEntryTimeSet == pdFALSE )
+ {
+ vTaskSetTimeOutState( &xTimeOut );
+ xEntryTimeSet = pdTRUE;
+ }
}
}
- taskEXIT_CRITICAL();
+ taskEXIT_CRITICAL();
- if( xReturn == errQUEUE_FULL )
+ taskENTER_CRITICAL();
{
- if( xTicksToWait > ( portTickType ) 0 )
+ if( prvIsQueueFull( pxQueue ) )
{
+ /* Need to call xTaskCheckForTimeout again as time could
+ have passed since it was last called if this is not the
+ first time around this loop. */
if( xTaskCheckForTimeOut( &xTimeOut, &xTicksToWait ) == pdFALSE )
{
- xReturn = queueERRONEOUS_UNBLOCK;
+ traceBLOCKING_ON_QUEUE_SEND( pxQueue );
+ vTaskPlaceOnEventList( &( pxQueue->xTasksWaitingToSend ), xTicksToWait );
+ taskYIELD();
}
else
{
- traceQUEUE_SEND_FAILED( pxQueue );
+ taskEXIT_CRITICAL();
+ return errQUEUE_FULL;
}
}
- else
- {
- traceQUEUE_SEND_FAILED( pxQueue );
- }
}
+ taskEXIT_CRITICAL();
}
- while( xReturn == queueERRONEOUS_UNBLOCK );
-
- return xReturn;
}
#endif /* configUSE_ALTERNATIVE_API */
@@ -685,58 +613,12 @@ xTimeOutType xTimeOut;
signed portBASE_TYPE xQueueAltGenericReceive( xQueueHandle pxQueue, void * const pvBuffer, portTickType xTicksToWait, portBASE_TYPE xJustPeeking )
{
- signed portBASE_TYPE xReturn = pdTRUE;
+ signed portBASE_TYPE xEntryTimeSet = pdFALSE;
xTimeOutType xTimeOut;
signed portCHAR *pcOriginalReadPosition;
- /* The source code that implements the alternative (Alt) API is
- simpler because it makes more use of critical sections. This is
- the approach taken by many other RTOSes, but FreeRTOS.org has the
- preferred fully featured API too. The fully featured API has more
- complex code that takes longer to execute, but makes less use of
- critical sections. */
-
- do
+ for( ;; )
{
- /* If there are no messages in the queue we may have to block. */
- if( xTicksToWait > ( portTickType ) 0 )
- {
- portENTER_CRITICAL();
- {
- if( xReturn == pdPASS )
- {
- /* This is the first time through - capture the time
- inside the critical section to ensure we attempt to
- block at least once. */
- vTaskSetTimeOutState( &xTimeOut );
- }
-
- if( prvIsQueueEmpty( pxQueue ) )
- {
- /* Need to call xTaskCheckForTimeout again as time could
- have passed since it was last called if this is not the
- first time around this loop. */
- if( xTaskCheckForTimeOut( &xTimeOut, &xTicksToWait ) == pdFALSE )
- {
- traceBLOCKING_ON_QUEUE_RECEIVE( pxQueue );
-
- #if ( configUSE_MUTEXES == 1 )
- {
- if( pxQueue->uxQueueType == queueQUEUE_IS_MUTEX )
- {
- vTaskPriorityInherit( ( void * ) pxQueue->pxMutexHolder );
- }
- }
- #endif
-
- vTaskPlaceOnEventList( &( pxQueue->xTasksWaitingToReceive ), xTicksToWait );
- taskYIELD();
- }
- }
- }
- portEXIT_CRITICAL();
- }
-
taskENTER_CRITICAL();
{
if( pxQueue->uxMessagesWaiting > ( unsigned portBASE_TYPE ) 0 )
@@ -788,43 +670,66 @@ xTimeOutType xTimeOut;
the pending ready list as the scheduler is still suspended. */
if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE )
{
- /* The task waiting has a higher priority that this task. */
+ /* The task waiting has a higher priority than this task. */
taskYIELD();
}
}
}
- xReturn = pdPASS;
+ taskEXIT_CRITICAL();
+ return pdPASS;
}
else
{
- xReturn = errQUEUE_EMPTY;
+ if( xTicksToWait == ( portTickType ) 0 )
+ {
+ taskEXIT_CRITICAL();
+ return errQUEUE_EMPTY;
+ }
+ else if( xEntryTimeSet == pdFALSE )
+ {
+ vTaskSetTimeOutState( &xTimeOut );
+ xEntryTimeSet = pdTRUE;
+ }
}
}
taskEXIT_CRITICAL();
- if( xReturn == errQUEUE_EMPTY )
+ taskENTER_CRITICAL();
{
- if( xTicksToWait > ( portTickType ) 0 )
+ if( prvIsQueueEmpty( pxQueue ) )
{
+ /* Need to call xTaskCheckForTimeout again as time could
+ have passed since it was last called if this is not the
+ first time around this loop. */
if( xTaskCheckForTimeOut( &xTimeOut, &xTicksToWait ) == pdFALSE )
{
- xReturn = queueERRONEOUS_UNBLOCK;
+ traceBLOCKING_ON_QUEUE_RECEIVE( pxQueue );
+
+ #if ( configUSE_MUTEXES == 1 )
+ {
+ if( pxQueue->uxQueueType == queueQUEUE_IS_MUTEX )
+ {
+ portENTER_CRITICAL();
+ vTaskPriorityInherit( ( void * ) pxQueue->pxMutexHolder );
+ portEXIT_CRITICAL();
+ }
+ }
+ #endif
+
+ vTaskPlaceOnEventList( &( pxQueue->xTasksWaitingToReceive ), xTicksToWait );
+ taskYIELD();
}
else
{
- traceQUEUE_RECEIVE_FAILED( pxQueue );
+ taskEXIT_CRITICAL();
+ return errQUEUE_EMPTY;
}
}
- else
- {
- traceQUEUE_RECEIVE_FAILED( pxQueue );
- }
}
- } while( xReturn == queueERRONEOUS_UNBLOCK );
-
- return xReturn;
+ taskEXIT_CRITICAL();
+ }
}
@@ -886,66 +791,12 @@ unsigned portBASE_TYPE uxSavedInterruptStatus;
signed portBASE_TYPE xQueueGenericReceive( xQueueHandle pxQueue, void * const pvBuffer, portTickType xTicksToWait, portBASE_TYPE xJustPeeking )
{
-signed portBASE_TYPE xReturn = pdTRUE;
+signed portBASE_TYPE xEntryTimeSet = pdFALSE;
xTimeOutType xTimeOut;
signed portCHAR *pcOriginalReadPosition;
- do
+ for( ;; )
{
- /* If there are no messages in the queue we may have to block. */
- if( xTicksToWait > ( portTickType ) 0 )
- {
- vTaskSuspendAll();
- prvLockQueue( pxQueue );
-
- if( xReturn == pdTRUE )
- {
- /* This is the first time through - we need to capture the
- time while the scheduler is locked to ensure we attempt to
- block at least once. */
- vTaskSetTimeOutState( &xTimeOut );
- }
-
- if( prvIsQueueEmpty( pxQueue ) )
- {
- /* Need to call xTaskCheckForTimeout again as time could
- have passed since it was last called if this is not the
- first time around this loop. */
- if( xTaskCheckForTimeOut( &xTimeOut, &xTicksToWait ) == pdFALSE )
- {
- traceBLOCKING_ON_QUEUE_RECEIVE( pxQueue );
-
- #if ( configUSE_MUTEXES == 1 )
- {
- if( pxQueue->uxQueueType == queueQUEUE_IS_MUTEX )
- {
- portENTER_CRITICAL();
- vTaskPriorityInherit( ( void * ) pxQueue->pxMutexHolder );
- portEXIT_CRITICAL();
- }
- }
- #endif
-
- vTaskPlaceOnEventList( &( pxQueue->xTasksWaitingToReceive ), xTicksToWait );
- prvUnlockQueue( pxQueue );
- if( !xTaskResumeAll() )
- {
- taskYIELD();
- }
- }
- else
- {
- prvUnlockQueue( pxQueue );
- ( void ) xTaskResumeAll();
- }
- }
- else
- {
- prvUnlockQueue( pxQueue );
- ( void ) xTaskResumeAll();
- }
- }
-
taskENTER_CRITICAL();
{
if( pxQueue->uxMessagesWaiting > ( unsigned portBASE_TYPE ) 0 )
@@ -1004,37 +855,68 @@ signed portCHAR *pcOriginalReadPosition;
}
- xReturn = pdPASS;
+ taskEXIT_CRITICAL();
+ return pdPASS;
}
else
{
- xReturn = errQUEUE_EMPTY;
+ if( xTicksToWait == ( portTickType ) 0 )
+ {
+ taskEXIT_CRITICAL();
+ return errQUEUE_EMPTY;
+ }
+ else if( xEntryTimeSet == pdFALSE )
+ {
+ vTaskSetTimeOutState( &xTimeOut );
+ xEntryTimeSet = pdTRUE;
+ }
}
}
taskEXIT_CRITICAL();
- if( xReturn == errQUEUE_EMPTY )
+ vTaskSuspendAll();
+ prvLockQueue( pxQueue );
+
+ if( prvIsQueueEmpty( pxQueue ) )
{
- if( xTicksToWait > ( portTickType ) 0 )
+ /* Need to call xTaskCheckForTimeout again as time could
+ have passed since it was last called if this is not the
+ first time around this loop. */
+ if( xTaskCheckForTimeOut( &xTimeOut, &xTicksToWait ) == pdFALSE )
{
- if( xTaskCheckForTimeOut( &xTimeOut, &xTicksToWait ) == pdFALSE )
+ traceBLOCKING_ON_QUEUE_RECEIVE( pxQueue );
+
+ #if ( configUSE_MUTEXES == 1 )
{
- xReturn = queueERRONEOUS_UNBLOCK;
+ if( pxQueue->uxQueueType == queueQUEUE_IS_MUTEX )
+ {
+ portENTER_CRITICAL();
+ vTaskPriorityInherit( ( void * ) pxQueue->pxMutexHolder );
+ portEXIT_CRITICAL();
+ }
}
- else
+ #endif
+
+ vTaskPlaceOnEventList( &( pxQueue->xTasksWaitingToReceive ), xTicksToWait );
+ prvUnlockQueue( pxQueue );
+ if( !xTaskResumeAll() )
{
- traceQUEUE_RECEIVE_FAILED( pxQueue );
+ taskYIELD();
}
}
else
{
- traceQUEUE_RECEIVE_FAILED( pxQueue );
+ prvUnlockQueue( pxQueue );
+ ( void ) xTaskResumeAll();
+ return errQUEUE_EMPTY;
}
}
-
- } while( xReturn == queueERRONEOUS_UNBLOCK );
-
- return xReturn;
+ else
+ {
+ prvUnlockQueue( pxQueue );
+ ( void ) xTaskResumeAll();
+ }
+ }
}
/*-----------------------------------------------------------*/