]> git.sur5r.net Git - freertos/blobdiff - FreeRTOS/Source/tasks.c
Introduce configRECORD_STACK_HIGH_ADDRESS, which when set will result in both limits...
[freertos] / FreeRTOS / Source / tasks.c
index 8aea1cd9155284522fbdf8c3100fcd02093a0c3b..ec08e448dbd43e3d2d81d52d957bb6b21763b714 100644 (file)
@@ -137,6 +137,15 @@ a statically allocated stack and a dynamically allocated TCB. */
 #define tskSTATICALLY_ALLOCATED_STACK_ONLY                     ( ( uint8_t ) 1 )\r
 #define tskSTATICALLY_ALLOCATED_STACK_AND_TCB          ( ( uint8_t ) 2 )\r
 \r
+/* If any of the following are set then task stacks are filled with a known\r
+value so the high water mark can be determined.  If none of the following are\r
+set then don't fill the stack so there is no unnecessary dependency on memset. */\r
+#if( ( configCHECK_FOR_STACK_OVERFLOW > 1 ) || ( configUSE_TRACE_FACILITY == 1 ) || ( INCLUDE_uxTaskGetStackHighWaterMark == 1 ) )\r
+       #define tskSET_NEW_STACKS_TO_KNOWN_VALUE        1\r
+#else\r
+       #define tskSET_NEW_STACKS_TO_KNOWN_VALUE        0\r
+#endif\r
+\r
 /*\r
  * Macros used by vListTask to indicate which state a task is in.\r
  */\r
@@ -304,8 +313,8 @@ typedef struct tskTaskControlBlock
        StackType_t                     *pxStack;                       /*< Points to the start of the stack. */\r
        char                            pcTaskName[ configMAX_TASK_NAME_LEN ];/*< Descriptive name given to the task when created.  Facilitates debugging only. */ /*lint !e971 Unqualified char types are allowed for strings and single characters only. */\r
 \r
-       #if ( portSTACK_GROWTH > 0 )\r
-               StackType_t             *pxEndOfStack;          /*< Points to the end of the stack on architectures where the stack grows up from low memory. */\r
+       #if ( ( portSTACK_GROWTH > 0 ) || ( configRECORD_STACK_HIGH_ADDRESS == 1 ) )\r
+               StackType_t             *pxEndOfStack;          /*< Points to the highest valid address for the stack. */\r
        #endif\r
 \r
        #if ( portCRITICAL_NESTING_IN_TCB == 1 )\r
@@ -327,7 +336,7 @@ typedef struct tskTaskControlBlock
        #endif\r
 \r
        #if( configNUM_THREAD_LOCAL_STORAGE_POINTERS > 0 )\r
-               void *pvThreadLocalStoragePointers[ configNUM_THREAD_LOCAL_STORAGE_POINTERS ];\r
+               void                    *pvThreadLocalStoragePointers[ configNUM_THREAD_LOCAL_STORAGE_POINTERS ];\r
        #endif\r
 \r
        #if( configGENERATE_RUN_TIME_STATS == 1 )\r
@@ -352,7 +361,7 @@ typedef struct tskTaskControlBlock
 \r
        /* See the comments above the definition of\r
        tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE. */\r
-       #if( tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE != 0 )\r
+       #if( tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE != 0 ) /*lint !e731 Macro has been consolidated for readability reasons. */\r
                uint8_t ucStaticallyAllocated;          /*< Set to pdTRUE if the task is a statically allocated to ensure no attempt is made to free the memory. */\r
        #endif\r
 \r
@@ -366,8 +375,8 @@ typedef struct tskTaskControlBlock
 below to enable the use of older kernel aware debuggers. */\r
 typedef tskTCB TCB_t;\r
 \r
-/*lint -e956 A manual analysis and inspection has been used to determine which\r
-static variables must be declared volatile. */\r
+/*lint -save -e956 A manual analysis and inspection has been used to determine\r
+which static variables must be declared volatile. */\r
 \r
 PRIVILEGED_DATA TCB_t * volatile pxCurrentTCB = NULL;\r
 \r
