Some time and code size optimisations.

This commit is contained in:
Richard Barry 2011-02-06 15:44:56 +00:00
parent 1374a17f73
commit c26b230d28
4 changed files with 133 additions and 95 deletions

View File

@ -222,7 +222,7 @@ static void prvCheckPendingReadyList( void )
/* Are there any co-routines waiting to get moved to the ready list? These /* Are there any co-routines waiting to get moved to the ready list? These
are co-routines that have been readied by an ISR. The ISR cannot access are co-routines that have been readied by an ISR. The ISR cannot access
the ready lists itself. */ the ready lists itself. */
while( !listLIST_IS_EMPTY( &xPendingReadyCoRoutineList ) ) while( listLIST_IS_EMPTY( &xPendingReadyCoRoutineList ) == pdFALSE )
{ {
corCRCB *pxUnblockedCRCB; corCRCB *pxUnblockedCRCB;
@ -263,8 +263,10 @@ corCRCB *pxCRCB;
} }
/* See if this tick has made a timeout expire. */ /* See if this tick has made a timeout expire. */
while( ( pxCRCB = ( corCRCB * ) listGET_OWNER_OF_HEAD_ENTRY( pxDelayedCoRoutineList ) ) != NULL ) while( listLIST_IS_EMPTY( pxDelayedCoRoutineList ) == pdFALSE )
{ {
pxCRCB = ( corCRCB * ) listGET_OWNER_OF_HEAD_ENTRY( pxDelayedCoRoutineList );
if( xCoRoutineTickCount < listGET_LIST_ITEM_VALUE( &( pxCRCB->xGenericListItem ) ) ) if( xCoRoutineTickCount < listGET_LIST_ITEM_VALUE( &( pxCRCB->xGenericListItem ) ) )
{ {
/* Timeout not yet expired. */ /* Timeout not yet expired. */
@ -352,7 +354,8 @@ corCRCB *pxUnblockedCRCB;
signed portBASE_TYPE xReturn; signed portBASE_TYPE xReturn;
/* This function is called from within an interrupt. It can only access /* This function is called from within an interrupt. It can only access
event lists and the pending ready list. */ event lists and the pending ready list. This function assumes that a
check has already been made to ensure pxEventList is not empty. */
pxUnblockedCRCB = ( corCRCB * ) listGET_OWNER_OF_HEAD_ENTRY( pxEventList ); pxUnblockedCRCB = ( corCRCB * ) listGET_OWNER_OF_HEAD_ENTRY( pxEventList );
vListRemove( &( pxUnblockedCRCB->xEventListItem ) ); vListRemove( &( pxUnblockedCRCB->xEventListItem ) );
vListInsertEnd( ( xList * ) &( xPendingReadyCoRoutineList ), &( pxUnblockedCRCB->xEventListItem ) ); vListInsertEnd( ( xList * ) &( xPendingReadyCoRoutineList ), &( pxUnblockedCRCB->xEventListItem ) );

View File

@ -214,7 +214,7 @@ xList * const pxConstList = pxList; \
* \page listGET_OWNER_OF_HEAD_ENTRY listGET_OWNER_OF_HEAD_ENTRY * \page listGET_OWNER_OF_HEAD_ENTRY listGET_OWNER_OF_HEAD_ENTRY
* \ingroup LinkedList * \ingroup LinkedList
*/ */
#define listGET_OWNER_OF_HEAD_ENTRY( pxList ) ( ( pxList->uxNumberOfItems != ( unsigned portBASE_TYPE ) 0 ) ? ( (&( pxList->xListEnd ))->pxNext->pvOwner ) : ( NULL ) ) #define listGET_OWNER_OF_HEAD_ENTRY( pxList ) ( (&( pxList->xListEnd ))->pxNext->pvOwner )
/* /*
* Check to see if a list item is within a list. The list item maintains a * Check to see if a list item is within a list. The list item maintains a

View File

@ -697,7 +697,7 @@ xTimeOutType xTimeOut;
/* The data is being left in the queue, so see if there are /* The data is being left in the queue, so see if there are
any other tasks waiting for the data. */ any other tasks waiting for the data. */
if( !listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) ) if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE )
{ {
/* Tasks that are removed from the event list will get added to /* Tasks that are removed from the event list will get added to
the pending ready list as the scheduler is still suspended. */ the pending ready list as the scheduler is still suspended. */
@ -790,7 +790,7 @@ unsigned portBASE_TYPE uxSavedInterruptStatus;
be done when the queue is unlocked later. */ be done when the queue is unlocked later. */
if( pxQueue->xTxLock == queueUNLOCKED ) if( pxQueue->xTxLock == queueUNLOCKED )
{ {
if( !listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) ) if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE )
{ {
if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE ) if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE )
{ {
@ -880,7 +880,7 @@ signed char *pcOriginalReadPosition;
/* The data is being left in the queue, so see if there are /* The data is being left in the queue, so see if there are
any other tasks waiting for the data. */ any other tasks waiting for the data. */
if( !listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) ) if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE )
{ {
/* Tasks that are removed from the event list will get added to /* Tasks that are removed from the event list will get added to
the pending ready list as the scheduler is still suspended. */ the pending ready list as the scheduler is still suspended. */
@ -988,7 +988,7 @@ unsigned portBASE_TYPE uxSavedInterruptStatus;
that an ISR has removed data while the queue was locked. */ that an ISR has removed data while the queue was locked. */
if( pxQueue->xRxLock == queueUNLOCKED ) if( pxQueue->xRxLock == queueUNLOCKED )
{ {
if( !listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) ) if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) == pdFALSE )
{ {
if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) != pdFALSE ) if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) != pdFALSE )
{ {
@ -1117,7 +1117,7 @@ static void prvUnlockQueue( xQueueHandle pxQueue )
{ {
/* Data was posted while the queue was locked. Are any tasks /* Data was posted while the queue was locked. Are any tasks
blocked waiting for data to become available? */ blocked waiting for data to become available? */
if( !listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) ) if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE )
{ {
/* Tasks that are removed from the event list will get added to /* Tasks that are removed from the event list will get added to
the pending ready list as the scheduler is still suspended. */ the pending ready list as the scheduler is still suspended. */
@ -1145,7 +1145,7 @@ static void prvUnlockQueue( xQueueHandle pxQueue )
{ {
while( pxQueue->xRxLock > queueLOCKED_UNMODIFIED ) while( pxQueue->xRxLock > queueLOCKED_UNMODIFIED )
{ {
if( !listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) ) if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) == pdFALSE )
{ {
if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) != pdFALSE ) if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) != pdFALSE )
{ {

View File

@ -161,6 +161,7 @@ PRIVILEGED_DATA static volatile unsigned portBASE_TYPE uxMissedTicks = ( unsi
PRIVILEGED_DATA static volatile portBASE_TYPE xMissedYield = ( portBASE_TYPE ) pdFALSE; PRIVILEGED_DATA static volatile portBASE_TYPE xMissedYield = ( portBASE_TYPE ) pdFALSE;
PRIVILEGED_DATA static volatile portBASE_TYPE xNumOfOverflows = ( portBASE_TYPE ) 0; PRIVILEGED_DATA static volatile portBASE_TYPE xNumOfOverflows = ( portBASE_TYPE ) 0;
PRIVILEGED_DATA static unsigned portBASE_TYPE uxTaskNumber = ( unsigned portBASE_TYPE ) 0; PRIVILEGED_DATA static unsigned portBASE_TYPE uxTaskNumber = ( unsigned portBASE_TYPE ) 0;
PRIVILEGED_DATA static portTickType xNextTaskUnblockTime = ( portTickType ) portMAX_DELAY;
#if ( configGENERATE_RUN_TIME_STATS == 1 ) #if ( configGENERATE_RUN_TIME_STATS == 1 )
@ -268,14 +269,45 @@ PRIVILEGED_DATA static unsigned portBASE_TYPE uxTaskNumber = ( unsigned po
#define prvCheckDelayedTasks() \ #define prvCheckDelayedTasks() \
{ \ { \
register tskTCB *pxTCB; \ register tskTCB *pxTCB; \
portTickType xItemValue; \
\ \
while( ( pxTCB = ( tskTCB * ) listGET_OWNER_OF_HEAD_ENTRY( pxDelayedTaskList ) ) != NULL ) \ /* Is the tick count greater than or equal to the wake time of the first \
task referenced from the delayed tasks list? */ \
if( xTickCount >= xNextTaskUnblockTime ) \
{ \ { \
if( xTickCount < listGET_LIST_ITEM_VALUE( &( pxTCB->xGenericListItem ) ) ) \ for( ;; ) \
{ \ { \
if( listLIST_IS_EMPTY( pxDelayedTaskList ) != pdFALSE ) \
{ \
/* The delayed list is empty. Set xNextTaskUnblockTime to the \
maximum possible value so it is extremely unlikely that the \
if( xTickCount >= xNextTaskUnblockTime ) test will pass next \
time through. */ \
xNextTaskUnblockTime = portMAX_DELAY; \
break; \ break; \
} \ } \
else \
{ \
/* The delayed list is not empty, get the value of the item at \
the head of the delayed list. This is the time at which the \
task at the head of the delayed list should be removed from \
the Blocked state. */ \
pxTCB = ( tskTCB * ) listGET_OWNER_OF_HEAD_ENTRY( pxDelayedTaskList ); \
xItemValue = listGET_LIST_ITEM_VALUE( &( pxTCB->xGenericListItem ) ); \
\
if( xTickCount < xItemValue ) \
{ \
/* It is not time to unblock this item yet, but the item \
value is the time at which the task at the head of the \
blocked list should be removed from the Blocked state - \
so record the item value in xNextTaskUnblockTime. */ \
xNextTaskUnblockTime = xItemValue; \
break; \
} \
\
/* It is time to remove the item from the Blocked state. */ \
vListRemove( &( pxTCB->xGenericListItem ) ); \ vListRemove( &( pxTCB->xGenericListItem ) ); \
\
/* Is the task waiting on an event also? */ \ /* Is the task waiting on an event also? */ \
if( pxTCB->xEventListItem.pvContainer ) \ if( pxTCB->xEventListItem.pvContainer ) \
{ \ { \
@ -283,6 +315,8 @@ register tskTCB *pxTCB; \
} \ } \
prvAddTaskToReadyQueue( pxTCB ); \ prvAddTaskToReadyQueue( pxTCB ); \
} \ } \
} \
} \
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -342,6 +376,12 @@ static portTASK_FUNCTION_PROTO( prvIdleTask, pvParameters );
*/ */
static void prvCheckTasksWaitingTermination( void ) PRIVILEGED_FUNCTION; static void prvCheckTasksWaitingTermination( void ) PRIVILEGED_FUNCTION;
/*
* The currently executing task is entering the Blocked state. Add the task to
* either the current or the overflow delayed task list.
*/
static void prvAddCurrentTaskToDelayedList( portTickType xTimeToWake ) PRIVILEGED_FUNCTION;
/* /*
* Allocates memory from the heap for a TCB and associated stack. Checks the * Allocates memory from the heap for a TCB and associated stack. Checks the
* allocation was successful. * allocation was successful.
@ -637,7 +677,7 @@ tskTCB * pxNewTCB;
/* Update the wake time ready for the next call. */ /* Update the wake time ready for the next call. */
*pxPreviousWakeTime = xTimeToWake; *pxPreviousWakeTime = xTimeToWake;
if( xShouldDelay ) if( xShouldDelay != pdFALSE )
{ {
traceTASK_DELAY_UNTIL(); traceTASK_DELAY_UNTIL();
@ -645,22 +685,7 @@ tskTCB * pxNewTCB;
ourselves to the blocked list as the same list item is used for ourselves to the blocked list as the same list item is used for
both lists. */ both lists. */
vListRemove( ( xListItem * ) &( pxCurrentTCB->xGenericListItem ) ); vListRemove( ( xListItem * ) &( pxCurrentTCB->xGenericListItem ) );
prvAddCurrentTaskToDelayedList( xTimeToWake );
/* The list item will be inserted in wake time order. */
listSET_LIST_ITEM_VALUE( &( pxCurrentTCB->xGenericListItem ), xTimeToWake );
if( xTimeToWake < xTickCount )
{
/* Wake time has overflowed. Place this item in the
overflow list. */
vListInsert( ( xList * ) pxOverflowDelayedTaskList, ( xListItem * ) &( pxCurrentTCB->xGenericListItem ) );
}
else
{
/* The wake time has not overflowed, so we can use the
current block list. */
vListInsert( ( xList * ) pxDelayedTaskList, ( xListItem * ) &( pxCurrentTCB->xGenericListItem ) );
}
} }
} }
xAlreadyYielded = xTaskResumeAll(); xAlreadyYielded = xTaskResumeAll();
@ -706,22 +731,7 @@ tskTCB * pxNewTCB;
ourselves to the blocked list as the same list item is used for ourselves to the blocked list as the same list item is used for
both lists. */ both lists. */
vListRemove( ( xListItem * ) &( pxCurrentTCB->xGenericListItem ) ); vListRemove( ( xListItem * ) &( pxCurrentTCB->xGenericListItem ) );
prvAddCurrentTaskToDelayedList( xTimeToWake );
/* The list item will be inserted in wake time order. */
listSET_LIST_ITEM_VALUE( &( pxCurrentTCB->xGenericListItem ), xTimeToWake );
if( xTimeToWake < xTickCount )
{
/* Wake time has overflowed. Place this item in the
overflow list. */
vListInsert( ( xList * ) pxOverflowDelayedTaskList, ( xListItem * ) &( pxCurrentTCB->xGenericListItem ) );
}
else
{
/* The wake time has not overflowed, so we can use the
current block list. */
vListInsert( ( xList * ) pxDelayedTaskList, ( xListItem * ) &( pxCurrentTCB->xGenericListItem ) );
}
} }
xAlreadyYielded = xTaskResumeAll(); xAlreadyYielded = xTaskResumeAll();
} }
@ -1125,8 +1135,9 @@ signed portBASE_TYPE xAlreadyYielded = pdFALSE;
/* Move any readied tasks from the pending list into the /* Move any readied tasks from the pending list into the
appropriate ready list. */ appropriate ready list. */
while( ( pxTCB = ( tskTCB * ) listGET_OWNER_OF_HEAD_ENTRY( ( ( xList * ) &xPendingReadyList ) ) ) != NULL ) while( listLIST_IS_EMPTY( ( xList * ) &xPendingReadyList ) == pdFALSE )
{ {
pxTCB = ( tskTCB * ) listGET_OWNER_OF_HEAD_ENTRY( ( ( xList * ) &xPendingReadyList ) );
vListRemove( &( pxTCB->xEventListItem ) ); vListRemove( &( pxTCB->xEventListItem ) );
vListRemove( &( pxTCB->xGenericListItem ) ); vListRemove( &( pxTCB->xGenericListItem ) );
prvAddTaskToReadyQueue( pxTCB ); prvAddTaskToReadyQueue( pxTCB );
@ -1413,6 +1424,25 @@ void vTaskIncrementTick( void )
pxDelayedTaskList = pxOverflowDelayedTaskList; pxDelayedTaskList = pxOverflowDelayedTaskList;
pxOverflowDelayedTaskList = pxTemp; pxOverflowDelayedTaskList = pxTemp;
xNumOfOverflows++; xNumOfOverflows++;
if( listLIST_IS_EMPTY( pxDelayedTaskList ) != pdFALSE )
{
/* The delayed list is empty. Set xNextTaskUnblockTime to the
maximum possible value so it is extremely unlikely that the
if( xTickCount >= xNextTaskUnblockTime ) test will pass
until there is an item in the delayed list. */
xNextTaskUnblockTime = portMAX_DELAY;
}
else
{
tskTCB * pxTCB;
/* The delayed list is not empty, get the value of the item at
the head of the delayed list. This is the time at which the
task at the head of the delayed list should be removed from
the Blocked state. */
pxTCB = ( tskTCB * ) listGET_OWNER_OF_HEAD_ENTRY( pxDelayedTaskList );
xNextTaskUnblockTime = listGET_LIST_ITEM_VALUE( &( pxTCB->xGenericListItem ) );
}
} }
/* See if this tick has made a timeout expire. */ /* See if this tick has made a timeout expire. */
@ -1672,19 +1702,7 @@ portTickType xTimeToWake;
/* Calculate the time at which the task should be woken if the event does /* Calculate the time at which the task should be woken if the event does
not occur. This may overflow but this doesn't matter. */ not occur. This may overflow but this doesn't matter. */
xTimeToWake = xTickCount + xTicksToWait; xTimeToWake = xTickCount + xTicksToWait;
prvAddCurrentTaskToDelayedList( xTimeToWake );
listSET_LIST_ITEM_VALUE( &( pxCurrentTCB->xGenericListItem ), xTimeToWake );
if( xTimeToWake < xTickCount )
{
/* Wake time has overflowed. Place this item in the overflow list. */
vListInsert( ( xList * ) pxOverflowDelayedTaskList, ( xListItem * ) &( pxCurrentTCB->xGenericListItem ) );
}
else
{
/* The wake time has not overflowed, so we can use the current block list. */
vListInsert( ( xList * ) pxDelayedTaskList, ( xListItem * ) &( pxCurrentTCB->xGenericListItem ) );
}
} }
} }
#else #else
@ -1692,19 +1710,7 @@ portTickType xTimeToWake;
/* Calculate the time at which the task should be woken if the event does /* Calculate the time at which the task should be woken if the event does
not occur. This may overflow but this doesn't matter. */ not occur. This may overflow but this doesn't matter. */
xTimeToWake = xTickCount + xTicksToWait; xTimeToWake = xTickCount + xTicksToWait;
prvAddCurrentTaskToDelayedList( xTimeToWake );
listSET_LIST_ITEM_VALUE( &( pxCurrentTCB->xGenericListItem ), xTimeToWake );
if( xTimeToWake < xTickCount )
{
/* Wake time has overflowed. Place this item in the overflow list. */
vListInsert( ( xList * ) pxOverflowDelayedTaskList, ( xListItem * ) &( pxCurrentTCB->xGenericListItem ) );
}
else
{
/* The wake time has not overflowed, so we can use the current block list. */
vListInsert( ( xList * ) pxDelayedTaskList, ( xListItem * ) &( pxCurrentTCB->xGenericListItem ) );
}
} }
#endif #endif
} }
@ -1724,7 +1730,10 @@ portBASE_TYPE xReturn;
If an event is for a queue that is locked then this function will never If an event is for a queue that is locked then this function will never
get called - the lock count on the queue will get modified instead. This get called - the lock count on the queue will get modified instead. This
means we can always expect exclusive access to the event list here. */ means we can always expect exclusive access to the event list here.
This function assumes that a check has already been made to ensure that
pxEventList is not empty. */
pxUnblockedTCB = ( tskTCB * ) listGET_OWNER_OF_HEAD_ENTRY( pxEventList ); pxUnblockedTCB = ( tskTCB * ) listGET_OWNER_OF_HEAD_ENTRY( pxEventList );
vListRemove( &( pxUnblockedTCB->xEventListItem ) ); vListRemove( &( pxUnblockedTCB->xEventListItem ) );
@ -2020,7 +2029,7 @@ static void prvCheckTasksWaitingTermination( void )
xListIsEmpty = listLIST_IS_EMPTY( &xTasksWaitingTermination ); xListIsEmpty = listLIST_IS_EMPTY( &xTasksWaitingTermination );
xTaskResumeAll(); xTaskResumeAll();
if( !xListIsEmpty ) if( xListIsEmpty == pdFALSE )
{ {
tskTCB *pxTCB; tskTCB *pxTCB;
@ -2041,6 +2050,32 @@ static void prvCheckTasksWaitingTermination( void )
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
static void prvAddCurrentTaskToDelayedList( portTickType xTimeToWake )
{
/* The list item will be inserted in wake time order. */
listSET_LIST_ITEM_VALUE( &( pxCurrentTCB->xGenericListItem ), xTimeToWake );
if( xTimeToWake < xTickCount )
{
/* Wake time has overflowed. Place this item in the overflow list. */
vListInsert( ( xList * ) pxOverflowDelayedTaskList, ( xListItem * ) &( pxCurrentTCB->xGenericListItem ) );
}
else
{
/* The wake time has not overflowed, so we can use the current block list. */
vListInsert( ( xList * ) pxDelayedTaskList, ( xListItem * ) &( pxCurrentTCB->xGenericListItem ) );
/* If the task entering the blocked state was placed at the head of the
list of blocked tasks then xNextTaskUnmblockTime needs to be updated
too. */
if( xTimeToWake < xNextTaskUnblockTime )
{
xNextTaskUnblockTime = xTimeToWake;
}
}
}
/*-----------------------------------------------------------*/
static tskTCB *prvAllocateTCBAndStack( unsigned short usStackDepth, portSTACK_TYPE *puxStackBuffer ) static tskTCB *prvAllocateTCBAndStack( unsigned short usStackDepth, portSTACK_TYPE *puxStackBuffer )
{ {
tskTCB *pxNewTCB; tskTCB *pxNewTCB;