]> git.sur5r.net Git - freertos/blobdiff - Source/tasks.c
Add an option for 8 byte alignment.
[freertos] / Source / tasks.c
index bb21115d65c24c6cbfb6e499cae1164c9e4ccc01..f4a7f35c7f3cd07777a95a732dac4e77bcde340b 100644 (file)
@@ -1,24 +1,24 @@
 /*\r
-       FreeRTOS V4.0.1 - Copyright (C) 2003-2006 Richard Barry.\r
+       FreeRTOS.org V4.2.0 - Copyright (C) 2003-2007 Richard Barry.\r
 \r
-       This file is part of the FreeRTOS distribution.\r
+       This file is part of the FreeRTOS.org distribution.\r
 \r
-       FreeRTOS is free software; you can redistribute it and/or modify\r
+       FreeRTOS.org is free software; you can redistribute it and/or modify\r
        it under the terms of the GNU General Public License as published by\r
        the Free Software Foundation; either version 2 of the License, or\r
        (at your option) any later version.\r
 \r
-       FreeRTOS is distributed in the hope that it will be useful,\r
+       FreeRTOS.org is distributed in the hope that it will be useful,\r
        but WITHOUT ANY WARRANTY; without even the implied warranty of\r
        MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
        GNU General Public License for more details.\r
 \r
        You should have received a copy of the GNU General Public License\r
-       along with FreeRTOS; if not, write to the Free Software\r
+       along with FreeRTOS.org; if not, write to the Free Software\r
        Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\r
 \r
        A special exception to the GPL can be applied should you wish to distribute\r
-       a combined work that includes FreeRTOS, without being obliged to provide\r
+       a combined work that includes FreeRTOS.org, without being obliged to provide\r
        the source code for any proprietary components.  See the licensing section\r
        of http://www.FreeRTOS.org for full details of how and when the exception\r
        can be applied.\r
@@ -149,6 +149,50 @@ Changes from V3.2.4
 Changes from V4.0.0\r
 \r
        + Added the xMissedYield handling.\r
+\r
+Changes from V4.0.1\r
+\r
+       + The function vTaskList() now suspends the scheduler rather than disabling\r
+         interrupts during the creation of the task list.  \r
+       + Allow a task to delete itself by passing in its own handle.  Previously \r
+         this could only be done by passing in NULL.\r
+       + The tick hook function is now called only within a tick isr.  Previously\r
+         it was also called when the tick function was called during the scheduler\r
+         unlocking process.\r
+\r
+Changes from V4.0.3\r
+\r
+       + Extra checks have been placed in vTaskPrioritySet() to avoid unnecessary\r
+         yields.\r
+\r
+Changed from V4.0.4\r
+\r
+       + Bug fix:  The 'value' of the event list item is updated when the priority\r
+         of a task is changed.  Previously only the priority of the TCB itself was\r
+         changed.\r
+       + When resuming a task a check is first made to see if the task is actually\r
+         suspended.\r
+       + vTaskPrioritySet() and vTaskResume() no longer use the event list item.\r
+         This has not been necessary since V4.0.1 when the xMissedYield handling\r
+         was added.\r
+       + Implement xTaskResumeFromISR().\r
+\r
+Changes from V4.0.5\r
+\r
+       + Added utility functions and xOverflowCount variable to facilitate the\r
+         queue.c changes.\r
+\r
+Changes from V4.1.2\r
+       \r
+       + Tasks that block on events with a timeout of portMAX_DELAY are now\r
+         blocked indefinitely if configINCLUDE_vTaskSuspend is defined. \r
+         Previously portMAX_DELAY was just the longest block time possible.\r
+\r
+Changes from V4.1.3\r
+\r
+       + Very small change made to xTaskCheckForTimeout() as a result of the \r
+       SafeRTOS testing.  This corrects the case where the function can return an\r
+       invalid value - but only in an extremely unlikely scenario.\r
 */\r
 \r
 #include <stdio.h>\r