@@ -421,7 +430,7 @@ PRIVILEGED_DATA static volatile UBaseType_t uxSchedulerSuspended    = ( UBaseType_t
 \r
 #endif\r
 \r
-/*lint +e956 */\r
+/*lint -restore */\r
 \r
 /*-----------------------------------------------------------*/\r
 \r
@@ -565,13 +574,13 @@ static void prvResetNextTaskUnblockTime( void );
  * dynamically to fill in the structure's members.\r
  */\r
 static void prvInitialiseNewTask(      TaskFunction_t pxTaskCode,\r
-                                                                       const char * const pcName,\r
+                                                                       const char * const pcName,              /*lint !e971 Unqualified char types are allowed for strings and single characters only. */\r
                                                                        const uint32_t ulStackDepth,\r
                                                                        void * const pvParameters,\r
                                                                        UBaseType_t uxPriority,\r
                                                                        TaskHandle_t * const pxCreatedTask,\r
                                                                        TCB_t *pxNewTCB,\r
-                                                                       const MemoryRegion_t * const xRegions ) PRIVILEGED_FUNCTION; /*lint !e971 Unqualified char types are allowed for strings and single characters only. */\r
+                                                                       const MemoryRegion_t * const xRegions ) PRIVILEGED_FUNCTION;\r
 \r
 /*\r
  * Called after a new task has been created and initialised to place the task\r
@@ -584,12 +593,12 @@ static void prvAddNewTaskToReadyList( TCB_t *pxNewTCB ) PRIVILEGED_FUNCTION;
 #if( configSUPPORT_STATIC_ALLOCATION == 1 )\r
 \r
        TaskHandle_t xTaskCreateStatic( TaskFunction_t pxTaskCode,\r
-                                                                       const char * const pcName,\r
+                                                                       const char * const pcName,              /*lint !e971 Unqualified char types are allowed for strings and single characters only. */\r
                                                                        const uint32_t ulStackDepth,\r
                                                                        void * const pvParameters,\r
                                                                        UBaseType_t uxPriority,\r
                                                                        StackType_t * const puxStackBuffer,\r
