]> git.sur5r.net Git - freertos/blobdiff - FreeRTOS/Source/tasks.c
Fix potential memory leak in the Win32 FreeRTOS+TCP network interface initialisation...
[freertos] / FreeRTOS / Source / tasks.c
index 75fa4631c67da11771850eac54405294d8eb8490..13aaf135c04f32433086f929bfc21490591ce250 100644 (file)
@@ -1,6 +1,6 @@
 /*\r
- * FreeRTOS Kernel V10.1.1\r
- * Copyright (C) 2018 Amazon.com, Inc. or its affiliates.  All Rights Reserved.\r
+ * FreeRTOS Kernel V10.2.0\r
+ * Copyright (C) 2019 Amazon.com, Inc. or its affiliates.  All Rights Reserved.\r
  *\r
  * Permission is hereby granted, free of charge, to any person obtaining a copy of\r
  * this software and associated documentation files (the "Software"), to deal in\r
@@ -75,24 +75,7 @@ functions but without including stdio.h here. */
  */\r
 #define tskSTACK_FILL_BYTE     ( 0xa5U )\r
 \r
-/* Sometimes the FreeRTOSConfig.h settings only allow a task to be created using\r
-dynamically allocated RAM, in which case when any task is deleted it is known\r
-that both the task's stack and TCB need to be freed.  Sometimes the\r
-FreeRTOSConfig.h settings only allow a task to be created using statically\r
-allocated RAM, in which case when any task is deleted it is known that neither\r
-the task's stack or TCB should be freed.  Sometimes the FreeRTOSConfig.h\r
-settings allow a task to be created using either statically or dynamically\r
-allocated RAM, in which case a member of the TCB is used to record whether the\r
-stack and/or TCB were allocated statically or dynamically, so when a task is\r
-deleted the RAM that was allocated dynamically is freed again and no attempt is\r
-made to free the RAM that was allocated statically.\r
-tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE is only true if it is possible for a\r
-task to be created using either statically or dynamically allocated RAM.  Note\r
-that if portUSING_MPU_WRAPPERS is 1 then a protected task can be created with\r
-a statically allocated stack and a dynamically allocated TCB.\r
-!!!NOTE!!! If the definition of tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE is\r
-changed then the definition of StaticTask_t must also be updated. */\r
-#define tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE      ( ( configSUPPORT_STATIC_ALLOCATION == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) )\r
+/* Bits used to recored how a task's stack and TCB were allocated. */\r
 #define tskDYNAMICALLY_ALLOCATED_STACK_AND_TCB                 ( ( uint8_t ) 0 )\r
 #define tskSTATICALLY_ALLOCATED_STACK_ONLY                     ( ( uint8_t ) 1 )\r
 #define tskSTATICALLY_ALLOCATED_STACK_AND_TCB          ( ( uint8_t ) 2 )\r
@@ -326,7 +309,7 @@ typedef struct tskTaskControlBlock                  /* The old naming convention is used to pr
                volatile uint8_t ucNotifyState;\r
        #endif\r
 \r
-       /* See the comments above the definition of\r
+       /* See the comments in FreeRTOS.h with the definition of\r
        tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE. */\r
        #if( tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE != 0 ) /*lint !e731 !e9029 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
@@ -631,7 +614,7 @@ static void prvAddNewTaskToReadyList( TCB_t *pxNewTCB ) PRIVILEGED_FUNCTION;
                                task was created statically in case the task is later deleted. */\r
                                pxNewTCB->ucStaticallyAllocated = tskSTATICALLY_ALLOCATED_STACK_AND_TCB;\r
                        }\r
-                       #endif /* configSUPPORT_DYNAMIC_ALLOCATION */\r
+                       #endif /* tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE */\r
 \r
                        prvInitialiseNewTask( pxTaskCode, pcName, ulStackDepth, pvParameters, uxPriority, &xReturn, pxNewTCB, NULL );\r
                        prvAddNewTaskToReadyList( pxNewTCB );\r
@@ -673,7 +656,7 @@ static void prvAddNewTaskToReadyList( TCB_t *pxNewTCB ) PRIVILEGED_FUNCTION;
                                task was created statically in case the task is later deleted. */\r
                                pxNewTCB->ucStaticallyAllocated = tskSTATICALLY_ALLOCATED_STACK_AND_TCB;\r
                        }\r