@@ -185,6 +229,9 @@ Changes from V4.0.0
        #define configMAX_TASK_NAME_LEN 1\r
 #endif\r
 \r
+#ifndef INCLUDE_xTaskResumeFromISR\r
+       #define INCLUDE_xTaskResumeFromISR 1\r
+#endif \r
 \r
 /*\r
  * Task control block.  A task control block (TCB) is allocated to each task,\r
@@ -231,13 +278,13 @@ static xList xPendingReadyList;                                                   /*< Tasks that have been readied while the
 /* File private variables. --------------------------------*/\r
 static volatile unsigned portBASE_TYPE uxCurrentNumberOfTasks  = ( unsigned portBASE_TYPE ) 0;\r
 static volatile portTickType xTickCount                                                        = ( portTickType ) 0;\r
-static unsigned portBASE_TYPE uxTopUsedPriority                                = tskIDLE_PRIORITY;\r
+static unsigned portBASE_TYPE uxTopUsedPriority                                        = tskIDLE_PRIORITY;\r
 static volatile unsigned portBASE_TYPE uxTopReadyPriority              = tskIDLE_PRIORITY;\r
 static volatile signed portBASE_TYPE xSchedulerRunning                 = pdFALSE;\r
 static volatile unsigned portBASE_TYPE uxSchedulerSuspended            = ( unsigned portBASE_TYPE ) pdFALSE;\r
 static volatile unsigned portBASE_TYPE uxMissedTicks                   = ( unsigned portBASE_TYPE ) 0;\r
 static volatile portBASE_TYPE xMissedYield                                             = ( portBASE_TYPE ) pdFALSE;\r
-\r
+static volatile portBASE_TYPE xNumOfOverflows                                  = ( portBASE_TYPE ) 0;\r
 /* Debugging and trace facilities private variables and macros. ------------*/\r
 \r
 /*\r
@@ -275,28 +322,28 @@ static volatile portBASE_TYPE xMissedYield                                                = ( portBASE_TYPE ) pdFALSE;
  */\r
 #if ( configUSE_TRACE_FACILITY == 1 )\r
 \r
-       #define vWriteTraceToBuffer()                                                                                                           \\r
-       {                                                                                                                                                                       \\r
-               if( xTracing )                                                                                                                                  \\r
-               {                                                                                                                                                               \\r
-                       static unsigned portBASE_TYPE uxPreviousTask = 255;                                                     \\r
-                                                                                                                                                                               \\r
-                       if( uxPreviousTask != pxCurrentTCB->uxTCBNumber )                                                       \\r
-                       {                                                                                                                                                       \\r
-                               if( ( pcTraceBuffer + tskSIZE_OF_EACH_TRACE_LINE ) < pcTraceBufferEnd ) \\r
-                               {                                                                                                                                               \\r
-                                       uxPreviousTask = pxCurrentTCB->uxTCBNumber;                                                     \\r
+       #define vWriteTraceToBuffer()                                                                                                                                   \\r
+       {                                                                                                                                                                                               \\r
+               if( xTracing )                                                                                                                                                          \\r
+               {                                                                                                                                                                                       \\r
+                       static unsigned portBASE_TYPE uxPreviousTask = 255;                                                                             \\r
+                                                                                                                                                                                                       \\r
+                       if( uxPreviousTask != pxCurrentTCB->uxTCBNumber )                                                                               \\r
+                       {                                                                                                                                                                               \\r
+                               if( ( pcTraceBuffer + tskSIZE_OF_EACH_TRACE_LINE ) < pcTraceBufferEnd )                         \\r
+                               {                                                                                                                                                                       \\r
+                                       uxPreviousTask = pxCurrentTCB->uxTCBNumber;                                                                             \\r
                                        *( unsigned portLONG * ) pcTraceBuffer = ( unsigned portLONG ) xTickCount;              \\r
-                                       pcTraceBuffer += sizeof( unsigned portLONG );                                           \\r
+                                       pcTraceBuffer += sizeof( unsigned portLONG );                                                                   \\r
                                        *( unsigned portLONG * ) pcTraceBuffer = ( unsigned portLONG ) uxPreviousTask;  \\r
-                                       pcTraceBuffer += sizeof( unsigned portLONG );                                           \\r
-                               }                                                                                                                                               \\r
-                               else                                                                                                                                    \\r
-                               {                                                                                                                                               \\r
-                                       xTracing = pdFALSE;                                                                                                     \\r
-                               }                                                                                                                                               \\r
-                       }                                                                                                                                                       \\r
-               }                                                                                                                                                               \\r
+                                       pcTraceBuffer += sizeof( unsigned portLONG );                                                                   \\r
+                               }                                                                                                                                                                       \\r
+                               else                                                                                                                                                            \\r
+                               {                                                                                                                                                                       \\r
+                                       xTracing = pdFALSE;                                                                                                                             \\r
+                               }                                                                                                                                                                       \\r
+                       }                                                                                                                                                                               \\r
+               }                                                                                                                                                                                       \\r
        }\r
 \r
 #else\r
@@ -320,8 +367,7 @@ static volatile portBASE_TYPE xMissedYield                                          = ( portBASE_TYPE ) pdFALSE;
                uxTopReadyPriority = pxTCB->uxPriority;                                                                                                                                 \\r
        }                                                                                                                                                                                                                       \\r
        vListInsertEnd( ( xList * ) &( pxReadyTasksLists[ pxTCB->uxPriority ] ), &( pxTCB->xGenericListItem ) );        \\r
