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
#endif
#ifndef portPRE_DELETE_HOOK
#define portPRE_DELETE_HOOK( pvTaskToDelete, pxYieldPending )
#ifndef portPRE_TASK_DELETE_HOOK
#define portPRE_TASK_DELETE_HOOK( pvTaskToDelete, pxYieldPending )
#endif
#ifndef portSETUP_TCB

View file

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

View file

@ -679,7 +679,8 @@ tskTCB * pxNewTCB;
}
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( pxTCB == pxCurrentTCB )
@ -691,9 +692,16 @@ tskTCB * pxNewTCB;
after which it is not possible to yield away from this task -
hence xYieldPending is used to latch that a context switch is
required. */
portPRE_DELETE_HOOK( pxTCB, &xYieldPending );
portPRE_TASK_DELETE_HOOK( pxTCB, &xYieldPending );
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 );
/* 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 )
{
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 */
@ -1643,38 +1663,40 @@ portBASE_TYPE xSwitchRequired = pdFALSE;
taskSWITCH_DELAYED_LISTS();
}
/* 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 has been
found whose block time has not expired there is no need to look any
further down the list. */
/* 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
has been found whose block time has not expired there is no need to
look any further down the list. */
if( xConstTickCount >= xNextTaskUnblockTime )
{
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
/* 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;
}
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 must be removed
from the Blocked state. */
/* 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 must
be removed from the Blocked state. */
pxTCB = ( tskTCB * ) listGET_OWNER_OF_HEAD_ENTRY( pxDelayedTaskList );
xItemValue = listGET_LIST_ITEM_VALUE( &( pxTCB->xGenericListItem ) );
if( xConstTickCount < 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 must be removed from the Blocked state -
so record the item value in xNextTaskUnblockTime. */
/* 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 must be removed from the Blocked
state - so record the item value in
xNextTaskUnblockTime. */
xNextTaskUnblockTime = xItemValue;
break;
}
@ -1682,8 +1704,8 @@ portBASE_TYPE xSwitchRequired = pdFALSE;
/* It is time to remove the item from the Blocked state. */
( void ) uxListRemove( &( pxTCB->xGenericListItem ) );
/* Is the task waiting on an event also? If so remove it
from the event list. */
/* Is the task waiting on an event also? If so remove
it from the event list. */
if( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) != NULL )
{
( void ) uxListRemove( &( pxTCB->xEventListItem ) );
@ -1693,14 +1715,14 @@ portBASE_TYPE xSwitchRequired = pdFALSE;
list. */
prvAddTaskToReadyList( pxTCB );
/* A task being unblocked cannot cause an immediate context
switch if preemption is turned off. */
/* A task being unblocked cannot cause an immediate
context switch if preemption is turned off. */
#if ( configUSE_PREEMPTION == 1 )
{
/* Preemption is on, but a context switch should only
be performed if the unblocked task has a priority that
is equal to or higher than the currently executing
task. */
/* Preemption is on, but a context switch should
only be performed if the unblocked task has a
priority that is equal to or higher than the
currently executing task. */
if( pxTCB->uxPriority >= pxCurrentTCB->uxPriority )
{
xSwitchRequired = pdTRUE;
@ -2577,7 +2599,7 @@ static void prvAddCurrentTaskToDelayedList( portTickType xTimeToWake )
}
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 ) );
/* 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,
* 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
* 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
* 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
@ -222,7 +222,7 @@ static portTickType prvGetNextExpireTime( portBASE_TYPE *pxListWasEmpty ) PRIVIL
* If a timer has expired, process it. Otherwise, block the timer service task
* 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
/*-----------------------------------------------------------*/
static void prvProcessExpiredTimer( portTickType xNextExpireTime, portTickType xTimeNow )
static void prvProcessExpiredTimer( const portTickType xNextExpireTime, const portTickType xTimeNow )
{
xTIMER *pxTimer;
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
been performed to ensure the list is not empty. */
pxTimer = ( xTIMER * ) listGET_OWNER_OF_HEAD_ENTRY( pxCurrentTimerList );
( void ) uxListRemove( &( pxTimer->xTimerListItem ) );
traceTIMER_EXPIRED( pxTimer );
@ -363,12 +362,9 @@ portBASE_TYPE xResult;
expiry time and re-insert the timer in the list of active timers. */
if( pxTimer->uxAutoReload == ( unsigned portBASE_TYPE ) pdTRUE )
{
/* This is the only time a timer is inserted into a list using
a time relative to anything other than the current time. It
will therefore be inserted into the correct list relative to
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. */
/* The timer is inserted into a list using a time relative to anything
other than the current time. It will therefore be inserted into the
correct list relative to the time this task thinks it is now. */
if( prvInsertTimerInActiveList( pxTimer, ( xNextExpireTime + pxTimer->xTimerPeriodInTicks ), xTimeNow, xNextExpireTime ) == pdTRUE )
{
/* 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;
portBASE_TYPE xTimerListsWereSwitched;
@ -492,7 +488,7 @@ PRIVILEGED_DATA static portTickType xLastTime = ( portTickType ) 0U; /*lint !e95
if( xTimeNow < xLastTime )
{
prvSwitchTimerLists( xLastTime );
prvSwitchTimerLists();
*pxTimerListsWereSwitched = pdTRUE;
}
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;
@ -600,9 +596,10 @@ portTickType xTimeNow;
/* Start or restart a timer. */
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
list. Process it now. */
/* The timer expired before it was added to the active
timer list. Process it now. */
pxTimer->pxCallbackFunction( ( xTimerHandle ) pxTimer );
traceTIMER_EXPIRED( pxTimer );
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;
xList *pxTemp;
xTIMER *pxTimer;
portBASE_TYPE xResult;
/* Remove compiler warnings if configASSERT() is not defined. */
( void ) xLastTime;
/* The tick count has overflowed. The timer lists must be switched.
If there are any timers still referenced from the current timer list
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. */
pxTimer = ( xTIMER * ) listGET_OWNER_OF_HEAD_ENTRY( pxCurrentTimerList );
( void ) uxListRemove( &( pxTimer->xTimerListItem ) );
traceTIMER_EXPIRED( pxTimer );
/* 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
@ -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;
}