From: rtel Date: Thu, 12 Dec 2013 16:07:24 +0000 (+0000) Subject: Change the way one thread deletes another in the Windows simulator port (the way... X-Git-Tag: V8.0.0rc1~31 X-Git-Url: https://git.sur5r.net/?a=commitdiff_plain;h=4435518276589c5710536eaee46eb37e48efa15c;p=freertos 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. git-svn-id: https://svn.code.sf.net/p/freertos/code/trunk@2130 1d2547de-c912-0410-9cb9-b8ca96c0e9e2 --- diff --git a/FreeRTOS/Source/include/FreeRTOS.h b/FreeRTOS/Source/include/FreeRTOS.h index e4a1edd31..7b29229d3 100644 --- a/FreeRTOS/Source/include/FreeRTOS.h +++ b/FreeRTOS/Source/include/FreeRTOS.h @@ -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 diff --git a/FreeRTOS/Source/portable/MSVC-MingW/port.c b/FreeRTOS/Source/portable/MSVC-MingW/port.c index 8e8e82d5f..bfd651373 100644 --- a/FreeRTOS/Source/portable/MSVC-MingW/port.c +++ b/FreeRTOS/Source/portable/MSVC-MingW/port.c @@ -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 ); } /*-----------------------------------------------------------*/ diff --git a/FreeRTOS/Source/tasks.c b/FreeRTOS/Source/tasks.c index c3284ca3e..651d04648 100644 --- a/FreeRTOS/Source/tasks.c +++ b/FreeRTOS/Source/tasks.c @@ -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 diff --git a/FreeRTOS/Source/timers.c b/FreeRTOS/Source/timers.c index 5b389c2cf..a50c8c4cd 100644 --- a/FreeRTOS/Source/timers.c +++ b/FreeRTOS/Source/timers.c @@ -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; }