X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=FreeRTOS%2FSource%2Ftasks.c;h=13aaf135c04f32433086f929bfc21490591ce250;hb=87c1213e45a8d47f4c8023bc302808c3d34c925b;hp=dc022d7b040b6b804363fb2779a1f37397605a9b;hpb=150feff0c902fdfe7268997cc3ce12a193f40cb1;p=freertos diff --git a/FreeRTOS/Source/tasks.c b/FreeRTOS/Source/tasks.c index dc022d7b0..13aaf135c 100644 --- a/FreeRTOS/Source/tasks.c +++ b/FreeRTOS/Source/tasks.c @@ -1,6 +1,6 @@ /* - * FreeRTOS Kernel V10.0.1 - * Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * FreeRTOS Kernel V10.2.0 + * Copyright (C) 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. * * Permission is hereby granted, free of charge, to any person obtaining a copy of * this software and associated documentation files (the "Software"), to deal in @@ -75,24 +75,7 @@ functions but without including stdio.h here. */ */ #define tskSTACK_FILL_BYTE ( 0xa5U ) -/* Sometimes the FreeRTOSConfig.h settings only allow a task to be created using -dynamically allocated RAM, in which case when any task is deleted it is known -that both the task's stack and TCB need to be freed. Sometimes the -FreeRTOSConfig.h settings only allow a task to be created using statically -allocated RAM, in which case when any task is deleted it is known that neither -the task's stack or TCB should be freed. Sometimes the FreeRTOSConfig.h -settings allow a task to be created using either statically or dynamically -allocated RAM, in which case a member of the TCB is used to record whether the -stack and/or TCB were allocated statically or dynamically, so when a task is -deleted the RAM that was allocated dynamically is freed again and no attempt is -made to free the RAM that was allocated statically. -tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE is only true if it is possible for a -task to be created using either statically or dynamically allocated RAM. Note -that if portUSING_MPU_WRAPPERS is 1 then a protected task can be created with -a statically allocated stack and a dynamically allocated TCB. -!!!NOTE!!! If the definition of tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE is -changed then the definition of StaticTask_t must also be updated. */ -#define tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE ( ( configSUPPORT_STATIC_ALLOCATION == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) ) +/* Bits used to recored how a task's stack and TCB were allocated. */ #define tskDYNAMICALLY_ALLOCATED_STACK_AND_TCB ( ( uint8_t ) 0 ) #define tskSTATICALLY_ALLOCATED_STACK_ONLY ( ( uint8_t ) 1 ) #define tskSTATICALLY_ALLOCATED_STACK_AND_TCB ( ( uint8_t ) 2 ) @@ -100,7 +83,7 @@ changed then the definition of StaticTask_t must also be updated. */ /* If any of the following are set then task stacks are filled with a known value so the high water mark can be determined. If none of the following are set then don't fill the stack so there is no unnecessary dependency on memset. */ -#if( ( configCHECK_FOR_STACK_OVERFLOW > 1 ) || ( configUSE_TRACE_FACILITY == 1 ) || ( INCLUDE_uxTaskGetStackHighWaterMark == 1 ) ) +#if( ( configCHECK_FOR_STACK_OVERFLOW > 1 ) || ( configUSE_TRACE_FACILITY == 1 ) || ( INCLUDE_uxTaskGetStackHighWaterMark == 1 ) || ( INCLUDE_uxTaskGetStackHighWaterMark2 == 1 ) ) #define tskSET_NEW_STACKS_TO_KNOWN_VALUE 1 #else #define tskSET_NEW_STACKS_TO_KNOWN_VALUE 0 @@ -266,7 +249,7 @@ to its original value when it is released. */ * and stores task state information, including a pointer to the task's context * (the task's run time environment, including register values) */ -typedef struct TaskControlBlock_t +typedef struct tskTaskControlBlock /* The old naming convention is used to prevent breaking kernel aware debuggers. */ { volatile StackType_t *pxTopOfStack; /*< Points to the location of the last item placed on the tasks stack. THIS MUST BE THE FIRST MEMBER OF THE TCB STRUCT. */ @@ -326,7 +309,7 @@ typedef struct TaskControlBlock_t volatile uint8_t ucNotifyState; #endif - /* See the comments above the definition of + /* See the comments in FreeRTOS.h with the definition of tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE. */ #if( tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE != 0 ) /*lint !e731 !e9029 Macro has been consolidated for readability reasons. */ uint8_t ucStaticallyAllocated; /*< Set to pdTRUE if the task is a statically allocated to ensure no attempt is made to free the memory. */ @@ -336,6 +319,10 @@ typedef struct TaskControlBlock_t uint8_t ucDelayAborted; #endif + #if( configUSE_POSIX_ERRNO == 1 ) + int iTaskErrno; + #endif + } tskTCB; /* The old tskTCB name is maintained above then typedefed to the new TCB_t name @@ -346,8 +333,13 @@ typedef tskTCB TCB_t; which static variables must be declared volatile. */ PRIVILEGED_DATA TCB_t * volatile pxCurrentTCB = NULL; -/* Lists for ready and blocked tasks. --------------------*/ +/* Lists for ready and blocked tasks. -------------------- +xDelayedTaskList1 and xDelayedTaskList2 could be move to function scople but +doing so breaks some kernel aware debuggers and debuggers that rely on removing +the static qualifier. */ PRIVILEGED_DATA static List_t pxReadyTasksLists[ configMAX_PRIORITIES ];/*< Prioritised ready tasks. */ +PRIVILEGED_DATA static List_t xDelayedTaskList1; /*< Delayed tasks. */ +PRIVILEGED_DATA static List_t xDelayedTaskList2; /*< Delayed tasks (two lists are used - one for delays that have overflowed the current tick count. */ PRIVILEGED_DATA static List_t * volatile pxDelayedTaskList; /*< Points to the delayed task list currently being used. */ PRIVILEGED_DATA static List_t * volatile pxOverflowDelayedTaskList; /*< Points to the delayed task list currently being used to hold tasks that have overflowed the current tick count. */ PRIVILEGED_DATA static List_t xPendingReadyList; /*< Tasks that have been readied while the scheduler was suspended. They will be moved to the ready list when the scheduler is resumed. */ @@ -365,6 +357,12 @@ PRIVILEGED_DATA static List_t xPendingReadyList; /*< Tasks that have been r #endif +/* Global POSIX errno. Its value is changed upon context switching to match +the errno of the currently running task. */ +#if ( configUSE_POSIX_ERRNO == 1 ) + int FreeRTOS_errno = 0; +#endif + /* Other file private variables. --------------------------------*/ PRIVILEGED_DATA static volatile UBaseType_t uxCurrentNumberOfTasks = ( UBaseType_t ) 0U; PRIVILEGED_DATA static volatile TickType_t xTickCount = ( TickType_t ) configINITIAL_TICK_COUNT; @@ -387,6 +385,15 @@ when the scheduler is unsuspended. The pending ready list itself can only be accessed from a critical section. */ PRIVILEGED_DATA static volatile UBaseType_t uxSchedulerSuspended = ( UBaseType_t ) pdFALSE; +#if ( configGENERATE_RUN_TIME_STATS == 1 ) + + /* Do not move these variables to function scope as doing so prevents the + code working with debuggers that need to remove the static qualifier. */ + PRIVILEGED_DATA static uint32_t ulTaskSwitchedInTime = 0UL; /*< Holds the value of a timer/counter the last time a task was switched in. */ + PRIVILEGED_DATA static uint32_t ulTotalRunTime = 0UL; /*< Holds the total amount of execution time as defined by the run time counter clock. */ + +#endif + /*lint -restore */ /*-----------------------------------------------------------*/ @@ -497,7 +504,7 @@ static void prvAddCurrentTaskToDelayedList( TickType_t xTicksToWait, const BaseT * This function determines the 'high water mark' of the task stack by * determining how much of the stack remains at the original preset value. */ -#if ( ( configUSE_TRACE_FACILITY == 1 ) || ( INCLUDE_uxTaskGetStackHighWaterMark == 1 ) ) +#if ( ( configUSE_TRACE_FACILITY == 1 ) || ( INCLUDE_uxTaskGetStackHighWaterMark == 1 ) || ( INCLUDE_uxTaskGetStackHighWaterMark2 == 1 ) ) static configSTACK_DEPTH_TYPE prvTaskCheckFreeStackSpace( const uint8_t * pucStackByte ) PRIVILEGED_FUNCTION; @@ -607,7 +614,7 @@ static void prvAddNewTaskToReadyList( TCB_t *pxNewTCB ) PRIVILEGED_FUNCTION; task was created statically in case the task is later deleted. */ pxNewTCB->ucStaticallyAllocated = tskSTATICALLY_ALLOCATED_STACK_AND_TCB; } - #endif /* configSUPPORT_DYNAMIC_ALLOCATION */ + #endif /* tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE */ prvInitialiseNewTask( pxTaskCode, pcName, ulStackDepth, pvParameters, uxPriority, &xReturn, pxNewTCB, NULL ); prvAddNewTaskToReadyList( pxNewTCB ); @@ -649,7 +656,7 @@ static void prvAddNewTaskToReadyList( TCB_t *pxNewTCB ) PRIVILEGED_FUNCTION; task was created statically in case the task is later deleted. */ pxNewTCB->ucStaticallyAllocated = tskSTATICALLY_ALLOCATED_STACK_AND_TCB; } - #endif /* configSUPPORT_DYNAMIC_ALLOCATION */ + #endif /* tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE */ prvInitialiseNewTask( pxTaskDefinition->pvTaskCode, pxTaskDefinition->pcName, @@ -690,14 +697,14 @@ static void prvAddNewTaskToReadyList( TCB_t *pxNewTCB ) PRIVILEGED_FUNCTION; /* Store the stack location in the TCB. */ pxNewTCB->pxStack = pxTaskDefinition->puxStackBuffer; - #if( configSUPPORT_STATIC_ALLOCATION == 1 ) + #if( tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE != 0 ) { /* Tasks can be created statically or dynamically, so note this task had a statically allocated stack in case it is later deleted. The TCB was allocated dynamically. */ pxNewTCB->ucStaticallyAllocated = tskSTATICALLY_ALLOCATED_STACK_ONLY; } - #endif + #endif /* tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE */ prvInitialiseNewTask( pxTaskDefinition->pvTaskCode, pxTaskDefinition->pcName, @@ -794,7 +801,7 @@ static void prvAddNewTaskToReadyList( TCB_t *pxNewTCB ) PRIVILEGED_FUNCTION; task was created dynamically in case it is later deleted. */ pxNewTCB->ucStaticallyAllocated = tskDYNAMICALLY_ALLOCATED_STACK_AND_TCB; } - #endif /* configSUPPORT_STATIC_ALLOCATION */ + #endif /* tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE */ prvInitialiseNewTask( pxTaskCode, pcName, ( uint32_t ) usStackDepth, pvParameters, uxPriority, pxCreatedTask, pxNewTCB, NULL ); prvAddNewTaskToReadyList( pxNewTCB ); @@ -837,8 +844,6 @@ UBaseType_t x; uxPriority &= ~portPRIVILEGE_BIT; #endif /* portUSING_MPU_WRAPPERS == 1 */ - configASSERT( pcName ); - /* Avoid dependency on memset() if it is not required. */ #if( tskSET_NEW_STACKS_TO_KNOWN_VALUE == 1 ) { @@ -881,26 +886,35 @@ UBaseType_t x; #endif /* portSTACK_GROWTH */ /* Store the task name in the TCB. */ - for( x = ( UBaseType_t ) 0; x < ( UBaseType_t ) configMAX_TASK_NAME_LEN; x++ ) + if( pcName != NULL ) { - pxNewTCB->pcTaskName[ x ] = pcName[ x ]; - - /* Don't copy all configMAX_TASK_NAME_LEN if the string is shorter than - configMAX_TASK_NAME_LEN characters just in case the memory after the - string is not accessible (extremely unlikely). */ - if( pcName[ x ] == ( char ) 0x00 ) - { - break; - } - else + for( x = ( UBaseType_t ) 0; x < ( UBaseType_t ) configMAX_TASK_NAME_LEN; x++ ) { - mtCOVERAGE_TEST_MARKER(); + pxNewTCB->pcTaskName[ x ] = pcName[ x ]; + + /* Don't copy all configMAX_TASK_NAME_LEN if the string is shorter than + configMAX_TASK_NAME_LEN characters just in case the memory after the + string is not accessible (extremely unlikely). */ + if( pcName[ x ] == ( char ) 0x00 ) + { + break; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } } - } - /* Ensure the name string is terminated in the case that the string length - was greater or equal to configMAX_TASK_NAME_LEN. */ - pxNewTCB->pcTaskName[ configMAX_TASK_NAME_LEN - 1 ] = '\0'; + /* Ensure the name string is terminated in the case that the string length + was greater or equal to configMAX_TASK_NAME_LEN. */ + pxNewTCB->pcTaskName[ configMAX_TASK_NAME_LEN - 1 ] = '\0'; + } + else + { + /* The task has not been given a name, so just ensure there is a NULL + terminator when it is read out. */ + pxNewTCB->pcTaskName[ 0 ] = 0x00; + } /* This is used as an array index so must ensure it's not too large. First remove the privilege bit if one is present. */ @@ -996,11 +1010,49 @@ UBaseType_t x; the top of stack variable is updated. */ #if( portUSING_MPU_WRAPPERS == 1 ) { - pxNewTCB->pxTopOfStack = pxPortInitialiseStack( pxTopOfStack, pxTaskCode, pvParameters, xRunPrivileged ); + /* If the port has capability to detect stack overflow, + pass the stack end address to the stack initialization + function as well. */ + #if( portHAS_STACK_OVERFLOW_CHECKING == 1 ) + { + #if( portSTACK_GROWTH < 0 ) + { + pxNewTCB->pxTopOfStack = pxPortInitialiseStack( pxTopOfStack, pxNewTCB->pxStack, pxTaskCode, pvParameters, xRunPrivileged ); + } + #else /* portSTACK_GROWTH */ + { + pxNewTCB->pxTopOfStack = pxPortInitialiseStack( pxTopOfStack, pxNewTCB->pxEndOfStack, pxTaskCode, pvParameters, xRunPrivileged ); + } + #endif /* portSTACK_GROWTH */ + } + #else /* portHAS_STACK_OVERFLOW_CHECKING */ + { + pxNewTCB->pxTopOfStack = pxPortInitialiseStack( pxTopOfStack, pxTaskCode, pvParameters, xRunPrivileged ); + } + #endif /* portHAS_STACK_OVERFLOW_CHECKING */ } #else /* portUSING_MPU_WRAPPERS */ { - pxNewTCB->pxTopOfStack = pxPortInitialiseStack( pxTopOfStack, pxTaskCode, pvParameters ); + /* If the port has capability to detect stack overflow, + pass the stack end address to the stack initialization + function as well. */ + #if( portHAS_STACK_OVERFLOW_CHECKING == 1 ) + { + #if( portSTACK_GROWTH < 0 ) + { + pxNewTCB->pxTopOfStack = pxPortInitialiseStack( pxTopOfStack, pxNewTCB->pxStack, pxTaskCode, pvParameters ); + } + #else /* portSTACK_GROWTH */ + { + pxNewTCB->pxTopOfStack = pxPortInitialiseStack( pxTopOfStack, pxNewTCB->pxEndOfStack, pxTaskCode, pvParameters ); + } + #endif /* portSTACK_GROWTH */ + } + #else /* portHAS_STACK_OVERFLOW_CHECKING */ + { + pxNewTCB->pxTopOfStack = pxPortInitialiseStack( pxTopOfStack, pxTaskCode, pvParameters ); + } + #endif /* portHAS_STACK_OVERFLOW_CHECKING */ } #endif /* portUSING_MPU_WRAPPERS */ @@ -1321,7 +1373,7 @@ static void prvAddNewTaskToReadyList( TCB_t *pxNewTCB ) #endif /* INCLUDE_vTaskDelay */ /*-----------------------------------------------------------*/ -#if( ( INCLUDE_eTaskGetState == 1 ) || ( configUSE_TRACE_FACILITY == 1 ) ) +#if( ( INCLUDE_eTaskGetState == 1 ) || ( configUSE_TRACE_FACILITY == 1 ) || ( INCLUDE_xTaskAbortDelay == 1 ) ) eTaskState eTaskGetState( TaskHandle_t xTask ) { @@ -2052,6 +2104,7 @@ void vTaskSuspendAll( void ) post in the FreeRTOS support forum before reporting this as a bug! - http://goo.gl/wu4acr */ ++uxSchedulerSuspended; + portMEMORY_BARRIER(); } /*----------------------------------------------------------*/ @@ -2814,24 +2867,17 @@ BaseType_t xSwitchRequired = pdFALSE; TaskHookFunction_t xTaskGetApplicationTaskTag( TaskHandle_t xTask ) { - TCB_t *xTCB; + TCB_t *pxTCB; TaskHookFunction_t xReturn; - /* If xTask is NULL then we are setting our own task hook. */ - if( xTask == NULL ) - { - xTCB = ( TCB_t * ) pxCurrentTCB; - } - else - { - xTCB = ( TCB_t * ) xTask; - } + /* If xTask is NULL then set the calling task's hook. */ + pxTCB = prvGetTCBFromHandle( xTask ); /* Save the hook function in the TCB. A critical section is required as the value can be accessed from an interrupt. */ taskENTER_CRITICAL(); { - xReturn = xTCB->pxTaskTag; + xReturn = pxTCB->pxTaskTag; } taskEXIT_CRITICAL(); @@ -2841,6 +2887,31 @@ BaseType_t xSwitchRequired = pdFALSE; #endif /* configUSE_APPLICATION_TASK_TAG */ /*-----------------------------------------------------------*/ +#if ( configUSE_APPLICATION_TASK_TAG == 1 ) + + TaskHookFunction_t xTaskGetApplicationTaskTagFromISR( TaskHandle_t xTask ) + { + TCB_t *pxTCB; + TaskHookFunction_t xReturn; + UBaseType_t uxSavedInterruptStatus; + + /* If xTask is NULL then set the calling task's hook. */ + pxTCB = prvGetTCBFromHandle( xTask ); + + /* Save the hook function in the TCB. A critical section is required as + the value can be accessed from an interrupt. */ + uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR(); + { + xReturn = pxTCB->pxTaskTag; + } + portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus ); + + return xReturn; + } + +#endif /* configUSE_APPLICATION_TASK_TAG */ +/*-----------------------------------------------------------*/ + #if ( configUSE_APPLICATION_TASK_TAG == 1 ) BaseType_t xTaskCallApplicationTaskHook( TaskHandle_t xTask, void *pvParameter ) @@ -2851,7 +2922,7 @@ BaseType_t xSwitchRequired = pdFALSE; /* If xTask is NULL then we are calling our own task hook. */ if( xTask == NULL ) { - xTCB = ( TCB_t * ) pxCurrentTCB; + xTCB = pxCurrentTCB; } else { @@ -2888,42 +2959,53 @@ void vTaskSwitchContext( void ) #if ( configGENERATE_RUN_TIME_STATS == 1 ) { - PRIVILEGED_DATA static uint32_t ulTaskSwitchedInTime = 0UL; /*< Holds the value of a timer/counter the last time a task was switched in. */ - PRIVILEGED_DATA static uint32_t ulTotalRunTime = 0UL; /*< Holds the total amount of execution time as defined by the run time counter clock. */ - - #ifdef portALT_GET_RUN_TIME_COUNTER_VALUE - portALT_GET_RUN_TIME_COUNTER_VALUE( ulTotalRunTime ); - #else - ulTotalRunTime = portGET_RUN_TIME_COUNTER_VALUE(); - #endif + #ifdef portALT_GET_RUN_TIME_COUNTER_VALUE + portALT_GET_RUN_TIME_COUNTER_VALUE( ulTotalRunTime ); + #else + ulTotalRunTime = portGET_RUN_TIME_COUNTER_VALUE(); + #endif - /* Add the amount of time the task has been running to the - accumulated time so far. The time the task started running was - stored in ulTaskSwitchedInTime. Note that there is no overflow - protection here so count values are only valid until the timer - overflows. The guard against negative values is to protect - against suspect run time stat counter implementations - which - are provided by the application, not the kernel. */ - if( ulTotalRunTime > ulTaskSwitchedInTime ) - { - pxCurrentTCB->ulRunTimeCounter += ( ulTotalRunTime - ulTaskSwitchedInTime ); - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - ulTaskSwitchedInTime = ulTotalRunTime; + /* Add the amount of time the task has been running to the + accumulated time so far. The time the task started running was + stored in ulTaskSwitchedInTime. Note that there is no overflow + protection here so count values are only valid until the timer + overflows. The guard against negative values is to protect + against suspect run time stat counter implementations - which + are provided by the application, not the kernel. */ + if( ulTotalRunTime > ulTaskSwitchedInTime ) + { + pxCurrentTCB->ulRunTimeCounter += ( ulTotalRunTime - ulTaskSwitchedInTime ); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + ulTaskSwitchedInTime = ulTotalRunTime; } #endif /* configGENERATE_RUN_TIME_STATS */ /* Check for stack overflow, if configured. */ taskCHECK_FOR_STACK_OVERFLOW(); + /* Before the currently running task is switched out, save its errno. */ + #if( configUSE_POSIX_ERRNO == 1 ) + { + pxCurrentTCB->iTaskErrno = FreeRTOS_errno; + } + #endif + /* Select a new task to run using either the generic C or port optimised asm code. */ taskSELECT_HIGHEST_PRIORITY_TASK(); /*lint !e9079 void * is used as this macro is used with timers and co-routines too. Alignment is known to be fine as the type of the pointer stored and retrieved is the same. */ traceTASK_SWITCHED_IN(); + /* After the new task is switched in, update the global errno. */ + #if( configUSE_POSIX_ERRNO == 1 ) + { + FreeRTOS_errno = pxCurrentTCB->iTaskErrno; + } + #endif + #if ( configUSE_NEWLIB_REENTRANT == 1 ) { /* Switch Newlib's _impure_ptr variable to point to the _reent @@ -3035,6 +3117,20 @@ BaseType_t xReturn; { ( void ) uxListRemove( &( pxUnblockedTCB->xStateListItem ) ); prvAddTaskToReadyList( pxUnblockedTCB ); + + #if( configUSE_TICKLESS_IDLE != 0 ) + { + /* If a task is blocked on a kernel object then xNextTaskUnblockTime + might be set to the blocked task's time out time. If the task is + unblocked for a reason other than a timeout xNextTaskUnblockTime is + normally left unchanged, because it is automatically reset to a new + value when the tick count equals xNextTaskUnblockTime. However if + tickless idling is used it might be more important to enter sleep mode + at the earliest possible time - so reset xNextTaskUnblockTime here to + ensure it is updated at the earliest possible time. */ + prvResetNextTaskUnblockTime(); + } + #endif } else { @@ -3059,20 +3155,6 @@ BaseType_t xReturn; xReturn = pdFALSE; } - #if( configUSE_TICKLESS_IDLE != 0 ) - { - /* If a task is blocked on a kernel object then xNextTaskUnblockTime - might be set to the blocked task's time out time. If the task is - unblocked for a reason other than a timeout xNextTaskUnblockTime is - normally left unchanged, because it is automatically reset to a new - value when the tick count equals xNextTaskUnblockTime. However if - tickless idling is used it might be more important to enter sleep mode - at the earliest possible time - so reset xNextTaskUnblockTime here to - ensure it is updated at the earliest possible time. */ - prvResetNextTaskUnblockTime(); - } - #endif - return xReturn; } /*-----------------------------------------------------------*/ @@ -3209,7 +3291,7 @@ void vTaskMissedYield( void ) if( xTask != NULL ) { - pxTCB = ( TCB_t * ) xTask; + pxTCB = xTask; uxReturn = pxTCB->uxTaskNumber; } else @@ -3231,7 +3313,7 @@ void vTaskMissedYield( void ) if( xTask != NULL ) { - pxTCB = ( TCB_t * ) xTask; + pxTCB = xTask; pxTCB->uxTaskNumber = uxHandle; } } @@ -3260,7 +3342,7 @@ static portTASK_FUNCTION( prvIdleTask, pvParameters ) /* In case a task that has a secure context deletes itself, in which case the idle task is responsible for deleting the task's secure context, if any. */ - portTASK_CALLS_SECURE_FUNCTIONS(); + portALLOCATE_SECURE_CONTEXT( configMINIMAL_SECURE_STACK_SIZE ); for( ;; ) { @@ -3464,8 +3546,6 @@ static portTASK_FUNCTION( prvIdleTask, pvParameters ) static void prvInitialiseTaskLists( void ) { UBaseType_t uxPriority; -PRIVILEGED_DATA static List_t xDelayedTaskList1; /*< Delayed tasks. */ -PRIVILEGED_DATA static List_t xDelayedTaskList2; /*< Delayed tasks (two lists are used - one for delays that have overflowed the current tick count. */ for( uxPriority = ( UBaseType_t ) 0U; uxPriority < ( UBaseType_t ) configMAX_PRIORITIES; uxPriority++ ) { @@ -3653,7 +3733,7 @@ static void prvCheckTasksWaitingTermination( void ) #endif /* configUSE_TRACE_FACILITY */ /*-----------------------------------------------------------*/ -#if ( ( configUSE_TRACE_FACILITY == 1 ) || ( INCLUDE_uxTaskGetStackHighWaterMark == 1 ) ) +#if ( ( configUSE_TRACE_FACILITY == 1 ) || ( INCLUDE_uxTaskGetStackHighWaterMark == 1 ) || ( INCLUDE_uxTaskGetStackHighWaterMark2 == 1 ) ) static configSTACK_DEPTH_TYPE prvTaskCheckFreeStackSpace( const uint8_t * pucStackByte ) { @@ -3670,7 +3750,47 @@ static void prvCheckTasksWaitingTermination( void ) return ( configSTACK_DEPTH_TYPE ) ulCount; } -#endif /* ( ( configUSE_TRACE_FACILITY == 1 ) || ( INCLUDE_uxTaskGetStackHighWaterMark == 1 ) ) */ +#endif /* ( ( configUSE_TRACE_FACILITY == 1 ) || ( INCLUDE_uxTaskGetStackHighWaterMark == 1 ) || ( INCLUDE_uxTaskGetStackHighWaterMark2 == 1 ) ) */ +/*-----------------------------------------------------------*/ + +#if ( INCLUDE_uxTaskGetStackHighWaterMark2 == 1 ) + + /* uxTaskGetStackHighWaterMark() and uxTaskGetStackHighWaterMark2() are the + same except for their return type. Using configSTACK_DEPTH_TYPE allows the + user to determine the return type. It gets around the problem of the value + overflowing on 8-bit types without breaking backward compatibility for + applications that expect an 8-bit return type. */ + configSTACK_DEPTH_TYPE uxTaskGetStackHighWaterMark2( TaskHandle_t xTask ) + { + TCB_t *pxTCB; + uint8_t *pucEndOfStack; + configSTACK_DEPTH_TYPE uxReturn; + + /* uxTaskGetStackHighWaterMark() and uxTaskGetStackHighWaterMark2() are + the same except for their return type. Using configSTACK_DEPTH_TYPE + allows the user to determine the return type. It gets around the + problem of the value overflowing on 8-bit types without breaking + backward compatibility for applications that expect an 8-bit return + type. */ + + pxTCB = prvGetTCBFromHandle( xTask ); + + #if portSTACK_GROWTH < 0 + { + pucEndOfStack = ( uint8_t * ) pxTCB->pxStack; + } + #else + { + pucEndOfStack = ( uint8_t * ) pxTCB->pxEndOfStack; + } + #endif + + uxReturn = prvTaskCheckFreeStackSpace( pucEndOfStack ); + + return uxReturn; + } + +#endif /* INCLUDE_uxTaskGetStackHighWaterMark2 */ /*-----------------------------------------------------------*/ #if ( INCLUDE_uxTaskGetStackHighWaterMark == 1 ) @@ -4267,7 +4387,7 @@ TCB_t *pxTCB; /* Write the rest of the string. */ sprintf( pcWriteBuffer, "\t%c\t%u\t%u\t%u\r\n", cStatus, ( unsigned int ) pxTaskStatusArray[ x ].uxCurrentPriority, ( unsigned int ) pxTaskStatusArray[ x ].usStackHighWaterMark, ( unsigned int ) pxTaskStatusArray[ x ].xTaskNumber ); /*lint !e586 sprintf() allowed as this is compiled with many compilers and this is a utility function only - not part of the core kernel implementation. */ - pcWriteBuffer += strlen( pcWriteBuffer ); /*lint !e9016 Pointer arithmetic ok on char pointers. */ + pcWriteBuffer += strlen( pcWriteBuffer ); /*lint !e9016 Pointer arithmetic ok on char pointers especially as in this case where it best denotes the intent of the code. */ } /* Free the array again. NOTE! If configSUPPORT_DYNAMIC_ALLOCATION @@ -4389,7 +4509,7 @@ TCB_t *pxTCB; #endif } - pcWriteBuffer += strlen( pcWriteBuffer ); /*lint !e9016 Pointer arithmetic ok on char pointers. */ + pcWriteBuffer += strlen( pcWriteBuffer ); /*lint !e9016 Pointer arithmetic ok on char pointers especially as in this case where it best denotes the intent of the code. */ } } else @@ -4426,7 +4546,7 @@ TickType_t uxReturn; #if ( configUSE_MUTEXES == 1 ) - void *pvTaskIncrementMutexHeldCount( void ) + TaskHandle_t pvTaskIncrementMutexHeldCount( void ) { /* If xSemaphoreCreateMutex() is called before any tasks have been created then pxCurrentTCB will be NULL. */ @@ -4598,7 +4718,7 @@ TickType_t uxReturn; uint8_t ucOriginalNotifyState; configASSERT( xTaskToNotify ); - pxTCB = ( TCB_t * ) xTaskToNotify; + pxTCB = xTaskToNotify; taskENTER_CRITICAL(); { @@ -4644,8 +4764,9 @@ TickType_t uxReturn; default: /* Should not get here if all enums are handled. - Artificially force an assert. */ - configASSERT( ( volatile uint32_t ) 0 ); + Artificially force an assert by testing a value the + compiler can't assume is const. */ + configASSERT( pxTCB->ulNotifiedValue == ~0UL ); break; } @@ -4731,7 +4852,7 @@ TickType_t uxReturn; http://www.freertos.org/RTOS-Cortex-M3-M4.html */ portASSERT_IF_INTERRUPT_PRIORITY_INVALID(); - pxTCB = ( TCB_t * ) xTaskToNotify; + pxTCB = xTaskToNotify; uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR(); { @@ -4776,8 +4897,9 @@ TickType_t uxReturn; default: /* Should not get here if all enums are handled. - Artificially force an assert. */ - configASSERT( ( volatile uint32_t ) 0 ); + Artificially force an assert by testing a value the + compiler can't assume is const. */ + configASSERT( pxTCB->ulNotifiedValue == ~0UL ); break; } @@ -4858,7 +4980,7 @@ TickType_t uxReturn; http://www.freertos.org/RTOS-Cortex-M3-M4.html */ portASSERT_IF_INTERRUPT_PRIORITY_INVALID(); - pxTCB = ( TCB_t * ) xTaskToNotify; + pxTCB = xTaskToNotify; uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR(); { @@ -4948,6 +5070,13 @@ TickType_t uxReturn; #endif /* configUSE_TASK_NOTIFICATIONS */ /*-----------------------------------------------------------*/ +#if( ( configGENERATE_RUN_TIME_STATS == 1 ) && ( INCLUDE_xTaskGetIdleTaskHandle == 1 ) ) + TickType_t xTaskGetIdleRunTimeCounter( void ) + { + return xIdleTaskHandle->ulRunTimeCounter; + } +#endif +/*-----------------------------------------------------------*/ static void prvAddCurrentTaskToDelayedList( TickType_t xTicksToWait, const BaseType_t xCanBlockIndefinitely ) { @@ -5073,12 +5202,12 @@ when performing module tests). */ #include "freertos_tasks_c_additions.h" - static void freertos_tasks_c_additions_init( void ) - { - #ifdef FREERTOS_TASKS_C_ADDITIONS_INIT + #ifdef FREERTOS_TASKS_C_ADDITIONS_INIT + static void freertos_tasks_c_additions_init( void ) + { FREERTOS_TASKS_C_ADDITIONS_INIT(); - #endif - } + } + #endif #endif