]> git.sur5r.net Git - freertos/blobdiff - FreeRTOS/Source/tasks.c
FreeRTOS source:
[freertos] / FreeRTOS / Source / tasks.c
index bce9973d1e93248e32d3186a0c2df1034d5a9bc7..fe2f5ae1aa627b342c4d04dd91e7c43f02652ea4 100644 (file)
@@ -1,5 +1,5 @@
 /*\r
-    FreeRTOS V8.2.0 - Copyright (C) 2015 Real Time Engineers Ltd.\r
+    FreeRTOS V8.2.3 - Copyright (C) 2015 Real Time Engineers Ltd.\r
     All rights reserved\r
 \r
     VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.\r
@@ -8,14 +8,14 @@
 \r
     FreeRTOS is free software; you can redistribute it and/or modify it under\r
     the terms of the GNU General Public License (version 2) as published by the\r
-    Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception.\r
+    Free Software Foundation >>>> AND MODIFIED BY <<<< the FreeRTOS exception.\r
 \r
-       ***************************************************************************\r
+    ***************************************************************************\r
     >>!   NOTE: The modification to the GPL is included to allow you to     !<<\r
     >>!   distribute a combined work that includes FreeRTOS without being   !<<\r
     >>!   obliged to provide the source code for proprietary components     !<<\r
     >>!   outside of the FreeRTOS kernel.                                   !<<\r
-       ***************************************************************************\r
+    ***************************************************************************\r
 \r
     FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY\r
     WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS\r
     ***************************************************************************\r
 \r
     http://www.FreeRTOS.org/FAQHelp.html - Having a problem?  Start by reading\r
-       the FAQ page "My application does not run, what could be wrong?".  Have you\r
-       defined configASSERT()?\r
+    the FAQ page "My application does not run, what could be wrong?".  Have you\r
+    defined configASSERT()?\r
 \r
-       http://www.FreeRTOS.org/support - In return for receiving this top quality\r
-       embedded software for free we request you assist our global community by\r
-       participating in the support forum.\r
+    http://www.FreeRTOS.org/support - In return for receiving this top quality\r
+    embedded software for free we request you assist our global community by\r
+    participating in the support forum.\r
 \r
-       http://www.FreeRTOS.org/training - Investing in training allows your team to\r
-       be as productive as possible as early as possible.  Now you can receive\r
-       FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers\r
-       Ltd, and the world's leading authority on the world's leading RTOS.\r
+    http://www.FreeRTOS.org/training - Investing in training allows your team to\r
+    be as productive as possible as early as possible.  Now you can receive\r
+    FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers\r
+    Ltd, and the world's leading authority on the world's leading RTOS.\r
 \r
     http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,\r
     including FreeRTOS+Trace - an indispensable productivity tool, a DOS\r
@@ -99,8 +99,8 @@ functions but without including stdio.h here. */
 #endif /* configUSE_STATS_FORMATTING_FUNCTIONS == 1 ) */\r
 \r
 /* Sanity check the configuration. */\r
-#if configUSE_TICKLESS_IDLE != 0\r
-       #if INCLUDE_vTaskSuspend != 1\r
+#if( configUSE_TICKLESS_IDLE != 0 )\r
+       #if( INCLUDE_vTaskSuspend != 1 )\r
                #error INCLUDE_vTaskSuspend must be set to 1 if configUSE_TICKLESS_IDLE is not set to 0\r
        #endif /* INCLUDE_vTaskSuspend */\r
 #endif /* configUSE_TICKLESS_IDLE */\r
@@ -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
@@ -247,7 +247,7 @@ PRIVILEGED_DATA static volatile UBaseType_t uxPendedTicks                   = ( UBaseType_t ) 0
 PRIVILEGED_DATA static volatile BaseType_t xYieldPending                       = pdFALSE;\r
 PRIVILEGED_DATA static volatile BaseType_t xNumOfOverflows                     = ( BaseType_t ) 0;\r
 PRIVILEGED_DATA static UBaseType_t uxTaskNumber                                        = ( UBaseType_t ) 0U;\r