-                                                                       StaticTask_t * const pxTaskBuffer ) /*lint !e971 Unqualified char types are allowed for strings and single characters only. */\r
+                                                                       StaticTask_t * const pxTaskBuffer )\r
        {\r
        TCB_t *pxNewTCB;\r
        TaskHandle_t xReturn;\r
@@ -604,7 +613,7 @@ static void prvAddNewTaskToReadyList( TCB_t *pxNewTCB ) PRIVILEGED_FUNCTION;
                        pxNewTCB = ( TCB_t * ) pxTaskBuffer; /*lint !e740 Unusual cast is ok as the structures are designed to have the same alignment, and the size is checked by an assert. */\r
                        pxNewTCB->pxStack = ( StackType_t * ) puxStackBuffer;\r
 \r
-                       #if( tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE != 0 )\r
+                       #if( tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE != 0 ) /*lint !e731 Macro has been consolidated for readability reasons. */\r
                        {\r
                                /* Tasks can be created statically or dynamically, so note this\r
                                task was created statically in case the task is later deleted. */\r
@@ -674,11 +683,11 @@ static void prvAddNewTaskToReadyList( TCB_t *pxNewTCB ) PRIVILEGED_FUNCTION;
 #if( configSUPPORT_DYNAMIC_ALLOCATION == 1 )\r
 \r
        BaseType_t xTaskCreate( TaskFunction_t pxTaskCode,\r
-                                                       const char * const pcName,\r
+                                                       const char * const pcName,              /*lint !e971 Unqualified char types are allowed for strings and single characters only. */\r
                                                        const uint16_t usStackDepth,\r
                                                        void * const pvParameters,\r
                                                        UBaseType_t uxPriority,\r
-                                                       TaskHandle_t * const pxCreatedTask ) /*lint !e971 Unqualified char types are allowed for strings and single characters only. */\r
+                                                       TaskHandle_t * const pxCreatedTask )\r
        {\r
        TCB_t *pxNewTCB;\r
        BaseType_t xReturn;\r
@@ -741,7 +750,7 @@ static void prvAddNewTaskToReadyList( TCB_t *pxNewTCB ) PRIVILEGED_FUNCTION;
 \r
                if( pxNewTCB != NULL )\r
                {\r
-                       #if( tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE != 0 )\r
+                       #if( tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE != 0 ) /*lint !e731 Macro has been consolidated for readability reasons. */\r
                        {\r
                                /* Tasks can be created statically or dynamically, so note this\r
                                task was created dynamically in case it is later deleted. */\r
@@ -765,13 +774,13 @@ static void prvAddNewTaskToReadyList( TCB_t *pxNewTCB ) PRIVILEGED_FUNCTION;
 /*-----------------------------------------------------------*/\r
 \r
 static void prvInitialiseNewTask(      TaskFunction_t pxTaskCode,\r
-                                                                       const char * const pcName,\r
+                                                                       const char * const pcName,              /*lint !e971 Unqualified char types are allowed for strings and single characters only. */\r
                                                                        const uint32_t ulStackDepth,\r
                                                                        void * const pvParameters,\r
                                                                        UBaseType_t uxPriority,\r
                                                                        TaskHandle_t * const pxCreatedTask,\r
                                                                        TCB_t *pxNewTCB,\r
-                                                                       const MemoryRegion_t * const xRegions ) /*lint !e971 Unqualified char types are allowed for strings and single characters only. */\r
+                                                                       const MemoryRegion_t * const xRegions )\r
 {\r
 StackType_t *pxTopOfStack;\r
 UBaseType_t x;\r
@@ -791,12 +800,12 @@ UBaseType_t x;
        #endif /* portUSING_MPU_WRAPPERS == 1 */\r
 \r
        /* Avoid dependency on memset() if it is not required. */\r
-       #if( ( configCHECK_FOR_STACK_OVERFLOW > 1 ) || ( configUSE_TRACE_FACILITY == 1 ) || ( INCLUDE_uxTaskGetStackHighWaterMark == 1 ) )\r
+       #if( tskSET_NEW_STACKS_TO_KNOWN_VALUE == 1 )\r
        {\r
                /* Fill the stack with a known value to assist debugging. */\r
                ( void ) memset( pxNewTCB->pxStack, ( int ) tskSTACK_FILL_BYTE, ( size_t ) ulStackDepth * sizeof( StackType_t ) );\r
        }\r
-       #endif /* ( ( configCHECK_FOR_STACK_OVERFLOW > 1 ) || ( ( configUSE_TRACE_FACILITY == 1 ) || ( INCLUDE_uxTaskGetStackHighWaterMark == 1 ) ) ) */\r
+       #endif /* tskSET_NEW_STACKS_TO_KNOWN_VALUE */\r
 \r
        /* Calculate the top of stack address.  This depends on whether the stack\r
        grows from high memory to low (as per the 80x86) or vice versa.\r
@@ -809,6 +818,14 @@ UBaseType_t x;
 \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
+\r
+               #if( configRECORD_STACK_HIGH_ADDRESS == 1 )\r
+               {\r
+                       /* Also record the stack's high address, which may assist\r
+                       debugging. */\r
+                       pxNewTCB->pxEndOfStack = pxTopOfStack;\r
+               }\r
+               #endif /* configRECORD_STACK_HIGH_ADDRESS */\r
        }\r
        #else /* portSTACK_GROWTH */\r
        {\r
@@ -936,7 +953,7 @@ UBaseType_t x;
        /* Initialize the TCB stack to look as if the task was already running,\r
        but had been interrupted by the scheduler.  The return address is set\r
        to the start of the task function. Once the stack has been initialised\r
-       the     top of stack variable is updated. */\r
+       the top of stack variable is updated. */\r
        #if( portUSING_MPU_WRAPPERS == 1 )\r
        {\r
                pxNewTCB->pxTopOfStack = pxPortInitialiseStack( pxTopOfStack, pxTaskCode, pvParameters, xRunPrivileged );\r
@@ -1672,7 +1689,7 @@ static void prvAddNewTaskToReadyList( TCB_t *pxNewTCB )
                        {\r
                                /* Is it in the suspended list because it is in the     Suspended\r
                                state, or because is is blocked with no timeout? */\r
-                               if( listIS_CONTAINED_WITHIN( NULL, &( pxTCB->xEventListItem ) ) != pdFALSE )\r
+                               if( listIS_CONTAINED_WITHIN( NULL, &( pxTCB->xEventListItem ) ) != pdFALSE ) /*lint !e961.  The cast is only redundant when NULL is used. */\r
                                {\r
                                        xReturn = pdTRUE;\r
                                }\r
@@ -1840,7 +1857,7 @@ BaseType_t xReturn;
                xIdleTaskHandle = xTaskCreateStatic(    prvIdleTask,\r
                                                                                                "IDLE",\r
                                                                                                ulIdleTaskStackSize,\r
-                                                                                               ( void * ) NULL,\r
+                                                                                               ( void * ) NULL, /*lint !e961.  The cast is not redundant for all compilers. */\r
                                                                                                ( tskIDLE_PRIORITY | portPRIVILEGE_BIT ),\r
                                                                                                pxIdleTaskStackBuffer,\r
                                                                                                pxIdleTaskTCBBuffer ); /*lint !e961 MISRA exception, justified as it is not a redundant explicit cast to all supported compilers. */\r
@@ -1901,7 +1918,10 @@ BaseType_t xReturn;
 \r
                /* If configGENERATE_RUN_TIME_STATS is defined then the following\r
                macro must be defined to configure the timer/counter used to generate\r
-               the run time counter time base. */\r
+               the run time counter time base.   NOTE:  If configGENERATE_RUN_TIME_STATS\r
+               is set to 0 and the following line fails to build then ensure you do not\r
+               have portCONFIGURE_TIMER_FOR_RUN_TIME_STATS() defined in your\r
+               FreeRTOSConfig.h file. */\r
                portCONFIGURE_TIMER_FOR_RUN_TIME_STATS();\r
 \r
                /* Setting up the timer tick is hardware specific and thus in the\r
@@ -2488,7 +2508,7 @@ implementations require configUSE_TICKLESS_IDLE to be set to a value other than
                                mtCOVERAGE_TEST_MARKER();\r
                        }\r
                }\r
-               xTaskResumeAll();\r
+               ( void ) xTaskResumeAll();\r
 \r
                return xReturn;\r
        }\r
@@ -2510,13 +2530,13 @@ BaseType_t xSwitchRequired = pdFALSE;
        {\r
                /* Minor optimisation.  The tick count cannot change in this\r
                block. */\r
-               const TickType_t xConstTickCount = xTickCount + 1;\r
+               const TickType_t xConstTickCount = xTickCount + ( TickType_t ) 1;\r
 \r
                /* Increment the RTOS tick, switching the delayed and overflowed\r
                delayed lists if it wraps to 0. */\r
                xTickCount = xConstTickCount;\r
 \r
-               if( xConstTickCount == ( TickType_t ) 0U )\r
+               if( xConstTickCount == ( TickType_t ) 0U ) /*lint !e774 'if' does not always evaluate to false as it is looking for an overflow. */\r
                {\r
                        taskSWITCH_DELAYED_LISTS();\r
                }\r
@@ -2959,10 +2979,9 @@ BaseType_t xReturn;
 }\r
 /*-----------------------------------------------------------*/\r
 \r
-BaseType_t xTaskRemoveFromUnorderedEventList( ListItem_t * pxEventListItem, const TickType_t xItemValue )\r
+void vTaskRemoveFromUnorderedEventList( ListItem_t * pxEventListItem, const TickType_t xItemValue )\r
 {\r
 TCB_t *pxUnblockedTCB;\r
-BaseType_t xReturn;\r
 \r
        /* THIS FUNCTION MUST BE CALLED WITH THE SCHEDULER SUSPENDED.  It is used by\r
        the event flags implementation. */\r
@@ -2985,22 +3004,12 @@ BaseType_t xReturn;
 \r
        if( pxUnblockedTCB->uxPriority > pxCurrentTCB->uxPriority )\r
        {\r
-               /* Return true if the task removed from the event list has\r
-               a higher priority than the calling task.  This allows\r
-               the calling task to know if it should force a context\r
-               switch now. */\r
-               xReturn = pdTRUE;\r
-\r
-               /* Mark that a yield is pending in case the user is not using the\r
-               "xHigherPriorityTaskWoken" parameter to an ISR safe FreeRTOS function. */\r
+               /* The unblocked task has a priority above that of the calling task, so\r
+               a context switch is required.  This function is called with the\r
+               scheduler suspended so xYieldPending is set so the context switch\r
+               occurs immediately that the scheduler is resumed (unsuspended). */\r
                xYieldPending = pdTRUE;\r
        }\r
-       else\r
-       {\r
-               xReturn = pdFALSE;\r
-       }\r
-\r
-       return xReturn;\r
 }\r
 /*-----------------------------------------------------------*/\r
 \r
@@ -3435,7 +3444,7 @@ static void prvCheckTasksWaitingTermination( void )
                                                pxTaskStatus->eCurrentState = eBlocked;\r
                                        }\r
                                }\r
-                               xTaskResumeAll();\r
+                               ( void ) xTaskResumeAll();\r
                        }\r
                }\r
                #endif /* INCLUDE_vTaskSuspend */\r