-}      \r
-\r
+}              \r
 \r
 /*\r
  * Macro that looks at the list of tasks that are currently delayed to see if\r
@@ -331,24 +377,24 @@ static volatile portBASE_TYPE xMissedYield                                                = ( portBASE_TYPE ) pdFALSE;
  * once one tasks has been found whose timer has not expired we need not look\r
  * any further down the list.\r
  */\r
-#define prvCheckDelayedTasks()                                                                                                                                 \\r
-{                                                                                                                                                                                              \\r
-register tskTCB *pxTCB;                                                                                                                                                        \\r
-                                                                                                                                                                                               \\r
-       while( ( pxTCB = ( tskTCB * ) listGET_OWNER_OF_HEAD_ENTRY( pxDelayedTaskList ) ) != NULL )      \\r
-       {                                                                                                                                                                                       \\r
-               if( xTickCount < listGET_LIST_ITEM_VALUE( &( pxTCB->xGenericListItem ) ) )                              \\r
-               {                                                                                                                                                                               \\r
-                       break;                                                                                                                                                          \\r
-               }                                                                                                                                                                               \\r
-               vListRemove( &( pxTCB->xGenericListItem ) );                                                                                    \\r
-               /* Is the task waiting on an event also? */                                                                                             \\r
-               if( pxTCB->xEventListItem.pvContainer )                                                                                                 \\r
-               {                                                                                                                                                                               \\r
-                       vListRemove( &( pxTCB->xEventListItem ) );                                                                                      \\r
-               }                                                                                                                                                                               \\r
+#define prvCheckDelayedTasks()                                                                                                                                                                         \\r
+{                                                                                                                                                                                                                                      \\r
+register tskTCB *pxTCB;                                                                                                                                                                                                \\r
+                                                                                                                                                                                                                                       \\r
+       while( ( pxTCB = ( tskTCB * ) listGET_OWNER_OF_HEAD_ENTRY( pxDelayedTaskList ) ) != NULL )                                              \\r
+       {                                                                                                                                                                                                                               \\r
+               if( xTickCount < listGET_LIST_ITEM_VALUE( &( pxTCB->xGenericListItem ) ) )                                                                      \\r
+               {                                                                                                                                                                                                                       \\r
+                       break;                                                                                                                                                                                                  \\r
+               }                                                                                                                                                                                                                       \\r
+               vListRemove( &( pxTCB->xGenericListItem ) );                                                                                                                            \\r
+               /* Is the task waiting on an event also? */                                                                                                                                     \\r
+               if( pxTCB->xEventListItem.pvContainer )                                                                                                                                         \\r
+               {                                                                                                                                                                                                                       \\r
+                       vListRemove( &( pxTCB->xEventListItem ) );                                                                                                                              \\r
+               }                                                                                                                                                                                                                       \\r
                prvAddTaskToReadyQueue( pxTCB );                                                                                                                \\r
-       }                                                                                                                                                                                       \\r
+       }                                                                                                                                                                                                                               \\r
 }                                                                                                                                                                                      \r
 \r
 /*\r
@@ -568,6 +614,13 @@ static unsigned portBASE_TYPE uxTaskNumber = 0; /*lint !e956 Static is deliberat
 \r
                taskENTER_CRITICAL();\r
                {\r
+                       /* Ensure a yield is performed if the current task is being \r
+                       deleted. */\r
+                       if( pxTaskToDelete == pxCurrentTCB )\r
+                       {\r
+                               pxTaskToDelete = NULL;\r
+                       }\r
+\r
                        /* If null is passed in here then we are deleting ourselves. */\r
                        pxTCB = prvGetTCBFromHandle( pxTaskToDelete );\r
 \r
@@ -593,9 +646,12 @@ static unsigned portBASE_TYPE uxTaskNumber = 0; /*lint !e956 Static is deliberat
                taskEXIT_CRITICAL();\r
 \r
                /* Force a reschedule if we have just deleted the current task. */\r
-               if( ( void * ) pxTaskToDelete == NULL )\r
+               if( xSchedulerRunning != pdFALSE ) \r
                {\r
-                       taskYIELD();\r
+                       if( ( void * ) pxTaskToDelete == NULL )\r
+                       {\r
+                               taskYIELD();\r
+                       }\r
                }\r
        }\r
 \r