-                       #endif /* configSUPPORT_DYNAMIC_ALLOCATION */\r
+                       #endif /* tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE */\r
 \r
                        prvInitialiseNewTask(   pxTaskDefinition->pvTaskCode,\r
                                                                        pxTaskDefinition->pcName,\r
@@ -714,14 +697,14 @@ static void prvAddNewTaskToReadyList( TCB_t *pxNewTCB ) PRIVILEGED_FUNCTION;
                                /* Store the stack location in the TCB. */\r
                                pxNewTCB->pxStack = pxTaskDefinition->puxStackBuffer;\r
 \r
-                               #if( configSUPPORT_STATIC_ALLOCATION == 1 )\r
+                               #if( tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE != 0 )\r
                                {\r
                                        /* Tasks can be created statically or dynamically, so note\r
                                        this task had a statically allocated stack in case it is\r
                                        later deleted.  The TCB was allocated dynamically. */\r
                                        pxNewTCB->ucStaticallyAllocated = tskSTATICALLY_ALLOCATED_STACK_ONLY;\r
                                }\r
-                               #endif\r
+                               #endif /* tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE */\r
 \r
                                prvInitialiseNewTask(   pxTaskDefinition->pvTaskCode,\r
                                                                                pxTaskDefinition->pcName,\r
@@ -818,7 +801,7 @@ static void prvAddNewTaskToReadyList( TCB_t *pxNewTCB ) PRIVILEGED_FUNCTION;
                                task was created dynamically in case it is later deleted. */\r
                                pxNewTCB->ucStaticallyAllocated = tskDYNAMICALLY_ALLOCATED_STACK_AND_TCB;\r
                        }\r
-                       #endif /* configSUPPORT_STATIC_ALLOCATION */\r
+                       #endif /* tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE */\r
 \r
                        prvInitialiseNewTask( pxTaskCode, pcName, ( uint32_t ) usStackDepth, pvParameters, uxPriority, pxCreatedTask, pxNewTCB, NULL );\r
                        prvAddNewTaskToReadyList( pxNewTCB );\r
@@ -1027,11 +1010,49 @@ UBaseType_t x;
        the top of stack variable is updated. */\r
        #if( portUSING_MPU_WRAPPERS == 1 )\r
        {\r
-               pxNewTCB->pxTopOfStack = pxPortInitialiseStack( pxTopOfStack, pxTaskCode, pvParameters, xRunPrivileged );\r
+               /* If the port has capability to detect stack overflow,\r
+               pass the stack end address to the stack initialization\r
+               function as well. */\r
+               #if( portHAS_STACK_OVERFLOW_CHECKING == 1 )\r
+               {\r
+                       #if( portSTACK_GROWTH < 0 )\r
+                       {\r
+                               pxNewTCB->pxTopOfStack = pxPortInitialiseStack( pxTopOfStack, pxNewTCB->pxStack, pxTaskCode, pvParameters, xRunPrivileged );\r
+                       }\r
+                       #else /* portSTACK_GROWTH */\r
+                       {\r
+                               pxNewTCB->pxTopOfStack = pxPortInitialiseStack( pxTopOfStack, pxNewTCB->pxEndOfStack, pxTaskCode, pvParameters, xRunPrivileged );\r
+                       }\r
+                       #endif /* portSTACK_GROWTH */\r
+               }\r
+               #else /* portHAS_STACK_OVERFLOW_CHECKING */\r
+               {\r
+                       pxNewTCB->pxTopOfStack = pxPortInitialiseStack( pxTopOfStack, pxTaskCode, pvParameters, xRunPrivileged );\r
+               }\r
+               #endif /* portHAS_STACK_OVERFLOW_CHECKING */\r
        }\r
        #else /* portUSING_MPU_WRAPPERS */\r
        {\r
-               pxNewTCB->pxTopOfStack = pxPortInitialiseStack( pxTopOfStack, pxTaskCode, pvParameters );\r
+               /* If the port has capability to detect stack overflow,\r
+               pass the stack end address to the stack initialization\r
+               function as well. */\r
+               #if( portHAS_STACK_OVERFLOW_CHECKING == 1 )\r
+               {\r
+                       #if( portSTACK_GROWTH < 0 )\r
+                       {\r
+                               pxNewTCB->pxTopOfStack = pxPortInitialiseStack( pxTopOfStack, pxNewTCB->pxStack, pxTaskCode, pvParameters );\r
+                       }\r
+                       #else /* portSTACK_GROWTH */\r
+                       {\r
+                               pxNewTCB->pxTopOfStack = pxPortInitialiseStack( pxTopOfStack, pxNewTCB->pxEndOfStack, pxTaskCode, pvParameters );\r
+                       }\r
+                       #endif /* portSTACK_GROWTH */\r
+               }\r
+               #else /* portHAS_STACK_OVERFLOW_CHECKING */\r
+               {\r
+                       pxNewTCB->pxTopOfStack = pxPortInitialiseStack( pxTopOfStack, pxTaskCode, pvParameters );\r
+               }\r
+               #endif /* portHAS_STACK_OVERFLOW_CHECKING */\r
        }\r
        #endif /* portUSING_MPU_WRAPPERS */\r
 \r
@@ -1352,7 +1373,7 @@ static void prvAddNewTaskToReadyList( TCB_t *pxNewTCB )
 #endif /* INCLUDE_vTaskDelay */\r
 /*-----------------------------------------------------------*/\r
 \r
-#if( ( INCLUDE_eTaskGetState == 1 ) || ( configUSE_TRACE_FACILITY == 1 ) )\r
+#if( ( INCLUDE_eTaskGetState == 1 ) || ( configUSE_TRACE_FACILITY == 1 ) || ( INCLUDE_xTaskAbortDelay == 1 ) )\r
 \r
        eTaskState eTaskGetState( TaskHandle_t xTask )\r
        {\r
@@ -2083,6 +2104,7 @@ void vTaskSuspendAll( void )
        post in the FreeRTOS support forum before reporting this as a bug! -\r
        http://goo.gl/wu4acr */\r
        ++uxSchedulerSuspended;\r
+       portMEMORY_BARRIER();\r
 }\r
 /*----------------------------------------------------------*/\r
 \r
@@ -2937,28 +2959,28 @@ void vTaskSwitchContext( void )
 \r
                #if ( configGENERATE_RUN_TIME_STATS == 1 )\r
                {\r
-                               #ifdef portALT_GET_RUN_TIME_COUNTER_VALUE\r
-                                       portALT_GET_RUN_TIME_COUNTER_VALUE( ulTotalRunTime );\r
-                               #else\r
-                                       ulTotalRunTime = portGET_RUN_TIME_COUNTER_VALUE();\r
-                               #endif\r
+                       #ifdef portALT_GET_RUN_TIME_COUNTER_VALUE\r
+                               portALT_GET_RUN_TIME_COUNTER_VALUE( ulTotalRunTime );\r
+                       #else\r
+                               ulTotalRunTime = portGET_RUN_TIME_COUNTER_VALUE();\r
+                       #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
-                               stored in ulTaskSwitchedInTime.  Note that there is no overflow\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
-                               if( ulTotalRunTime > ulTaskSwitchedInTime )\r
-                               {\r
-                                       pxCurrentTCB->ulRunTimeCounter += ( ulTotalRunTime - ulTaskSwitchedInTime );\r
-                               }\r
-                               else\r
-                               {\r
-                                       mtCOVERAGE_TEST_MARKER();\r
-                               }\r
-                               ulTaskSwitchedInTime = ulTotalRunTime;\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
+                       stored in ulTaskSwitchedInTime.  Note that there is no overflow\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
+                       if( ulTotalRunTime > ulTaskSwitchedInTime )\r
+                       {\r
+                               pxCurrentTCB->ulRunTimeCounter += ( ulTotalRunTime - ulTaskSwitchedInTime );\r
+                       }\r
+                       else\r
+                       {\r
+                               mtCOVERAGE_TEST_MARKER();\r
+                       }\r
+                       ulTaskSwitchedInTime = ulTotalRunTime;\r
                }\r
                #endif /* configGENERATE_RUN_TIME_STATS */\r
 \r
@@ -3095,6 +3117,20 @@ BaseType_t xReturn;
        {\r
                ( void ) uxListRemove( &( pxUnblockedTCB->xStateListItem ) );\r
                prvAddTaskToReadyList( pxUnblockedTCB );\r
+\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 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
+                       ensure it is updated at the earliest possible time. */\r
+                       prvResetNextTaskUnblockTime();\r
+               }\r
+               #endif\r
        }\r
        else\r
        {\r
@@ -3119,20 +3155,6 @@ BaseType_t xReturn;
                xReturn = pdFALSE;\r
        }\r
 \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 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
