Change the way one thread deletes another in the Windows simulator port (the way one thread deleted itself was already changed in a previous check-in).

Reset the expected block time variable when a task is suspended or deleted in case the value held in the variables was associated with the task just suspended or deleted.
This commit is contained in:
Richard Barry 2013-12-12 16:07:24 +00:00
parent 0d1e12522b
commit acad916453
4 changed files with 86 additions and 56 deletions

View file

@ -294,8 +294,8 @@ typedef portTickType xEventBitsType;
#define portCLEAN_UP_TCB( pxTCB ) ( void ) pxTCB #define portCLEAN_UP_TCB( pxTCB ) ( void ) pxTCB
#endif #endif
#ifndef portPRE_DELETE_HOOK #ifndef portPRE_TASK_DELETE_HOOK
#define portPRE_DELETE_HOOK( pvTaskToDelete, pxYieldPending ) #define portPRE_TASK_DELETE_HOOK( pvTaskToDelete, pxYieldPending )
#endif #endif
#ifndef portSETUP_TCB #ifndef portSETUP_TCB

View file

@ -418,6 +418,10 @@ void *pvObjectList[ 2 ];
void vPortDeleteThread( void *pvTaskToDelete ) void vPortDeleteThread( void *pvTaskToDelete )
{ {
xThreadState *pxThreadState; xThreadState *pxThreadState;
unsigned long ulErrorCode;
/* Remove compiler warnings if configASSERT() is not defined. */
( void ) ulErrorCode;
/* Find the handle of the thread being deleted. */ /* Find the handle of the thread being deleted. */
pxThreadState = ( xThreadState * ) ( *( unsigned long *) pvTaskToDelete ); pxThreadState = ( xThreadState * ) ( *( unsigned long *) pvTaskToDelete );
@ -430,8 +434,11 @@ xThreadState *pxThreadState;
{ {
WaitForSingleObject( pvInterruptEventMutex, INFINITE ); WaitForSingleObject( pvInterruptEventMutex, INFINITE );
CloseHandle( pxThreadState->pvThread ); ulErrorCode = TerminateThread( pxThreadState->pvThread, 0 );
TerminateThread( pxThreadState->pvThread, 0 ); configASSERT( ulErrorCode );
ulErrorCode = CloseHandle( pxThreadState->pvThread );
configASSERT( ulErrorCode );
ReleaseMutex( pvInterruptEventMutex ); ReleaseMutex( pvInterruptEventMutex );
} }
@ -442,6 +449,10 @@ void vPortCloseRunningThread( void *pvTaskToDelete, volatile portBASE_TYPE *pxPe
{ {
xThreadState *pxThreadState; xThreadState *pxThreadState;
void *pvThread; void *pvThread;
unsigned long ulErrorCode;
/* Remove compiler warnings if configASSERT() is not defined. */
( void ) ulErrorCode;
/* Find the handle of the thread being deleted. */ /* Find the handle of the thread being deleted. */
pxThreadState = ( xThreadState * ) ( *( unsigned long *) pvTaskToDelete ); pxThreadState = ( xThreadState * ) ( *( unsigned long *) pvTaskToDelete );
@ -462,7 +473,9 @@ void *pvThread;
pxThreadState->pvThread = NULL; pxThreadState->pvThread = NULL;
/* Close the thread. */ /* Close the thread. */
CloseHandle( pvThread ); ulErrorCode = CloseHandle( pvThread );
configASSERT( ulErrorCode );
ExitThread( 0 ); ExitThread( 0 );
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/

View file

@ -679,7 +679,8 @@ tskTCB * pxNewTCB;
} }
taskEXIT_CRITICAL(); taskEXIT_CRITICAL();
/* Force a reschedule if we have just deleted the current task. */ /* Force a reschedule if it is the currently running task that has just
been deleted. */
if( xSchedulerRunning != pdFALSE ) if( xSchedulerRunning != pdFALSE )
{ {
if( pxTCB == pxCurrentTCB ) if( pxTCB == pxCurrentTCB )
@ -691,9 +692,16 @@ tskTCB * pxNewTCB;
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_DELETE_HOOK( pxTCB, &xYieldPending ); portPRE_TASK_DELETE_HOOK( pxTCB, &xYieldPending );
portYIELD_WITHIN_API(); portYIELD_WITHIN_API();
} }
else
{
/* Reset the next expected unblock time in case it referred to the task
that has just been deleted. */
pxTCB = ( tskTCB * ) listGET_OWNER_OF_HEAD_ENTRY( pxDelayedTaskList );
xNextTaskUnblockTime = listGET_LIST_ITEM_VALUE( &( pxTCB->xGenericListItem ) );
}
} }
} }
@ -1068,7 +1076,8 @@ tskTCB * pxNewTCB;
traceTASK_SUSPEND( pxTCB ); traceTASK_SUSPEND( pxTCB );
/* Remove task from the ready/delayed list and place in the suspended list. */ /* Remove task from the ready/delayed list and place in the
suspended list. */
if( uxListRemove( &( pxTCB->xGenericListItem ) ) == ( unsigned portBASE_TYPE ) 0 ) if( uxListRemove( &( pxTCB->xGenericListItem ) ) == ( unsigned portBASE_TYPE ) 0 )
{ {
taskRESET_READY_PRIORITY( pxTCB->uxPriority ); taskRESET_READY_PRIORITY( pxTCB->uxPriority );
@ -1111,6 +1120,17 @@ tskTCB * pxNewTCB;
} }
} }
} }
else
{
if( xSchedulerRunning != pdFALSE )
{
/* A task other than the currently running task was suspended, reset
the next expected unblock time in case it referred to the task that
is now in the Suspended state. */
pxTCB = ( tskTCB * ) listGET_OWNER_OF_HEAD_ENTRY( pxDelayedTaskList );
xNextTaskUnblockTime = listGET_LIST_ITEM_VALUE( &( pxTCB->xGenericListItem ) );
}
}
} }
#endif /* INCLUDE_vTaskSuspend */ #endif /* INCLUDE_vTaskSuspend */
@ -1643,38 +1663,40 @@ portBASE_TYPE xSwitchRequired = pdFALSE;
taskSWITCH_DELAYED_LISTS(); taskSWITCH_DELAYED_LISTS();
} }
/* See if this tick has made a timeout expire. Tasks are stored in the /* See if this tick has made a timeout expire. Tasks are stored in
queue in the order of their wake time - meaning once one task has been the queue in the order of their wake time - meaning once one task
found whose block time has not expired there is no need to look any has been found whose block time has not expired there is no need to
further down the list. */ look any further down the list. */
if( xConstTickCount >= xNextTaskUnblockTime ) if( xConstTickCount >= xNextTaskUnblockTime )
{ {
for( ;; ) for( ;; )
{ {
if( listLIST_IS_EMPTY( pxDelayedTaskList ) != pdFALSE ) if( listLIST_IS_EMPTY( pxDelayedTaskList ) != pdFALSE )
{ {
/* The delayed list is empty. Set xNextTaskUnblockTime to /* The delayed list is empty. Set xNextTaskUnblockTime
the maximum possible value so it is extremely unlikely that to the maximum possible value so it is extremely
the if( xTickCount >= xNextTaskUnblockTime ) test will pass unlikely that the
if( xTickCount >= xNextTaskUnblockTime ) test will pass
next time through. */ next time through. */
xNextTaskUnblockTime = portMAX_DELAY; xNextTaskUnblockTime = portMAX_DELAY;
break; break;
} }
else else
{ {
/* The delayed list is not empty, get the value of the item /* The delayed list is not empty, get the value of the
at the head of the delayed list. This is the time at which item at the head of the delayed list. This is the time
the task at the head of the delayed list must be removed at which the task at the head of the delayed list must
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 item /* It is not time to unblock this item yet, but the
value is the time at which the task at the head of the item value is the time at which the task at the head
blocked list must be removed from the Blocked state - of the blocked list must be removed from the Blocked
so record the item value in xNextTaskUnblockTime. */ state - so record the item value in
xNextTaskUnblockTime. */
xNextTaskUnblockTime = xItemValue; xNextTaskUnblockTime = xItemValue;
break; break;
} }
@ -1682,8 +1704,8 @@ 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 it /* Is the task waiting on an event also? If so remove
from the event list. */ it from the event list. */
if( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) != NULL ) if( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) != NULL )
{ {
( void ) uxListRemove( &( pxTCB->xEventListItem ) ); ( void ) uxListRemove( &( pxTCB->xEventListItem ) );
@ -1693,14 +1715,14 @@ portBASE_TYPE xSwitchRequired = pdFALSE;
list. */ list. */
prvAddTaskToReadyList( pxTCB ); prvAddTaskToReadyList( pxTCB );
/* A task being unblocked cannot cause an immediate context /* A task being unblocked cannot cause an immediate
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 only /* Preemption is on, but a context switch should
be performed if the unblocked task has a priority that only be performed if the unblocked task has a
is equal to or higher than the currently executing priority that is equal to or higher than the
task. */ currently executing task. */
if( pxTCB->uxPriority >= pxCurrentTCB->uxPriority ) if( pxTCB->uxPriority >= pxCurrentTCB->uxPriority )
{ {
xSwitchRequired = pdTRUE; xSwitchRequired = pdTRUE;
@ -2577,7 +2599,7 @@ static void prvAddCurrentTaskToDelayedList( portTickType xTimeToWake )
} }
else else
{ {
/* The wake time has not overflowed, so we can use the current block list. */ /* The wake time has not overflowed, so the current block list is used. */
vListInsert( pxDelayedTaskList, &( pxCurrentTCB->xGenericListItem ) ); vListInsert( pxDelayedTaskList, &( pxCurrentTCB->xGenericListItem ) );
/* If the task entering the blocked state was placed at the head of the /* If the task entering the blocked state was placed at the head of the

View file

@ -190,19 +190,19 @@ static void prvProcessReceivedCommands( void ) PRIVILEGED_FUNCTION;
* Insert the timer into either xActiveTimerList1, or xActiveTimerList2, * Insert the timer into either xActiveTimerList1, or xActiveTimerList2,
* depending on if the expire time causes a timer counter overflow. * depending on if the expire time causes a timer counter overflow.
*/ */
static portBASE_TYPE prvInsertTimerInActiveList( xTIMER *pxTimer, portTickType xNextExpiryTime, portTickType xTimeNow, portTickType xCommandTime ) PRIVILEGED_FUNCTION; static portBASE_TYPE prvInsertTimerInActiveList( xTIMER * const pxTimer, const portTickType xNextExpiryTime, const portTickType xTimeNow, const portTickType xCommandTime ) PRIVILEGED_FUNCTION;
/* /*
* An active timer has reached its expire time. Reload the timer if it is an * An active timer has reached its expire time. Reload the timer if it is an
* auto reload timer, then call its callback. * auto reload timer, then call its callback.
*/ */
static void prvProcessExpiredTimer( portTickType xNextExpireTime, portTickType xTimeNow ) PRIVILEGED_FUNCTION; static void prvProcessExpiredTimer( const portTickType xNextExpireTime, const portTickType xTimeNow ) PRIVILEGED_FUNCTION;
/* /*
* The tick count has overflowed. Switch the timer lists after ensuring the * The tick count has overflowed. Switch the timer lists after ensuring the
* current timer list does not still reference some timers. * current timer list does not still reference some timers.
*/ */
static void prvSwitchTimerLists( portTickType xLastTime ) PRIVILEGED_FUNCTION; static void prvSwitchTimerLists( void ) PRIVILEGED_FUNCTION;
/* /*
* Obtain the current tick count, setting *pxTimerListsWereSwitched to pdTRUE * Obtain the current tick count, setting *pxTimerListsWereSwitched to pdTRUE
@ -222,7 +222,7 @@ static portTickType prvGetNextExpireTime( portBASE_TYPE *pxListWasEmpty ) PRIVIL
* If a timer has expired, process it. Otherwise, block the timer service task * If a timer has expired, process it. Otherwise, block the timer service task
* until either a timer does expire or a command is received. * until either a timer does expire or a command is received.
*/ */
static void prvProcessTimerOrBlockTask( portTickType xNextExpireTime, portBASE_TYPE xListWasEmpty ) PRIVILEGED_FUNCTION; static void prvProcessTimerOrBlockTask( const portTickType xNextExpireTime, const portBASE_TYPE xListWasEmpty ) PRIVILEGED_FUNCTION;
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -348,14 +348,13 @@ xDAEMON_TASK_MESSAGE xMessage;
#endif #endif
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
static void prvProcessExpiredTimer( portTickType xNextExpireTime, portTickType xTimeNow ) static void prvProcessExpiredTimer( const portTickType xNextExpireTime, const portTickType xTimeNow )
{ {
xTIMER *pxTimer;
portBASE_TYPE xResult; portBASE_TYPE xResult;
xTIMER * const pxTimer = ( xTIMER * ) listGET_OWNER_OF_HEAD_ENTRY( pxCurrentTimerList );
/* Remove the timer from the list of active timers. A check has already /* Remove the timer from the list of active timers. A check has already
been performed to ensure the list is not empty. */ been performed to ensure the list is not empty. */
pxTimer = ( xTIMER * ) listGET_OWNER_OF_HEAD_ENTRY( pxCurrentTimerList );
( void ) uxListRemove( &( pxTimer->xTimerListItem ) ); ( void ) uxListRemove( &( pxTimer->xTimerListItem ) );
traceTIMER_EXPIRED( pxTimer ); traceTIMER_EXPIRED( pxTimer );
@ -363,12 +362,9 @@ portBASE_TYPE xResult;
expiry time and re-insert the timer in the list of active timers. */ expiry time and re-insert the timer in the list of active timers. */
if( pxTimer->uxAutoReload == ( unsigned portBASE_TYPE ) pdTRUE ) if( pxTimer->uxAutoReload == ( unsigned portBASE_TYPE ) pdTRUE )
{ {
/* This is the only time a timer is inserted into a list using /* The timer is inserted into a list using a time relative to anything
a time relative to anything other than the current time. It other than the current time. It will therefore be inserted into the
will therefore be inserted into the correct list relative to correct list relative to the time this task thinks it is now. */
the time this task thinks it is now, even if a command to
switch lists due to a tick count overflow is already waiting in
the timer queue. */
if( prvInsertTimerInActiveList( pxTimer, ( xNextExpireTime + pxTimer->xTimerPeriodInTicks ), xTimeNow, xNextExpireTime ) == pdTRUE ) if( prvInsertTimerInActiveList( pxTimer, ( xNextExpireTime + pxTimer->xTimerPeriodInTicks ), xTimeNow, xNextExpireTime ) == pdTRUE )
{ {
/* The timer expired before it was added to the active timer /* The timer expired before it was added to the active timer
@ -408,7 +404,7 @@ portBASE_TYPE xListWasEmpty;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
static void prvProcessTimerOrBlockTask( portTickType xNextExpireTime, portBASE_TYPE xListWasEmpty ) static void prvProcessTimerOrBlockTask( const portTickType xNextExpireTime, const portBASE_TYPE xListWasEmpty )
{ {
portTickType xTimeNow; portTickType xTimeNow;
portBASE_TYPE xTimerListsWereSwitched; portBASE_TYPE xTimerListsWereSwitched;
@ -492,7 +488,7 @@ PRIVILEGED_DATA static portTickType xLastTime = ( portTickType ) 0U; /*lint !e95
if( xTimeNow < xLastTime ) if( xTimeNow < xLastTime )
{ {
prvSwitchTimerLists( xLastTime ); prvSwitchTimerLists();
*pxTimerListsWereSwitched = pdTRUE; *pxTimerListsWereSwitched = pdTRUE;
} }
else else
@ -506,7 +502,7 @@ PRIVILEGED_DATA static portTickType xLastTime = ( portTickType ) 0U; /*lint !e95
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
static portBASE_TYPE prvInsertTimerInActiveList( xTIMER *pxTimer, portTickType xNextExpiryTime, portTickType xTimeNow, portTickType xCommandTime ) static portBASE_TYPE prvInsertTimerInActiveList( xTIMER * const pxTimer, const portTickType xNextExpiryTime, const portTickType xTimeNow, const portTickType xCommandTime )
{ {
portBASE_TYPE xProcessTimerNow = pdFALSE; portBASE_TYPE xProcessTimerNow = pdFALSE;
@ -600,9 +596,10 @@ portTickType xTimeNow;
/* Start or restart a timer. */ /* Start or restart a timer. */
if( prvInsertTimerInActiveList( pxTimer, xMessage.u.xTimerParameters.xMessageValue + pxTimer->xTimerPeriodInTicks, xTimeNow, xMessage.u.xTimerParameters.xMessageValue ) == pdTRUE ) if( prvInsertTimerInActiveList( pxTimer, xMessage.u.xTimerParameters.xMessageValue + pxTimer->xTimerPeriodInTicks, xTimeNow, xMessage.u.xTimerParameters.xMessageValue ) == pdTRUE )
{ {
/* The timer expired before it was added to the active timer /* The timer expired before it was added to the active
list. Process it now. */ timer list. Process it now. */
pxTimer->pxCallbackFunction( ( xTimerHandle ) pxTimer ); pxTimer->pxCallbackFunction( ( xTimerHandle ) pxTimer );
traceTIMER_EXPIRED( pxTimer );
if( pxTimer->uxAutoReload == ( unsigned portBASE_TYPE ) pdTRUE ) if( pxTimer->uxAutoReload == ( unsigned portBASE_TYPE ) pdTRUE )
{ {
@ -646,16 +643,13 @@ portTickType xTimeNow;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
static void prvSwitchTimerLists( portTickType xLastTime ) static void prvSwitchTimerLists( void )
{ {
portTickType xNextExpireTime, xReloadTime; portTickType xNextExpireTime, xReloadTime;
xList *pxTemp; xList *pxTemp;
xTIMER *pxTimer; xTIMER *pxTimer;
portBASE_TYPE xResult; portBASE_TYPE xResult;
/* Remove compiler warnings if configASSERT() is not defined. */
( void ) xLastTime;
/* The tick count has overflowed. The timer lists must be switched. /* The tick count has overflowed. The timer lists must be switched.
If there are any timers still referenced from the current timer list If there are any timers still referenced from the current timer list
then they must have expired and should be processed before the lists then they must have expired and should be processed before the lists
@ -667,6 +661,7 @@ portBASE_TYPE xResult;
/* Remove the timer from the list. */ /* Remove the timer from the list. */
pxTimer = ( xTIMER * ) listGET_OWNER_OF_HEAD_ENTRY( pxCurrentTimerList ); pxTimer = ( xTIMER * ) listGET_OWNER_OF_HEAD_ENTRY( pxCurrentTimerList );
( void ) uxListRemove( &( pxTimer->xTimerListItem ) ); ( void ) uxListRemove( &( pxTimer->xTimerListItem ) );
traceTIMER_EXPIRED( pxTimer );
/* Execute its callback, then send a command to restart the timer if /* Execute its callback, then send a command to restart the timer if
it is an auto-reload timer. It cannot be restarted here as the lists it is an auto-reload timer. It cannot be restarted here as the lists
@ -752,9 +747,9 @@ xTIMER *pxTimer = ( xTIMER * ) xTimer;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
void *pvTimerGetTimerID( xTimerHandle xTimer ) void *pvTimerGetTimerID( const xTimerHandle xTimer )
{ {
xTIMER *pxTimer = ( xTIMER * ) xTimer; xTIMER * const pxTimer = ( xTIMER * const ) xTimer;
return pxTimer->pvTimerID; return pxTimer->pvTimerID;
} }