@@ -771,7 +827,7 @@ static unsigned portBASE_TYPE uxTaskNumber = 0; /*lint !e956 Static is deliberat
        void vTaskPrioritySet( xTaskHandle pxTask, unsigned portBASE_TYPE uxNewPriority )\r
        {\r
        tskTCB *pxTCB;\r
-       unsigned portBASE_TYPE uxCurrentPriority;\r
+       unsigned portBASE_TYPE uxCurrentPriority, xYieldRequired = pdFALSE;\r
 \r
                /* Ensure the new priority is valid. */\r
                if( uxNewPriority >= configMAX_PRIORITIES )\r
@@ -788,7 +844,28 @@ static unsigned portBASE_TYPE uxTaskNumber = 0; /*lint !e956 Static is deliberat
 \r
                        if( uxCurrentPriority != uxNewPriority )\r
                        {\r
+                               /* The priority change may have readied a task of higher\r
+                               priority than the calling task. */\r
+                               if( uxNewPriority > pxCurrentTCB->uxPriority ) \r
+                               {\r
+                                       if( pxTask != NULL )\r
+                                       {\r
+                                               /* The priority of another task is being raised.  If we\r
+                                               were raising the priority of the currently running task\r
+                                               there would be no need to switch as it must have already\r
+                                               been the highest priority task. */\r
+                                               xYieldRequired = pdTRUE;\r
+                                       }\r
+                               }\r
+                               else if( pxTask == NULL )\r
+                               {\r
+                                       /* Setting our own priority down means there may now be another\r
+                                       task of higher priority that is ready to execute. */\r
+                                       xYieldRequired = pdTRUE;\r
+                               }\r
+                       \r
                                pxTCB->uxPriority = uxNewPriority;\r