@@ -3499,7 +3508,7 @@ static void prvCheckTasksWaitingTermination( void )
 \r
        static UBaseType_t prvListTasksWithinSingleList( TaskStatus_t *pxTaskStatusArray, List_t *pxList, eTaskState eState )\r
        {\r
-       volatile TCB_t *pxNextTCB, *pxFirstTCB;\r
+       configLIST_VOLATILE TCB_t *pxNextTCB, *pxFirstTCB;\r
        UBaseType_t uxTask = 0;\r
 \r
                if( listCURRENT_LIST_LENGTH( pxList ) > ( UBaseType_t ) 0 )\r
@@ -3600,7 +3609,7 @@ static void prvCheckTasksWaitingTermination( void )
                        vPortFree( pxTCB->pxStack );\r
                        vPortFree( pxTCB );\r
                }\r
-               #elif( tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE == 1 )\r
+               #elif( tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE != 0 ) /*lint !e731 Macro has been consolidated for readability reasons. */\r
                {\r
                        /* The task could have been allocated statically or dynamically, so\r
                        check what was statically allocated before trying to free the\r
@@ -4240,7 +4249,7 @@ TickType_t uxReturn;
                                }\r
                                else\r
                                {\r
-                                       pxCurrentTCB->ulNotifiedValue = ulReturn - 1;\r
+                                       pxCurrentTCB->ulNotifiedValue = ulReturn - ( uint32_t ) 1;\r
                                }\r
                        }\r
                        else\r
@@ -4800,8 +4809,26 @@ const TickType_t xConstTickCount = xTickCount;
        #endif /* INCLUDE_vTaskSuspend */\r
 }\r
 \r
+/* Code below here allows additional code to be inserted into this source file,\r
+especially where access to file scope functions and data is needed (for example\r
+when performing module tests). */\r
 \r
 #ifdef FREERTOS_MODULE_TEST\r
        #include "tasks_test_access_functions.h"\r
 #endif\r
 \r
+\r
+#if( configINCLUDE_FREERTOS_TASK_C_ADDITIONS_H == 1 )\r
+\r
+       #include "freertos_tasks_c_additions.h"\r
+\r
+       static void freertos_tasks_c_additions_init( void )\r
+       {\r
+               #ifdef FREERTOS_TASKS_C_ADDITIONS_INIT\r
+                       FREERTOS_TASKS_C_ADDITIONS_INIT();\r
+               #endif\r
+       }\r
+\r
+#endif\r
+\r
+\r