diff --git a/FreeRTOS/Source/tasks.c b/FreeRTOS/Source/tasks.c index 651d04648..66723ae99 100644 --- a/FreeRTOS/Source/tasks.c +++ b/FreeRTOS/Source/tasks.c @@ -339,25 +339,7 @@ count overflows. */ pxDelayedTaskList = pxOverflowDelayedTaskList; \ pxOverflowDelayedTaskList = pxTemp; \ xNumOfOverflows++; \ - \ - 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 ) ); \ - } \ + prvResetNextTaskUnblockTime(); \ } /*-----------------------------------------------------------*/ @@ -483,6 +465,14 @@ static tskTCB *prvAllocateTCBAndStack( unsigned short usStackDepth, portSTACK_TY #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 xReturn; @@ -689,7 +679,7 @@ tskTCB * pxNewTCB; /* The pre-delete hook is primarily for the Windows simulator, 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 required. */ portPRE_TASK_DELETE_HOOK( pxTCB, &xYieldPending ); @@ -697,10 +687,9 @@ tskTCB * pxNewTCB; } 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 ) ); + /* Reset the next expected unblock time in case it referred to + the task that has just been deleted. */ + prvResetNextTaskUnblockTime(); } } } @@ -1076,7 +1065,7 @@ tskTCB * pxNewTCB; 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. */ if( uxListRemove( &( pxTCB->xGenericListItem ) ) == ( unsigned portBASE_TYPE ) 0 ) { @@ -1124,11 +1113,10 @@ tskTCB * pxNewTCB; { 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 ) ); + /* 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. */ + prvResetNextTaskUnblockTime(); } } } @@ -1663,9 +1651,9 @@ 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 + /* 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 ) { @@ -1673,9 +1661,9 @@ portBASE_TYPE xSwitchRequired = pdFALSE; { 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 + /* 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; @@ -1683,19 +1671,19 @@ portBASE_TYPE xSwitchRequired = pdFALSE; } 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 + /* 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 + /* 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; @@ -1704,7 +1692,7 @@ 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 + /* Is the task waiting on an event also? If so remove it from the event list. */ if( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) != NULL ) { @@ -1715,13 +1703,13 @@ portBASE_TYPE xSwitchRequired = pdFALSE; list. */ 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. */ #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 + /* 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 ) { @@ -2782,6 +2770,31 @@ tskTCB *pxNewTCB; #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 ) ) xTaskHandle xTaskGetCurrentTaskHandle( void )