+                               listSET_LIST_ITEM_VALUE( &( pxTCB->xEventListItem ), configMAX_PRIORITIES - ( portTickType ) uxNewPriority );\r
 \r
                                /* If the task is in the blocked or suspended list we need do\r
                                nothing more than change it's priority variable. However, if\r
@@ -796,27 +873,20 @@ static unsigned portBASE_TYPE uxTaskNumber = 0; /*lint !e956 Static is deliberat
                                in the queue appropriate to its new priority. */\r
                                if( listIS_CONTAINED_WITHIN( &( pxReadyTasksLists[ uxCurrentPriority ] ), &( pxTCB->xGenericListItem ) ) )\r
                                {\r
-                                       if( uxSchedulerSuspended == ( unsigned portBASE_TYPE ) pdFALSE )\r
-                                       {\r
-                                               /* The task is currently in its ready list - remove before adding\r
-                                               it to it's new ready list. */\r
-                                               vListRemove( &( pxTCB->xGenericListItem ) );\r
-                                               prvAddTaskToReadyQueue( pxTCB );\r
-                                       }\r
-                                       else\r
-                                       {\r
-                                               /* We cannot access the delayed or ready lists, so will hold this\r
-                                               task pending until the scheduler is resumed. */\r
-                                               vListInsertEnd( ( xList * ) &( xPendingReadyList ), &( pxTCB->xEventListItem ) );\r
-                                       }\r
+                                       /* The task is currently in its ready list - remove before adding\r
+                                       it to it's new ready list.  As we are in a critical section we\r
+                                       can do this even if the scheduler is suspended. */\r
+                                       vListRemove( &( pxTCB->xGenericListItem ) );\r
+                                       prvAddTaskToReadyQueue( pxTCB );\r
                                }                       \r
+                               \r
+                               if( xYieldRequired == pdTRUE )\r
+                               {\r
+                                       taskYIELD();\r
+                               }                               \r
                        }\r
                }\r
                taskEXIT_CRITICAL();\r
-\r
-               /* The priority change may have readied a task of higher\r
-               priority than the calling task. */\r
-               taskYIELD();\r
        }\r
 \r
 #endif\r
@@ -830,6 +900,13 @@ static unsigned portBASE_TYPE uxTaskNumber = 0; /*lint !e956 Static is deliberat
 \r
                taskENTER_CRITICAL();\r
                {\r
+                       /* Ensure a yield is performed if the current task is being \r
+                       suspended. */\r
+                       if( pxTaskToSuspend == pxCurrentTCB )\r
+                       {\r
+                               pxTaskToSuspend = NULL;\r
+                       }\r
+\r
                        /* If null is passed in here then we are suspending ourselves. */\r
                        pxTCB = prvGetTCBFromHandle( pxTaskToSuspend );\r
 \r
@@ -861,7 +938,6 @@ static unsigned portBASE_TYPE uxTaskNumber = 0; /*lint !e956 Static is deliberat
        void vTaskResume( xTaskHandle pxTaskToResume )\r
        {\r
        tskTCB *pxTCB;\r
-       portBASE_TYPE xYieldRequired;\r
 \r
                /* Remove the task from whichever list it is currently in, and place\r
                it in the ready list. */\r