-               ensure it is updated at the earliest possible time. */\r
-               prvResetNextTaskUnblockTime();\r
-       }\r
-       #endif\r
-\r
        return xReturn;\r
 }\r
 /*-----------------------------------------------------------*/\r
@@ -3320,7 +3342,7 @@ static portTASK_FUNCTION( prvIdleTask, pvParameters )
        /* In case a task that has a secure context deletes itself, in which case\r
        the idle task is responsible for deleting the task's secure context, if\r
        any. */\r
-       portTASK_CALLS_SECURE_FUNCTIONS();\r
+       portALLOCATE_SECURE_CONTEXT( configMINIMAL_SECURE_STACK_SIZE );\r
 \r
        for( ;; )\r
        {\r
@@ -5048,6 +5070,13 @@ TickType_t uxReturn;
 #endif /* configUSE_TASK_NOTIFICATIONS */\r
 /*-----------------------------------------------------------*/\r
 \r
+#if( ( configGENERATE_RUN_TIME_STATS == 1 ) && ( INCLUDE_xTaskGetIdleTaskHandle == 1 ) )\r
+       TickType_t xTaskGetIdleRunTimeCounter( void )\r
+       {\r
+               return xIdleTaskHandle->ulRunTimeCounter;\r
+       }\r
+#endif\r
+/*-----------------------------------------------------------*/\r
 \r
 static void prvAddCurrentTaskToDelayedList( TickType_t xTicksToWait, const BaseType_t xCanBlockIndefinitely )\r
 {\r