-PRIVILEGED_DATA static volatile TickType_t xNextTaskUnblockTime                = portMAX_DELAY;\r
+PRIVILEGED_DATA static volatile TickType_t xNextTaskUnblockTime                = ( TickType_t ) 0U; /* Initialised to portMAX_DELAY before the scheduler starts. */\r
 \r
 /* Context switches are held pending while the scheduler is suspended.  Also,\r
 interrupts must not manipulate the xGenericListItem of a TCB, or any of the\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
@@ -387,9 +387,10 @@ count overflows. */
  * the task.  It is inserted at the end of the list.\r
  */\r
 #define prvAddTaskToReadyList( pxTCB )                                                                                                                         \\r
-       traceMOVED_TASK_TO_READY_STATE( 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
@@ -555,7 +556,7 @@ TCB_t * pxNewTCB;
 StackType_t *pxTopOfStack;\r
 \r
        configASSERT( pxTaskCode );\r
-       configASSERT( ( ( uxPriority & ( ~portPRIVILEGE_BIT ) ) < configMAX_PRIORITIES ) );\r
+       configASSERT( ( ( uxPriority & ( UBaseType_t ) ( ~portPRIVILEGE_BIT ) ) < ( UBaseType_t ) configMAX_PRIORITIES ) );\r
 \r
        /* Allocate the memory required by the TCB and stack for the new task,\r
        checking that the allocation was successful. */\r
@@ -598,7 +599,7 @@ StackType_t *pxTopOfStack;
                #if( portSTACK_GROWTH < 0 )\r
                {\r
                        pxTopOfStack = pxNewTCB->pxStack + ( usStackDepth - ( uint16_t ) 1 );\r
-                       pxTopOfStack = ( StackType_t * ) ( ( ( portPOINTER_SIZE_TYPE ) pxTopOfStack ) & ( ( portPOINTER_SIZE_TYPE ) ~portBYTE_ALIGNMENT_MASK  ) ); /*lint !e923 MISRA exception.  Avoiding casts between pointers and integers is not practical.  Size differences accounted for using portPOINTER_SIZE_TYPE type. */\r
+                       pxTopOfStack = ( StackType_t * ) ( ( ( portPOINTER_SIZE_TYPE ) pxTopOfStack ) & ( ~( ( portPOINTER_SIZE_TYPE ) portBYTE_ALIGNMENT_MASK ) ) ); /*lint !e923 MISRA exception.  Avoiding casts between pointers and integers is not practical.  Size differences accounted for using portPOINTER_SIZE_TYPE type. */\r
 \r
                        /* Check the alignment of the calculated top of stack is correct. */\r
                        configASSERT( ( ( ( portPOINTER_SIZE_TYPE ) pxTopOfStack & ( portPOINTER_SIZE_TYPE ) portBYTE_ALIGNMENT_MASK ) == 0UL ) );\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
@@ -1062,8 +1074,8 @@ StackType_t *pxTopOfStack;
 \r
                taskENTER_CRITICAL();\r
                {\r
-                       /* If null is passed in here then we are changing the\r
-                       priority of the calling function. */\r
+                       /* If null is passed in here then it is the priority of the that\r
+                       called uxTaskPriorityGet() that is being queried. */\r
                        pxTCB = prvGetTCBFromHandle( xTask );\r
                        uxReturn = pxTCB->uxPriority;\r
                }\r
@@ -1588,6 +1600,7 @@ BaseType_t xReturn;
                }\r
                #endif /* configUSE_NEWLIB_REENTRANT */\r
 \r
+               xNextTaskUnblockTime = portMAX_DELAY;\r
                xSchedulerRunning = pdTRUE;\r
                xTickCount = ( TickType_t ) 0U;\r
 \r
@@ -1644,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
@@ -1656,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
@@ -2221,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
@@ -2240,8 +2288,7 @@ void vTaskSwitchContext( void )
                #endif /* configGENERATE_RUN_TIME_STATS */\r
 \r
                /* Check for stack overflow, if configured. */\r
-               taskFIRST_CHECK_FOR_STACK_OVERFLOW();\r
-               taskSECOND_CHECK_FOR_STACK_OVERFLOW();\r
+               taskCHECK_FOR_STACK_OVERFLOW();\r
 \r
                /* Select a new task to run using either the generic C or port\r
                optimised asm code. */\r
@@ -2386,7 +2433,7 @@ TickType_t xTimeToWake;
 \r
 #if configUSE_TIMERS == 1\r
 \r
-       void vTaskPlaceOnEventListRestricted( List_t * const pxEventList, const TickType_t xTicksToWait )\r
+       void vTaskPlaceOnEventListRestricted( List_t * const pxEventList, const TickType_t xTicksToWait, const BaseType_t xWaitIndefinitely )\r
        {\r
        TickType_t xTimeToWake;\r
 \r
@@ -2395,7 +2442,7 @@ TickType_t xTimeToWake;
                /* This function should not be called by application code hence the\r
                'Restricted' in its name.  It is not part of the public API.  It is\r
                designed for use by kernel code, and has special calling requirements -\r
-               it should be called from a critical section. */\r
+               it should be called with the scheduler suspended. */\r
 \r
 \r
                /* Place the event list item of the TCB in the appropriate event list.\r
@@ -2406,7 +2453,8 @@ TickType_t xTimeToWake;
 \r
                /* We must remove this task from the ready list before adding it to the\r
                blocked list as the same list item is used for both lists.  This\r
-               function is called form a critical section. */\r
+               function is called with the scheduler locked so interrupts will not\r
+               access the lists at the same time. */\r
                if( uxListRemove( &( pxCurrentTCB->xGenericListItem ) ) == ( UBaseType_t ) 0 )\r
                {\r
                        /* The current task must be in a ready list, so there is no need to\r
@@ -2418,12 +2466,44 @@ TickType_t xTimeToWake;
                        mtCOVERAGE_TEST_MARKER();\r
                }\r
 \r
-               /* Calculate the time at which the task should be woken if the event does\r
-               not occur.  This may overflow but this doesn't matter. */\r
-               xTimeToWake = xTickCount + xTicksToWait;\r
+               /* If vTaskSuspend() is available then the suspended task list is also\r
+               available and a task that is blocking indefinitely can enter the\r
+               suspended state (it is not really suspended as it will re-enter the\r
+               Ready state when the event it is waiting indefinitely for occurs).\r
+               Blocking indefinitely is useful when using tickless idle mode as when\r
+               all tasks are blocked indefinitely all timers can be turned off. */\r
+               #if( INCLUDE_vTaskSuspend == 1 )\r
+               {\r
+                       if( xWaitIndefinitely == pdTRUE )\r
+                       {\r
+                               /* Add the task to the suspended task list instead of a delayed\r
+                               task list to ensure the task is not woken by a timing event.  It\r
+                               will block indefinitely. */\r
+                               vListInsertEnd( &xSuspendedTaskList, &( pxCurrentTCB->xGenericListItem ) );\r
+                       }\r
+                       else\r
+                       {\r
+                               /* Calculate the time at which the task should be woken if the\r
+                               event does not occur.  This may overflow but this doesn't\r
+                               matter. */\r
+                               xTimeToWake = xTickCount + xTicksToWait;\r
+                               traceTASK_DELAY_UNTIL();\r
+                               prvAddCurrentTaskToDelayedList( xTimeToWake );\r
+                       }\r
+               }\r
+               #else\r
+               {\r
+                       /* Calculate the time at which the task should be woken if the event\r
+                       does not occur.  This may overflow but this doesn't matter. */\r
+                       xTimeToWake = xTickCount + xTicksToWait;\r
+                       traceTASK_DELAY_UNTIL();\r
+                       prvAddCurrentTaskToDelayedList( xTimeToWake );\r
 \r
-               traceTASK_DELAY_UNTIL();\r
-               prvAddCurrentTaskToDelayedList( xTimeToWake );\r
+                       /* Remove compiler warnings when INCLUDE_vTaskSuspend() is not\r
+                       defined. */\r
+                       ( void ) xWaitIndefinitely;\r
+               }\r
+               #endif\r
        }\r
 \r
 #endif /* configUSE_TIMERS */\r
@@ -2479,12 +2559,12 @@ BaseType_t xReturn;
                xReturn = pdFALSE;\r
        }\r
 \r
-       #if( configUSE_TICKLESS_IDLE == 1 )\r
+       #if( configUSE_TICKLESS_IDLE != 0 )\r
        {\r
                /* If a task is blocked on a kernel object then xNextTaskUnblockTime\r
                might be set to the blocked task's time out time.  If the task is\r
                unblocked for a reason other than a timeout xNextTaskUnblockTime is\r
-               normally left unchanged, because it is automatically get reset to a new\r
+               normally left unchanged, because it is automatically reset to a new\r
                value when the tick count equals xNextTaskUnblockTime.  However if\r
                tickless idling is used it might be more important to enter sleep mode\r
                at the earliest possible time - so reset xNextTaskUnblockTime here to\r
@@ -2757,10 +2837,12 @@ static portTASK_FUNCTION( prvIdleTask, pvParameters )
 }\r
 /*-----------------------------------------------------------*/\r
 \r
-#if configUSE_TICKLESS_IDLE != 0\r
+#if( configUSE_TICKLESS_IDLE != 0 )\r
 \r
        eSleepModeStatus eTaskConfirmSleepModeStatus( void )\r
        {\r
+       /* The idle task exists in addition to the application tasks. */\r
+       const UBaseType_t uxNonApplicationTasks = 1;\r
        eSleepModeStatus eReturn = eStandardSleep;\r
 \r
                if( listCURRENT_LIST_LENGTH( &xPendingReadyList ) != 0 )\r
@@ -2775,29 +2857,23 @@ static portTASK_FUNCTION( prvIdleTask, pvParameters )
                }\r
                else\r
                {\r
-                       #if configUSE_TIMERS == 0\r
+                       /* If all the tasks are in the suspended list (which might mean they\r
+                       have an infinite block time rather than actually being suspended)\r
+                       then it is safe to turn all clocks off and just wait for external\r
+                       interrupts. */\r
+                       if( listCURRENT_LIST_LENGTH( &xSuspendedTaskList ) == ( uxCurrentNumberOfTasks - uxNonApplicationTasks ) )\r
                        {\r
-                               /* The idle task exists in addition to the application tasks. */\r
-                               const UBaseType_t uxNonApplicationTasks = 1;\r
-\r
-                               /* If timers are not being used and all the tasks are in the\r
-                               suspended list (which might mean they have an infinite block\r
-                               time rather than actually being suspended) then it is safe to\r
-                               turn all clocks off and just wait for external interrupts. */\r
-                               if( listCURRENT_LIST_LENGTH( &xSuspendedTaskList ) == ( uxCurrentNumberOfTasks - uxNonApplicationTasks ) )\r
-                               {\r
-                                       eReturn = eNoTasksWaitingTimeout;\r
-                               }\r
-                               else\r
-                               {\r
-                                       mtCOVERAGE_TEST_MARKER();\r
-                               }\r
+                               eReturn = eNoTasksWaitingTimeout;\r
+                       }\r
+                       else\r
+                       {\r
+                               mtCOVERAGE_TEST_MARKER();\r
                        }\r
-                       #endif /* configUSE_TIMERS */\r
                }\r
 \r
                return eReturn;\r
        }\r
+\r
 #endif /* configUSE_TICKLESS_IDLE */\r
 /*-----------------------------------------------------------*/\r
 \r
@@ -2956,7 +3032,8 @@ UBaseType_t x;
        {\r
        TCB_t *pxTCB;\r
 \r
-               /* If null is passed in here then we are deleting ourselves. */\r
+               /* If null is passed in here then we are modifying the MPU settings of\r
+               the calling task. */\r
                pxTCB = prvGetTCBFromHandle( xTaskToModify );\r
 \r
         vPortStoreTaskMPUSettings( &( pxTCB->xMPUSettings ), xRegions, NULL, 0 );\r
@@ -3005,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
@@ -3022,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
@@ -3034,7 +3111,7 @@ static void prvCheckTasksWaitingTermination( void )
                        }\r
                }\r
        }\r
