]> git.sur5r.net Git - freertos/blobdiff - FreeRTOS/Source/tasks.c
FreeRTOS source:
[freertos] / FreeRTOS / Source / tasks.c
index 11ca0e976b9a5c5d697802e271a5cbe460c04194..fe2f5ae1aa627b342c4d04dd91e7c43f02652ea4 100644 (file)
@@ -222,7 +222,7 @@ PRIVILEGED_DATA static List_t xPendingReadyList;                                            /*< Tasks that have been r
 #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
@@ -341,7 +341,7 @@ PRIVILEGED_DATA static volatile UBaseType_t uxSchedulerSuspended    = ( UBaseType_t
        {                                                                                                                                                                                               \\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
@@ -389,7 +389,8 @@ count overflows. */
 #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
@@ -751,10 +752,7 @@ StackType_t *pxTopOfStack;
                        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
@@ -774,15 +772,28 @@ StackType_t *pxTopOfStack;
                                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
@@ -1031,10 +1042,11 @@ StackType_t *pxTopOfStack;
                        #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
@@ -1645,6 +1657,34 @@ void vTaskSuspendAll( void )
        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
@@ -1657,6 +1697,13 @@ void vTaskSuspendAll( void )
                        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
@@ -2222,9 +2269,9 @@ void vTaskSwitchContext( void )
                                #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
@@ -3035,7 +3082,7 @@ static void prvCheckTasksWaitingTermination( void )
 \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
@@ -3052,7 +3099,7 @@ static void prvCheckTasksWaitingTermination( void )
                                        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
@@ -3064,7 +3111,7 @@ static void prvCheckTasksWaitingTermination( void )
                        }\r
                }\r
        }\r
-       #endif /* vTaskDelete */\r
+       #endif /* INCLUDE_vTaskDelete */\r
 }\r
 /*-----------------------------------------------------------*/\r
 \r
@@ -3148,7 +3195,10 @@ TCB_t *pxNewTCB;
                        {\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