mirror of
https://github.com/FreeRTOS/FreeRTOS-Kernel.git
synced 2025-04-19 21:11:57 -04:00
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:
parent
0d1e12522b
commit
acad916453
|
@ -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
|
||||
|
|
|
@ -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 );
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue