]> git.sur5r.net Git - freertos/commitdiff
Add stack check macros.
authorrichardbarry <richardbarry@1d2547de-c912-0410-9cb9-b8ca96c0e9e2>
Mon, 3 Mar 2008 20:56:55 +0000 (20:56 +0000)
committerrichardbarry <richardbarry@1d2547de-c912-0410-9cb9-b8ca96c0e9e2>
Mon, 3 Mar 2008 20:56:55 +0000 (20:56 +0000)
git-svn-id: https://svn.code.sf.net/p/freertos/code/trunk@224 1d2547de-c912-0410-9cb9-b8ca96c0e9e2

Source/include/FreeRTOS.h
Source/include/task.h
Source/tasks.c

index 585aebf8eb47b85e363fa8c4c4e0fefd1e8a3f7a..5fcd9e7a2d9679fe57501fa0159d98bcfe005321 100644 (file)
        #error Missing definition:  configUSE_16_BIT_TICKS should be defined in FreeRTOSConfig.h as either 1 or 0.  See the Configuration section of the FreeRTOS API documentation for details.\r
 #endif\r
 \r
-#ifndef INCLUDE_uxGetStackHighWaterMark\r
-       #define INCLUDE_uxGetStackHighWaterMark 0\r
+#ifndef INCLUDE_uxTaskGetStackHighWaterMark\r
+       #define INCLUDE_uxTaskGetStackHighWaterMark 0\r
 #endif\r
 \r
 #ifndef configUSE_RECURSIVE_MUTEXES\r
        #define traceBLOCKING_ON_QUEUE_SEND( pxQueue )\r
 #endif\r
 \r
+#ifndef configCHECK_FOR_STACK_OVERFLOW\r
+       #define configCHECK_FOR_STACK_OVERFLOW 0\r
+#endif\r
 \r
 /* The following event macros are embedded in the kernel API calls. */\r
 \r
index be136e7400e3b96a4ce1e0dfb8370ec08950c969..98f1cb78f676e3ce04fecb072652388bc85daeee 100644 (file)
@@ -868,9 +868,9 @@ unsigned portLONG ulTaskEndTrace( void );
 \r
 /**\r
  * task.h\r
- * <PRE>unsigned portBASE_TYPE uxGetStackHighWaterMark( void );</PRE>\r
+ * <PRE>unsigned portBASE_TYPE uxTaskGetStackHighWaterMark( void );</PRE>\r
  *\r
- * INCLUDE_uxGetStackHighWaterMark must be set to 1 in FreeRTOSConfig.h for\r
+ * INCLUDE_uxTaskGetStackHighWaterMark must be set to 1 in FreeRTOSConfig.h for\r
  * this function to be available.\r
  *\r
  * Returns the high water mark for the stack of the calling task.  That is,\r
@@ -878,7 +878,7 @@ unsigned portLONG ulTaskEndTrace( void );
  * started.  The small the returned number the closer the task has come\r
  * to overflowing its stack.\r
  */\r
-unsigned portBASE_TYPE uxGetStackHighWaterMark( void );\r
+unsigned portBASE_TYPE uxTaskGetStackHighWaterMark( void );\r
 \r
 /*-----------------------------------------------------------\r
  * SCHEDULER INTERNALS AVAILABLE FOR PORTING PURPOSES\r
index 15e61cf1b886316a2d969a64d97e722d297b3210..ad65c144e22f7e331b033ed9c42ee1cf4436425e 100644 (file)
 \r
        ***************************************************************************\r
 \r
-       Please ensure to read the configuration and relevant port sections of the \r
+       Please ensure to read the configuration and relevant port sections of the\r
        online documentation.\r
 \r
        +++ http://www.FreeRTOS.org +++\r
-       Documentation, latest information, license and contact details.  \r
+       Documentation, latest information, license and contact details.\r
 \r
        +++ http://www.SafeRTOS.com +++\r
        A version that is certified for use in safety critical systems.\r
        ***************************************************************************\r
 */\r
 \r
-/*\r
-Changes from V1.00:\r
-       \r
-       + Call to portRESTORE_CONTEXT has been removed.  The first context\r
-         switch is now performed within sPortStartScheduler().\r
-\r
-Changes from V1.01:\r
-\r
-       + More use of 8bit data types.\r
-       + Function name prefixes changed where the data type returned has changed.\r
-       + configUSE_TRACE_FACILITY is no longer defined by default.\r
-\r
-Changes from V1.2.0\r
-\r
-       + Introduced ucTopReadyPriority.  This tracks the highest priority ready\r
-         queue that contains a valid TCB and thus makes the context switch\r
-         slightly faster.\r
-\r
-       + prvAddTaskToReadyQueue() has been made a macro.\r
-\r
-Changes from V1.2.6\r
-\r
-       + Added conditional compilation directives.\r
-       + Extended API.\r
-       + Rearranged function order.\r
-       + Creating a task now causes a context switch if the task being created\r
-         has a higher priority than the calling task - assuming the kernel is\r
-         running.\r
-       + vTaskDelete() now only causes a context switch if the calling task is\r
-         the task being deleted.\r
-\r
-Changes from V2.0.0\r
-\r
-       + Allow the type of the tick count to be 16 or 32 bits.\r
-       + Introduce xPendingReadyList feature to allow the time interrupts have to\r
-         be disabled to be minimised.\r
-       + Remove the #if( INCLUDE_vTaskSuspendAll ) statements.  vTaskSuspendAll()\r
-         is now always included as it is used by the scheduler itself.\r
-\r
-Changes from V2.1.0\r
-\r
-       + Bug fix - pxCurrentTCB is now initialised before the call to\r
-         prvInitializeTaskLists().  Previously pxCurrentTCB could be accessed\r
-         while null.\r
-\r
-Changed from V2.1.1\r
-\r
-       + Change to where lStackSize is declared within sTaskCreate() to prevent\r
-         compiler warnings with 8051 port.\r
-\r
-Changes from V2.2.0\r
-\r
-       + Explicit use of 'signed' qualifier on portCHAR types added.\r
-       + Changed odd calculation of initial pxTopOfStack value when\r
-         portSTACK_GROWTH < 0.\r
-       + Removed pcVersionNumber definition.\r
-\r
-Changes from V2.5.3\r
-\r
-       + cTaskResumeAll() modified to ensure it can be called prior to the task\r
-         lists being initialised.\r
-\r
-Changes from V2.5.5\r
-\r
-       + Added API function vTaskDelayUntil().\r
-       + Added INCLUDE_vTaskDelay conditional compilation.\r
-\r
-Changes from V2.6.0\r
-\r
-       + Updated the vWriteTraceToBuffer macro to always be 4 byte aligned so it\r
-         can be used on ARM architectures.\r
-       + tskMAX_TASK_NAME_LEN definition replaced with the port specific\r
-         configMAX_TASK_NAME_LEN definition.\r
-       + Removed the call to strcpy when copying across the task name into the\r
-         TCB.\r
-       + Added ucTasksDeleted variable to prevent vTaskSuspendAll() being called\r
-         too often in the idle task.\r
-\r
-Changes between V3.0.0 and V2.6.1\r
-\r
-       + When resuming the scheduler a yield is performed if either a tick has\r
-         been missed, or a task is moved from the pending ready list into a ready\r
-         list.  Previously a yield was not performed on this second condition.\r
-       + Introduced the type portBASE_TYPE.  This necessitates several API\r
-         changes.\r
-       + Removed the sUsingPreemption variable.  The constant defined in\r
-         portmacro.h is now used directly.\r
-       + The idle task can now include an optional hook function - and no longer\r
-         completes its time slice if other tasks with equal priority to it are\r
-         ready to run.\r
-       + See the FreeRTOS.org documentation for more information on V2.x.x to\r
-         V3.x.x modifications.\r
-\r
-Changes from V3.1.1\r
-\r
-       + Modified vTaskPrioritySet() and vTaskResume() to allow these functions to\r
-         be called while the scheduler is suspended.\r
-       + Corrected the task ordering within event lists.\r
-\r
-Changes from V3.2.0\r
-\r
-       + Added function xTaskGetCurrentTaskHandle().\r
-\r
-Changes from V3.2.4\r
-\r
-       + Changed the volatile declarations on some variables to reflect the \r
-         changes to the list definitions.\r
-       + Changed the order of the TCB definition so there is commonality between\r
-         the task control block and a co-routine control block.\r
-       + Allow the scheduler to be started even if no tasks other than the idle\r
-         task has been created.  This allows co-routines to run even when no tasks\r
-         have been created.\r
-       + The need for a context switch is now signalled if a task woken by an \r
-         event has a priority greater or equal to the currently running task.\r
-         Previously this was only greater than.\r
-\r
-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
-Changes since V4.3.1:\r
-\r
-       + Added xTaskGetSchedulerState() function.\r
-       + Added prvIsTaskSuspended() to take into account the Occurrence of\r
-         vTaskResume() or vTaskResumeFromISR() being called passing in the\r
-         handle of a task that appears in the Suspended list only because it\r
-         is blocked on an event without a timeout being specified.\r
-       + Updated xTaskCheckForTimeout() to take into account that tasks blocked\r
-         using the Suspended list should never time out.\r
-*/\r
 \r
 #include <stdio.h>\r
 #include <stdlib.h>\r
