#if ( INCLUDE_vTaskDelete == 1 )\r
\r
PRIVILEGED_DATA static List_t xTasksWaitingTermination; /*< Tasks that have been deleted - but their memory not yet freed. */\r
- PRIVILEGED_DATA static volatile UBaseType_t uxTasksDeleted = ( UBaseType_t ) 0U;\r
+ PRIVILEGED_DATA static volatile UBaseType_t uxDeletedTasksWaitingCleanUp = ( UBaseType_t ) 0U;\r
\r
#endif\r
\r
{ \\r
UBaseType_t uxTopPriority; \\r
\\r
- /* Find the highest priority queue that contains ready tasks. */ \\r
+ /* Find the highest priority list that contains ready tasks. */ \\r
portGET_HIGHEST_PRIORITY( uxTopPriority, uxTopReadyPriority ); \\r
configASSERT( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ uxTopPriority ] ) ) > 0 ); \\r
listGET_OWNER_OF_NEXT_ENTRY( pxCurrentTCB, &( pxReadyTasksLists[ uxTopPriority ] ) ); \\r
#define prvAddTaskToReadyList( pxTCB ) \\r
traceMOVED_TASK_TO_READY_STATE( pxTCB ); \\r
taskRECORD_READY_PRIORITY( ( pxTCB )->uxPriority ); \\r
- vListInsertEnd( &( pxReadyTasksLists[ ( pxTCB )->uxPriority ] ), &( ( pxTCB )->xGenericListItem ) )\r
+ vListInsertEnd( &( pxReadyTasksLists[ ( pxTCB )->uxPriority ] ), &( ( pxTCB )->xGenericListItem ) ); \\r
+ tracePOST_MOVED_TASK_TO_READY_STATE( pxTCB )\r
/*-----------------------------------------------------------*/\r
\r
/*\r
being deleted. */\r
pxTCB = prvGetTCBFromHandle( xTaskToDelete );\r
\r
- /* Remove task from the ready list and place in the termination list.\r
- This will stop the task from be scheduled. The idle task will check\r
- the termination list and free up any memory allocated by the\r
- scheduler for the TCB and stack. */\r
+ /* Remove task from the ready list. */\r
if( uxListRemove( &( pxTCB->xGenericListItem ) ) == ( UBaseType_t ) 0 )\r
{\r
taskRESET_READY_PRIORITY( pxTCB->uxPriority );\r
mtCOVERAGE_TEST_MARKER();\r
}\r
\r
- vListInsertEnd( &xTasksWaitingTermination, &( pxTCB->xGenericListItem ) );\r
-\r
- /* Increment the ucTasksDeleted variable so the idle task knows\r
- there is a task that has been deleted and that it should therefore\r
- check the xTasksWaitingTermination list. */\r
- ++uxTasksDeleted;\r
+ if( pxTCB == pxCurrentTCB )\r
+ {\r
+ /* A task is deleting itself. This cannot complete within the\r
+ task itself, as a context switch to another task is required.\r
+ Place the task in the termination list. The idle task will\r
+ check the termination list and free up any memory allocated by\r
+ the scheduler for the TCB and stack of the deleted task. */\r
+ vListInsertEnd( &xTasksWaitingTermination, &( pxTCB->xGenericListItem ) );\r
+\r
+ /* Increment the ucTasksDeleted variable so the idle task knows\r
+ there is a task that has been deleted and that it should therefore\r
+ check the xTasksWaitingTermination list. */\r
+ ++uxDeletedTasksWaitingCleanUp;\r
+ }\r
+ else\r
+ {\r
+ --uxCurrentNumberOfTasks;\r
+ prvDeleteTCB( pxTCB );\r
+ }\r
\r
- /* Increment the uxTaskNumberVariable also so kernel aware debuggers\r
- can detect that the task lists need re-generating. */\r
+ /* Increment the uxTaskNumber also so kernel aware debuggers can\r
+ detect that the task lists need re-generating. */\r
uxTaskNumber++;\r
\r
traceTASK_DELETE( pxTCB );\r
#endif\r
\r
#if ( INCLUDE_vTaskDelete == 1 )\r
- else if( pxStateList == &xTasksWaitingTermination )\r
+ else if( ( pxStateList == &xTasksWaitingTermination ) || ( pxStateList == NULL ) )\r
{\r
/* The task being queried is referenced from the deleted\r
- tasks list. */\r
+ tasks list, or it is not referenced from any lists at \r
+ all. */\r
eReturn = eDeleted;\r
}\r
#endif\r
static TickType_t prvGetExpectedIdleTime( void )\r
{\r
TickType_t xReturn;\r
+ UBaseType_t uxHigherPriorityReadyTasks = pdFALSE;\r
+\r
+ /* uxHigherPriorityReadyTasks takes care of the case where\r
+ configUSE_PREEMPTION is 0, so there may be tasks above the idle priority\r
+ task that are in the Ready state, even though the idle task is\r
+ running. */\r
+ #if( configUSE_PORT_OPTIMISED_TASK_SELECTION == 0 )\r
+ {\r
+ if( uxTopReadyPriority > tskIDLE_PRIORITY )\r
+ {\r
+ uxHigherPriorityReadyTasks = pdTRUE;\r
+ }\r
+ }\r
+ #else\r
+ {\r
+ const UBaseType_t uxLeastSignificantBit = ( UBaseType_t ) 0x01;\r
+\r
+ /* When port optimised task selection is used the uxTopReadyPriority\r
+ variable is used as a bit map. If bits other than the least\r
+ significant bit are set then there are tasks that have a priority\r
+ above the idle priority that are in the Ready state. This takes\r
+ care of the case where the co-operative scheduler is in use. */\r
+ if( uxTopReadyPriority > uxLeastSignificantBit )\r
+ {\r
+ uxHigherPriorityReadyTasks = pdTRUE;\r
+ }\r
+ }\r
+ #endif\r
\r
if( pxCurrentTCB->uxPriority > tskIDLE_PRIORITY )\r
{\r
processed. */\r
xReturn = 0;\r
}\r
+ else if( uxHigherPriorityReadyTasks != pdFALSE )\r
+ {\r
+ /* There are tasks in the Ready state that have a priority above the\r
+ idle priority. This path can only be reached if\r
+ configUSE_PREEMPTION is 0. */\r
+ xReturn = 0;\r
+ }\r
else\r
{\r
xReturn = xNextTaskUnblockTime - xTickCount;\r
#endif\r
\r
/* Add the amount of time the task has been running to the\r
- accumulated time so far. The time the task started running was\r
+ accumulated time so far. The time the task started running was\r
stored in ulTaskSwitchedInTime. Note that there is no overflow\r
- protection here so count values are only valid until the timer\r
+ protection here so count values are only valid until the timer\r
overflows. The guard against negative values is to protect\r
against suspect run time stat counter implementations - which\r
are provided by the application, not the kernel. */\r
\r
/* ucTasksDeleted is used to prevent vTaskSuspendAll() being called\r
too often in the idle task. */\r
- while( uxTasksDeleted > ( UBaseType_t ) 0U )\r
+ while( uxDeletedTasksWaitingCleanUp > ( UBaseType_t ) 0U )\r
{\r
vTaskSuspendAll();\r
{\r
pxTCB = ( TCB_t * ) listGET_OWNER_OF_HEAD_ENTRY( ( &xTasksWaitingTermination ) );\r
( void ) uxListRemove( &( pxTCB->xGenericListItem ) );\r
--uxCurrentNumberOfTasks;\r
- --uxTasksDeleted;\r
+ --uxDeletedTasksWaitingCleanUp;\r
}\r
taskEXIT_CRITICAL();\r
\r
}\r
}\r
}\r
- #endif /* vTaskDelete */\r
+ #endif /* INCLUDE_vTaskDelete */\r
}\r
/*-----------------------------------------------------------*/\r
\r
{\r
/* The stack cannot be used as the TCB was not created. Free it\r
again. */\r
- vPortFree( pxStack );\r
+ if( puxStackBuffer == NULL )\r
+ {\r
+ vPortFree( pxStack );\r
+ }\r
}\r
}\r
else\r