@@ -872,31 +948,68 @@ static unsigned portBASE_TYPE uxTaskNumber = 0; /*lint !e956 Static is deliberat
                if( pxTCB != NULL )\r
                {\r
                        taskENTER_CRITICAL();\r
+                       {\r
+                               /* Is the task we are attempting to resume actually suspended? */\r
+                               if( listIS_CONTAINED_WITHIN( &xSuspendedTaskList, &( pxTCB->xGenericListItem ) ) != pdFALSE )\r
+                               {\r
+                                       /* Has the task already been resumed from within an ISR? */\r
+                                       if( listIS_CONTAINED_WITHIN( &xPendingReadyList, &( pxTCB->xEventListItem ) ) != pdTRUE )\r
+                                       {                       \r
+                                               /* As we are in a critical section we can access the ready \r
+                                               lists even if the scheduler is suspended. */\r
+                                               vListRemove(  &( pxTCB->xGenericListItem ) );\r
+                                               prvAddTaskToReadyQueue( pxTCB );\r
+\r
+                                               /* We may have just resumed a higher priority task. */\r
+                                               if( pxTCB->uxPriority >= pxCurrentTCB->uxPriority )\r
+                                               {\r
+                                                       /* This yield may not cause the task just resumed to run, but\r
+                                                       will leave the lists in the correct state for the next yield. */\r
+                                                       taskYIELD();\r
+                                               }\r
+                                       }\r
+                               }\r
+                       }\r
+                       taskEXIT_CRITICAL();\r
+               }\r
+       }\r
+\r
+#endif\r
+\r
+/*-----------------------------------------------------------*/\r
+\r
+#if ( ( INCLUDE_xTaskResumeFromISR == 1 ) && ( INCLUDE_vTaskSuspend == 1 ) )\r
+\r
+       portBASE_TYPE xTaskResumeFromISR( xTaskHandle pxTaskToResume )\r
+       {\r
+       portBASE_TYPE xYieldRequired = pdFALSE;\r
+       tskTCB *pxTCB;\r
+\r
+               pxTCB = ( tskTCB * ) pxTaskToResume;\r
+\r
+               /* Is the task we are attempting to resume actually suspended? */\r
+               if( listIS_CONTAINED_WITHIN( &xSuspendedTaskList, &( pxTCB->xGenericListItem ) ) != pdFALSE )\r
+               {\r
+                       /* Has the task already been resumed from within an ISR? */\r
+                       if( listIS_CONTAINED_WITHIN( &xPendingReadyList, &( pxTCB->xEventListItem ) ) != pdTRUE )\r
                        {\r
                                if( uxSchedulerSuspended == ( unsigned portBASE_TYPE ) pdFALSE )\r
                                {\r
                                        xYieldRequired = ( pxTCB->uxPriority >= pxCurrentTCB->uxPriority );\r
-                                       vListRemove(  &( pxTCB->xGenericListItem ) );\r
+                                       vListRemove(  &( pxTCB->xGenericListItem ) );   \r
                                        prvAddTaskToReadyQueue( pxTCB );\r
                                }\r
                                else\r
                                {\r
                                        /* We cannot access the delayed or ready lists, so will hold this\r
-                                       task pending until the scheduler is resumed. */\r
-                                       xYieldRequired = pdFALSE;\r
+                                       task pending until the scheduler is resumed, at which point a \r
+                                       yield will be preformed if necessary. */\r
                                        vListInsertEnd( ( xList * ) &( xPendingReadyList ), &( pxTCB->xEventListItem ) );\r
                                }\r
                        }\r
-                       taskEXIT_CRITICAL();\r
-\r
-                       /* We may have just resumed a higher priority task. */\r
-                       if( xYieldRequired )\r
-                       {\r
-                               /* This yield may not cause the task just resumed to run, but\r
-                               will leave the lists in the correct state for the next yield. */\r
-                               taskYIELD();\r
-                       }\r
                }\r
+\r
+               return xYieldRequired;\r
        }\r
 \r
 #endif\r
@@ -904,7 +1017,6 @@ static unsigned portBASE_TYPE uxTaskNumber = 0; /*lint !e956 Static is deliberat
 \r
 \r
 \r
-\r
 /*-----------------------------------------------------------\r
  * PUBLIC SCHEDULER CONTROL documented in task.h\r
  *----------------------------------------------------------*/\r
@@ -1080,7 +1192,7 @@ unsigned portBASE_TYPE uxNumberOfTasks;
                /* This is a VERY costly function that should be used for debug only.\r
                It leaves interrupts disabled for a LONG time. */\r
 \r