-       #endif /* vTaskDelete */\r
+       #endif /* INCLUDE_vTaskDelete */\r
 }\r
 /*-----------------------------------------------------------*/\r
 \r
@@ -3118,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
@@ -3320,9 +3400,8 @@ TCB_t *pxTCB;
 \r
        if( listLIST_IS_EMPTY( pxDelayedTaskList ) != pdFALSE )\r
        {\r
-               /* The new current delayed list is empty.  Set\r
-               xNextTaskUnblockTime to the maximum possible value so it is\r
-               extremely unlikely that the\r
+               /* The new current delayed list is empty.  Set xNextTaskUnblockTime to\r
+               the maximum possible value so it is     extremely unlikely that the\r
                if( xTickCount >= xNextTaskUnblockTime ) test will pass until\r
                there is an item in the delayed list. */\r
                xNextTaskUnblockTime = portMAX_DELAY;\r
@@ -3394,6 +3473,9 @@ TCB_t *pxTCB;
                locked then the mutex holder might now be NULL. */\r
                if( pxMutexHolder != NULL )\r
                {\r
+                       /* If the holder of the mutex has a priority below the priority of\r
+                       the task attempting to obtain the mutex then it will temporarily\r
+                       inherit the priority of the task attempting to obtain the mutex. */\r
                        if( pxTCB->uxPriority < pxCurrentTCB->uxPriority )\r
                        {\r
                                /* Adjust the mutex holder state to account for its new\r
@@ -3408,8 +3490,8 @@ TCB_t *pxTCB;
                                        mtCOVERAGE_TEST_MARKER();\r
                                }\r
 \r
-                               /* If the task being modified is in the ready state it will need to\r
-                               be moved into a new list. */\r
+                               /* If the task being modified is in the ready state it will need\r
+                               to be moved into a new list. */\r
                                if( listIS_CONTAINED_WITHIN( &( pxReadyTasksLists[ pxTCB->uxPriority ] ), &( pxTCB->xGenericListItem ) ) != pdFALSE )\r
                                {\r
                                        if( uxListRemove( &( pxTCB->xGenericListItem ) ) == ( UBaseType_t ) 0 )\r
@@ -3456,15 +3538,23 @@ TCB_t *pxTCB;
 \r
                if( pxMutexHolder != NULL )\r
                {\r
+                       /* A task can only have an inherited priority if it holds the mutex.\r
+                       If the mutex is held by a task then it cannot be given from an\r
+                       interrupt, and if a mutex is given by the holding task then it must\r
+                       be the running state task. */\r
+                       configASSERT( pxTCB == pxCurrentTCB );\r
+\r
                        configASSERT( pxTCB->uxMutexesHeld );\r
                        ( pxTCB->uxMutexesHeld )--;\r
 \r
+                       /* Has the holder of the mutex inherited the priority of another\r
+                       task? */\r
                        if( pxTCB->uxPriority != pxTCB->uxBasePriority )\r
                        {\r
                                /* Only disinherit if no other mutexes are held. */\r
                                if( pxTCB->uxMutexesHeld == ( UBaseType_t ) 0 )\r
                                {\r
-                                       /* A task can only have an inhertied priority if it holds\r
+                                       /* A task can only have an inherited priority if it holds\r
                                        the mutex.  If the mutex is held by a task then it cannot be\r
                                        given from an interrupt, and if a mutex is given by the\r
                                        holding task then it must be the running state task.  Remove\r
@@ -3540,7 +3630,6 @@ TCB_t *pxTCB;
                        {\r
                                portASSERT_IF_IN_ISR();\r
                        }\r
-\r
                }\r
                else\r
                {\r
@@ -3588,14 +3677,14 @@ TCB_t *pxTCB;
 \r
        static char *prvWriteNameToBuffer( char *pcBuffer, const char *pcTaskName )\r
        {\r
-       BaseType_t x;\r
+       size_t x;\r
 \r
                /* Start by copying the entire string. */\r
                strcpy( pcBuffer, pcTaskName );\r
 \r
                /* Pad the end of the string with spaces to ensure columns line up when\r
                printed out. */\r
-               for( x = strlen( pcBuffer ); x < ( configMAX_TASK_NAME_LEN - 1 ); x++ )\r
+               for( x = strlen( pcBuffer ); x < ( size_t ) ( configMAX_TASK_NAME_LEN - 1 ); x++ )\r
                {\r
                        pcBuffer[ x ] = ' ';\r
                }\r
@@ -3919,6 +4008,8 @@ TickType_t uxReturn;
                                        }\r
                                        #endif /* INCLUDE_vTaskSuspend */\r
 \r
+                                       traceTASK_NOTIFY_TAKE_BLOCK();\r
+\r
                                        /* All ports are written to allow a yield in a critical\r
                                        section (some will yield immediately, others wait until the\r
                                        critical section exits) - but it is not something that\r
@@ -3939,6 +4030,7 @@ TickType_t uxReturn;
 \r
                taskENTER_CRITICAL();\r
                {\r
+                       traceTASK_NOTIFY_TAKE();\r
                        ulReturn = pxCurrentTCB->ulNotifiedValue;\r
 \r
                        if( ulReturn != 0UL )\r
@@ -4034,6 +4126,8 @@ TickType_t uxReturn;
                                        }\r
                                        #endif /* INCLUDE_vTaskSuspend */\r
 \r
+                                       traceTASK_NOTIFY_WAIT_BLOCK();\r
+\r
                                        /* All ports are written to allow a yield in a critical\r
                                        section (some will yield immediately, others wait until the\r
                                        critical section exits) - but it is not something that\r
@@ -4054,6 +4148,8 @@ TickType_t uxReturn;
 \r
                taskENTER_CRITICAL();\r
                {\r
+                       traceTASK_NOTIFY_WAIT();\r
+\r
                        if( pulNotificationValue != NULL )\r
                        {\r
                                /* Output the current notification value, which may or may not\r
@@ -4090,7 +4186,7 @@ TickType_t uxReturn;
 \r
 #if( configUSE_TASK_NOTIFICATIONS == 1 )\r
 \r
-       BaseType_t xTaskNotify( TaskHandle_t xTaskToNotify, uint32_t ulValue, eNotifyAction eAction )\r
+       BaseType_t xTaskGenericNotify( TaskHandle_t xTaskToNotify, uint32_t ulValue, eNotifyAction eAction, uint32_t *pulPreviousNotificationValue )\r
        {\r
        TCB_t * pxTCB;\r
        eNotifyValue eOriginalNotifyState;\r
@@ -4101,6 +4197,11 @@ TickType_t uxReturn;
 \r
                taskENTER_CRITICAL();\r
                {\r
+                       if( pulPreviousNotificationValue != NULL )\r
+                       {\r
+                               *pulPreviousNotificationValue = pxTCB->ulNotifiedValue;\r
+                       }\r
+\r
                        eOriginalNotifyState = pxTCB->eNotifyState;\r
 \r
                        pxTCB->eNotifyState = eNotified;\r
@@ -4137,6 +4238,7 @@ TickType_t uxReturn;
                                        break;\r
                        }\r
 \r
+                       traceTASK_NOTIFY();\r
 \r
                        /* If the task is in the blocked state specifically to wait for a\r
                        notification then unblock it now. */\r
@@ -4148,6 +4250,22 @@ TickType_t uxReturn;
                                /* The task should not have been on an event list. */\r
                                configASSERT( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) == NULL );\r
 \r
+                               #if( configUSE_TICKLESS_IDLE != 0 )\r
+                               {\r
+                                       /* If a task is blocked waiting for a notification then\r
+                                       xNextTaskUnblockTime might be set to the blocked task's time\r
+                                       out time.  If the task is unblocked for a reason other than\r
+                                       a timeout xNextTaskUnblockTime is normally left unchanged,\r
+                                       because it will automatically get reset to a new value when\r
+                                       the tick count equals xNextTaskUnblockTime.  However if\r
+                                       tickless idling is used it might be more important to enter\r
+                                       sleep mode at the earliest possible time - so reset\r
+                                       xNextTaskUnblockTime here to ensure it is updated at the\r
+                                       earliest possible time. */\r
+                                       prvResetNextTaskUnblockTime();\r
+                               }\r
+                               #endif\r
+\r
                                if( pxTCB->uxPriority > pxCurrentTCB->uxPriority )\r
                                {\r
                                        /* The notified task has a priority above the currently\r
@@ -4174,7 +4292,7 @@ TickType_t uxReturn;
 \r
 #if( configUSE_TASK_NOTIFICATIONS == 1 )\r
 \r
-       BaseType_t xTaskNotifyFromISR( TaskHandle_t xTaskToNotify, uint32_t ulValue, eNotifyAction eAction, BaseType_t *pxHigherPriorityTaskWoken )\r
+       BaseType_t xTaskGenericNotifyFromISR( TaskHandle_t xTaskToNotify, uint32_t ulValue, eNotifyAction eAction, uint32_t *pulPreviousNotificationValue, BaseType_t *pxHigherPriorityTaskWoken )\r
        {\r
        TCB_t * pxTCB;\r
        eNotifyValue eOriginalNotifyState;\r
@@ -4205,8 +4323,12 @@ TickType_t uxReturn;
 \r
                uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR();\r
                {\r
-                       eOriginalNotifyState = pxTCB->eNotifyState;\r
+                       if( pulPreviousNotificationValue != NULL )\r
+                       {\r
+                               *pulPreviousNotificationValue = pxTCB->ulNotifiedValue;\r
+                       }\r
 \r
+                       eOriginalNotifyState = pxTCB->eNotifyState;\r
                        pxTCB->eNotifyState = eNotified;\r
 \r
                        switch( eAction )\r
@@ -4241,6 +4363,7 @@ TickType_t uxReturn;
                                        break;\r
                        }\r
 \r
+                       traceTASK_NOTIFY_FROM_ISR();\r
 \r
                        /* If the task is in the blocked state specifically to wait for a\r
                        notification then unblock it now. */\r
@@ -4323,6 +4446,8 @@ TickType_t uxReturn;
                        semaphore. */\r
                        ( pxTCB->ulNotifiedValue )++;\r
 \r
+                       traceTASK_NOTIFY_GIVE_FROM_ISR();\r
+\r
                        /* If the task is in the blocked state specifically to wait for a\r
                        notification then unblock it now. */\r
                        if( eOriginalNotifyState == eWaitingNotification )\r
@@ -4364,6 +4489,37 @@ TickType_t uxReturn;
 \r
 /*-----------------------------------------------------------*/\r
 \r
+#if( configUSE_TASK_NOTIFICATIONS == 1 )\r
+\r
+       BaseType_t xTaskNotifyStateClear( TaskHandle_t xTask )\r
+       {\r
+       TCB_t *pxTCB;\r
+       BaseType_t xReturn;\r
+\r
+               pxTCB = ( TCB_t * ) xTask;\r
+\r
+               /* If null is passed in here then it is the calling task that is having\r
+               its notification state cleared. */\r
+               pxTCB = prvGetTCBFromHandle( pxTCB );\r
+\r
+               taskENTER_CRITICAL();\r
+               {\r
+                       if( pxTCB->eNotifyState == eNotified )\r
+                       {\r
+                               pxTCB->eNotifyState = eNotWaitingNotification;\r
+                               xReturn = pdPASS;\r
+                       }\r
+                       else\r
+                       {\r
+                               xReturn = pdFAIL;\r
+                       }\r
+               }\r
+               taskEXIT_CRITICAL();\r
+\r
+               return xReturn;\r
+       }\r
+\r
+#endif /* configUSE_TASK_NOTIFICATIONS */\r
 \r
 #ifdef FREERTOS_MODULE_TEST\r
        #include "tasks_test_access_functions.h"\r