Introduce prvResetNextTaskUnblockTime() to encapsulate functionality from various places in the code into a single function.

This commit is contained in:
Richard Barry 2013-12-13 10:35:11 +00:00
parent acad916453
commit c17c65fc09

View File

@ -339,25 +339,7 @@ count overflows. */
pxDelayedTaskList = pxOverflowDelayedTaskList; \ pxDelayedTaskList = pxOverflowDelayedTaskList; \
pxOverflowDelayedTaskList = pxTemp; \ pxOverflowDelayedTaskList = pxTemp; \
xNumOfOverflows++; \ xNumOfOverflows++; \
\ prvResetNextTaskUnblockTime(); \
if( listLIST_IS_EMPTY( pxDelayedTaskList ) != pdFALSE ) \
{ \
/* The new current 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 \
{ \
/* The new current 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 ) ); \
} \
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -483,6 +465,14 @@ static tskTCB *prvAllocateTCBAndStack( unsigned short usStackDepth, portSTACK_TY
#endif #endif
/*
* Set xNextTaskUnblockTime to the time at which the next Blocked state task
* will exit the Blocked state.
*/
static void prvResetNextTaskUnblockTime( void );
/*-----------------------------------------------------------*/
signed portBASE_TYPE xTaskGenericCreate( pdTASK_CODE pxTaskCode, const signed char * const pcName, unsigned short usStackDepth, void *pvParameters, unsigned portBASE_TYPE uxPriority, xTaskHandle *pxCreatedTask, portSTACK_TYPE *puxStackBuffer, const xMemoryRegion * const xRegions ) signed portBASE_TYPE xTaskGenericCreate( pdTASK_CODE pxTaskCode, const signed char * const pcName, unsigned short usStackDepth, void *pvParameters, unsigned portBASE_TYPE uxPriority, xTaskHandle *pxCreatedTask, portSTACK_TYPE *puxStackBuffer, const xMemoryRegion * const xRegions )
{ {
signed portBASE_TYPE xReturn; signed portBASE_TYPE xReturn;
@ -689,7 +679,7 @@ tskTCB * pxNewTCB;
/* The pre-delete hook is primarily for the Windows simulator, /* The pre-delete hook is primarily for the Windows simulator,
in which Windows specific clean up operations are performed, in which Windows specific clean up operations are performed,
after which it is not possible to yield away from this task - after which it is not possible to yield away from this task -
hence xYieldPending is used to latch that a context switch is hence xYieldPending is used to latch that a context switch is
required. */ required. */
portPRE_TASK_DELETE_HOOK( pxTCB, &xYieldPending ); portPRE_TASK_DELETE_HOOK( pxTCB, &xYieldPending );
@ -697,10 +687,9 @@ tskTCB * pxNewTCB;
} }
else else
{ {
/* Reset the next expected unblock time in case it referred to the task /* Reset the next expected unblock time in case it referred to
that has just been deleted. */ the task that has just been deleted. */
pxTCB = ( tskTCB * ) listGET_OWNER_OF_HEAD_ENTRY( pxDelayedTaskList ); prvResetNextTaskUnblockTime();
xNextTaskUnblockTime = listGET_LIST_ITEM_VALUE( &( pxTCB->xGenericListItem ) );
} }
} }
} }
@ -1076,7 +1065,7 @@ tskTCB * pxNewTCB;
traceTASK_SUSPEND( pxTCB ); traceTASK_SUSPEND( pxTCB );
/* Remove task from the ready/delayed list and place in the /* Remove task from the ready/delayed list and place in the
suspended list. */ suspended list. */
if( uxListRemove( &( pxTCB->xGenericListItem ) ) == ( unsigned portBASE_TYPE ) 0 ) if( uxListRemove( &( pxTCB->xGenericListItem ) ) == ( unsigned portBASE_TYPE ) 0 )
{ {
@ -1124,11 +1113,10 @@ tskTCB * pxNewTCB;
{ {
if( xSchedulerRunning != pdFALSE ) if( xSchedulerRunning != pdFALSE )
{ {
/* A task other than the currently running task was suspended, reset /* A task other than the currently running task was suspended,
the next expected unblock time in case it referred to the task that reset the next expected unblock time in case it referred to the
is now in the Suspended state. */ task that is now in the Suspended state. */
pxTCB = ( tskTCB * ) listGET_OWNER_OF_HEAD_ENTRY( pxDelayedTaskList ); prvResetNextTaskUnblockTime();
xNextTaskUnblockTime = listGET_LIST_ITEM_VALUE( &( pxTCB->xGenericListItem ) );
} }
} }
} }
@ -1663,9 +1651,9 @@ portBASE_TYPE xSwitchRequired = pdFALSE;
taskSWITCH_DELAYED_LISTS(); taskSWITCH_DELAYED_LISTS();
} }
/* See if this tick has made a timeout expire. Tasks are stored in /* See if this tick has made a timeout expire. Tasks are stored in
the queue in the order of their wake time - meaning once one task the queue in the order of their wake time - meaning once one task
has been found whose block time has not expired there is no need to has been found whose block time has not expired there is no need to
look any further down the list. */ look any further down the list. */
if( xConstTickCount >= xNextTaskUnblockTime ) if( xConstTickCount >= xNextTaskUnblockTime )
{ {
@ -1673,9 +1661,9 @@ portBASE_TYPE xSwitchRequired = pdFALSE;
{ {
if( listLIST_IS_EMPTY( pxDelayedTaskList ) != pdFALSE ) if( listLIST_IS_EMPTY( pxDelayedTaskList ) != pdFALSE )
{ {
/* The delayed list is empty. Set xNextTaskUnblockTime /* The delayed list is empty. Set xNextTaskUnblockTime
to the maximum possible value so it is extremely to the maximum possible value so it is extremely
unlikely that the unlikely that the
if( xTickCount >= xNextTaskUnblockTime ) test will pass if( xTickCount >= xNextTaskUnblockTime ) test will pass
next time through. */ next time through. */
xNextTaskUnblockTime = portMAX_DELAY; xNextTaskUnblockTime = portMAX_DELAY;
@ -1683,19 +1671,19 @@ portBASE_TYPE xSwitchRequired = pdFALSE;
} }
else else
{ {
/* The delayed list is not empty, get the value of the /* The delayed list is not empty, get the value of the
item at the head of the delayed list. This is the time item at the head of the delayed list. This is the time
at which the task at the head of the delayed list must at which the task at the head of the delayed list must
be removed from the Blocked state. */ be removed from the Blocked state. */
pxTCB = ( tskTCB * ) listGET_OWNER_OF_HEAD_ENTRY( pxDelayedTaskList ); pxTCB = ( tskTCB * ) listGET_OWNER_OF_HEAD_ENTRY( pxDelayedTaskList );
xItemValue = listGET_LIST_ITEM_VALUE( &( pxTCB->xGenericListItem ) ); xItemValue = listGET_LIST_ITEM_VALUE( &( pxTCB->xGenericListItem ) );
if( xConstTickCount < xItemValue ) if( xConstTickCount < xItemValue )
{ {
/* It is not time to unblock this item yet, but the /* It is not time to unblock this item yet, but the
item value is the time at which the task at the head item value is the time at which the task at the head
of the blocked list must be removed from the Blocked of the blocked list must be removed from the Blocked
state - so record the item value in state - so record the item value in
xNextTaskUnblockTime. */ xNextTaskUnblockTime. */
xNextTaskUnblockTime = xItemValue; xNextTaskUnblockTime = xItemValue;
break; break;
@ -1704,7 +1692,7 @@ portBASE_TYPE xSwitchRequired = pdFALSE;
/* It is time to remove the item from the Blocked state. */ /* It is time to remove the item from the Blocked state. */
( void ) uxListRemove( &( pxTCB->xGenericListItem ) ); ( void ) uxListRemove( &( pxTCB->xGenericListItem ) );
/* Is the task waiting on an event also? If so remove /* Is the task waiting on an event also? If so remove
it from the event list. */ it from the event list. */
if( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) != NULL ) if( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) != NULL )
{ {
@ -1715,13 +1703,13 @@ portBASE_TYPE xSwitchRequired = pdFALSE;
list. */ list. */
prvAddTaskToReadyList( pxTCB ); prvAddTaskToReadyList( pxTCB );
/* A task being unblocked cannot cause an immediate /* A task being unblocked cannot cause an immediate
context switch if preemption is turned off. */ context switch if preemption is turned off. */
#if ( configUSE_PREEMPTION == 1 ) #if ( configUSE_PREEMPTION == 1 )
{ {
/* Preemption is on, but a context switch should /* Preemption is on, but a context switch should
only be performed if the unblocked task has a only be performed if the unblocked task has a
priority that is equal to or higher than the priority that is equal to or higher than the
currently executing task. */ currently executing task. */
if( pxTCB->uxPriority >= pxCurrentTCB->uxPriority ) if( pxTCB->uxPriority >= pxCurrentTCB->uxPriority )
{ {
@ -2782,6 +2770,31 @@ tskTCB *pxNewTCB;
#endif /* INCLUDE_vTaskDelete */ #endif /* INCLUDE_vTaskDelete */
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
static void prvResetNextTaskUnblockTime( void )
{
tskTCB *pxTCB;
if( listLIST_IS_EMPTY( pxDelayedTaskList ) != pdFALSE )
{
/* The new current 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
{
/* The new current 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 ) );
}
}
/*-----------------------------------------------------------*/
#if ( ( INCLUDE_xTaskGetCurrentTaskHandle == 1 ) || ( configUSE_MUTEXES == 1 ) ) #if ( ( INCLUDE_xTaskGetCurrentTaskHandle == 1 ) || ( configUSE_MUTEXES == 1 ) )
xTaskHandle xTaskGetCurrentTaskHandle( void ) xTaskHandle xTaskGetCurrentTaskHandle( void )