-               taskENTER_CRITICAL();\r
+        vTaskSuspendAll();\r
                {\r
                        /* Run through all the lists that could potentially contain a TCB and\r
                        report the task name, state and stack high water mark. */\r
@@ -1120,7 +1232,7 @@ unsigned portBASE_TYPE uxNumberOfTasks;
                                prvListTaskWithinSingleList( pcWriteBuffer, ( xList * ) &xSuspendedTaskList, tskSUSPENDED_CHAR );\r
                        }\r
                }\r
-               taskEXIT_CRITICAL();\r
+        xTaskResumeAll();\r
        }\r
 \r
 #endif\r
@@ -1180,11 +1292,13 @@ inline void vTaskIncrementTick( void )
                {\r
                        xList *pxTemp;\r
 \r
-                       /* Tick count has overflowed so we need to swap the delay lists.  If there are\r
-                       any items in pxDelayedTaskList here then there is an error! */\r
+                       /* Tick count has overflowed so we need to swap the delay lists.  \r
+                       If there are any items in pxDelayedTaskList here then there is \r
+                       an error! */\r
                        pxTemp = pxDelayedTaskList;\r
                        pxDelayedTaskList = pxOverflowDelayedTaskList;\r
                        pxOverflowDelayedTaskList = pxTemp;\r
+            xNumOfOverflows++;\r
                }\r
 \r
                /* See if this tick has made a timeout expire. */\r
@@ -1193,13 +1307,28 @@ inline void vTaskIncrementTick( void )
        else\r
        {\r
                ++uxMissedTicks;\r
+\r
+               /* The tick hook gets called at regular intervals, even if the \r
+               scheduler is locked. */\r
+               #if ( configUSE_TICK_HOOK == 1 )\r
+               {\r
+                       extern void vApplicationTickHook( void );\r
+\r
+                       vApplicationTickHook();\r
+               }\r
+               #endif\r
        }\r
 \r
        #if ( configUSE_TICK_HOOK == 1 )\r
        {\r
                extern void vApplicationTickHook( void );\r
 \r
-               vApplicationTickHook();\r
+               /* Guard against the tick hook being called when the missed tick\r
+               count is being unwound (when the scheduler is being unlocked. */\r
+               if( uxMissedTicks == 0 )\r
+               {\r
+                       vApplicationTickHook();\r
+               }\r
        }\r
        #endif\r
 }\r
@@ -1301,27 +1430,61 @@ portTickType xTimeToWake;
        is the first to be woken by the event. */\r
        vListInsert( ( xList * ) pxEventList, ( xListItem * ) &( pxCurrentTCB->xEventListItem ) );\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
-\r
        /* We must remove ourselves from the ready list before adding ourselves\r
        to the blocked list as the same list item is used for both lists.  We have\r
        exclusive access to the ready lists as the scheduler is locked. */\r
        vListRemove( ( xListItem * ) &( pxCurrentTCB->xGenericListItem ) );\r
 \r
-       listSET_LIST_ITEM_VALUE( &( pxCurrentTCB->xGenericListItem ), xTimeToWake );\r
 \r
-       if( xTimeToWake < xTickCount )\r
-       {\r
-               /* Wake time has overflowed.  Place this item in the overflow list. */\r
-               vListInsert( ( xList * ) pxOverflowDelayedTaskList, ( xListItem * ) &( pxCurrentTCB->xGenericListItem ) );\r
+       #if ( INCLUDE_vTaskSuspend == 1 )\r
+       {                        \r
+               if( xTicksToWait == portMAX_DELAY )\r
+               {\r
+                       /* Add ourselves to the suspended task list instead of a delayed task\r
+                       list to ensure we are not woken by a timing event.  We will block\r
+                       indefinitely. */\r
+                       vListInsertEnd( ( xList * ) &xSuspendedTaskList, ( xListItem * ) &( pxCurrentTCB->xGenericListItem ) );\r
+               }\r
+               else\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
+               \r
+                       listSET_LIST_ITEM_VALUE( &( pxCurrentTCB->xGenericListItem ), xTimeToWake );\r
+               \r
+                       if( xTimeToWake < xTickCount )\r
+                       {\r
+                               /* Wake time has overflowed.  Place this item in the overflow list. */\r
+                               vListInsert( ( xList * ) pxOverflowDelayedTaskList, ( xListItem * ) &( pxCurrentTCB->xGenericListItem ) );\r
+                       }\r
+                       else\r
+                       {\r
+                               /* The wake time has not overflowed, so we can use the current block list. */\r
+                               vListInsert( ( xList * ) pxDelayedTaskList, ( xListItem * ) &( pxCurrentTCB->xGenericListItem ) );\r
+                       }\r
+               }\r
        }\r