@@ -345,6 +171,8 @@ static volatile portBASE_TYPE xNumOfOverflows                                       = ( portBASE_TYPE ) 0;
 \r
 #endif\r
 \r
+/*-----------------------------------------------------------*/\r
+\r
 /*\r
  * Macro that writes a trace of scheduler activity to a buffer.  This trace\r
  * shows which task is running when and is very useful as a debugging tool.\r
@@ -382,7 +210,7 @@ static volatile portBASE_TYPE xNumOfOverflows                                       = ( portBASE_TYPE ) 0;
        #define vWriteTraceToBuffer()\r
 \r
 #endif\r
-\r
+/*-----------------------------------------------------------*/\r
 \r
 /*\r
  * Place the task represented by pxTCB into the appropriate ready queue for\r
@@ -398,7 +226,8 @@ static volatile portBASE_TYPE xNumOfOverflows                                       = ( portBASE_TYPE ) 0;
                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
@@ -424,9 +253,82 @@ register tskTCB *pxTCB;                                                                                                                                                                                            \
                {                                                                                                                                                                                                                       \\r
                        vListRemove( &( pxTCB->xEventListItem ) );                                                                                                                              \\r
                }                                                                                                                                                                                                                       \\r
-               prvAddTaskToReadyQueue( pxTCB );                                                                                                                \\r
+               prvAddTaskToReadyQueue( pxTCB );                                                                                                                                                        \\r
        }                                                                                                                                                                                                                               \\r
-}                                                                                                                                                                                      \r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+/*\r
+ * Call the stack overflow hook function if the stack of the task being swapped\r
+ * out is currently overflowed, or looks like it might have overflowed in the\r
+ * past.\r
+ *\r
+ * Setting configCHECK_FOR_STACK_OVERFLOW to 1 will cause the macro to check\r
+ * the current stack state only - comparing the current top of stack value to\r
+ * the stack limit.  Setting configCHECK_FOR_STACK_OVERFLOW to greater than 1\r
+ * will also cause the last few stack bytes to be checked to ensure the value\r
+ * to which the bytes were set when the task was created have not been \r
+ * overwritten.  Note this second test does not guarantee that an overflown\r
+ * stack will always be recognised.\r
+ */\r
+\r
+#if( configCHECK_FOR_STACK_OVERFLOW == 0 )\r
+\r
+       /* FreeRTOSConfig.h is not set to check for stack overflows. */\r
+       #define taskCHECK_FOR_STACK_OVERFLOW()\r
+\r
+#endif /* configCHECK_FOR_STACK_OVERFLOW == 0 */\r
+\r
+#if( ( configCHECK_FOR_STACK_OVERFLOW > 0 ) && ( portSTACK_GROWTH >= 0 ) )\r
+\r
+       /* This is an invalid setting. */\r
+       #error configCHECK_FOR_STACK_OVERFLOW can only be set to a non zero value on architectures where the stack grows down from high memory.\r
+\r
+#endif /* ( configCHECK_FOR_STACK_OVERFLOW > 0 ) && ( portSTACK_GROWTH >= 0 ) */\r
+\r
+#if( configCHECK_FOR_STACK_OVERFLOW == 1 )\r
+\r
+       /* Only the current stack state is to be checked. */\r
+       #define taskCHECK_FOR_STACK_OVERFLOW()                                                                                                                          \\r
+       {                                                                                                                                                                                                       \\r
+       extern void vApplicationStackOverflowHook( xTaskHandle *pxTask, signed portCHAR *pcTaskName );          \\r
+                                                                                                                                                                                                               \\r
+               /* Is the currently saved stack pointer within the stack limit? */                                                              \\r
+               if( pxCurrentTCB->pxTopOfStack <= pxCurrentTCB->pxStack )                                                                               \\r
+               {                                                                                                                                                                                               \\r
+                       vApplicationStackOverflowHook( pxCurrentTCB, pxCurrentTCB->pcTaskName );                                        \\r
+               }                                                                                                                                                                                               \\r
+       }\r
+\r
+#endif /* configCHECK_FOR_STACK_OVERFLOW == 1 */\r
+\r
+#if( configCHECK_FOR_STACK_OVERFLOW > 1 )\r
+\r
+       /* Both the current statck state and the stack fill bytes are to be checked. */\r
+       #define taskCHECK_FOR_STACK_OVERFLOW()                                                                                                                                                                                                                  \\r
+       {                                                                                                                                                                                                                                                                                               \\r
+       extern void vApplicationStackOverflowHook( xTaskHandle *pxTask, signed portCHAR *pcTaskName );                                                                                                  \\r
+       static const unsigned portCHAR ucExpectedStackBytes[] = {       tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE,         \\r
+                                                                                                                               tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE,         \\r
+                                                                                                                               tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE,         \\r
+                                                                                                                               tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE,         \\r
+                                                                                                                               tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE };       \\r
+                                                                                                                                                                                                                                                                                                       \\r
+               /* Is the currently saved stack pointer within the stack limit? */                                                                                                                                                      \\r
+               if( pxCurrentTCB->pxTopOfStack <= pxCurrentTCB->pxStack )                                                                                                                                                                       \\r
+               {                                                                                                                                                                                                                                                                                       \\r
+                       vApplicationStackOverflowHook( pxCurrentTCB, pxCurrentTCB->pcTaskName );                                                                                                                                \\r
+               }                                                                                                                                                                                                                                                                                       \\r
+                                                                                                                                                                                                                                                                                                       \\r
+               /* Has the extremity of the task stack ever been written over? */                                                                                                                                                       \\r
+               if( memcmp( pxCurrentTCB->pxStack, ucExpectedStackBytes, sizeof( ucExpectedStackBytes ) ) != 0 )                                                                                        \\r
+               {                                                                                                                                                                                                                                                                                       \\r
+                       vApplicationStackOverflowHook( pxCurrentTCB, pxCurrentTCB->pcTaskName );                                                                                                                                \\r
+               }                                                                                                                                                                                                                                                                                       \\r
+       }\r
+\r
+#endif /* #if( configCHECK_FOR_STACK_OVERFLOW > 1 ) */\r
+/*-----------------------------------------------------------*/\r
 \r
 /*\r
  * Several functions take an xTaskHandle parameter that can optionally be NULL,\r
@@ -508,7 +410,7 @@ static tskTCB *prvAllocateTCBAndStack( unsigned portSHORT usStackDepth );
  * This function determines the 'high water mark' of the task stack by\r
  * determining how much of the stack remains at the original preset value.\r
  */\r
-#if ( ( configUSE_TRACE_FACILITY == 1 ) || ( INCLUDE_uxGetStackHighWaterMark == 1 ) )\r
+#if ( ( configUSE_TRACE_FACILITY == 1 ) || ( INCLUDE_uxTaskGetStackHighWaterMark == 1 ) )\r
 \r
        unsigned portSHORT usTaskCheckFreeStackSpace( const unsigned portCHAR * pucStackByte );\r
 \r
@@ -528,8 +430,6 @@ static tskTCB *prvAllocateTCBAndStack( unsigned portSHORT usStackDepth );
 \r
 \r
 \r
-\r
-\r
 /*-----------------------------------------------------------\r
  * TASK CREATION API documented in task.h\r
  *----------------------------------------------------------*/\r
@@ -663,7 +563,7 @@ tskTCB * pxNewTCB;
 \r
                taskENTER_CRITICAL();\r
                {\r
-                       /* Ensure a yield is performed if the current task is being \r
+                       /* Ensure a yield is performed if the current task is being\r
                        deleted. */\r
                        if( pxTaskToDelete == pxCurrentTCB )\r
                        {\r
@@ -697,7 +597,7 @@ tskTCB * pxNewTCB;
                taskEXIT_CRITICAL();\r
 \r
                /* Force a reschedule if we have just deleted the current task. */\r
-               if( xSchedulerRunning != pdFALSE ) \r
+               if( xSchedulerRunning != pdFALSE )\r
                {\r
                        if( ( void * ) pxTaskToDelete == NULL )\r
                        {\r
@@ -912,7 +812,7 @@ tskTCB * pxNewTCB;
                        {\r
                                /* The priority change may have readied a task of higher\r
                                priority than the calling task. */\r
-                               if( uxNewPriority > uxCurrentPriority ) \r
+                               if( uxNewPriority > uxCurrentPriority )\r
                                {\r
                                        if( pxTask != NULL )\r
                                        {\r
@@ -985,7 +885,7 @@ tskTCB * pxNewTCB;
 \r
                taskENTER_CRITICAL();\r
                {\r
-                       /* Ensure a yield is performed if the current task is being \r
+                       /* Ensure a yield is performed if the current task is being\r
                        suspended. */\r
                        if( pxTaskToSuspend == pxCurrentTCB )\r
                        {\r
@@ -1407,8 +1307,8 @@ inline void vTaskIncrementTick( void )
                {\r
                        xList *pxTemp;\r
 \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
+                       /* 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
@@ -1423,7 +1323,7 @@ inline void vTaskIncrementTick( void )
        {\r
                ++uxMissedTicks;\r
 \r
-               /* The tick hook gets called at regular intervals, even if the \r
+               /* The tick hook gets called at regular intervals, even if the\r
                scheduler is locked. */\r
                #if ( configUSE_TICK_HOOK == 1 )\r
                {\r
@@ -1514,6 +1414,8 @@ void vTaskSwitchContext( void )
                return;\r
        }\r
 \r
+       taskCHECK_FOR_STACK_OVERFLOW();\r
+\r
        /* Find the highest priority queue that contains ready tasks. */\r
        while( listLIST_IS_EMPTY( &( pxReadyTasksLists[ uxTopReadyPriority ] ) ) )\r
        {\r
@@ -1548,7 +1450,7 @@ portTickType xTimeToWake;
 \r
 \r
        #if ( INCLUDE_vTaskSuspend == 1 )\r
-       {                        \r
+       {                       \r
                if( xTicksToWait == portMAX_DELAY )\r
                {\r
                        /* Add ourselves to the suspended task list instead of a delayed task\r
@@ -1933,7 +1835,8 @@ tskTCB *pxNewTCB;
 #endif\r
 /*-----------------------------------------------------------*/\r
 \r
-#if ( ( configUSE_TRACE_FACILITY == 1 ) || ( INCLUDE_uxGetStackHighWaterMark == 1 ) )\r
+#if ( ( configUSE_TRACE_FACILITY == 1 ) || ( INCLUDE_uxTaskGetStackHighWaterMark == 1 ) )\r
+\r
        unsigned portSHORT usTaskCheckFreeStackSpace( const unsigned portCHAR * pucStackByte )\r
        {\r
        register unsigned portSHORT usCount = 0;\r
@@ -1948,14 +1851,17 @@ tskTCB *pxNewTCB;
 \r
                return usCount;\r
        }\r
+\r
 #endif\r
 /*-----------------------------------------------------------*/\r
 \r
-#if ( INCLUDE_uxGetStackHighWaterMark == 1 )\r
-       unsigned portBASE_TYPE uxGetStackHighWaterMark( void )\r
+#if ( INCLUDE_uxTaskGetStackHighWaterMark == 1 )\r
+\r
+       unsigned portBASE_TYPE uxTaskGetStackHighWaterMark( void )\r
        {\r
                return usTaskCheckFreeStackSpace( pxCurrentTCB->pxStack );\r
        }\r
+\r
 #endif\r
 /*-----------------------------------------------------------*/\r
 \r