-       else\r
+       #else\r
        {\r
-               /* The wake time has not overflowed, so we can use the current block list. */\r
-               vListInsert( ( xList * ) pxDelayedTaskList, ( xListItem * ) &( pxCurrentTCB->xGenericListItem ) );\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
+               \r
+                       listSET_LIST_ITEM_VALUE( &( pxCurrentTCB->xGenericListItem ), xTimeToWake );\r
+               \r
+                       if( xTimeToWake < xTickCount )\r
+                       {\r
+                               /* Wake time has overflowed.  Place this item in the overflow list. */\r
+                               vListInsert( ( xList * ) pxOverflowDelayedTaskList, ( xListItem * ) &( pxCurrentTCB->xGenericListItem ) );\r
+                       }\r
+                       else\r
+                       {\r
+                               /* The wake time has not overflowed, so we can use the current block list. */\r
+                               vListInsert( ( xList * ) pxDelayedTaskList, ( xListItem * ) &( pxCurrentTCB->xGenericListItem ) );\r
+                       }\r
        }\r
+       #endif\r
 }\r
 /*-----------------------------------------------------------*/\r
 \r
@@ -1370,10 +1533,47 @@ portBASE_TYPE xReturn;
 \r
        return xReturn;\r
 }\r
+/*-----------------------------------------------------------*/\r
 \r
+void vTaskSetTimeOutState( xTimeOutType *pxTimeOut )\r
+{\r
+    pxTimeOut->xOverflowCount = xNumOfOverflows;\r
+    pxTimeOut->xTimeOnEntering = xTickCount;\r
+}\r
+/*-----------------------------------------------------------*/\r
 \r
+portBASE_TYPE xTaskCheckForTimeOut( xTimeOutType *pxTimeOut, portTickType *pxTicksToWait )\r
+{\r
+portBASE_TYPE xReturn;\r
 \r
+    if( ( xNumOfOverflows != pxTimeOut->xOverflowCount ) && ( xTickCount >= pxTimeOut->xTimeOnEntering ) )\r
+    {\r
+        /* The tick count is greater than the time at which vTaskSetTimeout() \r
+               was called, but has also overflowed since vTaskSetTimeOut() was called.\r
+        It must have wrapped all the way around and gone past us again. This\r
+        passed since vTaskSetTimeout() was called. */\r
+        xReturn = pdTRUE;\r
+    }\r
+    else if( ( xTickCount - pxTimeOut->xTimeOnEntering ) < *pxTicksToWait )\r
+    {\r
+        /* Not a genuine timeout. Adjust parameters for time remaining. */\r
+        *pxTicksToWait -= ( xTickCount - pxTimeOut->xTimeOnEntering );\r
+        vTaskSetTimeOutState( pxTimeOut );\r
+        xReturn = pdFALSE;\r
+    }\r
+    else\r
+    {\r
+        xReturn = pdTRUE;\r
+    }\r
+\r
+    return xReturn;\r
+}\r
+/*-----------------------------------------------------------*/\r
 \r
+void vTaskMissedYield( void )\r
+{\r
+       xMissedYield = pdTRUE;\r
+}\r
 \r
 /*\r
  * -----------------------------------------------------------\r