2022-02-24 07:14:22 -05:00
/*
2024-01-05 04:14:26 -05:00
* FreeRTOS Kernel V11 .0 .1
* Copyright ( C ) 2021 Amazon . com , Inc . or its affiliates . All Rights Reserved .
*
* SPDX - FileCopyrightText : 2021 Amazon . com , Inc . or its affiliates
*
* SPDX - License - Identifier : MIT
*
* SPDX - FileContributor : 2023 - 2024 Espressif Systems ( Shanghai ) CO LTD
2022-02-24 07:14:22 -05:00
*
* 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
* the Software without restriction , including without limitation the rights to
* use , copy , modify , merge , publish , distribute , sublicense , and / or sell copies of
* the Software , and to permit persons to whom the Software is furnished to do so ,
* subject to the following conditions :
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software .
*
* THE SOFTWARE IS PROVIDED " AS IS " , WITHOUT WARRANTY OF ANY KIND , EXPRESS OR
* IMPLIED , INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY , FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT . IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM , DAMAGES OR OTHER LIABILITY , WHETHER
* IN AN ACTION OF CONTRACT , TORT OR OTHERWISE , ARISING FROM , OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE .
*
* https : //www.FreeRTOS.org
* https : //github.com/FreeRTOS
*
*/
/* Standard includes. */
# include <stdlib.h>
# include <string.h>
/* Defining MPU_WRAPPERS_INCLUDED_FROM_API_FILE prevents task.h from redefining
* all the API functions to use the MPU wrappers . That should only be done when
* task . h is included from an application file . */
# define MPU_WRAPPERS_INCLUDED_FROM_API_FILE
/* FreeRTOS includes. */
# include "FreeRTOS.h"
# include "task.h"
# include "timers.h"
# include "stack_macros.h"
2024-01-05 04:14:26 -05:00
/* The MPU ports require MPU_WRAPPERS_INCLUDED_FROM_API_FILE to be defined
2022-02-24 07:14:22 -05:00
* for the header files above , but not in this file , in order to generate the
* correct privileged Vs unprivileged linkage and placement . */
2024-01-05 04:14:26 -05:00
# undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE
2022-02-24 07:14:22 -05:00
/* Set configUSE_STATS_FORMATTING_FUNCTIONS to 2 to include the stats formatting
* functions but without including stdio . h here . */
# if ( configUSE_STATS_FORMATTING_FUNCTIONS == 1 )
/* At the bottom of this file are two optional functions that can be used
* to generate human readable text from the raw data generated by the
* uxTaskGetSystemState ( ) function . Note the formatting functions are provided
* for convenience only , and are NOT considered part of the kernel . */
# include <stdio.h>
# endif /* configUSE_STATS_FORMATTING_FUNCTIONS == 1 ) */
# if ( configUSE_PREEMPTION == 0 )
/* If the cooperative scheduler is being used then a yield should not be
* performed just because a higher priority task has been woken . */
2024-01-05 04:14:26 -05:00
# define taskYIELD_TASK_CORE_IF_USING_PREEMPTION( pxTCB )
# define taskYIELD_ANY_CORE_IF_USING_PREEMPTION( pxTCB )
2022-02-24 07:14:22 -05:00
# else
2024-01-05 04:14:26 -05:00
# if ( configNUMBER_OF_CORES == 1 )
/* This macro requests the running task pxTCB to yield. In single core
* scheduler , a running task always runs on core 0 and portYIELD_WITHIN_API ( )
* can be used to request the task running on core 0 to yield . Therefore , pxTCB
* is not used in this macro . */
# define taskYIELD_TASK_CORE_IF_USING_PREEMPTION( pxTCB ) \
do { \
( void ) ( pxTCB ) ; \
portYIELD_WITHIN_API ( ) ; \
} while ( 0 )
# define taskYIELD_ANY_CORE_IF_USING_PREEMPTION( pxTCB ) \
do { \
if ( pxCurrentTCB - > uxPriority < ( pxTCB ) - > uxPriority ) \
{ \
portYIELD_WITHIN_API ( ) ; \
} \
else \
{ \
mtCOVERAGE_TEST_MARKER ( ) ; \
} \
} while ( 0 )
# else /* if ( configNUMBER_OF_CORES == 1 ) */
/* Yield the core on which this task is running. */
# define taskYIELD_TASK_CORE_IF_USING_PREEMPTION( pxTCB ) prvYieldCore( ( pxTCB )->xTaskRunState )
/* Yield for the task if a running task has priority lower than this task. */
# define taskYIELD_ANY_CORE_IF_USING_PREEMPTION( pxTCB ) prvYieldForTask( pxTCB )
# endif /* #if ( configNUMBER_OF_CORES == 1 ) */
# endif /* if ( configUSE_PREEMPTION == 0 ) */
2022-02-24 07:14:22 -05:00
/* Values that can be assigned to the ucNotifyState member of the TCB. */
# define taskNOT_WAITING_NOTIFICATION ( ( uint8_t ) 0 ) /* Must be zero as it is the initialised value. */
# define taskWAITING_NOTIFICATION ( ( uint8_t ) 1 )
# define taskNOTIFICATION_RECEIVED ( ( uint8_t ) 2 )
/*
* The value used to fill the stack of a task when the task is created . This
* is used purely for checking the high water mark for tasks .
*/
# define tskSTACK_FILL_BYTE ( 0xa5U )
/* Bits used to record 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 )
/* 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 ) || ( INCLUDE_uxTaskGetStackHighWaterMark2 == 1 ) )
# define tskSET_NEW_STACKS_TO_KNOWN_VALUE 1
# else
# define tskSET_NEW_STACKS_TO_KNOWN_VALUE 0
# endif
/*
* Macros used by vListTask to indicate which state a task is in .
*/
# define tskRUNNING_CHAR ( 'X' )
# define tskBLOCKED_CHAR ( 'B' )
# define tskREADY_CHAR ( 'R' )
# define tskDELETED_CHAR ( 'D' )
# define tskSUSPENDED_CHAR ( 'S' )
/*
* Some kernel aware debuggers require the data the debugger needs access to to
* be global , rather than file scope .
*/
# ifdef portREMOVE_STATIC_QUALIFIER
# define static
# endif
/* The name allocated to the Idle task. This can be overridden by defining
* configIDLE_TASK_NAME in FreeRTOSConfig . h . */
# ifndef configIDLE_TASK_NAME
# define configIDLE_TASK_NAME "IDLE"
# endif
# if ( configUSE_PORT_OPTIMISED_TASK_SELECTION == 0 )
/* If configUSE_PORT_OPTIMISED_TASK_SELECTION is 0 then task selection is
* performed in a generic way that is not optimised to any particular
* microcontroller architecture . */
/* uxTopReadyPriority holds the priority of the highest priority ready
* state task . */
# define taskRECORD_READY_PRIORITY( uxPriority ) \
2024-01-05 04:14:26 -05:00
do { \
2022-02-24 07:14:22 -05:00
if ( ( uxPriority ) > uxTopReadyPriority ) \
{ \
uxTopReadyPriority = ( uxPriority ) ; \
} \
2024-01-05 04:14:26 -05:00
} while ( 0 ) /* taskRECORD_READY_PRIORITY */
/*-----------------------------------------------------------*/
# if ( configNUMBER_OF_CORES == 1 )
# define taskSELECT_HIGHEST_PRIORITY_TASK() \
do { \
UBaseType_t uxTopPriority = uxTopReadyPriority ; \
\
/* Find the highest priority queue that contains ready tasks. */ \
while ( listLIST_IS_EMPTY ( & ( pxReadyTasksLists [ uxTopPriority ] ) ) ) \
{ \
configASSERT ( uxTopPriority ) ; \
- - uxTopPriority ; \
} \
\
/* listGET_OWNER_OF_NEXT_ENTRY indexes through the list, so the tasks of \
* the same priority get an equal share of the processor time . */ \
listGET_OWNER_OF_NEXT_ENTRY ( pxCurrentTCB , & ( pxReadyTasksLists [ uxTopPriority ] ) ) ; \
uxTopReadyPriority = uxTopPriority ; \
} while ( 0 ) /* taskSELECT_HIGHEST_PRIORITY_TASK */
# else /* if ( configNUMBER_OF_CORES == 1 ) */
# define taskSELECT_HIGHEST_PRIORITY_TASK( xCoreID ) prvSelectHighestPriorityTask( xCoreID )
# endif /* if ( configNUMBER_OF_CORES == 1 ) */
2022-02-24 07:14:22 -05:00
2024-01-05 04:14:26 -05:00
/*-----------------------------------------------------------*/
2022-02-24 07:14:22 -05:00
/* Define away taskRESET_READY_PRIORITY() and portRESET_READY_PRIORITY() as
* they are only required when a port optimised method of task selection is
* being used . */
# define taskRESET_READY_PRIORITY( uxPriority )
# define portRESET_READY_PRIORITY( uxPriority, uxTopReadyPriority )
# else /* configUSE_PORT_OPTIMISED_TASK_SELECTION */
/* If configUSE_PORT_OPTIMISED_TASK_SELECTION is 1 then task selection is
* performed in a way that is tailored to the particular microcontroller
* architecture being used . */
/* A port optimised version is provided. Call the port defined macros. */
2024-01-05 04:14:26 -05:00
# define taskRECORD_READY_PRIORITY( uxPriority ) portRECORD_READY_PRIORITY( ( uxPriority ), uxTopReadyPriority )
2022-02-24 07:14:22 -05:00
2024-01-05 04:14:26 -05:00
/*-----------------------------------------------------------*/
# define taskSELECT_HIGHEST_PRIORITY_TASK() \
do { \
UBaseType_t uxTopPriority ; \
\
/* Find the highest priority list that contains ready tasks. */ \
portGET_HIGHEST_PRIORITY ( uxTopPriority , uxTopReadyPriority ) ; \
configASSERT ( listCURRENT_LIST_LENGTH ( & ( pxReadyTasksLists [ uxTopPriority ] ) ) > 0 ) ; \
listGET_OWNER_OF_NEXT_ENTRY ( pxCurrentTCB , & ( pxReadyTasksLists [ uxTopPriority ] ) ) ; \
} while ( 0 )
/*-----------------------------------------------------------*/
2022-02-24 07:14:22 -05:00
/* A port optimised version is provided, call it only if the TCB being reset
* is being referenced from a ready list . If it is referenced from a delayed
* or suspended list then it won ' t be in a ready list . */
# define taskRESET_READY_PRIORITY( uxPriority ) \
2024-01-05 04:14:26 -05:00
do { \
2022-02-24 07:14:22 -05:00
if ( listCURRENT_LIST_LENGTH ( & ( pxReadyTasksLists [ ( uxPriority ) ] ) ) = = ( UBaseType_t ) 0 ) \
{ \
portRESET_READY_PRIORITY ( ( uxPriority ) , ( uxTopReadyPriority ) ) ; \
} \
2024-01-05 04:14:26 -05:00
} while ( 0 )
2022-02-24 07:14:22 -05:00
# endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */
/*-----------------------------------------------------------*/
/* pxDelayedTaskList and pxOverflowDelayedTaskList are switched when the tick
* count overflows . */
# define taskSWITCH_DELAYED_LISTS() \
2024-01-05 04:14:26 -05:00
do { \
2022-02-24 07:14:22 -05:00
List_t * pxTemp ; \
\
/* The delayed tasks list should be empty when the lists are switched. */ \
configASSERT ( ( listLIST_IS_EMPTY ( pxDelayedTaskList ) ) ) ; \
\
pxTemp = pxDelayedTaskList ; \
pxDelayedTaskList = pxOverflowDelayedTaskList ; \
pxOverflowDelayedTaskList = pxTemp ; \
xNumOfOverflows + + ; \
prvResetNextTaskUnblockTime ( ) ; \
2024-01-05 04:14:26 -05:00
} while ( 0 )
2022-02-24 07:14:22 -05:00
/*-----------------------------------------------------------*/
/*
* Place the task represented by pxTCB into the appropriate ready list for
* the task . It is inserted at the end of the list .
*/
2024-01-05 04:14:26 -05:00
# define prvAddTaskToReadyList( pxTCB ) \
do { \
traceMOVED_TASK_TO_READY_STATE ( pxTCB ) ; \
taskRECORD_READY_PRIORITY ( ( pxTCB ) - > uxPriority ) ; \
listINSERT_END ( & ( pxReadyTasksLists [ ( pxTCB ) - > uxPriority ] ) , & ( ( pxTCB ) - > xStateListItem ) ) ; \
tracePOST_MOVED_TASK_TO_READY_STATE ( pxTCB ) ; \
} while ( 0 )
2022-02-24 07:14:22 -05:00
/*-----------------------------------------------------------*/
/*
* Several functions take a TaskHandle_t parameter that can optionally be NULL ,
* where NULL is used to indicate that the handle of the currently executing
* task should be used in place of the parameter . This macro simply checks to
* see if the parameter is NULL and returns a pointer to the appropriate TCB .
*/
# define prvGetTCBFromHandle( pxHandle ) ( ( ( pxHandle ) == NULL ) ? pxCurrentTCB : ( pxHandle ) )
/* The item value of the event list item is normally used to hold the priority
* of the task to which it belongs ( coded to allow it to be held in reverse
* priority order ) . However , it is occasionally borrowed for other purposes . It
* is important its value is not updated due to a task priority change while it is
* being used for another purpose . The following bit definition is used to inform
* the scheduler that the value should not be changed - in which case it is the
* responsibility of whichever module is using the value to ensure it gets set back
* to its original value when it is released . */
2024-01-05 04:14:26 -05:00
# if ( configTICK_TYPE_WIDTH_IN_BITS == TICK_TYPE_WIDTH_16_BITS )
# define taskEVENT_LIST_ITEM_VALUE_IN_USE ( ( uint16_t ) 0x8000U )
# elif ( configTICK_TYPE_WIDTH_IN_BITS == TICK_TYPE_WIDTH_32_BITS )
# define taskEVENT_LIST_ITEM_VALUE_IN_USE ( ( uint32_t ) 0x80000000UL )
# elif ( configTICK_TYPE_WIDTH_IN_BITS == TICK_TYPE_WIDTH_64_BITS )
# define taskEVENT_LIST_ITEM_VALUE_IN_USE ( ( uint64_t ) 0x8000000000000000ULL )
2022-02-24 07:14:22 -05:00
# endif
/* Indicates that the task is not actively running on any core. */
2024-01-05 04:14:26 -05:00
# define taskTASK_NOT_RUNNING ( ( BaseType_t ) ( -1 ) )
2022-02-24 07:14:22 -05:00
/* Indicates that the task is actively running but scheduled to yield. */
2024-01-05 04:14:26 -05:00
# define taskTASK_SCHEDULED_TO_YIELD ( ( BaseType_t ) ( -2 ) )
2022-02-24 07:14:22 -05:00
/* Returns pdTRUE if the task is actively running and not scheduled to yield. */
2024-01-05 04:14:26 -05:00
# if ( configNUMBER_OF_CORES == 1 )
# define taskTASK_IS_RUNNING( pxTCB ) ( ( ( pxTCB ) == pxCurrentTCB ) ? ( pdTRUE ) : ( pdFALSE ) )
# define taskTASK_IS_RUNNING_OR_SCHEDULED_TO_YIELD( pxTCB ) ( ( ( pxTCB ) == pxCurrentTCB ) ? ( pdTRUE ) : ( pdFALSE ) )
# else
# define taskTASK_IS_RUNNING( pxTCB ) ( ( ( ( pxTCB )->xTaskRunState >= ( BaseType_t ) 0 ) && ( ( pxTCB )->xTaskRunState < ( BaseType_t ) configNUMBER_OF_CORES ) ) ? ( pdTRUE ) : ( pdFALSE ) )
# define taskTASK_IS_RUNNING_OR_SCHEDULED_TO_YIELD( pxTCB ) ( ( ( pxTCB )->xTaskRunState != taskTASK_NOT_RUNNING ) ? ( pdTRUE ) : ( pdFALSE ) )
# endif
2022-02-24 07:14:22 -05:00
2024-01-05 04:14:26 -05:00
/* Indicates that the task is an Idle task. */
# define taskATTRIBUTE_IS_IDLE ( UBaseType_t ) ( 1UL << 0UL )
# if ( ( configNUMBER_OF_CORES > 1 ) && ( portCRITICAL_NESTING_IN_TCB == 1 ) )
# define portGET_CRITICAL_NESTING_COUNT() ( pxCurrentTCBs[ portGET_CORE_ID() ]->uxCriticalNesting )
# define portSET_CRITICAL_NESTING_COUNT( x ) ( pxCurrentTCBs[ portGET_CORE_ID() ]->uxCriticalNesting = ( x ) )
# define portINCREMENT_CRITICAL_NESTING_COUNT() ( pxCurrentTCBs[ portGET_CORE_ID() ]->uxCriticalNesting++ )
# define portDECREMENT_CRITICAL_NESTING_COUNT() ( pxCurrentTCBs[ portGET_CORE_ID() ]->uxCriticalNesting-- )
# endif /* #if ( ( configNUMBER_OF_CORES > 1 ) && ( portCRITICAL_NESTING_IN_TCB == 1 ) ) */
# define taskBITS_PER_BYTE ( ( size_t ) 8 )
# if ( configNUMBER_OF_CORES > 1 )
/* Yields the given core. This must be called from a critical section and xCoreID
* must be valid . This macro is not required in single core since there is only
* one core to yield . */
# define prvYieldCore( xCoreID ) \
do { \
if ( ( xCoreID ) = = ( BaseType_t ) portGET_CORE_ID ( ) ) \
{ \
/* Pending a yield for this core since it is in the critical section. */ \
xYieldPendings [ ( xCoreID ) ] = pdTRUE ; \
} \
else \
{ \
/* Request other core to yield if it is not requested before. */ \
if ( pxCurrentTCBs [ ( xCoreID ) ] - > xTaskRunState ! = taskTASK_SCHEDULED_TO_YIELD ) \
{ \
portYIELD_CORE ( xCoreID ) ; \
pxCurrentTCBs [ ( xCoreID ) ] - > xTaskRunState = taskTASK_SCHEDULED_TO_YIELD ; \
} \
} \
} while ( 0 )
# endif /* #if ( configNUMBER_OF_CORES > 1 ) */
/*-----------------------------------------------------------*/
2022-02-24 07:14:22 -05:00
/*
* Task control block . A task control block ( TCB ) is allocated for each task ,
* and stores task state information , including a pointer to the task ' s context
* ( the task ' s run time environment , including register values )
*/
typedef struct tskTaskControlBlock /* The old naming convention is used to prevent breaking kernel aware debuggers. */
{
2024-01-05 04:14:26 -05:00
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. */
2022-02-24 07:14:22 -05:00
# if ( portUSING_MPU_WRAPPERS == 1 )
2024-01-05 04:14:26 -05:00
xMPU_SETTINGS xMPUSettings ; /**< The MPU settings are defined as part of the port layer. THIS MUST BE THE SECOND MEMBER OF THE TCB STRUCT. */
2022-02-24 07:14:22 -05:00
# endif
2024-01-05 04:14:26 -05:00
# if ( configUSE_CORE_AFFINITY == 1 ) && ( configNUMBER_OF_CORES > 1 )
UBaseType_t uxCoreAffinityMask ; /**< Used to link the task to certain cores. UBaseType_t must have greater than or equal to the number of bits as configNUMBER_OF_CORES. */
2022-02-24 07:14:22 -05:00
# endif
2024-01-05 04:14:26 -05:00
ListItem_t xStateListItem ; /**< The list that the state list item of a task is reference from denotes the state of that task (Ready, Blocked, Suspended ). */
ListItem_t xEventListItem ; /**< Used to reference a task from an event list. */
UBaseType_t uxPriority ; /**< The priority of the task. 0 is the lowest priority. */
StackType_t * pxStack ; /**< Points to the start of the stack. */
# if ( configNUMBER_OF_CORES > 1 )
volatile BaseType_t xTaskRunState ; /**< Used to identify the core the task is running on, if the task is running. Otherwise, identifies the task's state - not running or yielding. */
UBaseType_t uxTaskAttributes ; /**< Task's attributes - currently used to identify the idle tasks. */
# endif
char pcTaskName [ configMAX_TASK_NAME_LEN ] ; /**< Descriptive name given to the task when created. Facilitates debugging only. */
2022-02-24 07:14:22 -05:00
# if ( configUSE_TASK_PREEMPTION_DISABLE == 1 )
2024-01-05 04:14:26 -05:00
BaseType_t xPreemptionDisable ; /**< Used to prevent the task from being preempted. */
2022-02-24 07:14:22 -05:00
# endif
# if ( ( portSTACK_GROWTH > 0 ) || ( configRECORD_STACK_HIGH_ADDRESS == 1 ) )
2024-01-05 04:14:26 -05:00
StackType_t * pxEndOfStack ; /**< Points to the highest valid address for the stack. */
2022-02-24 07:14:22 -05:00
# endif
# if ( portCRITICAL_NESTING_IN_TCB == 1 )
2024-01-05 04:14:26 -05:00
UBaseType_t uxCriticalNesting ; /**< Holds the critical section nesting depth for ports that do not maintain their own count in the port layer. */
2022-02-24 07:14:22 -05:00
# endif
# if ( configUSE_TRACE_FACILITY == 1 )
2024-01-05 04:14:26 -05:00
UBaseType_t uxTCBNumber ; /**< Stores a number that increments each time a TCB is created. It allows debuggers to determine when a task has been deleted and then recreated. */
UBaseType_t uxTaskNumber ; /**< Stores a number specifically for use by third party trace code. */
2022-02-24 07:14:22 -05:00
# endif
# if ( configUSE_MUTEXES == 1 )
2024-01-05 04:14:26 -05:00
UBaseType_t uxBasePriority ; /**< The priority last assigned to the task - used by the priority inheritance mechanism. */
2022-02-24 07:14:22 -05:00
UBaseType_t uxMutexesHeld ;
# endif
# if ( configUSE_APPLICATION_TASK_TAG == 1 )
TaskHookFunction_t pxTaskTag ;
# endif
# if ( configNUM_THREAD_LOCAL_STORAGE_POINTERS > 0 )
void * pvThreadLocalStoragePointers [ configNUM_THREAD_LOCAL_STORAGE_POINTERS ] ;
# endif
# if ( configGENERATE_RUN_TIME_STATS == 1 )
2024-01-05 04:14:26 -05:00
configRUN_TIME_COUNTER_TYPE ulRunTimeCounter ; /**< Stores the amount of time the task has spent in the Running state. */
2022-02-24 07:14:22 -05:00
# endif
2024-01-05 04:14:26 -05:00
# if ( configUSE_C_RUNTIME_TLS_SUPPORT == 1 )
configTLS_BLOCK_TYPE xTLSBlock ; /**< Memory block used as Thread Local Storage (TLS) Block for the task. */
2022-02-24 07:14:22 -05:00
# endif
# if ( configUSE_TASK_NOTIFICATIONS == 1 )
volatile uint32_t ulNotifiedValue [ configTASK_NOTIFICATION_ARRAY_ENTRIES ] ;
volatile uint8_t ucNotifyState [ configTASK_NOTIFICATION_ARRAY_ENTRIES ] ;
# endif
/* See the comments in FreeRTOS.h with the definition of
* tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE . */
2024-01-05 04:14:26 -05:00
# if ( tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE != 0 )
uint8_t ucStaticallyAllocated ; /**< Set to pdTRUE if the task is a statically allocated to ensure no attempt is made to free the memory. */
2022-02-24 07:14:22 -05:00
# endif
# if ( INCLUDE_xTaskAbortDelay == 1 )
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
* below to enable the use of older kernel aware debuggers . */
typedef tskTCB TCB_t ;
2024-01-05 04:14:26 -05:00
# if ( configNUMBER_OF_CORES == 1 )
/* MISRA Ref 8.4.1 [Declaration shall be visible] */
/* More details at: https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/MISRA.md#rule-84 */
/* coverity[misra_c_2012_rule_8_4_violation] */
portDONT_DISCARD PRIVILEGED_DATA TCB_t * volatile pxCurrentTCB = NULL ;
# else
/* MISRA Ref 8.4.1 [Declaration shall be visible] */
/* More details at: https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/MISRA.md#rule-84 */
/* coverity[misra_c_2012_rule_8_4_violation] */
portDONT_DISCARD PRIVILEGED_DATA TCB_t * volatile pxCurrentTCBs [ configNUMBER_OF_CORES ] ;
# define pxCurrentTCB xTaskGetCurrentTaskHandle()
# endif
2022-02-24 07:14:22 -05:00
/* Lists for ready and blocked tasks. --------------------
* xDelayedTaskList1 and xDelayedTaskList2 could be moved to function scope but
* doing so breaks some kernel aware debuggers and debuggers that rely on removing
* the static qualifier . */
2024-01-05 04:14:26 -05:00
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. */
2022-02-24 07:14:22 -05:00
# if ( INCLUDE_vTaskDelete == 1 )
2024-01-05 04:14:26 -05:00
PRIVILEGED_DATA static List_t xTasksWaitingTermination ; /**< Tasks that have been deleted - but their memory not yet freed. */
2022-02-24 07:14:22 -05:00
PRIVILEGED_DATA static volatile UBaseType_t uxDeletedTasksWaitingCleanUp = ( UBaseType_t ) 0U ;
# endif
# if ( INCLUDE_vTaskSuspend == 1 )
2024-01-05 04:14:26 -05:00
PRIVILEGED_DATA static List_t xSuspendedTaskList ; /**< Tasks that are currently suspended. */
2022-02-24 07:14:22 -05:00
# 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 ;
PRIVILEGED_DATA static volatile UBaseType_t uxTopReadyPriority = tskIDLE_PRIORITY ;
2024-02-02 10:33:27 -05:00
# if ( ( ESP_PLATFORM == 1 ) && ( configNUM_CORES > 1 ) )
/*
* Workaround for non - thread safe multi - core OS startup ( see IDF - 4524 )
*/
PRIVILEGED_DATA static volatile BaseType_t xSchedulerRunningPerCore [ configNUM_CORES ] = { pdFALSE } ;
# define xSchedulerRunning xSchedulerRunningPerCore[ portGET_CORE_ID() ]
# else // ( ESP_PLATFORM == 1 ) && ( configNUM_CORES > 1 )
PRIVILEGED_DATA static volatile BaseType_t xSchedulerRunning = pdFALSE ;
# endif // ( ESP_PLATFORM == 1 ) && ( configNUM_CORES > 1 )
2022-02-24 07:14:22 -05:00
PRIVILEGED_DATA static volatile TickType_t xPendedTicks = ( TickType_t ) 0U ;
2024-01-05 04:14:26 -05:00
PRIVILEGED_DATA static volatile BaseType_t xYieldPendings [ configNUMBER_OF_CORES ] = { pdFALSE } ;
2022-02-24 07:14:22 -05:00
PRIVILEGED_DATA static volatile BaseType_t xNumOfOverflows = ( BaseType_t ) 0 ;
PRIVILEGED_DATA static UBaseType_t uxTaskNumber = ( UBaseType_t ) 0U ;
PRIVILEGED_DATA static volatile TickType_t xNextTaskUnblockTime = ( TickType_t ) 0U ; /* Initialised to portMAX_DELAY before the scheduler starts. */
2024-01-05 04:14:26 -05:00
PRIVILEGED_DATA static TaskHandle_t xIdleTaskHandles [ configNUMBER_OF_CORES ] ; /**< Holds the handles of the idle tasks. The idle tasks are created automatically when the scheduler is started. */
2022-02-24 07:14:22 -05:00
/* Improve support for OpenOCD. The kernel tracks Ready tasks via priority lists.
* For tracking the state of remote threads , OpenOCD uses uxTopUsedPriority
* to determine the number of priority lists to read back from the remote target . */
2024-01-05 04:14:26 -05:00
static const volatile UBaseType_t uxTopUsedPriority = configMAX_PRIORITIES - 1U ;
2022-02-24 07:14:22 -05:00
/* Context switches are held pending while the scheduler is suspended. Also,
* interrupts must not manipulate the xStateListItem of a TCB , or any of the
* lists the xStateListItem can be referenced from , if the scheduler is suspended .
* If an interrupt needs to unblock a task while the scheduler is suspended then it
* moves the task ' s event list item into the xPendingReadyList , ready for the
* kernel to move the task from the pending ready list into the real ready list
* when the scheduler is unsuspended . The pending ready list itself can only be
* accessed from a critical section .
*
2024-01-05 04:14:26 -05:00
* Updates to uxSchedulerSuspended must be protected by both the task lock and the ISR lock
* and must not be done from an ISR . Reads must be protected by either lock and may be done
* from either an ISR or a task . */
PRIVILEGED_DATA static volatile UBaseType_t uxSchedulerSuspended = ( UBaseType_t ) 0U ;
2022-02-24 07:14:22 -05:00
# 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 . */
2024-01-05 04:14:26 -05:00
PRIVILEGED_DATA static configRUN_TIME_COUNTER_TYPE ulTaskSwitchedInTime [ configNUMBER_OF_CORES ] = { 0U } ; /**< Holds the value of a timer/counter the last time a task was switched in. */
PRIVILEGED_DATA static volatile configRUN_TIME_COUNTER_TYPE ulTotalRunTime [ configNUMBER_OF_CORES ] = { 0U } ; /**< Holds the total amount of execution time as defined by the run time counter clock. */
2022-02-24 07:14:22 -05:00
# endif
/*-----------------------------------------------------------*/
/* File private functions. --------------------------------*/
/*
2024-01-05 04:14:26 -05:00
* Creates the idle tasks during scheduler start .
2022-02-24 07:14:22 -05:00
*/
static BaseType_t prvCreateIdleTasks ( void ) ;
2024-01-05 04:14:26 -05:00
# if ( configNUMBER_OF_CORES > 1 )
2022-02-24 07:14:22 -05:00
/*
* Checks to see if another task moved the current task out of the ready
2024-01-05 04:14:26 -05:00
* list while it was waiting to enter a critical section and yields , if so .
2022-02-24 07:14:22 -05:00
*/
2024-01-05 04:14:26 -05:00
static void prvCheckForRunStateChange ( void ) ;
# endif /* #if ( configNUMBER_OF_CORES > 1 ) */
2022-02-24 07:14:22 -05:00
2024-01-05 04:14:26 -05:00
# if ( configNUMBER_OF_CORES > 1 )
2022-02-24 07:14:22 -05:00
/*
* Yields a core , or cores if multiple priorities are not allowed to run
* simultaneously , to allow the task pxTCB to run .
*/
2024-01-05 04:14:26 -05:00
static void prvYieldForTask ( const TCB_t * pxTCB ) ;
# endif /* #if ( configNUMBER_OF_CORES > 1 ) */
# if ( configNUMBER_OF_CORES > 1 )
2022-02-24 07:14:22 -05:00
/*
2024-01-05 04:14:26 -05:00
* Selects the highest priority available task for the given core .
2022-02-24 07:14:22 -05:00
*/
2024-01-05 04:14:26 -05:00
static void prvSelectHighestPriorityTask ( BaseType_t xCoreID ) ;
# endif /* #if ( configNUMBER_OF_CORES > 1 ) */
2022-02-24 07:14:22 -05:00
/**
* Utility task that simply returns pdTRUE if the task referenced by xTask is
* currently in the Suspended state , or pdFALSE if the task referenced by xTask
* is in any other state .
*/
# if ( INCLUDE_vTaskSuspend == 1 )
static BaseType_t prvTaskIsTaskSuspended ( const TaskHandle_t xTask ) PRIVILEGED_FUNCTION ;
# endif /* INCLUDE_vTaskSuspend */
/*
* Utility to ready all the lists used by the scheduler . This is called
* automatically upon the creation of the first task .
*/
static void prvInitialiseTaskLists ( void ) PRIVILEGED_FUNCTION ;
/*
* The idle task , which as all tasks is implemented as a never ending loop .
* The idle task is automatically created and added to the ready lists upon
* creation of the first user task .
*
2024-01-05 04:14:26 -05:00
* In the FreeRTOS SMP , configNUMBER_OF_CORES - 1 passive idle tasks are also
* created to ensure that each core has an idle task to run when no other
* task is available to run .
*
* The portTASK_FUNCTION_PROTO ( ) macro is used to allow port / compiler specific
* language extensions . The equivalent prototype for these functions are :
*
* void prvIdleTask ( void * pvParameters ) ;
* void prvPassiveIdleTask ( void * pvParameters ) ;
*
2022-02-24 07:14:22 -05:00
*/
static portTASK_FUNCTION_PROTO ( prvIdleTask , pvParameters ) PRIVILEGED_FUNCTION ;
2024-01-05 04:14:26 -05:00
# if ( configNUMBER_OF_CORES > 1 )
static portTASK_FUNCTION_PROTO ( prvPassiveIdleTask , pvParameters ) PRIVILEGED_FUNCTION ;
2022-02-24 07:14:22 -05:00
# endif
/*
* Utility to free all memory allocated by the scheduler to hold a TCB ,
* including the stack pointed to by the TCB .
*
* This does not free memory allocated by the task itself ( i . e . memory
* allocated by calls to pvPortMalloc from within the tasks application code ) .
*/
# if ( INCLUDE_vTaskDelete == 1 )
static void prvDeleteTCB ( TCB_t * pxTCB ) PRIVILEGED_FUNCTION ;
# endif
/*
* Used only by the idle task . This checks to see if anything has been placed
* in the list of tasks waiting to be deleted . If so the task is cleaned up
* and its TCB deleted .
*/
static void prvCheckTasksWaitingTermination ( void ) PRIVILEGED_FUNCTION ;
/*
* The currently executing task is entering the Blocked state . Add the task to
* either the current or the overflow delayed task list .
*/
static void prvAddCurrentTaskToDelayedList ( TickType_t xTicksToWait ,
const BaseType_t xCanBlockIndefinitely ) PRIVILEGED_FUNCTION ;
/*
* Fills an TaskStatus_t structure with information on each task that is
* referenced from the pxList list ( which may be a ready list , a delayed list ,
* a suspended list , etc . ) .
*
* THIS FUNCTION IS INTENDED FOR DEBUGGING ONLY , AND SHOULD NOT BE CALLED FROM
* NORMAL APPLICATION CODE .
*/
# if ( configUSE_TRACE_FACILITY == 1 )
static UBaseType_t prvListTasksWithinSingleList ( TaskStatus_t * pxTaskStatusArray ,
List_t * pxList ,
eTaskState eState ) PRIVILEGED_FUNCTION ;
# endif
/*
* Searches pxList for a task with name pcNameToQuery - returning a handle to
* the task if it is found , or NULL if the task is not found .
*/
# if ( INCLUDE_xTaskGetHandle == 1 )
static TCB_t * prvSearchForNameWithinSingleList ( List_t * pxList ,
const char pcNameToQuery [ ] ) PRIVILEGED_FUNCTION ;
# endif
/*
* When a task is created , the stack of the task is filled with a known value .
* 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 ) || ( INCLUDE_uxTaskGetStackHighWaterMark2 == 1 ) )
static configSTACK_DEPTH_TYPE prvTaskCheckFreeStackSpace ( const uint8_t * pucStackByte ) PRIVILEGED_FUNCTION ;
# endif
/*
* Return the amount of time , in ticks , that will pass before the kernel will
* next move a task from the Blocked state to the Running state .
*
* This conditional compilation should use inequality to 0 , not equality to 1.
* This is to ensure portSUPPRESS_TICKS_AND_SLEEP ( ) can be called when user
* defined low power mode implementations require configUSE_TICKLESS_IDLE to be
* set to a value other than 1.
*/
# if ( configUSE_TICKLESS_IDLE != 0 )
static TickType_t prvGetExpectedIdleTime ( void ) PRIVILEGED_FUNCTION ;
# endif
/*
* Set xNextTaskUnblockTime to the time at which the next Blocked state task
* will exit the Blocked state .
*/
static void prvResetNextTaskUnblockTime ( void ) PRIVILEGED_FUNCTION ;
2024-01-05 04:14:26 -05:00
# if ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 )
2022-02-24 07:14:22 -05:00
/*
* Helper function used to pad task names with spaces when printing out
* human readable tables of task information .
*/
static char * prvWriteNameToBuffer ( char * pcBuffer ,
const char * pcTaskName ) PRIVILEGED_FUNCTION ;
# endif
/*
* Called after a Task_t structure has been allocated either statically or
* dynamically to fill in the structure ' s members .
*/
static void prvInitialiseNewTask ( TaskFunction_t pxTaskCode ,
2024-01-05 04:14:26 -05:00
const char * const pcName ,
2022-02-24 07:14:22 -05:00
const uint32_t ulStackDepth ,
void * const pvParameters ,
UBaseType_t uxPriority ,
TaskHandle_t * const pxCreatedTask ,
TCB_t * pxNewTCB ,
const MemoryRegion_t * const xRegions ) PRIVILEGED_FUNCTION ;
/*
* Called after a new task has been created and initialised to place the task
* under the control of the scheduler .
*/
static void prvAddNewTaskToReadyList ( TCB_t * pxNewTCB ) PRIVILEGED_FUNCTION ;
2024-01-05 04:14:26 -05:00
/*
* Create a task with static buffer for both TCB and stack . Returns a handle to
* the task if it is created successfully . Otherwise , returns NULL .
*/
# if ( configSUPPORT_STATIC_ALLOCATION == 1 )
static TCB_t * prvCreateStaticTask ( TaskFunction_t pxTaskCode ,
const char * const pcName ,
const uint32_t ulStackDepth ,
void * const pvParameters ,
UBaseType_t uxPriority ,
StackType_t * const puxStackBuffer ,
StaticTask_t * const pxTaskBuffer ,
TaskHandle_t * const pxCreatedTask ) PRIVILEGED_FUNCTION ;
# endif /* #if ( configSUPPORT_STATIC_ALLOCATION == 1 ) */
/*
* Create a restricted task with static buffer for both TCB and stack . Returns
* a handle to the task if it is created successfully . Otherwise , returns NULL .
*/
# if ( ( portUSING_MPU_WRAPPERS == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 1 ) )
static TCB_t * prvCreateRestrictedStaticTask ( const TaskParameters_t * const pxTaskDefinition ,
TaskHandle_t * const pxCreatedTask ) PRIVILEGED_FUNCTION ;
# endif /* #if ( ( portUSING_MPU_WRAPPERS == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 1 ) ) */
/*
* Create a restricted task with static buffer for task stack and allocated buffer
* for TCB . Returns a handle to the task if it is created successfully . Otherwise ,
* returns NULL .
*/
# if ( ( portUSING_MPU_WRAPPERS == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) )
static TCB_t * prvCreateRestrictedTask ( const TaskParameters_t * const pxTaskDefinition ,
TaskHandle_t * const pxCreatedTask ) PRIVILEGED_FUNCTION ;
# endif /* #if ( ( portUSING_MPU_WRAPPERS == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) ) */
/*
* Create a task with allocated buffer for both TCB and stack . Returns a handle to
* the task if it is created successfully . Otherwise , returns NULL .
*/
# if ( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
static TCB_t * prvCreateTask ( TaskFunction_t pxTaskCode ,
const char * const pcName ,
const configSTACK_DEPTH_TYPE usStackDepth ,
void * const pvParameters ,
UBaseType_t uxPriority ,
TaskHandle_t * const pxCreatedTask ) PRIVILEGED_FUNCTION ;
# endif /* #if ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) */
2022-02-24 07:14:22 -05:00
/*
* freertos_tasks_c_additions_init ( ) should only be called if the user definable
* macro FREERTOS_TASKS_C_ADDITIONS_INIT ( ) is defined , as that is the only macro
* called by the function .
*/
# ifdef FREERTOS_TASKS_C_ADDITIONS_INIT
static void freertos_tasks_c_additions_init ( void ) PRIVILEGED_FUNCTION ;
# endif
2024-01-05 04:14:26 -05:00
# if ( configUSE_PASSIVE_IDLE_HOOK == 1 )
extern void vApplicationPassiveIdleHook ( void ) ;
# endif /* #if ( configUSE_PASSIVE_IDLE_HOOK == 1 ) */
2022-02-24 07:14:22 -05:00
2024-01-05 04:14:26 -05:00
# if ( ( configUSE_TRACE_FACILITY == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 ) )
2022-02-24 07:14:22 -05:00
2024-01-05 04:14:26 -05:00
/*
* Convert the snprintf return value to the number of characters
* written . The following are the possible cases :
*
* 1. The buffer supplied to snprintf is large enough to hold the
* generated string . The return value in this case is the number
* of characters actually written , not counting the terminating
* null character .
* 2. The buffer supplied to snprintf is NOT large enough to hold
* the generated string . The return value in this case is the
* number of characters that would have been written if the
* buffer had been sufficiently large , not counting the
* terminating null character .
* 3. Encoding error . The return value in this case is a negative
* number .
*
* From 1 and 2 above = = > Only when the return value is non - negative
* and less than the supplied buffer length , the string has been
* completely written .
*/
static size_t prvSnprintfReturnValueToCharsWritten ( int iSnprintfReturnValue ,
size_t n ) ;
2022-02-24 07:14:22 -05:00
2024-01-05 04:14:26 -05:00
# endif /* #if ( ( configUSE_TRACE_FACILITY == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 ) ) */
2022-02-24 07:14:22 -05:00
/*-----------------------------------------------------------*/
2024-01-05 04:14:26 -05:00
# if ( configNUMBER_OF_CORES > 1 )
static void prvCheckForRunStateChange ( void )
2022-02-24 07:14:22 -05:00
{
2024-01-05 04:14:26 -05:00
UBaseType_t uxPrevCriticalNesting ;
const TCB_t * pxThisTCB ;
/* This must only be called from within a task. */
portASSERT_IF_IN_ISR ( ) ;
2022-02-24 07:14:22 -05:00
/* This function is always called with interrupts disabled
* so this is safe . */
pxThisTCB = pxCurrentTCBs [ portGET_CORE_ID ( ) ] ;
2024-01-05 04:14:26 -05:00
while ( pxThisTCB - > xTaskRunState = = taskTASK_SCHEDULED_TO_YIELD )
2022-02-24 07:14:22 -05:00
{
/* We are only here if we just entered a critical section
* or if we just suspended the scheduler , and another task
* has requested that we yield .
*
* This is slightly complicated since we need to save and restore
* the suspension and critical nesting counts , as well as release
2024-01-05 04:14:26 -05:00
* and reacquire the correct locks . And then , do it all over again
2022-02-24 07:14:22 -05:00
* if our state changed again during the reacquisition . */
2024-01-05 04:14:26 -05:00
uxPrevCriticalNesting = portGET_CRITICAL_NESTING_COUNT ( ) ;
2022-02-24 07:14:22 -05:00
if ( uxPrevCriticalNesting > 0U )
{
2024-01-05 04:14:26 -05:00
portSET_CRITICAL_NESTING_COUNT ( 0U ) ;
2022-02-24 07:14:22 -05:00
portRELEASE_ISR_LOCK ( ) ;
}
else
{
2024-01-05 04:14:26 -05:00
/* The scheduler is suspended. uxSchedulerSuspended is updated
* only when the task is not requested to yield . */
mtCOVERAGE_TEST_MARKER ( ) ;
2022-02-24 07:14:22 -05:00
}
2024-01-05 04:14:26 -05:00
portRELEASE_TASK_LOCK ( ) ;
2022-02-24 07:14:22 -05:00
portMEMORY_BARRIER ( ) ;
2024-01-05 04:14:26 -05:00
configASSERT ( pxThisTCB - > xTaskRunState = = taskTASK_SCHEDULED_TO_YIELD ) ;
2022-02-24 07:14:22 -05:00
portENABLE_INTERRUPTS ( ) ;
/* Enabling interrupts should cause this core to immediately
* service the pending interrupt and yield . If the run state is still
* yielding here then that is a problem . */
2024-01-05 04:14:26 -05:00
configASSERT ( pxThisTCB - > xTaskRunState ! = taskTASK_SCHEDULED_TO_YIELD ) ;
2022-02-24 07:14:22 -05:00
portDISABLE_INTERRUPTS ( ) ;
portGET_TASK_LOCK ( ) ;
portGET_ISR_LOCK ( ) ;
2024-01-05 04:14:26 -05:00
portSET_CRITICAL_NESTING_COUNT ( uxPrevCriticalNesting ) ;
2022-02-24 07:14:22 -05:00
if ( uxPrevCriticalNesting = = 0U )
{
portRELEASE_ISR_LOCK ( ) ;
}
}
}
2024-01-05 04:14:26 -05:00
# endif /* #if ( configNUMBER_OF_CORES > 1 ) */
2022-02-24 07:14:22 -05:00
/*-----------------------------------------------------------*/
2024-01-05 04:14:26 -05:00
# if ( configNUMBER_OF_CORES > 1 )
static void prvYieldForTask ( const TCB_t * pxTCB )
2022-02-24 07:14:22 -05:00
{
2024-01-05 04:14:26 -05:00
BaseType_t xLowestPriorityToPreempt ;
BaseType_t xCurrentCoreTaskPriority ;
BaseType_t xLowestPriorityCore = ( BaseType_t ) - 1 ;
BaseType_t xCoreID ;
2022-02-24 07:14:22 -05:00
2024-01-05 04:14:26 -05:00
# if ( configRUN_MULTIPLE_PRIORITIES == 0 )
BaseType_t xYieldCount = 0 ;
# endif /* #if ( configRUN_MULTIPLE_PRIORITIES == 0 ) */
2022-02-24 07:14:22 -05:00
2024-01-05 04:14:26 -05:00
/* This must be called from a critical section. */
configASSERT ( portGET_CRITICAL_NESTING_COUNT ( ) > 0U ) ;
2022-02-24 07:14:22 -05:00
2024-01-05 04:14:26 -05:00
# if ( configRUN_MULTIPLE_PRIORITIES == 0 )
2022-02-24 07:14:22 -05:00
/* No task should yield for this one if it is a lower priority
* than priority level of currently ready tasks . */
2024-01-05 04:14:26 -05:00
if ( pxTCB - > uxPriority > = uxTopReadyPriority )
# else
/* Yield is not required for a task which is already running. */
if ( taskTASK_IS_RUNNING ( pxTCB ) = = pdFALSE )
# endif
{
xLowestPriorityToPreempt = ( BaseType_t ) pxTCB - > uxPriority ;
2022-02-24 07:14:22 -05:00
2024-01-05 04:14:26 -05:00
/* xLowestPriorityToPreempt will be decremented to -1 if the priority of pxTCB
* is 0. This is ok as we will give system idle tasks a priority of - 1 below . */
- - xLowestPriorityToPreempt ;
2022-02-24 07:14:22 -05:00
2024-01-05 04:14:26 -05:00
for ( xCoreID = ( BaseType_t ) 0 ; xCoreID < ( BaseType_t ) configNUMBER_OF_CORES ; xCoreID + + )
{
xCurrentCoreTaskPriority = ( BaseType_t ) pxCurrentTCBs [ xCoreID ] - > uxPriority ;
2022-02-24 07:14:22 -05:00
2024-01-05 04:14:26 -05:00
/* System idle tasks are being assigned a priority of tskIDLE_PRIORITY - 1 here. */
if ( ( pxCurrentTCBs [ xCoreID ] - > uxTaskAttributes & taskATTRIBUTE_IS_IDLE ) ! = 0U )
{
xCurrentCoreTaskPriority = xCurrentCoreTaskPriority - 1 ;
}
2022-02-24 07:14:22 -05:00
2024-01-05 04:14:26 -05:00
if ( ( taskTASK_IS_RUNNING ( pxCurrentTCBs [ xCoreID ] ) ! = pdFALSE ) & & ( xYieldPendings [ xCoreID ] = = pdFALSE ) )
2022-02-24 07:14:22 -05:00
{
2024-01-05 04:14:26 -05:00
# if ( configRUN_MULTIPLE_PRIORITIES == 0 )
if ( taskTASK_IS_RUNNING ( pxTCB ) = = pdFALSE )
2022-02-24 07:14:22 -05:00
# endif
{
2024-01-05 04:14:26 -05:00
if ( xCurrentCoreTaskPriority < = xLowestPriorityToPreempt )
{
# if ( configUSE_CORE_AFFINITY == 1 )
if ( ( pxTCB - > uxCoreAffinityMask & ( ( UBaseType_t ) 1U < < ( UBaseType_t ) xCoreID ) ) ! = 0U )
# endif
{
# if ( configUSE_TASK_PREEMPTION_DISABLE == 1 )
if ( pxCurrentTCBs [ xCoreID ] - > xPreemptionDisable = = pdFALSE )
# endif
{
xLowestPriorityToPreempt = xCurrentCoreTaskPriority ;
xLowestPriorityCore = xCoreID ;
}
}
}
else
{
mtCOVERAGE_TEST_MARKER ( ) ;
}
}
# if ( configRUN_MULTIPLE_PRIORITIES == 0 )
{
/* Yield all currently running non-idle tasks with a priority lower than
* the task that needs to run . */
if ( ( xCurrentCoreTaskPriority > ( ( BaseType_t ) tskIDLE_PRIORITY - 1 ) ) & &
( xCurrentCoreTaskPriority < ( BaseType_t ) pxTCB - > uxPriority ) )
{
prvYieldCore ( xCoreID ) ;
xYieldCount + + ;
}
else
{
mtCOVERAGE_TEST_MARKER ( ) ;
}
2022-02-24 07:14:22 -05:00
}
2024-01-05 04:14:26 -05:00
# endif /* #if ( configRUN_MULTIPLE_PRIORITIES == 0 ) */
}
else
{
mtCOVERAGE_TEST_MARKER ( ) ;
2022-02-24 07:14:22 -05:00
}
}
2024-01-05 04:14:26 -05:00
# if ( configRUN_MULTIPLE_PRIORITIES == 0 )
if ( ( xYieldCount = = 0 ) & & ( xLowestPriorityCore > = 0 ) )
# else /* #if ( configRUN_MULTIPLE_PRIORITIES == 0 ) */
if ( xLowestPriorityCore > = 0 )
# endif /* #if ( configRUN_MULTIPLE_PRIORITIES == 0 ) */
2022-02-24 07:14:22 -05:00
{
2024-01-05 04:14:26 -05:00
prvYieldCore ( xLowestPriorityCore ) ;
2022-02-24 07:14:22 -05:00
}
2024-01-05 04:14:26 -05:00
# if ( configRUN_MULTIPLE_PRIORITIES == 0 )
/* Verify that the calling core always yields to higher priority tasks. */
if ( ( ( pxCurrentTCBs [ portGET_CORE_ID ( ) ] - > uxTaskAttributes & taskATTRIBUTE_IS_IDLE ) = = 0U ) & &
( pxTCB - > uxPriority > pxCurrentTCBs [ portGET_CORE_ID ( ) ] - > uxPriority ) )
2022-02-24 07:14:22 -05:00
{
2024-01-05 04:14:26 -05:00
configASSERT ( ( xYieldPendings [ portGET_CORE_ID ( ) ] = = pdTRUE ) | |
( taskTASK_IS_RUNNING ( pxCurrentTCBs [ portGET_CORE_ID ( ) ] ) = = pdFALSE ) ) ;
2022-02-24 07:14:22 -05:00
}
2024-01-05 04:14:26 -05:00
# endif
2022-02-24 07:14:22 -05:00
}
}
2024-01-05 04:14:26 -05:00
# endif /* #if ( configNUMBER_OF_CORES > 1 ) */
2022-02-24 07:14:22 -05:00
/*-----------------------------------------------------------*/
2024-01-05 04:14:26 -05:00
# if ( configNUMBER_OF_CORES > 1 )
static void prvSelectHighestPriorityTask ( BaseType_t xCoreID )
2022-02-24 07:14:22 -05:00
{
UBaseType_t uxCurrentPriority = uxTopReadyPriority ;
BaseType_t xTaskScheduled = pdFALSE ;
BaseType_t xDecrementTopPriority = pdTRUE ;
2024-01-05 04:14:26 -05:00
# if ( configUSE_CORE_AFFINITY == 1 )
const TCB_t * pxPreviousTCB = NULL ;
2022-02-24 07:14:22 -05:00
# endif
2024-01-05 04:14:26 -05:00
# if ( configRUN_MULTIPLE_PRIORITIES == 0 )
2022-02-24 07:14:22 -05:00
BaseType_t xPriorityDropped = pdFALSE ;
# endif
2024-01-05 04:14:26 -05:00
/* This function should be called when scheduler is running. */
configASSERT ( xSchedulerRunning = = pdTRUE ) ;
/* A new task is created and a running task with the same priority yields
* itself to run the new task . When a running task yields itself , it is still
* in the ready list . This running task will be selected before the new task
* since the new task is always added to the end of the ready list .
* The other problem is that the running task still in the same position of
* the ready list when it yields itself . It is possible that it will be selected
* earlier then other tasks which waits longer than this task .
*
* To fix these problems , the running task should be put to the end of the
* ready list before searching for the ready task in the ready list . */
if ( listIS_CONTAINED_WITHIN ( & ( pxReadyTasksLists [ pxCurrentTCBs [ xCoreID ] - > uxPriority ] ) ,
& pxCurrentTCBs [ xCoreID ] - > xStateListItem ) = = pdTRUE )
{
( void ) uxListRemove ( & pxCurrentTCBs [ xCoreID ] - > xStateListItem ) ;
vListInsertEnd ( & ( pxReadyTasksLists [ pxCurrentTCBs [ xCoreID ] - > uxPriority ] ) ,
& pxCurrentTCBs [ xCoreID ] - > xStateListItem ) ;
}
2022-02-24 07:14:22 -05:00
while ( xTaskScheduled = = pdFALSE )
{
2024-01-05 04:14:26 -05:00
# if ( configRUN_MULTIPLE_PRIORITIES == 0 )
{
if ( uxCurrentPriority < uxTopReadyPriority )
2022-02-24 07:14:22 -05:00
{
2024-01-05 04:14:26 -05:00
/* We can't schedule any tasks, other than idle, that have a
* priority lower than the priority of a task currently running
* on another core . */
uxCurrentPriority = tskIDLE_PRIORITY ;
2022-02-24 07:14:22 -05:00
}
2024-01-05 04:14:26 -05:00
}
2022-02-24 07:14:22 -05:00
# endif
if ( listLIST_IS_EMPTY ( & ( pxReadyTasksLists [ uxCurrentPriority ] ) ) = = pdFALSE )
{
2024-01-05 04:14:26 -05:00
const List_t * const pxReadyList = & ( pxReadyTasksLists [ uxCurrentPriority ] ) ;
const ListItem_t * pxEndMarker = listGET_END_MARKER ( pxReadyList ) ;
ListItem_t * pxIterator ;
2022-02-24 07:14:22 -05:00
/* The ready task list for uxCurrentPriority is not empty, so uxTopReadyPriority
2024-01-05 04:14:26 -05:00
* must not be decremented any further . */
2022-02-24 07:14:22 -05:00
xDecrementTopPriority = pdFALSE ;
2024-01-05 04:14:26 -05:00
for ( pxIterator = listGET_HEAD_ENTRY ( pxReadyList ) ; pxIterator ! = pxEndMarker ; pxIterator = listGET_NEXT ( pxIterator ) )
2022-02-24 07:14:22 -05:00
{
2024-01-05 04:14:26 -05:00
/* MISRA Ref 11.5.3 [Void pointer assignment] */
/* More details at: https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/MISRA.md#rule-115 */
/* coverity[misra_c_2012_rule_11_5_violation] */
TCB_t * pxTCB = ( TCB_t * ) listGET_LIST_ITEM_OWNER ( pxIterator ) ;
2022-02-24 07:14:22 -05:00
2024-01-05 04:14:26 -05:00
# if ( configRUN_MULTIPLE_PRIORITIES == 0 )
2022-02-24 07:14:22 -05:00
{
2024-01-05 04:14:26 -05:00
/* When falling back to the idle priority because only one priority
* level is allowed to run at a time , we should ONLY schedule the true
* idle tasks , not user tasks at the idle priority . */
if ( uxCurrentPriority < uxTopReadyPriority )
2022-02-24 07:14:22 -05:00
{
2024-01-05 04:14:26 -05:00
if ( ( pxTCB - > uxTaskAttributes & taskATTRIBUTE_IS_IDLE ) = = 0U )
2022-02-24 07:14:22 -05:00
{
2024-01-05 04:14:26 -05:00
continue ;
2022-02-24 07:14:22 -05:00
}
}
2024-01-05 04:14:26 -05:00
}
# endif /* #if ( configRUN_MULTIPLE_PRIORITIES == 0 ) */
2022-02-24 07:14:22 -05:00
if ( pxTCB - > xTaskRunState = = taskTASK_NOT_RUNNING )
{
2024-01-05 04:14:26 -05:00
# if ( configUSE_CORE_AFFINITY == 1 )
if ( ( pxTCB - > uxCoreAffinityMask & ( ( UBaseType_t ) 1U < < ( UBaseType_t ) xCoreID ) ) ! = 0U )
2022-02-24 07:14:22 -05:00
# endif
{
2024-01-05 04:14:26 -05:00
/* If the task is not being executed by any core swap it in. */
2022-02-24 07:14:22 -05:00
pxCurrentTCBs [ xCoreID ] - > xTaskRunState = taskTASK_NOT_RUNNING ;
2024-01-05 04:14:26 -05:00
# if ( configUSE_CORE_AFFINITY == 1 )
2022-02-24 07:14:22 -05:00
pxPreviousTCB = pxCurrentTCBs [ xCoreID ] ;
# endif
2024-01-05 04:14:26 -05:00
pxTCB - > xTaskRunState = xCoreID ;
2022-02-24 07:14:22 -05:00
pxCurrentTCBs [ xCoreID ] = pxTCB ;
xTaskScheduled = pdTRUE ;
}
}
else if ( pxTCB = = pxCurrentTCBs [ xCoreID ] )
{
2024-01-05 04:14:26 -05:00
configASSERT ( ( pxTCB - > xTaskRunState = = xCoreID ) | | ( pxTCB - > xTaskRunState = = taskTASK_SCHEDULED_TO_YIELD ) ) ;
# if ( configUSE_CORE_AFFINITY == 1 )
if ( ( pxTCB - > uxCoreAffinityMask & ( ( UBaseType_t ) 1U < < ( UBaseType_t ) xCoreID ) ) ! = 0U )
2022-02-24 07:14:22 -05:00
# endif
{
2024-01-05 04:14:26 -05:00
/* The task is already running on this core, mark it as scheduled. */
pxTCB - > xTaskRunState = xCoreID ;
2022-02-24 07:14:22 -05:00
xTaskScheduled = pdTRUE ;
}
}
2024-01-05 04:14:26 -05:00
else
{
/* This task is running on the core other than xCoreID. */
mtCOVERAGE_TEST_MARKER ( ) ;
}
2022-02-24 07:14:22 -05:00
if ( xTaskScheduled ! = pdFALSE )
{
2024-01-05 04:14:26 -05:00
/* A task has been selected to run on this core. */
2022-02-24 07:14:22 -05:00
break ;
}
2024-01-05 04:14:26 -05:00
}
2022-02-24 07:14:22 -05:00
}
else
{
if ( xDecrementTopPriority ! = pdFALSE )
{
uxTopReadyPriority - - ;
2024-01-05 04:14:26 -05:00
# if ( configRUN_MULTIPLE_PRIORITIES == 0 )
{
xPriorityDropped = pdTRUE ;
}
2022-02-24 07:14:22 -05:00
# endif
}
}
2024-01-05 04:14:26 -05:00
/* There are configNUMBER_OF_CORES Idle tasks created when scheduler started.
* The scheduler should be able to select a task to run when uxCurrentPriority
* is tskIDLE_PRIORITY . uxCurrentPriority is never decreased to value blow
* tskIDLE_PRIORITY . */
if ( uxCurrentPriority > tskIDLE_PRIORITY )
2022-02-24 07:14:22 -05:00
{
2024-01-05 04:14:26 -05:00
uxCurrentPriority - - ;
}
else
{
/* This function is called when idle task is not created. Break the
* loop to prevent uxCurrentPriority overrun . */
break ;
2022-02-24 07:14:22 -05:00
}
}
2024-01-05 04:14:26 -05:00
# if ( configRUN_MULTIPLE_PRIORITIES == 0 )
{
if ( xTaskScheduled = = pdTRUE )
2022-02-24 07:14:22 -05:00
{
2024-01-05 04:14:26 -05:00
if ( xPriorityDropped ! = pdFALSE )
2022-02-24 07:14:22 -05:00
{
2024-01-05 04:14:26 -05:00
/* There may be several ready tasks that were being prevented from running because there was
* a higher priority task running . Now that the last of the higher priority tasks is no longer
* running , make sure all the other idle tasks yield . */
BaseType_t x ;
for ( x = ( BaseType_t ) 0 ; x < ( BaseType_t ) configNUMBER_OF_CORES ; x + + )
2022-02-24 07:14:22 -05:00
{
2024-01-05 04:14:26 -05:00
if ( ( pxCurrentTCBs [ x ] - > uxTaskAttributes & taskATTRIBUTE_IS_IDLE ) ! = 0U )
{
prvYieldCore ( x ) ;
}
2022-02-24 07:14:22 -05:00
}
}
}
2024-01-05 04:14:26 -05:00
}
# endif /* #if ( configRUN_MULTIPLE_PRIORITIES == 0 ) */
2022-02-24 07:14:22 -05:00
2024-01-05 04:14:26 -05:00
# if ( configUSE_CORE_AFFINITY == 1 )
{
if ( xTaskScheduled = = pdTRUE )
{
2022-02-24 07:14:22 -05:00
if ( ( pxPreviousTCB ! = NULL ) & & ( listIS_CONTAINED_WITHIN ( & ( pxReadyTasksLists [ pxPreviousTCB - > uxPriority ] ) , & ( pxPreviousTCB - > xStateListItem ) ) ! = pdFALSE ) )
{
2024-01-05 04:14:26 -05:00
/* A ready task was just evicted from this core. See if it can be
* scheduled on any other core . */
2022-02-24 07:14:22 -05:00
UBaseType_t uxCoreMap = pxPreviousTCB - > uxCoreAffinityMask ;
2024-01-05 04:14:26 -05:00
BaseType_t xLowestPriority = ( BaseType_t ) pxPreviousTCB - > uxPriority ;
2022-02-24 07:14:22 -05:00
BaseType_t xLowestPriorityCore = - 1 ;
2024-01-05 04:14:26 -05:00
BaseType_t x ;
if ( ( pxPreviousTCB - > uxTaskAttributes & taskATTRIBUTE_IS_IDLE ) ! = 0U )
{
xLowestPriority = xLowestPriority - 1 ;
}
2022-02-24 07:14:22 -05:00
2024-01-05 04:14:26 -05:00
if ( ( uxCoreMap & ( ( UBaseType_t ) 1U < < ( UBaseType_t ) xCoreID ) ) ! = 0U )
2022-02-24 07:14:22 -05:00
{
2024-01-05 04:14:26 -05:00
/* pxPreviousTCB was removed from this core and this core is not excluded
* from it ' s core affinity mask .
*
* pxPreviousTCB is preempted by the new higher priority task
* pxCurrentTCBs [ xCoreID ] . When searching a new core for pxPreviousTCB ,
* we do not need to look at the cores on which pxCurrentTCBs [ xCoreID ]
* is allowed to run . The reason is - when more than one cores are
* eligible for an incoming task , we preempt the core with the minimum
* priority task . Because this core ( i . e . xCoreID ) was preempted for
* pxCurrentTCBs [ xCoreID ] , this means that all the others cores
* where pxCurrentTCBs [ xCoreID ] can run , are running tasks with priority
* no lower than pxPreviousTCB ' s priority . Therefore , the only cores where
* which can be preempted for pxPreviousTCB are the ones where
* pxCurrentTCBs [ xCoreID ] is not allowed to run ( and obviously ,
* pxPreviousTCB is allowed to run ) .
*
* This is an optimization which reduces the number of cores needed to be
* searched for pxPreviousTCB to run . */
2022-02-24 07:14:22 -05:00
uxCoreMap & = ~ ( pxCurrentTCBs [ xCoreID ] - > uxCoreAffinityMask ) ;
}
else
{
2024-01-05 04:14:26 -05:00
/* pxPreviousTCB's core affinity mask is changed and it is no longer
* allowed to run on this core . Searching all the cores in pxPreviousTCB ' s
* new core affinity mask to find a core on which it can run . */
2022-02-24 07:14:22 -05:00
}
2024-01-05 04:14:26 -05:00
uxCoreMap & = ( ( 1U < < configNUMBER_OF_CORES ) - 1U ) ;
2022-02-24 07:14:22 -05:00
2024-01-05 04:14:26 -05:00
for ( x = ( ( BaseType_t ) configNUMBER_OF_CORES - 1 ) ; x > = ( BaseType_t ) 0 ; x - - )
2022-02-24 07:14:22 -05:00
{
2024-01-05 04:14:26 -05:00
UBaseType_t uxCore = ( UBaseType_t ) x ;
BaseType_t xTaskPriority ;
2022-02-24 07:14:22 -05:00
2024-01-05 04:14:26 -05:00
if ( ( uxCoreMap & ( ( UBaseType_t ) 1U < < uxCore ) ) ! = 0U )
{
xTaskPriority = ( BaseType_t ) pxCurrentTCBs [ uxCore ] - > uxPriority ;
2022-02-24 07:14:22 -05:00
2024-01-05 04:14:26 -05:00
if ( ( pxCurrentTCBs [ uxCore ] - > uxTaskAttributes & taskATTRIBUTE_IS_IDLE ) ! = 0U )
{
xTaskPriority = xTaskPriority - ( BaseType_t ) 1 ;
}
2022-02-24 07:14:22 -05:00
2024-01-05 04:14:26 -05:00
uxCoreMap & = ~ ( ( UBaseType_t ) 1U < < uxCore ) ;
2022-02-24 07:14:22 -05:00
2024-01-05 04:14:26 -05:00
if ( ( xTaskPriority < xLowestPriority ) & &
( taskTASK_IS_RUNNING ( pxCurrentTCBs [ uxCore ] ) ! = pdFALSE ) & &
( xYieldPendings [ uxCore ] = = pdFALSE ) )
2022-02-24 07:14:22 -05:00
{
2024-01-05 04:14:26 -05:00
# if ( configUSE_TASK_PREEMPTION_DISABLE == 1 )
if ( pxCurrentTCBs [ uxCore ] - > xPreemptionDisable = = pdFALSE )
# endif
{
xLowestPriority = xTaskPriority ;
xLowestPriorityCore = ( BaseType_t ) uxCore ;
}
2022-02-24 07:14:22 -05:00
}
}
}
2024-01-05 04:14:26 -05:00
if ( xLowestPriorityCore > = 0 )
2022-02-24 07:14:22 -05:00
{
prvYieldCore ( xLowestPriorityCore ) ;
}
}
2024-01-05 04:14:26 -05:00
}
}
# endif /* #if ( configUSE_CORE_AFFINITY == 1 ) */
2022-02-24 07:14:22 -05:00
}
2024-01-05 04:14:26 -05:00
# endif /* ( configNUMBER_OF_CORES > 1 ) */
2022-02-24 07:14:22 -05:00
/*-----------------------------------------------------------*/
# if ( configSUPPORT_STATIC_ALLOCATION == 1 )
2024-01-05 04:14:26 -05:00
static TCB_t * prvCreateStaticTask ( TaskFunction_t pxTaskCode ,
const char * const pcName ,
const uint32_t ulStackDepth ,
void * const pvParameters ,
UBaseType_t uxPriority ,
StackType_t * const puxStackBuffer ,
StaticTask_t * const pxTaskBuffer ,
TaskHandle_t * const pxCreatedTask )
2022-02-24 07:14:22 -05:00
{
TCB_t * pxNewTCB ;
configASSERT ( puxStackBuffer ! = NULL ) ;
configASSERT ( pxTaskBuffer ! = NULL ) ;
# if ( configASSERT_DEFINED == 1 )
2024-01-05 04:14:26 -05:00
{
/* Sanity check that the size of the structure used to declare a
* variable of type StaticTask_t equals the size of the real task
* structure . */
volatile size_t xSize = sizeof ( StaticTask_t ) ;
configASSERT ( xSize = = sizeof ( TCB_t ) ) ;
( void ) xSize ; /* Prevent unused variable warning when configASSERT() is not used. */
}
2022-02-24 07:14:22 -05:00
# endif /* configASSERT_DEFINED */
if ( ( pxTaskBuffer ! = NULL ) & & ( puxStackBuffer ! = NULL ) )
{
/* The memory used for the task's TCB and stack are passed into this
* function - use them . */
2024-01-05 04:14:26 -05:00
/* MISRA Ref 11.3.1 [Misaligned access] */
/* More details at: https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/MISRA.md#rule-113 */
/* coverity[misra_c_2012_rule_11_3_violation] */
pxNewTCB = ( TCB_t * ) pxTaskBuffer ;
( void ) memset ( ( void * ) pxNewTCB , 0x00 , sizeof ( TCB_t ) ) ;
2022-02-24 07:14:22 -05:00
pxNewTCB - > pxStack = ( StackType_t * ) puxStackBuffer ;
2024-01-05 04:14:26 -05:00
# if ( tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE != 0 )
{
/* Tasks can be created statically or dynamically, so note this
* task was created statically in case the task is later deleted . */
pxNewTCB - > ucStaticallyAllocated = tskSTATICALLY_ALLOCATED_STACK_AND_TCB ;
}
2022-02-24 07:14:22 -05:00
# endif /* tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE */
2024-01-05 04:14:26 -05:00
prvInitialiseNewTask ( pxTaskCode , pcName , ulStackDepth , pvParameters , uxPriority , pxCreatedTask , pxNewTCB , NULL ) ;
}
else
{
pxNewTCB = NULL ;
}
return pxNewTCB ;
}
/*-----------------------------------------------------------*/
2022-03-20 23:09:24 -04:00
2024-01-05 04:14:26 -05:00
TaskHandle_t xTaskCreateStatic ( TaskFunction_t pxTaskCode ,
const char * const pcName ,
const uint32_t ulStackDepth ,
void * const pvParameters ,
UBaseType_t uxPriority ,
StackType_t * const puxStackBuffer ,
StaticTask_t * const pxTaskBuffer )
{
TaskHandle_t xReturn = NULL ;
TCB_t * pxNewTCB ;
traceENTER_xTaskCreateStatic ( pxTaskCode , pcName , ulStackDepth , pvParameters , uxPriority , puxStackBuffer , pxTaskBuffer ) ;
pxNewTCB = prvCreateStaticTask ( pxTaskCode , pcName , ulStackDepth , pvParameters , uxPriority , puxStackBuffer , pxTaskBuffer , & xReturn ) ;
if ( pxNewTCB ! = NULL )
{
# if ( ( configNUMBER_OF_CORES > 1 ) && ( configUSE_CORE_AFFINITY == 1 ) )
{
/* Set the task's affinity before scheduling it. */
pxNewTCB - > uxCoreAffinityMask = tskNO_AFFINITY ;
}
2022-03-20 23:09:24 -04:00
# endif
2022-02-24 07:14:22 -05:00
prvAddNewTaskToReadyList ( pxNewTCB ) ;
}
else
{
2024-01-05 04:14:26 -05:00
mtCOVERAGE_TEST_MARKER ( ) ;
2022-02-24 07:14:22 -05:00
}
2024-01-05 04:14:26 -05:00
traceRETURN_xTaskCreateStatic ( xReturn ) ;
2022-02-24 07:14:22 -05:00
return xReturn ;
}
/*-----------------------------------------------------------*/
2024-01-05 04:14:26 -05:00
# if ( ( configNUMBER_OF_CORES > 1 ) && ( configUSE_CORE_AFFINITY == 1 ) )
TaskHandle_t xTaskCreateStaticAffinitySet ( TaskFunction_t pxTaskCode ,
const char * const pcName ,
const uint32_t ulStackDepth ,
void * const pvParameters ,
UBaseType_t uxPriority ,
StackType_t * const puxStackBuffer ,
StaticTask_t * const pxTaskBuffer ,
UBaseType_t uxCoreAffinityMask )
2022-03-20 23:09:24 -04:00
{
2024-01-05 04:14:26 -05:00
TaskHandle_t xReturn = NULL ;
TCB_t * pxNewTCB ;
traceENTER_xTaskCreateStaticAffinitySet ( pxTaskCode , pcName , ulStackDepth , pvParameters , uxPriority , puxStackBuffer , pxTaskBuffer , uxCoreAffinityMask ) ;
pxNewTCB = prvCreateStaticTask ( pxTaskCode , pcName , ulStackDepth , pvParameters , uxPriority , puxStackBuffer , pxTaskBuffer , & xReturn ) ;
if ( pxNewTCB ! = NULL )
{
/* Set the task's affinity before scheduling it. */
pxNewTCB - > uxCoreAffinityMask = uxCoreAffinityMask ;
prvAddNewTaskToReadyList ( pxNewTCB ) ;
}
else
{
mtCOVERAGE_TEST_MARKER ( ) ;
}
traceRETURN_xTaskCreateStaticAffinitySet ( xReturn ) ;
return xReturn ;
2022-03-20 23:09:24 -04:00
}
2024-01-05 04:14:26 -05:00
# endif /* #if ( ( configNUMBER_OF_CORES > 1 ) && ( configUSE_CORE_AFFINITY == 1 ) ) */
2022-03-20 23:09:24 -04:00
2024-01-05 04:14:26 -05:00
# endif /* SUPPORT_STATIC_ALLOCATION */
/*-----------------------------------------------------------*/
# if ( ( portUSING_MPU_WRAPPERS == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 1 ) )
static TCB_t * prvCreateRestrictedStaticTask ( const TaskParameters_t * const pxTaskDefinition ,
TaskHandle_t * const pxCreatedTask )
2022-02-24 07:14:22 -05:00
{
TCB_t * pxNewTCB ;
configASSERT ( pxTaskDefinition - > puxStackBuffer ! = NULL ) ;
configASSERT ( pxTaskDefinition - > pxTaskBuffer ! = NULL ) ;
if ( ( pxTaskDefinition - > puxStackBuffer ! = NULL ) & & ( pxTaskDefinition - > pxTaskBuffer ! = NULL ) )
{
/* Allocate space for the TCB. Where the memory comes from depends
* on the implementation of the port malloc function and whether or
* not static allocation is being used . */
pxNewTCB = ( TCB_t * ) pxTaskDefinition - > pxTaskBuffer ;
2024-01-05 04:14:26 -05:00
( void ) memset ( ( void * ) pxNewTCB , 0x00 , sizeof ( TCB_t ) ) ;
2022-02-24 07:14:22 -05:00
/* Store the stack location in the TCB. */
pxNewTCB - > pxStack = pxTaskDefinition - > puxStackBuffer ;
# if ( tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE != 0 )
2024-01-05 04:14:26 -05:00
{
/* Tasks can be created statically or dynamically, so note this
* task was created statically in case the task is later deleted . */
pxNewTCB - > ucStaticallyAllocated = tskSTATICALLY_ALLOCATED_STACK_AND_TCB ;
}
2022-02-24 07:14:22 -05:00
# endif /* tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE */
prvInitialiseNewTask ( pxTaskDefinition - > pvTaskCode ,
pxTaskDefinition - > pcName ,
( uint32_t ) pxTaskDefinition - > usStackDepth ,
pxTaskDefinition - > pvParameters ,
pxTaskDefinition - > uxPriority ,
pxCreatedTask , pxNewTCB ,
pxTaskDefinition - > xRegions ) ;
2024-01-05 04:14:26 -05:00
}
else
{
pxNewTCB = NULL ;
}
2022-02-24 07:14:22 -05:00
2024-01-05 04:14:26 -05:00
return pxNewTCB ;
}
/*-----------------------------------------------------------*/
BaseType_t xTaskCreateRestrictedStatic ( const TaskParameters_t * const pxTaskDefinition ,
TaskHandle_t * pxCreatedTask )
{
TCB_t * pxNewTCB ;
BaseType_t xReturn ;
traceENTER_xTaskCreateRestrictedStatic ( pxTaskDefinition , pxCreatedTask ) ;
configASSERT ( pxTaskDefinition ! = NULL ) ;
pxNewTCB = prvCreateRestrictedStaticTask ( pxTaskDefinition , pxCreatedTask ) ;
if ( pxNewTCB ! = NULL )
{
# if ( ( configNUMBER_OF_CORES > 1 ) && ( configUSE_CORE_AFFINITY == 1 ) )
{
/* Set the task's affinity before scheduling it. */
pxNewTCB - > uxCoreAffinityMask = tskNO_AFFINITY ;
}
2022-03-20 23:09:24 -04:00
# endif
2022-02-24 07:14:22 -05:00
prvAddNewTaskToReadyList ( pxNewTCB ) ;
xReturn = pdPASS ;
}
2024-01-05 04:14:26 -05:00
else
{
xReturn = errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY ;
}
traceRETURN_xTaskCreateRestrictedStatic ( xReturn ) ;
2022-02-24 07:14:22 -05:00
return xReturn ;
}
/*-----------------------------------------------------------*/
2024-01-05 04:14:26 -05:00
# if ( ( configNUMBER_OF_CORES > 1 ) && ( configUSE_CORE_AFFINITY == 1 ) )
BaseType_t xTaskCreateRestrictedStaticAffinitySet ( const TaskParameters_t * const pxTaskDefinition ,
UBaseType_t uxCoreAffinityMask ,
TaskHandle_t * pxCreatedTask )
2022-03-20 23:09:24 -04:00
{
2024-01-05 04:14:26 -05:00
TCB_t * pxNewTCB ;
BaseType_t xReturn ;
traceENTER_xTaskCreateRestrictedStaticAffinitySet ( pxTaskDefinition , uxCoreAffinityMask , pxCreatedTask ) ;
configASSERT ( pxTaskDefinition ! = NULL ) ;
pxNewTCB = prvCreateRestrictedStaticTask ( pxTaskDefinition , pxCreatedTask ) ;
if ( pxNewTCB ! = NULL )
{
/* Set the task's affinity before scheduling it. */
pxNewTCB - > uxCoreAffinityMask = uxCoreAffinityMask ;
prvAddNewTaskToReadyList ( pxNewTCB ) ;
xReturn = pdPASS ;
}
else
{
xReturn = errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY ;
}
traceRETURN_xTaskCreateRestrictedStaticAffinitySet ( xReturn ) ;
return xReturn ;
2022-03-20 23:09:24 -04:00
}
2024-01-05 04:14:26 -05:00
# endif /* #if ( ( configNUMBER_OF_CORES > 1 ) && ( configUSE_CORE_AFFINITY == 1 ) ) */
2022-03-20 23:09:24 -04:00
2024-01-05 04:14:26 -05:00
# endif /* ( portUSING_MPU_WRAPPERS == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 1 ) */
/*-----------------------------------------------------------*/
# if ( ( portUSING_MPU_WRAPPERS == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) )
static TCB_t * prvCreateRestrictedTask ( const TaskParameters_t * const pxTaskDefinition ,
TaskHandle_t * const pxCreatedTask )
2022-02-24 07:14:22 -05:00
{
TCB_t * pxNewTCB ;
configASSERT ( pxTaskDefinition - > puxStackBuffer ) ;
if ( pxTaskDefinition - > puxStackBuffer ! = NULL )
{
2024-01-05 04:14:26 -05:00
/* MISRA Ref 11.5.1 [Malloc memory assignment] */
/* More details at: https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/MISRA.md#rule-115 */
/* coverity[misra_c_2012_rule_11_5_violation] */
2022-02-24 07:14:22 -05:00
pxNewTCB = ( TCB_t * ) pvPortMalloc ( sizeof ( TCB_t ) ) ;
if ( pxNewTCB ! = NULL )
{
2024-01-05 04:14:26 -05:00
( void ) memset ( ( void * ) pxNewTCB , 0x00 , sizeof ( TCB_t ) ) ;
2022-02-24 07:14:22 -05:00
/* Store the stack location in the TCB. */
pxNewTCB - > pxStack = pxTaskDefinition - > puxStackBuffer ;
# if ( tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE != 0 )
2024-01-05 04:14:26 -05:00
{
/* 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 ;
}
2022-02-24 07:14:22 -05:00
# endif /* tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE */
prvInitialiseNewTask ( pxTaskDefinition - > pvTaskCode ,
pxTaskDefinition - > pcName ,
( uint32_t ) pxTaskDefinition - > usStackDepth ,
pxTaskDefinition - > pvParameters ,
pxTaskDefinition - > uxPriority ,
pxCreatedTask , pxNewTCB ,
pxTaskDefinition - > xRegions ) ;
2024-01-05 04:14:26 -05:00
}
}
else
{
pxNewTCB = NULL ;
}
2022-02-24 07:14:22 -05:00
2024-01-05 04:14:26 -05:00
return pxNewTCB ;
}
/*-----------------------------------------------------------*/
2022-03-20 23:09:24 -04:00
2024-01-05 04:14:26 -05:00
BaseType_t xTaskCreateRestricted ( const TaskParameters_t * const pxTaskDefinition ,
TaskHandle_t * pxCreatedTask )
{
TCB_t * pxNewTCB ;
BaseType_t xReturn ;
traceENTER_xTaskCreateRestricted ( pxTaskDefinition , pxCreatedTask ) ;
pxNewTCB = prvCreateRestrictedTask ( pxTaskDefinition , pxCreatedTask ) ;
if ( pxNewTCB ! = NULL )
{
# if ( ( configNUMBER_OF_CORES > 1 ) && ( configUSE_CORE_AFFINITY == 1 ) )
{
/* Set the task's affinity before scheduling it. */
pxNewTCB - > uxCoreAffinityMask = tskNO_AFFINITY ;
2022-02-24 07:14:22 -05:00
}
2024-01-05 04:14:26 -05:00
# endif /* #if ( ( configNUMBER_OF_CORES > 1 ) && ( configUSE_CORE_AFFINITY == 1 ) ) */
prvAddNewTaskToReadyList ( pxNewTCB ) ;
xReturn = pdPASS ;
}
else
{
xReturn = errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY ;
2022-02-24 07:14:22 -05:00
}
2024-01-05 04:14:26 -05:00
traceRETURN_xTaskCreateRestricted ( xReturn ) ;
2022-02-24 07:14:22 -05:00
return xReturn ;
}
/*-----------------------------------------------------------*/
2024-01-05 04:14:26 -05:00
# if ( ( configNUMBER_OF_CORES > 1 ) && ( configUSE_CORE_AFFINITY == 1 ) )
BaseType_t xTaskCreateRestrictedAffinitySet ( const TaskParameters_t * const pxTaskDefinition ,
UBaseType_t uxCoreAffinityMask ,
TaskHandle_t * pxCreatedTask )
2022-03-20 23:09:24 -04:00
{
2024-01-05 04:14:26 -05:00
TCB_t * pxNewTCB ;
BaseType_t xReturn ;
traceENTER_xTaskCreateRestrictedAffinitySet ( pxTaskDefinition , uxCoreAffinityMask , pxCreatedTask ) ;
pxNewTCB = prvCreateRestrictedTask ( pxTaskDefinition , pxCreatedTask ) ;
if ( pxNewTCB ! = NULL )
{
/* Set the task's affinity before scheduling it. */
pxNewTCB - > uxCoreAffinityMask = uxCoreAffinityMask ;
prvAddNewTaskToReadyList ( pxNewTCB ) ;
xReturn = pdPASS ;
}
else
{
xReturn = errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY ;
}
traceRETURN_xTaskCreateRestrictedAffinitySet ( xReturn ) ;
return xReturn ;
2022-03-20 23:09:24 -04:00
}
2024-01-05 04:14:26 -05:00
# endif /* #if ( ( configNUMBER_OF_CORES > 1 ) && ( configUSE_CORE_AFFINITY == 1 ) ) */
2022-03-20 23:09:24 -04:00
2024-01-05 04:14:26 -05:00
# endif /* portUSING_MPU_WRAPPERS */
/*-----------------------------------------------------------*/
# if ( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
static TCB_t * prvCreateTask ( TaskFunction_t pxTaskCode ,
const char * const pcName ,
const configSTACK_DEPTH_TYPE usStackDepth ,
void * const pvParameters ,
UBaseType_t uxPriority ,
TaskHandle_t * const pxCreatedTask )
2022-02-24 07:14:22 -05:00
{
TCB_t * pxNewTCB ;
/* If the stack grows down then allocate the stack then the TCB so the stack
* does not grow into the TCB . Likewise if the stack grows up then allocate
* the TCB then the stack . */
# if ( portSTACK_GROWTH > 0 )
2024-01-05 04:14:26 -05:00
{
/* Allocate space for the TCB. Where the memory comes from depends on
* the implementation of the port malloc function and whether or not static
* allocation is being used . */
/* MISRA Ref 11.5.1 [Malloc memory assignment] */
/* More details at: https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/MISRA.md#rule-115 */
/* coverity[misra_c_2012_rule_11_5_violation] */
pxNewTCB = ( TCB_t * ) pvPortMalloc ( sizeof ( TCB_t ) ) ;
if ( pxNewTCB ! = NULL )
2022-02-24 07:14:22 -05:00
{
2024-01-05 04:14:26 -05:00
( void ) memset ( ( void * ) pxNewTCB , 0x00 , sizeof ( TCB_t ) ) ;
2022-02-24 07:14:22 -05:00
2024-01-05 04:14:26 -05:00
/* Allocate space for the stack used by the task being created.
* The base of the stack memory stored in the TCB so the task can
* be deleted later if required . */
/* MISRA Ref 11.5.1 [Malloc memory assignment] */
/* More details at: https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/MISRA.md#rule-115 */
/* coverity[misra_c_2012_rule_11_5_violation] */
pxNewTCB - > pxStack = ( StackType_t * ) pvPortMallocStack ( ( ( ( size_t ) usStackDepth ) * sizeof ( StackType_t ) ) ) ;
2022-02-24 07:14:22 -05:00
2024-01-05 04:14:26 -05:00
if ( pxNewTCB - > pxStack = = NULL )
{
/* Could not allocate the stack. Delete the allocated TCB. */
vPortFree ( pxNewTCB ) ;
pxNewTCB = NULL ;
2022-02-24 07:14:22 -05:00
}
}
2024-01-05 04:14:26 -05:00
}
2022-02-24 07:14:22 -05:00
# else /* portSTACK_GROWTH */
2024-01-05 04:14:26 -05:00
{
StackType_t * pxStack ;
2022-02-24 07:14:22 -05:00
2024-01-05 04:14:26 -05:00
/* Allocate space for the stack used by the task being created. */
/* MISRA Ref 11.5.1 [Malloc memory assignment] */
/* More details at: https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/MISRA.md#rule-115 */
/* coverity[misra_c_2012_rule_11_5_violation] */
pxStack = pvPortMallocStack ( ( ( ( size_t ) usStackDepth ) * sizeof ( StackType_t ) ) ) ;
2022-02-24 07:14:22 -05:00
2024-01-05 04:14:26 -05:00
if ( pxStack ! = NULL )
{
/* Allocate space for the TCB. */
/* MISRA Ref 11.5.1 [Malloc memory assignment] */
/* More details at: https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/MISRA.md#rule-115 */
/* coverity[misra_c_2012_rule_11_5_violation] */
pxNewTCB = ( TCB_t * ) pvPortMalloc ( sizeof ( TCB_t ) ) ;
if ( pxNewTCB ! = NULL )
2022-02-24 07:14:22 -05:00
{
2024-01-05 04:14:26 -05:00
( void ) memset ( ( void * ) pxNewTCB , 0x00 , sizeof ( TCB_t ) ) ;
2022-02-24 07:14:22 -05:00
2024-01-05 04:14:26 -05:00
/* Store the stack location in the TCB. */
pxNewTCB - > pxStack = pxStack ;
2022-02-24 07:14:22 -05:00
}
else
{
2024-01-05 04:14:26 -05:00
/* The stack cannot be used as the TCB was not created. Free
* it again . */
vPortFreeStack ( pxStack ) ;
2022-02-24 07:14:22 -05:00
}
}
2024-01-05 04:14:26 -05:00
else
{
pxNewTCB = NULL ;
}
}
2022-02-24 07:14:22 -05:00
# endif /* portSTACK_GROWTH */
2024-01-05 04:14:26 -05:00
if ( pxNewTCB ! = NULL )
{
# if ( tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE != 0 )
{
/* Tasks can be created statically or dynamically, so note this
* task was created dynamically in case it is later deleted . */
pxNewTCB - > ucStaticallyAllocated = tskDYNAMICALLY_ALLOCATED_STACK_AND_TCB ;
}
# endif /* tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE */
prvInitialiseNewTask ( pxTaskCode , pcName , ( uint32_t ) usStackDepth , pvParameters , uxPriority , pxCreatedTask , pxNewTCB , NULL ) ;
}
return pxNewTCB ;
}
/*-----------------------------------------------------------*/
BaseType_t xTaskCreate ( TaskFunction_t pxTaskCode ,
const char * const pcName ,
const configSTACK_DEPTH_TYPE usStackDepth ,
void * const pvParameters ,
UBaseType_t uxPriority ,
TaskHandle_t * const pxCreatedTask )
{
TCB_t * pxNewTCB ;
BaseType_t xReturn ;
traceENTER_xTaskCreate ( pxTaskCode , pcName , usStackDepth , pvParameters , uxPriority , pxCreatedTask ) ;
2022-02-24 07:14:22 -05:00
2024-01-05 04:14:26 -05:00
pxNewTCB = prvCreateTask ( pxTaskCode , pcName , usStackDepth , pvParameters , uxPriority , pxCreatedTask ) ;
2022-03-20 23:09:24 -04:00
2024-01-05 04:14:26 -05:00
if ( pxNewTCB ! = NULL )
{
# if ( ( configNUMBER_OF_CORES > 1 ) && ( configUSE_CORE_AFFINITY == 1 ) )
{
/* Set the task's affinity before scheduling it. */
pxNewTCB - > uxCoreAffinityMask = tskNO_AFFINITY ;
}
2022-03-20 23:09:24 -04:00
# endif
2022-02-24 07:14:22 -05:00
prvAddNewTaskToReadyList ( pxNewTCB ) ;
xReturn = pdPASS ;
}
else
{
xReturn = errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY ;
}
2024-01-05 04:14:26 -05:00
traceRETURN_xTaskCreate ( xReturn ) ;
2022-02-24 07:14:22 -05:00
return xReturn ;
}
2024-01-05 04:14:26 -05:00
/*-----------------------------------------------------------*/
# if ( ( configNUMBER_OF_CORES > 1 ) && ( configUSE_CORE_AFFINITY == 1 ) )
BaseType_t xTaskCreateAffinitySet ( TaskFunction_t pxTaskCode ,
const char * const pcName ,
const configSTACK_DEPTH_TYPE usStackDepth ,
void * const pvParameters ,
UBaseType_t uxPriority ,
UBaseType_t uxCoreAffinityMask ,
TaskHandle_t * const pxCreatedTask )
{
TCB_t * pxNewTCB ;
BaseType_t xReturn ;
traceENTER_xTaskCreateAffinitySet ( pxTaskCode , pcName , usStackDepth , pvParameters , uxPriority , uxCoreAffinityMask , pxCreatedTask ) ;
pxNewTCB = prvCreateTask ( pxTaskCode , pcName , usStackDepth , pvParameters , uxPriority , pxCreatedTask ) ;
if ( pxNewTCB ! = NULL )
{
/* Set the task's affinity before scheduling it. */
pxNewTCB - > uxCoreAffinityMask = uxCoreAffinityMask ;
prvAddNewTaskToReadyList ( pxNewTCB ) ;
xReturn = pdPASS ;
}
else
{
xReturn = errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY ;
}
traceRETURN_xTaskCreateAffinitySet ( xReturn ) ;
return xReturn ;
}
# endif /* #if ( ( configNUMBER_OF_CORES > 1 ) && ( configUSE_CORE_AFFINITY == 1 ) ) */
2022-02-24 07:14:22 -05:00
# endif /* configSUPPORT_DYNAMIC_ALLOCATION */
/*-----------------------------------------------------------*/
static void prvInitialiseNewTask ( TaskFunction_t pxTaskCode ,
2024-01-05 04:14:26 -05:00
const char * const pcName ,
2022-02-24 07:14:22 -05:00
const uint32_t ulStackDepth ,
void * const pvParameters ,
UBaseType_t uxPriority ,
TaskHandle_t * const pxCreatedTask ,
TCB_t * pxNewTCB ,
const MemoryRegion_t * const xRegions )
{
StackType_t * pxTopOfStack ;
UBaseType_t x ;
# if ( portUSING_MPU_WRAPPERS == 1 )
/* Should the task be created in privileged mode? */
BaseType_t xRunPrivileged ;
if ( ( uxPriority & portPRIVILEGE_BIT ) ! = 0U )
{
xRunPrivileged = pdTRUE ;
}
else
{
xRunPrivileged = pdFALSE ;
}
uxPriority & = ~ portPRIVILEGE_BIT ;
# endif /* portUSING_MPU_WRAPPERS == 1 */
/* Avoid dependency on memset() if it is not required. */
# if ( tskSET_NEW_STACKS_TO_KNOWN_VALUE == 1 )
2024-01-05 04:14:26 -05:00
{
/* Fill the stack with a known value to assist debugging. */
( void ) memset ( pxNewTCB - > pxStack , ( int ) tskSTACK_FILL_BYTE , ( size_t ) ulStackDepth * sizeof ( StackType_t ) ) ;
}
2022-02-24 07:14:22 -05:00
# endif /* tskSET_NEW_STACKS_TO_KNOWN_VALUE */
/* Calculate the top of stack address. This depends on whether the stack
* grows from high memory to low ( as per the 80 x86 ) or vice versa .
* portSTACK_GROWTH is used to make the result positive or negative as required
* by the port . */
# if ( portSTACK_GROWTH < 0 )
2024-01-05 04:14:26 -05:00
{
pxTopOfStack = & ( pxNewTCB - > pxStack [ ulStackDepth - ( uint32_t ) 1 ] ) ;
pxTopOfStack = ( StackType_t * ) ( ( ( portPOINTER_SIZE_TYPE ) pxTopOfStack ) & ( ~ ( ( portPOINTER_SIZE_TYPE ) portBYTE_ALIGNMENT_MASK ) ) ) ;
2022-02-24 07:14:22 -05:00
2024-01-05 04:14:26 -05:00
/* Check the alignment of the calculated top of stack is correct. */
configASSERT ( ( ( ( portPOINTER_SIZE_TYPE ) pxTopOfStack & ( portPOINTER_SIZE_TYPE ) portBYTE_ALIGNMENT_MASK ) = = 0UL ) ) ;
2022-02-24 07:14:22 -05:00
2024-01-05 04:14:26 -05:00
# if ( configRECORD_STACK_HIGH_ADDRESS == 1 )
{
/* Also record the stack's high address, which may assist
* debugging . */
pxNewTCB - > pxEndOfStack = pxTopOfStack ;
2022-02-24 07:14:22 -05:00
}
2024-01-05 04:14:26 -05:00
# endif /* configRECORD_STACK_HIGH_ADDRESS */
}
2022-02-24 07:14:22 -05:00
# else /* portSTACK_GROWTH */
2024-01-05 04:14:26 -05:00
{
pxTopOfStack = pxNewTCB - > pxStack ;
pxTopOfStack = ( StackType_t * ) ( ( ( ( portPOINTER_SIZE_TYPE ) pxTopOfStack ) + portBYTE_ALIGNMENT_MASK ) & ( ~ ( ( portPOINTER_SIZE_TYPE ) portBYTE_ALIGNMENT_MASK ) ) ) ;
2022-02-24 07:14:22 -05:00
2024-01-05 04:14:26 -05:00
/* Check the alignment of the calculated top of stack is correct. */
configASSERT ( ( ( ( portPOINTER_SIZE_TYPE ) pxTopOfStack & ( portPOINTER_SIZE_TYPE ) portBYTE_ALIGNMENT_MASK ) = = 0UL ) ) ;
2022-02-24 07:14:22 -05:00
2024-01-05 04:14:26 -05:00
/* The other extreme of the stack space is required if stack checking is
* performed . */
pxNewTCB - > pxEndOfStack = pxNewTCB - > pxStack + ( ulStackDepth - ( uint32_t ) 1 ) ;
}
2022-02-24 07:14:22 -05:00
# endif /* portSTACK_GROWTH */
/* Store the task name in the TCB. */
if ( pcName ! = NULL )
{
for ( x = ( UBaseType_t ) 0 ; x < ( UBaseType_t ) configMAX_TASK_NAME_LEN ; x + + )
{
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 . */
2024-01-05 04:14:26 -05:00
pxNewTCB - > pcTaskName [ configMAX_TASK_NAME_LEN - 1U ] = ' \0 ' ;
2022-02-24 07:14:22 -05:00
}
else
{
2024-01-05 04:14:26 -05:00
mtCOVERAGE_TEST_MARKER ( ) ;
2022-02-24 07:14:22 -05:00
}
2024-01-05 04:14:26 -05:00
/* This is used as an array index so must ensure it's not too large. */
configASSERT ( uxPriority < configMAX_PRIORITIES ) ;
2022-02-24 07:14:22 -05:00
if ( uxPriority > = ( UBaseType_t ) configMAX_PRIORITIES )
{
uxPriority = ( UBaseType_t ) configMAX_PRIORITIES - ( UBaseType_t ) 1U ;
}
else
{
mtCOVERAGE_TEST_MARKER ( ) ;
}
pxNewTCB - > uxPriority = uxPriority ;
# if ( configUSE_MUTEXES == 1 )
2024-01-05 04:14:26 -05:00
{
pxNewTCB - > uxBasePriority = uxPriority ;
}
2022-02-24 07:14:22 -05:00
# endif /* configUSE_MUTEXES */
vListInitialiseItem ( & ( pxNewTCB - > xStateListItem ) ) ;
vListInitialiseItem ( & ( pxNewTCB - > xEventListItem ) ) ;
/* Set the pxNewTCB as a link back from the ListItem_t. This is so we can get
* back to the containing TCB from a generic item in a list . */
listSET_LIST_ITEM_OWNER ( & ( pxNewTCB - > xStateListItem ) , pxNewTCB ) ;
/* Event lists are always in priority order. */
2024-01-05 04:14:26 -05:00
listSET_LIST_ITEM_VALUE ( & ( pxNewTCB - > xEventListItem ) , ( TickType_t ) configMAX_PRIORITIES - ( TickType_t ) uxPriority ) ;
2022-02-24 07:14:22 -05:00
listSET_LIST_ITEM_OWNER ( & ( pxNewTCB - > xEventListItem ) , pxNewTCB ) ;
# if ( portUSING_MPU_WRAPPERS == 1 )
2024-01-05 04:14:26 -05:00
{
vPortStoreTaskMPUSettings ( & ( pxNewTCB - > xMPUSettings ) , xRegions , pxNewTCB - > pxStack , ulStackDepth ) ;
}
2022-02-24 07:14:22 -05:00
# else
2024-01-05 04:14:26 -05:00
{
/* Avoid compiler warning about unreferenced parameter. */
( void ) xRegions ;
}
2022-02-24 07:14:22 -05:00
# endif
2024-01-05 04:14:26 -05:00
# if ( configUSE_C_RUNTIME_TLS_SUPPORT == 1 )
{
/* Allocate and initialize memory for the task's TLS Block. */
configINIT_TLS_BLOCK ( pxNewTCB - > xTLSBlock , pxTopOfStack ) ;
}
2022-02-24 07:14:22 -05:00
# endif
/* Initialize the TCB stack to look as if the task was already running,
* but had been interrupted by the scheduler . The return address is set
* to the start of the task function . Once the stack has been initialised
* the top of stack variable is updated . */
# if ( portUSING_MPU_WRAPPERS == 1 )
2024-01-05 04:14:26 -05:00
{
/* 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 )
2022-02-24 07:14:22 -05:00
{
2024-01-05 04:14:26 -05:00
# if ( portSTACK_GROWTH < 0 )
{
pxNewTCB - > pxTopOfStack = pxPortInitialiseStack ( pxTopOfStack , pxNewTCB - > pxStack , pxTaskCode , pvParameters , xRunPrivileged , & ( pxNewTCB - > xMPUSettings ) ) ;
}
# else /* portSTACK_GROWTH */
{
pxNewTCB - > pxTopOfStack = pxPortInitialiseStack ( pxTopOfStack , pxNewTCB - > pxEndOfStack , pxTaskCode , pvParameters , xRunPrivileged , & ( pxNewTCB - > xMPUSettings ) ) ;
}
# endif /* portSTACK_GROWTH */
}
# else /* portHAS_STACK_OVERFLOW_CHECKING */
{
pxNewTCB - > pxTopOfStack = pxPortInitialiseStack ( pxTopOfStack , pxTaskCode , pvParameters , xRunPrivileged , & ( pxNewTCB - > xMPUSettings ) ) ;
2022-02-24 07:14:22 -05:00
}
2024-01-05 04:14:26 -05:00
# endif /* portHAS_STACK_OVERFLOW_CHECKING */
}
2022-02-24 07:14:22 -05:00
# else /* portUSING_MPU_WRAPPERS */
2024-01-05 04:14:26 -05:00
{
/* 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 )
2022-02-24 07:14:22 -05:00
{
2024-01-05 04:14:26 -05:00
# 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 ) ;
2022-02-24 07:14:22 -05:00
}
2024-01-05 04:14:26 -05:00
# endif /* portHAS_STACK_OVERFLOW_CHECKING */
}
2022-02-24 07:14:22 -05:00
# endif /* portUSING_MPU_WRAPPERS */
2024-01-05 04:14:26 -05:00
/* Initialize task state and task attributes. */
# if ( configNUMBER_OF_CORES > 1 )
2022-02-24 07:14:22 -05:00
{
2024-01-05 04:14:26 -05:00
pxNewTCB - > xTaskRunState = taskTASK_NOT_RUNNING ;
2022-02-24 07:14:22 -05:00
2024-01-05 04:14:26 -05:00
/* Is this an idle task? */
if ( ( ( TaskFunction_t ) pxTaskCode = = ( TaskFunction_t ) prvIdleTask ) | | ( ( TaskFunction_t ) pxTaskCode = = ( TaskFunction_t ) prvPassiveIdleTask ) )
2022-02-24 07:14:22 -05:00
{
2024-01-05 04:14:26 -05:00
pxNewTCB - > uxTaskAttributes | = taskATTRIBUTE_IS_IDLE ;
2022-02-24 07:14:22 -05:00
}
}
2024-01-05 04:14:26 -05:00
# endif /* #if ( configNUMBER_OF_CORES > 1 ) */
2022-02-24 07:14:22 -05:00
if ( pxCreatedTask ! = NULL )
{
/* Pass the handle out in an anonymous way. The handle can be used to
* change the created task ' s priority , delete the created task , etc . */
* pxCreatedTask = ( TaskHandle_t ) pxNewTCB ;
}
else
{
mtCOVERAGE_TEST_MARKER ( ) ;
}
}
/*-----------------------------------------------------------*/
2024-01-05 04:14:26 -05:00
# if ( configNUMBER_OF_CORES == 1 )
2022-02-24 07:14:22 -05:00
2024-01-05 04:14:26 -05:00
static void prvAddNewTaskToReadyList ( TCB_t * pxNewTCB )
{
/* Ensure interrupts don't access the task lists while the lists are being
* updated . */
taskENTER_CRITICAL ( ) ;
2022-02-24 07:14:22 -05:00
{
2024-01-05 04:14:26 -05:00
uxCurrentNumberOfTasks + + ;
if ( pxCurrentTCB = = NULL )
2022-02-24 07:14:22 -05:00
{
2024-01-05 04:14:26 -05:00
/* There are no other tasks, or all the other tasks are in
* the suspended state - make this the current task . */
pxCurrentTCB = pxNewTCB ;
if ( uxCurrentNumberOfTasks = = ( UBaseType_t ) 1 )
{
/* This is the first task to be created so do the preliminary
* initialisation required . We will not recover if this call
* fails , but we will report the failure . */
prvInitialiseTaskLists ( ) ;
}
else
{
mtCOVERAGE_TEST_MARKER ( ) ;
}
2022-02-24 07:14:22 -05:00
}
else
{
2024-01-05 04:14:26 -05:00
/* If the scheduler is not already running, make this task the
* current task if it is the highest priority task to be created
* so far . */
if ( xSchedulerRunning = = pdFALSE )
2022-02-24 07:14:22 -05:00
{
2024-01-05 04:14:26 -05:00
if ( pxCurrentTCB - > uxPriority < = pxNewTCB - > uxPriority )
2022-02-24 07:14:22 -05:00
{
2024-01-05 04:14:26 -05:00
pxCurrentTCB = pxNewTCB ;
}
else
{
mtCOVERAGE_TEST_MARKER ( ) ;
2022-02-24 07:14:22 -05:00
}
}
2024-01-05 04:14:26 -05:00
else
{
mtCOVERAGE_TEST_MARKER ( ) ;
}
}
uxTaskNumber + + ;
# if ( configUSE_TRACE_FACILITY == 1 )
{
/* Add a counter into the TCB for tracing only. */
pxNewTCB - > uxTCBNumber = uxTaskNumber ;
2022-02-24 07:14:22 -05:00
}
2024-01-05 04:14:26 -05:00
# endif /* configUSE_TRACE_FACILITY */
traceTASK_CREATE ( pxNewTCB ) ;
prvAddTaskToReadyList ( pxNewTCB ) ;
portSETUP_TCB ( pxNewTCB ) ;
}
taskEXIT_CRITICAL ( ) ;
if ( xSchedulerRunning ! = pdFALSE )
{
/* If the created task is of a higher priority than the current task
* then it should run now . */
taskYIELD_ANY_CORE_IF_USING_PREEMPTION ( pxNewTCB ) ;
2022-02-24 07:14:22 -05:00
}
else
{
mtCOVERAGE_TEST_MARKER ( ) ;
}
2024-01-05 04:14:26 -05:00
}
# else /* #if ( configNUMBER_OF_CORES == 1 ) */
static void prvAddNewTaskToReadyList ( TCB_t * pxNewTCB )
{
/* Ensure interrupts don't access the task lists while the lists are being
* updated . */
taskENTER_CRITICAL ( ) ;
{
uxCurrentNumberOfTasks + + ;
if ( xSchedulerRunning = = pdFALSE )
{
if ( uxCurrentNumberOfTasks = = ( UBaseType_t ) 1 )
{
/* This is the first task to be created so do the preliminary
* initialisation required . We will not recover if this call
* fails , but we will report the failure . */
prvInitialiseTaskLists ( ) ;
}
else
{
mtCOVERAGE_TEST_MARKER ( ) ;
}
if ( ( pxNewTCB - > uxTaskAttributes & taskATTRIBUTE_IS_IDLE ) ! = 0U )
{
BaseType_t xCoreID ;
/* Check if a core is free. */
for ( xCoreID = ( BaseType_t ) 0 ; xCoreID < ( BaseType_t ) configNUMBER_OF_CORES ; xCoreID + + )
{
if ( pxCurrentTCBs [ xCoreID ] = = NULL )
{
pxNewTCB - > xTaskRunState = xCoreID ;
pxCurrentTCBs [ xCoreID ] = pxNewTCB ;
break ;
}
else
{
mtCOVERAGE_TEST_MARKER ( ) ;
}
}
}
else
{
mtCOVERAGE_TEST_MARKER ( ) ;
}
}
2022-02-24 07:14:22 -05:00
2024-01-05 04:14:26 -05:00
uxTaskNumber + + ;
2022-02-24 07:14:22 -05:00
2024-01-05 04:14:26 -05:00
# if ( configUSE_TRACE_FACILITY == 1 )
2022-02-24 07:14:22 -05:00
{
/* Add a counter into the TCB for tracing only. */
pxNewTCB - > uxTCBNumber = uxTaskNumber ;
}
2024-01-05 04:14:26 -05:00
# endif /* configUSE_TRACE_FACILITY */
traceTASK_CREATE ( pxNewTCB ) ;
2022-02-24 07:14:22 -05:00
2024-01-05 04:14:26 -05:00
prvAddTaskToReadyList ( pxNewTCB ) ;
2022-02-24 07:14:22 -05:00
2024-01-05 04:14:26 -05:00
portSETUP_TCB ( pxNewTCB ) ;
2022-02-24 07:14:22 -05:00
2024-01-05 04:14:26 -05:00
if ( xSchedulerRunning ! = pdFALSE )
{
/* If the created task is of a higher priority than another
* currently running task and preemption is on then it should
* run now . */
taskYIELD_ANY_CORE_IF_USING_PREEMPTION ( pxNewTCB ) ;
}
else
{
mtCOVERAGE_TEST_MARKER ( ) ;
}
}
taskEXIT_CRITICAL ( ) ;
}
# endif /* #if ( configNUMBER_OF_CORES == 1 ) */
/*-----------------------------------------------------------*/
# if ( ( configUSE_TRACE_FACILITY == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 ) )
static size_t prvSnprintfReturnValueToCharsWritten ( int iSnprintfReturnValue ,
size_t n )
{
size_t uxCharsWritten ;
if ( iSnprintfReturnValue < 0 )
2022-02-24 07:14:22 -05:00
{
2024-01-05 04:14:26 -05:00
/* Encoding error - Return 0 to indicate that nothing
* was written to the buffer . */
uxCharsWritten = 0 ;
}
else if ( iSnprintfReturnValue > = ( int ) n )
{
/* This is the case when the supplied buffer is not
* large to hold the generated string . Return the
* number of characters actually written without
* counting the terminating NULL character . */
uxCharsWritten = n - 1U ;
2022-02-24 07:14:22 -05:00
}
else
{
2024-01-05 04:14:26 -05:00
/* Complete string was written to the buffer. */
uxCharsWritten = ( size_t ) iSnprintfReturnValue ;
2022-02-24 07:14:22 -05:00
}
2024-01-05 04:14:26 -05:00
return uxCharsWritten ;
2022-02-24 07:14:22 -05:00
}
2024-01-05 04:14:26 -05:00
# endif /* #if ( ( configUSE_TRACE_FACILITY == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 ) ) */
2022-02-24 07:14:22 -05:00
/*-----------------------------------------------------------*/
# if ( INCLUDE_vTaskDelete == 1 )
void vTaskDelete ( TaskHandle_t xTaskToDelete )
{
TCB_t * pxTCB ;
2024-01-05 04:14:26 -05:00
traceENTER_vTaskDelete ( xTaskToDelete ) ;
2022-02-24 07:14:22 -05:00
taskENTER_CRITICAL ( ) ;
{
/* If null is passed in here then it is the calling task that is
* being deleted . */
pxTCB = prvGetTCBFromHandle ( xTaskToDelete ) ;
/* Remove task from the ready/delayed list. */
if ( uxListRemove ( & ( pxTCB - > xStateListItem ) ) = = ( UBaseType_t ) 0 )
{
taskRESET_READY_PRIORITY ( pxTCB - > uxPriority ) ;
}
else
{
mtCOVERAGE_TEST_MARKER ( ) ;
}
/* Is the task waiting on an event also? */
if ( listLIST_ITEM_CONTAINER ( & ( pxTCB - > xEventListItem ) ) ! = NULL )
{
( void ) uxListRemove ( & ( pxTCB - > xEventListItem ) ) ;
}
else
{
mtCOVERAGE_TEST_MARKER ( ) ;
}
/* Increment the uxTaskNumber also so kernel aware debuggers can
* detect that the task lists need re - generating . This is done before
* portPRE_TASK_DELETE_HOOK ( ) as in the Windows port that macro will
* not return . */
uxTaskNumber + + ;
/* If the task is running (or yielding), we must add it to the
* termination list so that an idle task can delete it when it is
* no longer running . */
2024-01-05 04:14:26 -05:00
if ( taskTASK_IS_RUNNING_OR_SCHEDULED_TO_YIELD ( pxTCB ) ! = pdFALSE )
{
/* A running task or a task which is scheduled to yield is being
* deleted . This cannot complete when the task is still running
* on a core , as a context switch to another task is required .
* Place the task in the termination list . The idle task will check
* the termination list and free up any memory allocated by the
* scheduler for the TCB and stack of the deleted task . */
2022-02-24 07:14:22 -05:00
vListInsertEnd ( & xTasksWaitingTermination , & ( pxTCB - > xStateListItem ) ) ;
/* Increment the ucTasksDeleted variable so the idle task knows
* there is a task that has been deleted and that it should therefore
* check the xTasksWaitingTermination list . */
+ + uxDeletedTasksWaitingCleanUp ;
/* Call the delete hook before portPRE_TASK_DELETE_HOOK() as
* portPRE_TASK_DELETE_HOOK ( ) does not return in the Win32 port . */
traceTASK_DELETE ( pxTCB ) ;
/* The pre-delete hook is primarily for the Windows simulator,
* in which Windows specific clean up operations are performed ,
* after which it is not possible to yield away from this task -
* hence xYieldPending is used to latch that a context switch is
* required . */
2024-01-05 04:14:26 -05:00
# if ( configNUMBER_OF_CORES == 1 )
portPRE_TASK_DELETE_HOOK ( pxTCB , & ( xYieldPendings [ 0 ] ) ) ;
# else
portPRE_TASK_DELETE_HOOK ( pxTCB , & ( xYieldPendings [ pxTCB - > xTaskRunState ] ) ) ;
# endif
2022-02-24 07:14:22 -05:00
}
else
{
- - uxCurrentNumberOfTasks ;
traceTASK_DELETE ( pxTCB ) ;
/* Reset the next expected unblock time in case it referred to
* the task that has just been deleted . */
prvResetNextTaskUnblockTime ( ) ;
}
2024-01-05 04:14:26 -05:00
}
2022-02-24 07:14:22 -05:00
2024-01-05 04:14:26 -05:00
# if ( configNUMBER_OF_CORES == 1 )
{
taskEXIT_CRITICAL ( ) ;
/* If the task is not deleting itself, call prvDeleteTCB from outside of
* critical section . If a task deletes itself , prvDeleteTCB is called
* from prvCheckTasksWaitingTermination which is called from Idle task . */
if ( pxTCB ! = pxCurrentTCB )
2022-02-24 07:14:22 -05:00
{
2024-01-05 04:14:26 -05:00
prvDeleteTCB ( pxTCB ) ;
}
2022-02-24 07:14:22 -05:00
2024-01-05 04:14:26 -05:00
/* Force a reschedule if it is the currently running task that has just
* been deleted . */
if ( xSchedulerRunning ! = pdFALSE )
{
if ( pxTCB = = pxCurrentTCB )
{
configASSERT ( uxSchedulerSuspended = = 0 ) ;
portYIELD_WITHIN_API ( ) ;
}
else
{
mtCOVERAGE_TEST_MARKER ( ) ;
}
}
}
# else /* #if ( configNUMBER_OF_CORES == 1 ) */
{
/* If a running task is not deleting itself, call prvDeleteTCB. If a running
* task deletes itself , prvDeleteTCB is called from prvCheckTasksWaitingTermination
* which is called from Idle task . */
if ( pxTCB - > xTaskRunState = = taskTASK_NOT_RUNNING )
{
prvDeleteTCB ( pxTCB ) ;
}
2022-02-24 07:14:22 -05:00
2024-01-05 04:14:26 -05:00
/* Force a reschedule if the task that has just been deleted was running. */
if ( ( xSchedulerRunning ! = pdFALSE ) & & ( taskTASK_IS_RUNNING ( pxTCB ) = = pdTRUE ) )
{
if ( pxTCB - > xTaskRunState = = ( BaseType_t ) portGET_CORE_ID ( ) )
2022-02-24 07:14:22 -05:00
{
configASSERT ( uxSchedulerSuspended = = 0 ) ;
vTaskYieldWithinAPI ( ) ;
}
else
{
2024-01-05 04:14:26 -05:00
prvYieldCore ( pxTCB - > xTaskRunState ) ;
2022-02-24 07:14:22 -05:00
}
}
2024-01-05 04:14:26 -05:00
taskEXIT_CRITICAL ( ) ;
2022-02-24 07:14:22 -05:00
}
2024-01-05 04:14:26 -05:00
# endif /* #if ( configNUMBER_OF_CORES == 1 ) */
traceRETURN_vTaskDelete ( ) ;
2022-02-24 07:14:22 -05:00
}
# endif /* INCLUDE_vTaskDelete */
/*-----------------------------------------------------------*/
# if ( INCLUDE_xTaskDelayUntil == 1 )
BaseType_t xTaskDelayUntil ( TickType_t * const pxPreviousWakeTime ,
const TickType_t xTimeIncrement )
{
TickType_t xTimeToWake ;
BaseType_t xAlreadyYielded , xShouldDelay = pdFALSE ;
2024-01-05 04:14:26 -05:00
traceENTER_xTaskDelayUntil ( pxPreviousWakeTime , xTimeIncrement ) ;
2022-02-24 07:14:22 -05:00
configASSERT ( pxPreviousWakeTime ) ;
configASSERT ( ( xTimeIncrement > 0U ) ) ;
vTaskSuspendAll ( ) ;
{
/* Minor optimisation. The tick count cannot change in this
* block . */
const TickType_t xConstTickCount = xTickCount ;
2024-01-05 04:14:26 -05:00
configASSERT ( uxSchedulerSuspended = = 1U ) ;
2022-02-24 07:14:22 -05:00
/* Generate the tick time at which the task wants to wake. */
xTimeToWake = * pxPreviousWakeTime + xTimeIncrement ;
if ( xConstTickCount < * pxPreviousWakeTime )
{
/* The tick count has overflowed since this function was
* lasted called . In this case the only time we should ever
* actually delay is if the wake time has also overflowed ,
* and the wake time is greater than the tick time . When this
* is the case it is as if neither time had overflowed . */
if ( ( xTimeToWake < * pxPreviousWakeTime ) & & ( xTimeToWake > xConstTickCount ) )
{
xShouldDelay = pdTRUE ;
}
else
{
mtCOVERAGE_TEST_MARKER ( ) ;
}
}
else
{
/* The tick time has not overflowed. In this case we will
* delay if either the wake time has overflowed , and / or the
* tick time is less than the wake time . */
if ( ( xTimeToWake < * pxPreviousWakeTime ) | | ( xTimeToWake > xConstTickCount ) )
{
xShouldDelay = pdTRUE ;
}
else
{
mtCOVERAGE_TEST_MARKER ( ) ;
}
}
/* Update the wake time ready for the next call. */
* pxPreviousWakeTime = xTimeToWake ;
if ( xShouldDelay ! = pdFALSE )
{
traceTASK_DELAY_UNTIL ( xTimeToWake ) ;
/* prvAddCurrentTaskToDelayedList() needs the block time, not
* the time to wake , so subtract the current tick count . */
prvAddCurrentTaskToDelayedList ( xTimeToWake - xConstTickCount , pdFALSE ) ;
}
else
{
mtCOVERAGE_TEST_MARKER ( ) ;
}
}
xAlreadyYielded = xTaskResumeAll ( ) ;
/* Force a reschedule if xTaskResumeAll has not already done so, we may
* have put ourselves to sleep . */
if ( xAlreadyYielded = = pdFALSE )
{
2024-01-05 04:14:26 -05:00
taskYIELD_WITHIN_API ( ) ;
2022-02-24 07:14:22 -05:00
}
else
{
mtCOVERAGE_TEST_MARKER ( ) ;
}
2024-01-05 04:14:26 -05:00
traceRETURN_xTaskDelayUntil ( xShouldDelay ) ;
2022-02-24 07:14:22 -05:00
return xShouldDelay ;
}
# endif /* INCLUDE_xTaskDelayUntil */
/*-----------------------------------------------------------*/
# if ( INCLUDE_vTaskDelay == 1 )
void vTaskDelay ( const TickType_t xTicksToDelay )
{
BaseType_t xAlreadyYielded = pdFALSE ;
2024-01-05 04:14:26 -05:00
traceENTER_vTaskDelay ( xTicksToDelay ) ;
2022-02-24 07:14:22 -05:00
/* A delay time of zero just forces a reschedule. */
if ( xTicksToDelay > ( TickType_t ) 0U )
{
vTaskSuspendAll ( ) ;
{
2024-01-05 04:14:26 -05:00
configASSERT ( uxSchedulerSuspended = = 1U ) ;
2022-02-24 07:14:22 -05:00
traceTASK_DELAY ( ) ;
/* A task that is removed from the event list while the
* scheduler is suspended will not get placed in the ready
* list or removed from the blocked list until the scheduler
* is resumed .
*
* This task cannot be in an event list as it is the currently
* executing task . */
prvAddCurrentTaskToDelayedList ( xTicksToDelay , pdFALSE ) ;
}
xAlreadyYielded = xTaskResumeAll ( ) ;
}
else
{
mtCOVERAGE_TEST_MARKER ( ) ;
}
/* Force a reschedule if xTaskResumeAll has not already done so, we may
* have put ourselves to sleep . */
if ( xAlreadyYielded = = pdFALSE )
{
2024-01-05 04:14:26 -05:00
taskYIELD_WITHIN_API ( ) ;
2022-02-24 07:14:22 -05:00
}
else
{
mtCOVERAGE_TEST_MARKER ( ) ;
}
2024-01-05 04:14:26 -05:00
traceRETURN_vTaskDelay ( ) ;
2022-02-24 07:14:22 -05:00
}
# endif /* INCLUDE_vTaskDelay */
/*-----------------------------------------------------------*/
# if ( ( INCLUDE_eTaskGetState == 1 ) || ( configUSE_TRACE_FACILITY == 1 ) || ( INCLUDE_xTaskAbortDelay == 1 ) )
eTaskState eTaskGetState ( TaskHandle_t xTask )
{
eTaskState eReturn ;
2024-01-05 04:14:26 -05:00
List_t const * pxStateList ;
List_t const * pxEventList ;
List_t const * pxDelayedList ;
List_t const * pxOverflowedDelayedList ;
2022-02-24 07:14:22 -05:00
const TCB_t * const pxTCB = xTask ;
2024-01-05 04:14:26 -05:00
traceENTER_eTaskGetState ( xTask ) ;
2022-02-24 07:14:22 -05:00
2024-01-05 04:14:26 -05:00
configASSERT ( pxTCB ) ;
2022-02-24 07:14:22 -05:00
2024-01-05 04:14:26 -05:00
# if ( configNUMBER_OF_CORES == 1 )
if ( pxTCB = = pxCurrentTCB )
{
/* The task calling this function is querying its own state. */
eReturn = eRunning ;
}
else
# endif
2022-02-24 07:14:22 -05:00
{
2024-01-05 04:14:26 -05:00
taskENTER_CRITICAL ( ) ;
{
pxStateList = listLIST_ITEM_CONTAINER ( & ( pxTCB - > xStateListItem ) ) ;
pxEventList = listLIST_ITEM_CONTAINER ( & ( pxTCB - > xEventListItem ) ) ;
pxDelayedList = pxDelayedTaskList ;
pxOverflowedDelayedList = pxOverflowDelayedTaskList ;
}
taskEXIT_CRITICAL ( ) ;
2022-02-24 07:14:22 -05:00
2024-01-05 04:14:26 -05:00
if ( pxEventList = = & xPendingReadyList )
2022-02-24 07:14:22 -05:00
{
2024-01-05 04:14:26 -05:00
/* The task has been placed on the pending ready list, so its
* state is eReady regardless of what list the task ' s state list
* item is currently placed on . */
eReturn = eReady ;
}
else if ( ( pxStateList = = pxDelayedList ) | | ( pxStateList = = pxOverflowedDelayedList ) )
{
/* The task being queried is referenced from one of the Blocked
* lists . */
eReturn = eBlocked ;
}
# if ( INCLUDE_vTaskSuspend == 1 )
else if ( pxStateList = = & xSuspendedTaskList )
2022-02-24 07:14:22 -05:00
{
2024-01-05 04:14:26 -05:00
/* The task being queried is referenced from the suspended
* list . Is it genuinely suspended or is it blocked
* indefinitely ? */
if ( listLIST_ITEM_CONTAINER ( & ( pxTCB - > xEventListItem ) ) = = NULL )
{
# if ( configUSE_TASK_NOTIFICATIONS == 1 )
2022-02-24 07:14:22 -05:00
{
BaseType_t x ;
/* The task does not appear on the event list item of
* and of the RTOS objects , but could still be in the
* blocked state if it is waiting on its notification
* rather than waiting on an object . If not , is
* suspended . */
eReturn = eSuspended ;
2024-01-05 04:14:26 -05:00
for ( x = ( BaseType_t ) 0 ; x < ( BaseType_t ) configTASK_NOTIFICATION_ARRAY_ENTRIES ; x + + )
2022-02-24 07:14:22 -05:00
{
if ( pxTCB - > ucNotifyState [ x ] = = taskWAITING_NOTIFICATION )
{
eReturn = eBlocked ;
break ;
}
}
}
2024-01-05 04:14:26 -05:00
# else /* if ( configUSE_TASK_NOTIFICATIONS == 1 ) */
2022-02-24 07:14:22 -05:00
{
eReturn = eSuspended ;
}
2024-01-05 04:14:26 -05:00
# endif /* if ( configUSE_TASK_NOTIFICATIONS == 1 ) */
}
else
{
eReturn = eBlocked ;
}
2022-02-24 07:14:22 -05:00
}
2024-01-05 04:14:26 -05:00
# endif /* if ( INCLUDE_vTaskSuspend == 1 ) */
# if ( INCLUDE_vTaskDelete == 1 )
else if ( ( pxStateList = = & xTasksWaitingTermination ) | | ( pxStateList = = NULL ) )
2022-02-24 07:14:22 -05:00
{
2024-01-05 04:14:26 -05:00
/* The task being queried is referenced from the deleted
* tasks list , or it is not referenced from any lists at
* all . */
eReturn = eDeleted ;
2022-02-24 07:14:22 -05:00
}
2024-01-05 04:14:26 -05:00
# endif
2022-02-24 07:14:22 -05:00
else
{
2024-01-05 04:14:26 -05:00
# if ( configNUMBER_OF_CORES == 1 )
{
/* If the task is not in any other state, it must be in the
* Ready ( including pending ready ) state . */
eReturn = eReady ;
}
# else /* #if ( configNUMBER_OF_CORES == 1 ) */
{
if ( taskTASK_IS_RUNNING ( pxTCB ) = = pdTRUE )
{
/* Is it actively running on a core? */
eReturn = eRunning ;
}
else
{
/* If the task is not in any other state, it must be in the
* Ready ( including pending ready ) state . */
eReturn = eReady ;
}
}
# endif /* #if ( configNUMBER_OF_CORES == 1 ) */
2022-02-24 07:14:22 -05:00
}
}
2024-01-05 04:14:26 -05:00
traceRETURN_eTaskGetState ( eReturn ) ;
2022-02-24 07:14:22 -05:00
return eReturn ;
2024-01-05 04:14:26 -05:00
}
2022-02-24 07:14:22 -05:00
# endif /* INCLUDE_eTaskGetState */
/*-----------------------------------------------------------*/
# if ( INCLUDE_uxTaskPriorityGet == 1 )
UBaseType_t uxTaskPriorityGet ( const TaskHandle_t xTask )
{
TCB_t const * pxTCB ;
UBaseType_t uxReturn ;
2024-01-05 04:14:26 -05:00
traceENTER_uxTaskPriorityGet ( xTask ) ;
2022-02-24 07:14:22 -05:00
taskENTER_CRITICAL ( ) ;
{
/* If null is passed in here then it is the priority of the task
* that called uxTaskPriorityGet ( ) that is being queried . */
pxTCB = prvGetTCBFromHandle ( xTask ) ;
uxReturn = pxTCB - > uxPriority ;
}
taskEXIT_CRITICAL ( ) ;
2024-01-05 04:14:26 -05:00
traceRETURN_uxTaskPriorityGet ( uxReturn ) ;
2022-02-24 07:14:22 -05:00
return uxReturn ;
}
# endif /* INCLUDE_uxTaskPriorityGet */
/*-----------------------------------------------------------*/
# if ( INCLUDE_uxTaskPriorityGet == 1 )
UBaseType_t uxTaskPriorityGetFromISR ( const TaskHandle_t xTask )
{
TCB_t const * pxTCB ;
2024-01-05 04:14:26 -05:00
UBaseType_t uxReturn ;
UBaseType_t uxSavedInterruptStatus ;
traceENTER_uxTaskPriorityGetFromISR ( xTask ) ;
2022-02-24 07:14:22 -05:00
/* RTOS ports that support interrupt nesting have the concept of a
* maximum system call ( or maximum API call ) interrupt priority .
* Interrupts that are above the maximum system call priority are keep
* permanently enabled , even when the RTOS kernel is in a critical section ,
* but cannot make any calls to FreeRTOS API functions . If configASSERT ( )
* is defined in FreeRTOSConfig . h then
* portASSERT_IF_INTERRUPT_PRIORITY_INVALID ( ) will result in an assertion
* failure if a FreeRTOS API function is called from an interrupt that has
* been assigned a priority above the configured maximum system call
* priority . Only FreeRTOS functions that end in FromISR can be called
* from interrupts that have been assigned a priority at or ( logically )
* below the maximum system call interrupt priority . FreeRTOS maintains a
* separate interrupt safe API to ensure interrupt entry is as fast and as
* simple as possible . More information ( albeit Cortex - M specific ) is
* provided on the following link :
* https : //www.FreeRTOS.org/RTOS-Cortex-M3-M4.html */
portASSERT_IF_INTERRUPT_PRIORITY_INVALID ( ) ;
2024-01-05 04:14:26 -05:00
uxSavedInterruptStatus = taskENTER_CRITICAL_FROM_ISR ( ) ;
2022-02-24 07:14:22 -05:00
{
/* If null is passed in here then it is the priority of the calling
* task that is being queried . */
pxTCB = prvGetTCBFromHandle ( xTask ) ;
uxReturn = pxTCB - > uxPriority ;
}
2024-01-05 04:14:26 -05:00
taskEXIT_CRITICAL_FROM_ISR ( uxSavedInterruptStatus ) ;
traceRETURN_uxTaskPriorityGetFromISR ( uxReturn ) ;
2022-02-24 07:14:22 -05:00
return uxReturn ;
}
# endif /* INCLUDE_uxTaskPriorityGet */
/*-----------------------------------------------------------*/
2024-01-05 04:14:26 -05:00
# if ( ( INCLUDE_uxTaskPriorityGet == 1 ) && ( configUSE_MUTEXES == 1 ) )
UBaseType_t uxTaskBasePriorityGet ( const TaskHandle_t xTask )
{
TCB_t const * pxTCB ;
UBaseType_t uxReturn ;
traceENTER_uxTaskBasePriorityGet ( xTask ) ;
taskENTER_CRITICAL ( ) ;
{
/* If null is passed in here then it is the base priority of the task
* that called uxTaskBasePriorityGet ( ) that is being queried . */
pxTCB = prvGetTCBFromHandle ( xTask ) ;
uxReturn = pxTCB - > uxBasePriority ;
}
taskEXIT_CRITICAL ( ) ;
traceRETURN_uxTaskBasePriorityGet ( uxReturn ) ;
return uxReturn ;
}
# endif /* #if ( ( INCLUDE_uxTaskPriorityGet == 1 ) && ( configUSE_MUTEXES == 1 ) ) */
/*-----------------------------------------------------------*/
# if ( ( INCLUDE_uxTaskPriorityGet == 1 ) && ( configUSE_MUTEXES == 1 ) )
UBaseType_t uxTaskBasePriorityGetFromISR ( const TaskHandle_t xTask )
{
TCB_t const * pxTCB ;
UBaseType_t uxReturn ;
UBaseType_t uxSavedInterruptStatus ;
traceENTER_uxTaskBasePriorityGetFromISR ( xTask ) ;
/* RTOS ports that support interrupt nesting have the concept of a
* maximum system call ( or maximum API call ) interrupt priority .
* Interrupts that are above the maximum system call priority are keep
* permanently enabled , even when the RTOS kernel is in a critical section ,
* but cannot make any calls to FreeRTOS API functions . If configASSERT ( )
* is defined in FreeRTOSConfig . h then
* portASSERT_IF_INTERRUPT_PRIORITY_INVALID ( ) will result in an assertion
* failure if a FreeRTOS API function is called from an interrupt that has
* been assigned a priority above the configured maximum system call
* priority . Only FreeRTOS functions that end in FromISR can be called
* from interrupts that have been assigned a priority at or ( logically )
* below the maximum system call interrupt priority . FreeRTOS maintains a
* separate interrupt safe API to ensure interrupt entry is as fast and as
* simple as possible . More information ( albeit Cortex - M specific ) is
* provided on the following link :
* https : //www.FreeRTOS.org/RTOS-Cortex-M3-M4.html */
portASSERT_IF_INTERRUPT_PRIORITY_INVALID ( ) ;
uxSavedInterruptStatus = taskENTER_CRITICAL_FROM_ISR ( ) ;
{
/* If null is passed in here then it is the base priority of the calling
* task that is being queried . */
pxTCB = prvGetTCBFromHandle ( xTask ) ;
uxReturn = pxTCB - > uxBasePriority ;
}
taskEXIT_CRITICAL_FROM_ISR ( uxSavedInterruptStatus ) ;
traceRETURN_uxTaskBasePriorityGetFromISR ( uxReturn ) ;
return uxReturn ;
}
# endif /* #if ( ( INCLUDE_uxTaskPriorityGet == 1 ) && ( configUSE_MUTEXES == 1 ) ) */
/*-----------------------------------------------------------*/
2022-02-24 07:14:22 -05:00
# if ( INCLUDE_vTaskPrioritySet == 1 )
void vTaskPrioritySet ( TaskHandle_t xTask ,
UBaseType_t uxNewPriority )
{
TCB_t * pxTCB ;
UBaseType_t uxCurrentBasePriority , uxPriorityUsedOnEntry ;
BaseType_t xYieldRequired = pdFALSE ;
2024-01-05 04:14:26 -05:00
# if ( configNUMBER_OF_CORES > 1 )
BaseType_t xYieldForTask = pdFALSE ;
# endif
traceENTER_vTaskPrioritySet ( xTask , uxNewPriority ) ;
configASSERT ( uxNewPriority < configMAX_PRIORITIES ) ;
2022-02-24 07:14:22 -05:00
/* Ensure the new priority is valid. */
if ( uxNewPriority > = ( UBaseType_t ) configMAX_PRIORITIES )
{
uxNewPriority = ( UBaseType_t ) configMAX_PRIORITIES - ( UBaseType_t ) 1U ;
}
else
{
mtCOVERAGE_TEST_MARKER ( ) ;
}
taskENTER_CRITICAL ( ) ;
{
/* If null is passed in here then it is the priority of the calling
* task that is being changed . */
pxTCB = prvGetTCBFromHandle ( xTask ) ;
traceTASK_PRIORITY_SET ( pxTCB , uxNewPriority ) ;
# if ( configUSE_MUTEXES == 1 )
2024-01-05 04:14:26 -05:00
{
uxCurrentBasePriority = pxTCB - > uxBasePriority ;
}
2022-02-24 07:14:22 -05:00
# else
2024-01-05 04:14:26 -05:00
{
uxCurrentBasePriority = pxTCB - > uxPriority ;
}
2022-02-24 07:14:22 -05:00
# endif
if ( uxCurrentBasePriority ! = uxNewPriority )
{
/* The priority change may have readied a task of higher
* priority than a running task . */
if ( uxNewPriority > uxCurrentBasePriority )
{
2024-01-05 04:14:26 -05:00
# if ( configNUMBER_OF_CORES == 1 )
{
if ( pxTCB ! = pxCurrentTCB )
{
/* The priority of a task other than the currently
* running task is being raised . Is the priority being
* raised above that of the running task ? */
if ( uxNewPriority > pxCurrentTCB - > uxPriority )
{
xYieldRequired = pdTRUE ;
}
else
{
mtCOVERAGE_TEST_MARKER ( ) ;
}
}
else
{
/* The priority of the running task is being raised,
* but the running task must already be the highest
* priority task able to run so no yield is required . */
}
}
# else /* #if ( configNUMBER_OF_CORES == 1 ) */
{
/* The priority of a task is being raised so
* perform a yield for this task later . */
xYieldForTask = pdTRUE ;
}
# endif /* #if ( configNUMBER_OF_CORES == 1 ) */
2022-02-24 07:14:22 -05:00
}
2024-01-05 04:14:26 -05:00
else if ( taskTASK_IS_RUNNING ( pxTCB ) = = pdTRUE )
2022-02-24 07:14:22 -05:00
{
/* Setting the priority of a running task down means
* there may now be another task of higher priority that
* is ready to execute . */
# if ( configUSE_TASK_PREEMPTION_DISABLE == 1 )
if ( pxTCB - > xPreemptionDisable = = pdFALSE )
# endif
{
xYieldRequired = pdTRUE ;
}
}
else
{
/* Setting the priority of any other task down does not
* require a yield as the running task must be above the
* new priority of the task being modified . */
}
/* Remember the ready list the task might be referenced from
* before its uxPriority member is changed so the
* taskRESET_READY_PRIORITY ( ) macro can function correctly . */
uxPriorityUsedOnEntry = pxTCB - > uxPriority ;
# if ( configUSE_MUTEXES == 1 )
2024-01-05 04:14:26 -05:00
{
/* Only change the priority being used if the task is not
* currently using an inherited priority or the new priority
* is bigger than the inherited priority . */
if ( ( pxTCB - > uxBasePriority = = pxTCB - > uxPriority ) | | ( uxNewPriority > pxTCB - > uxPriority ) )
2022-02-24 07:14:22 -05:00
{
2024-01-05 04:14:26 -05:00
pxTCB - > uxPriority = uxNewPriority ;
2022-02-24 07:14:22 -05:00
}
2024-01-05 04:14:26 -05:00
else
2022-02-24 07:14:22 -05:00
{
2024-01-05 04:14:26 -05:00
mtCOVERAGE_TEST_MARKER ( ) ;
2022-02-24 07:14:22 -05:00
}
2024-01-05 04:14:26 -05:00
/* The base priority gets set whatever. */
pxTCB - > uxBasePriority = uxNewPriority ;
}
# else /* if ( configUSE_MUTEXES == 1 ) */
{
pxTCB - > uxPriority = uxNewPriority ;
}
2022-02-24 07:14:22 -05:00
# endif /* if ( configUSE_MUTEXES == 1 ) */
/* Only reset the event list item value if the value is not
* being used for anything else . */
2024-01-05 04:14:26 -05:00
if ( ( listGET_LIST_ITEM_VALUE ( & ( pxTCB - > xEventListItem ) ) & taskEVENT_LIST_ITEM_VALUE_IN_USE ) = = ( ( TickType_t ) 0UL ) )
2022-02-24 07:14:22 -05:00
{
2024-01-05 04:14:26 -05:00
listSET_LIST_ITEM_VALUE ( & ( pxTCB - > xEventListItem ) , ( ( TickType_t ) configMAX_PRIORITIES - ( TickType_t ) uxNewPriority ) ) ;
2022-02-24 07:14:22 -05:00
}
else
{
mtCOVERAGE_TEST_MARKER ( ) ;
}
/* If the task is in the blocked or suspended list we need do
* nothing more than change its priority variable . However , if
* the task is in a ready list it needs to be removed and placed
* in the list appropriate to its new priority . */
if ( listIS_CONTAINED_WITHIN ( & ( pxReadyTasksLists [ uxPriorityUsedOnEntry ] ) , & ( pxTCB - > xStateListItem ) ) ! = pdFALSE )
{
/* The task is currently in its ready list - remove before
* adding it to its new ready list . As we are in a critical
* section we can do this even if the scheduler is suspended . */
if ( uxListRemove ( & ( pxTCB - > xStateListItem ) ) = = ( UBaseType_t ) 0 )
{
/* It is known that the task is in its ready list so
* there is no need to check again and the port level
* reset macro can be called directly . */
portRESET_READY_PRIORITY ( uxPriorityUsedOnEntry , uxTopReadyPriority ) ;
}
else
{
mtCOVERAGE_TEST_MARKER ( ) ;
}
prvAddTaskToReadyList ( pxTCB ) ;
}
else
{
2024-01-05 04:14:26 -05:00
# if ( configNUMBER_OF_CORES == 1 )
2022-02-24 07:14:22 -05:00
{
2024-01-05 04:14:26 -05:00
mtCOVERAGE_TEST_MARKER ( ) ;
2022-02-24 07:14:22 -05:00
}
2024-01-05 04:14:26 -05:00
# else
2022-02-24 07:14:22 -05:00
{
2024-01-05 04:14:26 -05:00
/* It's possible that xYieldForTask was already set to pdTRUE because
* its priority is being raised . However , since it is not in a ready list
* we don ' t actually need to yield for it . */
xYieldForTask = pdFALSE ;
2022-02-24 07:14:22 -05:00
}
2024-01-05 04:14:26 -05:00
# endif
}
if ( xYieldRequired ! = pdFALSE )
{
/* The running task priority is set down. Request the task to yield. */
taskYIELD_TASK_CORE_IF_USING_PREEMPTION ( pxTCB ) ;
}
else
{
# if ( configNUMBER_OF_CORES > 1 )
if ( xYieldForTask ! = pdFALSE )
{
/* The priority of the task is being raised. If a running
* task has priority lower than this task , it should yield
* for this task . */
taskYIELD_ANY_CORE_IF_USING_PREEMPTION ( pxTCB ) ;
}
else
# endif /* if ( configNUMBER_OF_CORES > 1 ) */
2022-02-24 07:14:22 -05:00
{
mtCOVERAGE_TEST_MARKER ( ) ;
}
2024-01-05 04:14:26 -05:00
}
2022-02-24 07:14:22 -05:00
/* Remove compiler warning about unused variables when the port
* optimised task selection is not being used . */
( void ) uxPriorityUsedOnEntry ;
}
}
taskEXIT_CRITICAL ( ) ;
2024-01-05 04:14:26 -05:00
traceRETURN_vTaskPrioritySet ( ) ;
2022-02-24 07:14:22 -05:00
}
# endif /* INCLUDE_vTaskPrioritySet */
/*-----------------------------------------------------------*/
2024-01-05 04:14:26 -05:00
# if ( ( configNUMBER_OF_CORES > 1 ) && ( configUSE_CORE_AFFINITY == 1 ) )
void vTaskCoreAffinitySet ( const TaskHandle_t xTask ,
UBaseType_t uxCoreAffinityMask )
{
TCB_t * pxTCB ;
BaseType_t xCoreID ;
UBaseType_t uxPrevCoreAffinityMask ;
# if ( configUSE_PREEMPTION == 1 )
UBaseType_t uxPrevNotAllowedCores ;
# endif
traceENTER_vTaskCoreAffinitySet ( xTask , uxCoreAffinityMask ) ;
2022-02-24 07:14:22 -05:00
2024-01-05 04:14:26 -05:00
taskENTER_CRITICAL ( ) ;
2022-02-24 07:14:22 -05:00
{
2024-01-05 04:14:26 -05:00
pxTCB = prvGetTCBFromHandle ( xTask ) ;
2022-02-24 07:14:22 -05:00
2024-01-05 04:14:26 -05:00
uxPrevCoreAffinityMask = pxTCB - > uxCoreAffinityMask ;
pxTCB - > uxCoreAffinityMask = uxCoreAffinityMask ;
2022-02-24 07:14:22 -05:00
2024-01-05 04:14:26 -05:00
if ( xSchedulerRunning ! = pdFALSE )
{
if ( taskTASK_IS_RUNNING ( pxTCB ) = = pdTRUE )
{
xCoreID = ( BaseType_t ) pxTCB - > xTaskRunState ;
2022-02-24 07:14:22 -05:00
2024-01-05 04:14:26 -05:00
/* If the task can no longer run on the core it was running,
* request the core to yield . */
if ( ( uxCoreAffinityMask & ( ( UBaseType_t ) 1U < < ( UBaseType_t ) xCoreID ) ) = = 0U )
{
prvYieldCore ( xCoreID ) ;
}
}
else
2022-02-24 07:14:22 -05:00
{
2024-01-05 04:14:26 -05:00
# if ( configUSE_PREEMPTION == 1 )
2022-02-24 07:14:22 -05:00
{
2024-01-05 04:14:26 -05:00
/* Calculate the cores on which this task was not allowed to
* run previously . */
uxPrevNotAllowedCores = ( ~ uxPrevCoreAffinityMask ) & ( ( 1U < < configNUMBER_OF_CORES ) - 1U ) ;
/* Does the new core mask enables this task to run on any of the
* previously not allowed cores ? If yes , check if this task can be
* scheduled on any of those cores . */
if ( ( uxPrevNotAllowedCores & uxCoreAffinityMask ) ! = 0U )
2022-02-24 07:14:22 -05:00
{
2024-01-05 04:14:26 -05:00
prvYieldForTask ( pxTCB ) ;
2022-02-24 07:14:22 -05:00
}
}
2024-01-05 04:14:26 -05:00
# else /* #if( configUSE_PREEMPTION == 1 ) */
{
mtCOVERAGE_TEST_MARKER ( ) ;
}
# endif /* #if( configUSE_PREEMPTION == 1 ) */
2022-02-24 07:14:22 -05:00
}
}
}
2024-01-05 04:14:26 -05:00
taskEXIT_CRITICAL ( ) ;
2022-02-24 07:14:22 -05:00
2024-01-05 04:14:26 -05:00
traceRETURN_vTaskCoreAffinitySet ( ) ;
}
# endif /* #if ( ( configNUMBER_OF_CORES > 1 ) && ( configUSE_CORE_AFFINITY == 1 ) ) */
2022-02-24 07:14:22 -05:00
/*-----------------------------------------------------------*/
2024-01-05 04:14:26 -05:00
# if ( ( configNUMBER_OF_CORES > 1 ) && ( configUSE_CORE_AFFINITY == 1 ) )
UBaseType_t vTaskCoreAffinityGet ( ConstTaskHandle_t xTask )
{
const TCB_t * pxTCB ;
UBaseType_t uxCoreAffinityMask ;
2022-02-24 07:14:22 -05:00
2024-01-05 04:14:26 -05:00
traceENTER_vTaskCoreAffinityGet ( xTask ) ;
2022-02-24 07:14:22 -05:00
2024-01-05 04:14:26 -05:00
taskENTER_CRITICAL ( ) ;
{
pxTCB = prvGetTCBFromHandle ( xTask ) ;
uxCoreAffinityMask = pxTCB - > uxCoreAffinityMask ;
2022-02-24 07:14:22 -05:00
}
2024-01-05 04:14:26 -05:00
taskEXIT_CRITICAL ( ) ;
2022-02-24 07:14:22 -05:00
2024-01-05 04:14:26 -05:00
traceRETURN_vTaskCoreAffinityGet ( uxCoreAffinityMask ) ;
return uxCoreAffinityMask ;
}
# endif /* #if ( ( configNUMBER_OF_CORES > 1 ) && ( configUSE_CORE_AFFINITY == 1 ) ) */
2022-02-24 07:14:22 -05:00
/*-----------------------------------------------------------*/
# if ( configUSE_TASK_PREEMPTION_DISABLE == 1 )
void vTaskPreemptionDisable ( const TaskHandle_t xTask )
{
TCB_t * pxTCB ;
2024-01-05 04:14:26 -05:00
traceENTER_vTaskPreemptionDisable ( xTask ) ;
2022-02-24 07:14:22 -05:00
taskENTER_CRITICAL ( ) ;
{
pxTCB = prvGetTCBFromHandle ( xTask ) ;
pxTCB - > xPreemptionDisable = pdTRUE ;
}
taskEXIT_CRITICAL ( ) ;
2024-01-05 04:14:26 -05:00
traceRETURN_vTaskPreemptionDisable ( ) ;
2022-02-24 07:14:22 -05:00
}
2024-01-05 04:14:26 -05:00
# endif /* #if ( configUSE_TASK_PREEMPTION_DISABLE == 1 ) */
2022-02-24 07:14:22 -05:00
/*-----------------------------------------------------------*/
# if ( configUSE_TASK_PREEMPTION_DISABLE == 1 )
void vTaskPreemptionEnable ( const TaskHandle_t xTask )
{
TCB_t * pxTCB ;
BaseType_t xCoreID ;
2024-01-05 04:14:26 -05:00
traceENTER_vTaskPreemptionEnable ( xTask ) ;
2022-02-24 07:14:22 -05:00
taskENTER_CRITICAL ( ) ;
{
pxTCB = prvGetTCBFromHandle ( xTask ) ;
pxTCB - > xPreemptionDisable = pdFALSE ;
if ( xSchedulerRunning ! = pdFALSE )
{
2024-01-05 04:14:26 -05:00
if ( taskTASK_IS_RUNNING ( pxTCB ) = = pdTRUE )
2022-02-24 07:14:22 -05:00
{
xCoreID = ( BaseType_t ) pxTCB - > xTaskRunState ;
prvYieldCore ( xCoreID ) ;
}
}
}
taskEXIT_CRITICAL ( ) ;
2024-01-05 04:14:26 -05:00
traceRETURN_vTaskPreemptionEnable ( ) ;
2022-02-24 07:14:22 -05:00
}
2024-01-05 04:14:26 -05:00
# endif /* #if ( configUSE_TASK_PREEMPTION_DISABLE == 1 ) */
2022-02-24 07:14:22 -05:00
/*-----------------------------------------------------------*/
# if ( INCLUDE_vTaskSuspend == 1 )
void vTaskSuspend ( TaskHandle_t xTaskToSuspend )
{
TCB_t * pxTCB ;
2024-01-05 04:14:26 -05:00
# if ( configNUMBER_OF_CORES > 1 )
BaseType_t xTaskRunningOnCore ;
# endif
traceENTER_vTaskSuspend ( xTaskToSuspend ) ;
2022-02-24 07:14:22 -05:00
taskENTER_CRITICAL ( ) ;
{
/* If null is passed in here then it is the running task that is
* being suspended . */
pxTCB = prvGetTCBFromHandle ( xTaskToSuspend ) ;
traceTASK_SUSPEND ( pxTCB ) ;
2024-01-05 04:14:26 -05:00
# if ( configNUMBER_OF_CORES > 1 )
xTaskRunningOnCore = pxTCB - > xTaskRunState ;
# endif
2022-02-24 07:14:22 -05:00
/* Remove task from the ready/delayed list and place in the
* suspended list . */
if ( uxListRemove ( & ( pxTCB - > xStateListItem ) ) = = ( UBaseType_t ) 0 )
{
taskRESET_READY_PRIORITY ( pxTCB - > uxPriority ) ;
}
else
{
mtCOVERAGE_TEST_MARKER ( ) ;
}
/* Is the task waiting on an event also? */
if ( listLIST_ITEM_CONTAINER ( & ( pxTCB - > xEventListItem ) ) ! = NULL )
{
( void ) uxListRemove ( & ( pxTCB - > xEventListItem ) ) ;
}
else
{
mtCOVERAGE_TEST_MARKER ( ) ;
}
vListInsertEnd ( & xSuspendedTaskList , & ( pxTCB - > xStateListItem ) ) ;
# if ( configUSE_TASK_NOTIFICATIONS == 1 )
2024-01-05 04:14:26 -05:00
{
BaseType_t x ;
2022-02-24 07:14:22 -05:00
2024-01-05 04:14:26 -05:00
for ( x = ( BaseType_t ) 0 ; x < ( BaseType_t ) configTASK_NOTIFICATION_ARRAY_ENTRIES ; x + + )
{
if ( pxTCB - > ucNotifyState [ x ] = = taskWAITING_NOTIFICATION )
2022-02-24 07:14:22 -05:00
{
2024-01-05 04:14:26 -05:00
/* The task was blocked to wait for a notification, but is
* now suspended , so no notification was received . */
pxTCB - > ucNotifyState [ x ] = taskNOT_WAITING_NOTIFICATION ;
2022-02-24 07:14:22 -05:00
}
}
2024-01-05 04:14:26 -05:00
}
2022-02-24 07:14:22 -05:00
# endif /* if ( configUSE_TASK_NOTIFICATIONS == 1 ) */
2024-01-05 04:14:26 -05:00
}
# if ( configNUMBER_OF_CORES == 1 )
{
taskEXIT_CRITICAL ( ) ;
if ( xSchedulerRunning ! = pdFALSE )
{
/* Reset the next expected unblock time in case it referred to the
* task that is now in the Suspended state . */
taskENTER_CRITICAL ( ) ;
{
prvResetNextTaskUnblockTime ( ) ;
}
taskEXIT_CRITICAL ( ) ;
}
else
{
mtCOVERAGE_TEST_MARKER ( ) ;
}
2022-02-24 07:14:22 -05:00
2024-01-05 04:14:26 -05:00
if ( pxTCB = = pxCurrentTCB )
{
if ( xSchedulerRunning ! = pdFALSE )
{
/* The current task has just been suspended. */
configASSERT ( uxSchedulerSuspended = = 0 ) ;
portYIELD_WITHIN_API ( ) ;
}
else
{
/* The scheduler is not running, but the task that was pointed
* to by pxCurrentTCB has just been suspended and pxCurrentTCB
* must be adjusted to point to a different task . */
if ( listCURRENT_LIST_LENGTH ( & xSuspendedTaskList ) = = uxCurrentNumberOfTasks )
{
/* No other tasks are ready, so set pxCurrentTCB back to
* NULL so when the next task is created pxCurrentTCB will
* be set to point to it no matter what its relative priority
* is . */
pxCurrentTCB = NULL ;
}
else
{
vTaskSwitchContext ( ) ;
}
}
}
else
{
mtCOVERAGE_TEST_MARKER ( ) ;
}
}
# else /* #if ( configNUMBER_OF_CORES == 1 ) */
{
2022-02-24 07:14:22 -05:00
if ( xSchedulerRunning ! = pdFALSE )
{
/* Reset the next expected unblock time in case it referred to the
* task that is now in the Suspended state . */
prvResetNextTaskUnblockTime ( ) ;
}
else
{
mtCOVERAGE_TEST_MARKER ( ) ;
}
2024-01-05 04:14:26 -05:00
if ( taskTASK_IS_RUNNING ( pxTCB ) = = pdTRUE )
2022-02-24 07:14:22 -05:00
{
if ( xSchedulerRunning ! = pdFALSE )
{
2024-01-05 04:14:26 -05:00
if ( xTaskRunningOnCore = = ( BaseType_t ) portGET_CORE_ID ( ) )
2022-02-24 07:14:22 -05:00
{
/* The current task has just been suspended. */
configASSERT ( uxSchedulerSuspended = = 0 ) ;
vTaskYieldWithinAPI ( ) ;
}
else
{
prvYieldCore ( xTaskRunningOnCore ) ;
}
}
else
{
2024-01-05 04:14:26 -05:00
/* This code path is not possible because only Idle tasks are
* assigned a core before the scheduler is started ( i . e .
* taskTASK_IS_RUNNING is only true for idle tasks before
* the scheduler is started ) and idle tasks cannot be
* suspended . */
mtCOVERAGE_TEST_MARKER ( ) ;
2022-02-24 07:14:22 -05:00
}
}
else
{
2024-01-05 04:14:26 -05:00
mtCOVERAGE_TEST_MARKER ( ) ;
2022-02-24 07:14:22 -05:00
}
2024-01-05 04:14:26 -05:00
taskEXIT_CRITICAL ( ) ;
}
# endif /* #if ( configNUMBER_OF_CORES == 1 ) */
traceRETURN_vTaskSuspend ( ) ;
2022-02-24 07:14:22 -05:00
}
# endif /* INCLUDE_vTaskSuspend */
/*-----------------------------------------------------------*/
# if ( INCLUDE_vTaskSuspend == 1 )
static BaseType_t prvTaskIsTaskSuspended ( const TaskHandle_t xTask )
{
BaseType_t xReturn = pdFALSE ;
const TCB_t * const pxTCB = xTask ;
2024-01-05 04:14:26 -05:00
/* Accesses xPendingReadyList so must be called from a critical
* section . */
2022-02-24 07:14:22 -05:00
/* It does not make sense to check if the calling task is suspended. */
configASSERT ( xTask ) ;
/* Is the task being resumed actually in the suspended list? */
if ( listIS_CONTAINED_WITHIN ( & xSuspendedTaskList , & ( pxTCB - > xStateListItem ) ) ! = pdFALSE )
{
/* Has the task already been resumed from within an ISR? */
if ( listIS_CONTAINED_WITHIN ( & xPendingReadyList , & ( pxTCB - > xEventListItem ) ) = = pdFALSE )
{
/* Is it in the suspended list because it is in the Suspended
2024-01-05 04:14:26 -05:00
* state , or because it is blocked with no timeout ? */
if ( listIS_CONTAINED_WITHIN ( NULL , & ( pxTCB - > xEventListItem ) ) ! = pdFALSE )
2022-02-24 07:14:22 -05:00
{
2024-01-05 04:14:26 -05:00
# if ( configUSE_TASK_NOTIFICATIONS == 1 )
{
BaseType_t x ;
/* The task does not appear on the event list item of
* and of the RTOS objects , but could still be in the
* blocked state if it is waiting on its notification
* rather than waiting on an object . If not , is
* suspended . */
xReturn = pdTRUE ;
for ( x = ( BaseType_t ) 0 ; x < ( BaseType_t ) configTASK_NOTIFICATION_ARRAY_ENTRIES ; x + + )
{
if ( pxTCB - > ucNotifyState [ x ] = = taskWAITING_NOTIFICATION )
{
xReturn = pdFALSE ;
break ;
}
}
}
# else /* if ( configUSE_TASK_NOTIFICATIONS == 1 ) */
{
xReturn = pdTRUE ;
}
# endif /* if ( configUSE_TASK_NOTIFICATIONS == 1 ) */
2022-02-24 07:14:22 -05:00
}
else
{
mtCOVERAGE_TEST_MARKER ( ) ;
}
}
else
{
mtCOVERAGE_TEST_MARKER ( ) ;
}
}
else
{
mtCOVERAGE_TEST_MARKER ( ) ;
}
return xReturn ;
2024-01-05 04:14:26 -05:00
}
2022-02-24 07:14:22 -05:00
# endif /* INCLUDE_vTaskSuspend */
/*-----------------------------------------------------------*/
# if ( INCLUDE_vTaskSuspend == 1 )
void vTaskResume ( TaskHandle_t xTaskToResume )
{
TCB_t * const pxTCB = xTaskToResume ;
2024-01-05 04:14:26 -05:00
traceENTER_vTaskResume ( xTaskToResume ) ;
2022-02-24 07:14:22 -05:00
/* It does not make sense to resume the calling task. */
configASSERT ( xTaskToResume ) ;
2024-01-05 04:14:26 -05:00
# if ( configNUMBER_OF_CORES == 1 )
/* The parameter cannot be NULL as it is impossible to resume the
* currently executing task . */
if ( ( pxTCB ! = pxCurrentTCB ) & & ( pxTCB ! = NULL ) )
# else
/* The parameter cannot be NULL as it is impossible to resume the
* currently executing task . It is also impossible to resume a task
* that is actively running on another core but it is not safe
* to check their run state here . Therefore , we get into a critical
* section and check if the task is actually suspended or not . */
if ( pxTCB ! = NULL )
# endif
2022-02-24 07:14:22 -05:00
{
taskENTER_CRITICAL ( ) ;
{
if ( prvTaskIsTaskSuspended ( pxTCB ) ! = pdFALSE )
{
traceTASK_RESUME ( pxTCB ) ;
/* The ready list can be accessed even if the scheduler is
* suspended because this is inside a critical section . */
( void ) uxListRemove ( & ( pxTCB - > xStateListItem ) ) ;
prvAddTaskToReadyList ( pxTCB ) ;
2024-01-05 04:14:26 -05:00
/* This yield may not cause the task just resumed to run,
* but will leave the lists in the correct state for the
* next yield . */
taskYIELD_ANY_CORE_IF_USING_PREEMPTION ( pxTCB ) ;
2022-02-24 07:14:22 -05:00
}
else
{
mtCOVERAGE_TEST_MARKER ( ) ;
}
}
taskEXIT_CRITICAL ( ) ;
}
else
{
mtCOVERAGE_TEST_MARKER ( ) ;
}
2024-01-05 04:14:26 -05:00
traceRETURN_vTaskResume ( ) ;
2022-02-24 07:14:22 -05:00
}
# endif /* INCLUDE_vTaskSuspend */
/*-----------------------------------------------------------*/
# if ( ( INCLUDE_xTaskResumeFromISR == 1 ) && ( INCLUDE_vTaskSuspend == 1 ) )
BaseType_t xTaskResumeFromISR ( TaskHandle_t xTaskToResume )
{
BaseType_t xYieldRequired = pdFALSE ;
TCB_t * const pxTCB = xTaskToResume ;
UBaseType_t uxSavedInterruptStatus ;
2024-01-05 04:14:26 -05:00
traceENTER_xTaskResumeFromISR ( xTaskToResume ) ;
2022-02-24 07:14:22 -05:00
configASSERT ( xTaskToResume ) ;
/* RTOS ports that support interrupt nesting have the concept of a
* maximum system call ( or maximum API call ) interrupt priority .
* Interrupts that are above the maximum system call priority are keep
* permanently enabled , even when the RTOS kernel is in a critical section ,
* but cannot make any calls to FreeRTOS API functions . If configASSERT ( )
* is defined in FreeRTOSConfig . h then
* portASSERT_IF_INTERRUPT_PRIORITY_INVALID ( ) will result in an assertion
* failure if a FreeRTOS API function is called from an interrupt that has
* been assigned a priority above the configured maximum system call
* priority . Only FreeRTOS functions that end in FromISR can be called
* from interrupts that have been assigned a priority at or ( logically )
* below the maximum system call interrupt priority . FreeRTOS maintains a
* separate interrupt safe API to ensure interrupt entry is as fast and as
* simple as possible . More information ( albeit Cortex - M specific ) is
* provided on the following link :
* https : //www.FreeRTOS.org/RTOS-Cortex-M3-M4.html */
portASSERT_IF_INTERRUPT_PRIORITY_INVALID ( ) ;
2024-01-05 04:14:26 -05:00
uxSavedInterruptStatus = taskENTER_CRITICAL_FROM_ISR ( ) ;
2022-02-24 07:14:22 -05:00
{
if ( prvTaskIsTaskSuspended ( pxTCB ) ! = pdFALSE )
{
traceTASK_RESUME_FROM_ISR ( pxTCB ) ;
/* Check the ready lists can be accessed. */
2024-01-05 04:14:26 -05:00
if ( uxSchedulerSuspended = = ( UBaseType_t ) 0U )
2022-02-24 07:14:22 -05:00
{
2024-01-05 04:14:26 -05:00
# if ( configNUMBER_OF_CORES == 1 )
{
/* Ready lists can be accessed so move the task from the
* suspended list to the ready list directly . */
if ( pxTCB - > uxPriority > pxCurrentTCB - > uxPriority )
{
xYieldRequired = pdTRUE ;
/* Mark that a yield is pending in case the user is not
* using the return value to initiate a context switch
* from the ISR using the port specific portYIELD_FROM_ISR ( ) . */
xYieldPendings [ 0 ] = pdTRUE ;
}
else
{
mtCOVERAGE_TEST_MARKER ( ) ;
}
}
# endif /* #if ( configNUMBER_OF_CORES == 1 ) */
2022-02-24 07:14:22 -05:00
( void ) uxListRemove ( & ( pxTCB - > xStateListItem ) ) ;
prvAddTaskToReadyList ( pxTCB ) ;
}
else
{
/* The delayed or ready lists cannot be accessed so the task
* is held in the pending ready list until the scheduler is
* unsuspended . */
vListInsertEnd ( & ( xPendingReadyList ) , & ( pxTCB - > xEventListItem ) ) ;
}
2024-01-05 04:14:26 -05:00
# if ( ( configNUMBER_OF_CORES > 1 ) && ( configUSE_PREEMPTION == 1 ) )
{
prvYieldForTask ( pxTCB ) ;
2022-02-24 07:14:22 -05:00
if ( xYieldPendings [ portGET_CORE_ID ( ) ] ! = pdFALSE )
{
xYieldRequired = pdTRUE ;
}
2024-01-05 04:14:26 -05:00
}
# endif /* #if ( ( configNUMBER_OF_CORES > 1 ) && ( configUSE_PREEMPTION == 1 ) ) */
2022-02-24 07:14:22 -05:00
}
else
{
mtCOVERAGE_TEST_MARKER ( ) ;
}
}
2024-01-05 04:14:26 -05:00
taskEXIT_CRITICAL_FROM_ISR ( uxSavedInterruptStatus ) ;
traceRETURN_xTaskResumeFromISR ( xYieldRequired ) ;
2022-02-24 07:14:22 -05:00
return xYieldRequired ;
}
# endif /* ( ( INCLUDE_xTaskResumeFromISR == 1 ) && ( INCLUDE_vTaskSuspend == 1 ) ) */
/*-----------------------------------------------------------*/
static BaseType_t prvCreateIdleTasks ( void )
{
BaseType_t xReturn = pdPASS ;
BaseType_t xCoreID ;
char cIdleName [ configMAX_TASK_NAME_LEN ] ;
2024-01-05 04:14:26 -05:00
TaskFunction_t pxIdleTaskFunction = NULL ;
BaseType_t xIdleTaskNameIndex ;
2022-02-24 07:14:22 -05:00
2024-01-05 04:14:26 -05:00
for ( xIdleTaskNameIndex = ( BaseType_t ) 0 ; xIdleTaskNameIndex < ( BaseType_t ) configMAX_TASK_NAME_LEN ; xIdleTaskNameIndex + + )
2022-02-24 07:14:22 -05:00
{
2024-01-05 04:14:26 -05:00
cIdleName [ xIdleTaskNameIndex ] = configIDLE_TASK_NAME [ xIdleTaskNameIndex ] ;
2022-02-24 07:14:22 -05:00
2024-01-05 04:14:26 -05:00
/* 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 ( cIdleName [ xIdleTaskNameIndex ] = = ( char ) 0x00 )
2022-02-24 07:14:22 -05:00
{
break ;
}
else
{
mtCOVERAGE_TEST_MARKER ( ) ;
}
2024-01-05 04:14:26 -05:00
}
2022-02-24 07:14:22 -05:00
2024-01-05 04:14:26 -05:00
/* Add each idle task at the lowest priority. */
for ( xCoreID = ( BaseType_t ) 0 ; xCoreID < ( BaseType_t ) configNUMBER_OF_CORES ; xCoreID + + )
{
# if ( configNUMBER_OF_CORES == 1 )
2022-02-24 07:14:22 -05:00
{
2024-01-05 04:14:26 -05:00
pxIdleTaskFunction = prvIdleTask ;
}
# else /* #if ( configNUMBER_OF_CORES == 1 ) */
{
/* In the FreeRTOS SMP, configNUMBER_OF_CORES - 1 passive idle tasks
* are also created to ensure that each core has an idle task to
* run when no other task is available to run . */
if ( xCoreID = = 0 )
2022-02-24 07:14:22 -05:00
{
2024-01-05 04:14:26 -05:00
pxIdleTaskFunction = prvIdleTask ;
2022-02-24 07:14:22 -05:00
}
else
{
2024-01-05 04:14:26 -05:00
pxIdleTaskFunction = prvPassiveIdleTask ;
2022-02-24 07:14:22 -05:00
}
}
2024-01-05 04:14:26 -05:00
# endif /* #if ( configNUMBER_OF_CORES == 1 ) */
2022-02-24 07:14:22 -05:00
2024-01-05 04:14:26 -05:00
/* Update the idle task name with suffix to differentiate the idle tasks.
* This function is not required in single core FreeRTOS since there is
* only one idle task . */
# if ( configNUMBER_OF_CORES > 1 )
2022-02-24 07:14:22 -05:00
{
2024-01-05 04:14:26 -05:00
/* Append the idle task number to the end of the name if there is space. */
if ( xIdleTaskNameIndex < ( BaseType_t ) configMAX_TASK_NAME_LEN )
2022-02-24 07:14:22 -05:00
{
2024-01-05 04:14:26 -05:00
cIdleName [ xIdleTaskNameIndex ] = ( char ) ( xCoreID + ' 0 ' ) ;
/* And append a null character if there is space. */
if ( ( xIdleTaskNameIndex + 1 ) < ( BaseType_t ) configMAX_TASK_NAME_LEN )
{
cIdleName [ xIdleTaskNameIndex + 1 ] = ' \0 ' ;
}
else
{
mtCOVERAGE_TEST_MARKER ( ) ;
}
2022-02-24 07:14:22 -05:00
}
else
{
mtCOVERAGE_TEST_MARKER ( ) ;
}
}
2024-01-05 04:14:26 -05:00
# endif /* if ( configNUMBER_OF_CORES > 1 ) */
2022-02-24 07:14:22 -05:00
# if ( configSUPPORT_STATIC_ALLOCATION == 1 )
2024-01-05 04:14:26 -05:00
{
StaticTask_t * pxIdleTaskTCBBuffer = NULL ;
StackType_t * pxIdleTaskStackBuffer = NULL ;
uint32_t ulIdleTaskStackSize ;
/* The Idle task is created using user provided RAM - obtain the
* address of the RAM then create the idle task . */
# if ( configNUMBER_OF_CORES == 1 )
{
vApplicationGetIdleTaskMemory ( & pxIdleTaskTCBBuffer , & pxIdleTaskStackBuffer , & ulIdleTaskStackSize ) ;
}
# else
2022-02-24 07:14:22 -05:00
{
if ( xCoreID = = 0 )
{
vApplicationGetIdleTaskMemory ( & pxIdleTaskTCBBuffer , & pxIdleTaskStackBuffer , & ulIdleTaskStackSize ) ;
}
else
{
2024-01-05 04:14:26 -05:00
vApplicationGetPassiveIdleTaskMemory ( & pxIdleTaskTCBBuffer , & pxIdleTaskStackBuffer , & ulIdleTaskStackSize , xCoreID - 1 ) ;
2022-02-24 07:14:22 -05:00
}
}
2024-01-05 04:14:26 -05:00
# endif /* if ( configNUMBER_OF_CORES == 1 ) */
xIdleTaskHandles [ xCoreID ] = xTaskCreateStatic ( pxIdleTaskFunction ,
cIdleName ,
ulIdleTaskStackSize ,
( void * ) NULL ,
portPRIVILEGE_BIT , /* In effect ( tskIDLE_PRIORITY | portPRIVILEGE_BIT ), but tskIDLE_PRIORITY is zero. */
pxIdleTaskStackBuffer ,
pxIdleTaskTCBBuffer ) ;
2022-02-24 07:14:22 -05:00
2024-01-05 04:14:26 -05:00
if ( xIdleTaskHandles [ xCoreID ] ! = NULL )
{
xReturn = pdPASS ;
}
else
{
xReturn = pdFAIL ;
2022-02-24 07:14:22 -05:00
}
2024-01-05 04:14:26 -05:00
}
# else /* if ( configSUPPORT_STATIC_ALLOCATION == 1 ) */
{
/* The Idle task is being created using dynamically allocated RAM. */
xReturn = xTaskCreate ( pxIdleTaskFunction ,
cIdleName ,
configMINIMAL_STACK_SIZE ,
( void * ) NULL ,
portPRIVILEGE_BIT , /* In effect ( tskIDLE_PRIORITY | portPRIVILEGE_BIT ), but tskIDLE_PRIORITY is zero. */
& xIdleTaskHandles [ xCoreID ] ) ;
}
2022-02-24 07:14:22 -05:00
# endif /* configSUPPORT_STATIC_ALLOCATION */
2024-01-05 04:14:26 -05:00
/* Break the loop if any of the idle task is failed to be created. */
if ( xReturn = = pdFAIL )
{
break ;
}
else
{
mtCOVERAGE_TEST_MARKER ( ) ;
}
2022-02-24 07:14:22 -05:00
}
return xReturn ;
}
2024-01-05 04:14:26 -05:00
/*-----------------------------------------------------------*/
2022-02-24 07:14:22 -05:00
void vTaskStartScheduler ( void )
{
BaseType_t xReturn ;
2024-01-05 04:14:26 -05:00
traceENTER_vTaskStartScheduler ( ) ;
# if ( configUSE_CORE_AFFINITY == 1 ) && ( configNUMBER_OF_CORES > 1 )
{
/* Sanity check that the UBaseType_t must have greater than or equal to
* the number of bits as confNUMBER_OF_CORES . */
configASSERT ( ( sizeof ( UBaseType_t ) * taskBITS_PER_BYTE ) > = configNUMBER_OF_CORES ) ;
}
# endif /* #if ( configUSE_CORE_AFFINITY == 1 ) && ( configNUMBER_OF_CORES > 1 ) */
xReturn = prvCreateIdleTasks ( ) ;
2022-02-24 07:14:22 -05:00
# if ( configUSE_TIMERS == 1 )
2024-01-05 04:14:26 -05:00
{
if ( xReturn = = pdPASS )
2022-02-24 07:14:22 -05:00
{
xReturn = xTimerCreateTimerTask ( ) ;
}
2024-01-05 04:14:26 -05:00
else
{
mtCOVERAGE_TEST_MARKER ( ) ;
}
}
2022-02-24 07:14:22 -05:00
# endif /* configUSE_TIMERS */
if ( xReturn = = pdPASS )
{
/* freertos_tasks_c_additions_init() should only be called if the user
* definable macro FREERTOS_TASKS_C_ADDITIONS_INIT ( ) is defined , as that is
* the only macro called by the function . */
# ifdef FREERTOS_TASKS_C_ADDITIONS_INIT
2024-01-05 04:14:26 -05:00
{
freertos_tasks_c_additions_init ( ) ;
}
2022-02-24 07:14:22 -05:00
# endif
/* Interrupts are turned off here, to ensure a tick does not occur
* before or during the call to xPortStartScheduler ( ) . The stacks of
* the created tasks contain a status word with interrupts switched on
* so interrupts will automatically get re - enabled when the first task
* starts to run . */
portDISABLE_INTERRUPTS ( ) ;
2024-01-05 04:14:26 -05:00
# if ( configUSE_C_RUNTIME_TLS_SUPPORT == 1 )
{
/* Switch C-Runtime's TLS Block to point to the TLS
* block specific to the task that will run first . */
configSET_TLS_BLOCK ( pxCurrentTCB - > xTLSBlock ) ;
}
# endif
2022-02-24 07:14:22 -05:00
xNextTaskUnblockTime = portMAX_DELAY ;
xSchedulerRunning = pdTRUE ;
xTickCount = ( TickType_t ) configINITIAL_TICK_COUNT ;
/* If configGENERATE_RUN_TIME_STATS is defined then the following
* macro must be defined to configure the timer / counter used to generate
* the run time counter time base . NOTE : If configGENERATE_RUN_TIME_STATS
* is set to 0 and the following line fails to build then ensure you do not
* have portCONFIGURE_TIMER_FOR_RUN_TIME_STATS ( ) defined in your
* FreeRTOSConfig . h file . */
portCONFIGURE_TIMER_FOR_RUN_TIME_STATS ( ) ;
traceTASK_SWITCHED_IN ( ) ;
/* Setting up the timer tick is hardware specific and thus in the
* portable interface . */
2024-01-05 04:14:26 -05:00
/* The return value for xPortStartScheduler is not required
* hence using a void datatype . */
( void ) xPortStartScheduler ( ) ;
/* In most cases, xPortStartScheduler() will not return. If it
* returns pdTRUE then there was not enough heap memory available
* to create either the Idle or the Timer task . If it returned
* pdFALSE , then the application called xTaskEndScheduler ( ) .
* Most ports don ' t implement xTaskEndScheduler ( ) as there is
* nothing to return to . */
2022-02-24 07:14:22 -05:00
}
else
{
/* This line will only be reached if the kernel could not be started,
* because there was not enough FreeRTOS heap to create the idle task
* or the timer task . */
configASSERT ( xReturn ! = errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY ) ;
}
/* Prevent compiler warnings if INCLUDE_xTaskGetIdleTaskHandle is set to 0,
2024-01-05 04:14:26 -05:00
* meaning xIdleTaskHandles are not used anywhere else . */
( void ) xIdleTaskHandles ;
2022-02-24 07:14:22 -05:00
/* OpenOCD makes use of uxTopUsedPriority for thread debugging. Prevent uxTopUsedPriority
* from getting optimized out as it is no longer used by the kernel . */
( void ) uxTopUsedPriority ;
2024-01-05 04:14:26 -05:00
traceRETURN_vTaskStartScheduler ( ) ;
2022-02-24 07:14:22 -05:00
}
/*-----------------------------------------------------------*/
void vTaskEndScheduler ( void )
{
2024-01-05 04:14:26 -05:00
traceENTER_vTaskEndScheduler ( ) ;
2022-02-24 07:14:22 -05:00
/* Stop the scheduler interrupts and call the portable scheduler end
* routine so the original ISRs can be restored if necessary . The port
* layer must ensure interrupts enable bit is left in the correct state . */
portDISABLE_INTERRUPTS ( ) ;
xSchedulerRunning = pdFALSE ;
vPortEndScheduler ( ) ;
2024-01-05 04:14:26 -05:00
traceRETURN_vTaskEndScheduler ( ) ;
2022-02-24 07:14:22 -05:00
}
/*----------------------------------------------------------*/
void vTaskSuspendAll ( void )
{
2024-01-05 04:14:26 -05:00
traceENTER_vTaskSuspendAll ( ) ;
2022-02-24 07:14:22 -05:00
2024-01-05 04:14:26 -05:00
# if ( configNUMBER_OF_CORES == 1 )
2022-02-24 07:14:22 -05:00
{
2024-01-05 04:14:26 -05:00
/* A critical section is not required as the variable is of type
* BaseType_t . Please read Richard Barry ' s reply in the following link to a
* post in the FreeRTOS support forum before reporting this as a bug ! -
* https : //goo.gl/wu4acr */
2022-02-24 07:14:22 -05:00
2024-01-05 04:14:26 -05:00
/* portSOFTWARE_BARRIER() is only implemented for emulated/simulated ports that
2022-02-24 07:14:22 -05:00
* do not otherwise exhibit real time behaviour . */
portSOFTWARE_BARRIER ( ) ;
2024-01-05 04:14:26 -05:00
/* The scheduler is suspended if uxSchedulerSuspended is non-zero. An increment
* is used to allow calls to vTaskSuspendAll ( ) to nest . */
+ + uxSchedulerSuspended ;
/* Enforces ordering for ports and optimised compilers that may otherwise place
* the above increment elsewhere . */
portMEMORY_BARRIER ( ) ;
}
# else /* #if ( configNUMBER_OF_CORES == 1 ) */
{
UBaseType_t ulState ;
/* This must only be called from within a task. */
portASSERT_IF_IN_ISR ( ) ;
if ( xSchedulerRunning ! = pdFALSE )
{
/* Writes to uxSchedulerSuspended must be protected by both the task AND ISR locks.
* We must disable interrupts before we grab the locks in the event that this task is
* interrupted and switches context before incrementing uxSchedulerSuspended .
* It is safe to re - enable interrupts after releasing the ISR lock and incrementing
* uxSchedulerSuspended since that will prevent context switches . */
ulState = portSET_INTERRUPT_MASK ( ) ;
/* portSOFRWARE_BARRIER() is only implemented for emulated/simulated ports that
* do not otherwise exhibit real time behaviour . */
portSOFTWARE_BARRIER ( ) ;
portGET_TASK_LOCK ( ) ;
/* uxSchedulerSuspended is increased after prvCheckForRunStateChange. The
* purpose is to prevent altering the variable when fromISR APIs are readying
* it . */
if ( uxSchedulerSuspended = = 0U )
{
if ( portGET_CRITICAL_NESTING_COUNT ( ) = = 0U )
{
prvCheckForRunStateChange ( ) ;
}
else
{
mtCOVERAGE_TEST_MARKER ( ) ;
}
}
else
{
mtCOVERAGE_TEST_MARKER ( ) ;
}
portGET_ISR_LOCK ( ) ;
2022-02-24 07:14:22 -05:00
2024-01-05 04:14:26 -05:00
/* The scheduler is suspended if uxSchedulerSuspended is non-zero. An increment
* is used to allow calls to vTaskSuspendAll ( ) to nest . */
+ + uxSchedulerSuspended ;
portRELEASE_ISR_LOCK ( ) ;
2022-02-24 07:14:22 -05:00
2024-01-05 04:14:26 -05:00
portCLEAR_INTERRUPT_MASK ( ulState ) ;
}
else
2022-02-24 07:14:22 -05:00
{
2024-01-05 04:14:26 -05:00
mtCOVERAGE_TEST_MARKER ( ) ;
2022-02-24 07:14:22 -05:00
}
}
2024-01-05 04:14:26 -05:00
# endif /* #if ( configNUMBER_OF_CORES == 1 ) */
traceRETURN_vTaskSuspendAll ( ) ;
2022-02-24 07:14:22 -05:00
}
2024-01-05 04:14:26 -05:00
2022-02-24 07:14:22 -05:00
/*----------------------------------------------------------*/
# if ( configUSE_TICKLESS_IDLE != 0 )
static TickType_t prvGetExpectedIdleTime ( void )
{
TickType_t xReturn ;
UBaseType_t uxHigherPriorityReadyTasks = pdFALSE ;
/* uxHigherPriorityReadyTasks takes care of the case where
* configUSE_PREEMPTION is 0 , so there may be tasks above the idle priority
* task that are in the Ready state , even though the idle task is
* running . */
# if ( configUSE_PORT_OPTIMISED_TASK_SELECTION == 0 )
2024-01-05 04:14:26 -05:00
{
if ( uxTopReadyPriority > tskIDLE_PRIORITY )
2022-02-24 07:14:22 -05:00
{
2024-01-05 04:14:26 -05:00
uxHigherPriorityReadyTasks = pdTRUE ;
2022-02-24 07:14:22 -05:00
}
2024-01-05 04:14:26 -05:00
}
2022-02-24 07:14:22 -05:00
# else
2024-01-05 04:14:26 -05:00
{
const UBaseType_t uxLeastSignificantBit = ( UBaseType_t ) 0x01 ;
2022-02-24 07:14:22 -05:00
2024-01-05 04:14:26 -05:00
/* When port optimised task selection is used the uxTopReadyPriority
* variable is used as a bit map . If bits other than the least
* significant bit are set then there are tasks that have a priority
* above the idle priority that are in the Ready state . This takes
* care of the case where the co - operative scheduler is in use . */
if ( uxTopReadyPriority > uxLeastSignificantBit )
{
uxHigherPriorityReadyTasks = pdTRUE ;
2022-02-24 07:14:22 -05:00
}
2024-01-05 04:14:26 -05:00
}
2022-02-24 07:14:22 -05:00
# endif /* if ( configUSE_PORT_OPTIMISED_TASK_SELECTION == 0 ) */
if ( pxCurrentTCB - > uxPriority > tskIDLE_PRIORITY )
{
xReturn = 0 ;
}
2024-01-05 04:14:26 -05:00
else if ( listCURRENT_LIST_LENGTH ( & ( pxReadyTasksLists [ tskIDLE_PRIORITY ] ) ) > 1U )
2022-02-24 07:14:22 -05:00
{
/* There are other idle priority tasks in the ready state. If
* time slicing is used then the very next tick interrupt must be
* processed . */
xReturn = 0 ;
}
else if ( uxHigherPriorityReadyTasks ! = pdFALSE )
{
/* There are tasks in the Ready state that have a priority above the
* idle priority . This path can only be reached if
* configUSE_PREEMPTION is 0. */
xReturn = 0 ;
}
else
{
2024-01-05 04:14:26 -05:00
xReturn = xNextTaskUnblockTime ;
xReturn - = xTickCount ;
2022-02-24 07:14:22 -05:00
}
return xReturn ;
}
# endif /* configUSE_TICKLESS_IDLE */
/*----------------------------------------------------------*/
BaseType_t xTaskResumeAll ( void )
{
TCB_t * pxTCB = NULL ;
BaseType_t xAlreadyYielded = pdFALSE ;
2024-01-05 04:14:26 -05:00
traceENTER_xTaskResumeAll ( ) ;
# if ( configNUMBER_OF_CORES > 1 )
if ( xSchedulerRunning ! = pdFALSE )
# endif
2022-02-24 07:14:22 -05:00
{
/* It is possible that an ISR caused a task to be removed from an event
* list while the scheduler was suspended . If this was the case then the
* removed task will have been added to the xPendingReadyList . Once the
* scheduler has been resumed it is safe to move all the pending ready
* tasks from this list into their appropriate ready list . */
taskENTER_CRITICAL ( ) ;
{
BaseType_t xCoreID ;
2024-01-05 04:14:26 -05:00
xCoreID = ( BaseType_t ) portGET_CORE_ID ( ) ;
2022-02-24 07:14:22 -05:00
/* If uxSchedulerSuspended is zero then this function does not match a
* previous call to vTaskSuspendAll ( ) . */
2024-01-05 04:14:26 -05:00
configASSERT ( uxSchedulerSuspended ! = 0U ) ;
2022-02-24 07:14:22 -05:00
- - uxSchedulerSuspended ;
portRELEASE_TASK_LOCK ( ) ;
2024-01-05 04:14:26 -05:00
if ( uxSchedulerSuspended = = ( UBaseType_t ) 0U )
2022-02-24 07:14:22 -05:00
{
if ( uxCurrentNumberOfTasks > ( UBaseType_t ) 0U )
{
/* Move any readied tasks from the pending list into the
* appropriate ready list . */
while ( listLIST_IS_EMPTY ( & xPendingReadyList ) = = pdFALSE )
{
2024-01-05 04:14:26 -05:00
/* MISRA Ref 11.5.3 [Void pointer assignment] */
/* More details at: https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/MISRA.md#rule-115 */
/* coverity[misra_c_2012_rule_11_5_violation] */
pxTCB = listGET_OWNER_OF_HEAD_ENTRY ( ( & xPendingReadyList ) ) ;
listREMOVE_ITEM ( & ( pxTCB - > xEventListItem ) ) ;
portMEMORY_BARRIER ( ) ;
listREMOVE_ITEM ( & ( pxTCB - > xStateListItem ) ) ;
2022-02-24 07:14:22 -05:00
prvAddTaskToReadyList ( pxTCB ) ;
2024-01-05 04:14:26 -05:00
# if ( configNUMBER_OF_CORES == 1 )
{
/* If the moved task has a priority higher than the current
* task then a yield must be performed . */
if ( pxTCB - > uxPriority > pxCurrentTCB - > uxPriority )
{
xYieldPendings [ xCoreID ] = pdTRUE ;
}
else
{
mtCOVERAGE_TEST_MARKER ( ) ;
}
}
# else /* #if ( configNUMBER_OF_CORES == 1 ) */
{
/* All appropriate tasks yield at the moment a task is added to xPendingReadyList.
* If the current core yielded then vTaskSwitchContext ( ) has already been called
* which sets xYieldPendings for the current core to pdTRUE . */
}
# endif /* #if ( configNUMBER_OF_CORES == 1 ) */
2022-02-24 07:14:22 -05:00
}
if ( pxTCB ! = NULL )
{
/* A task was unblocked while the scheduler was suspended,
* which may have prevented the next unblock time from being
* re - calculated , in which case re - calculate it now . Mainly
* important for low power tickless implementations , where
* this can prevent an unnecessary exit from low power
* state . */
prvResetNextTaskUnblockTime ( ) ;
}
/* If any ticks occurred while the scheduler was suspended then
* they should be processed now . This ensures the tick count does
2024-01-05 04:14:26 -05:00
* not slip , and that any delayed tasks are resumed at the correct
2022-02-24 07:14:22 -05:00
* time .
*
* It should be safe to call xTaskIncrementTick here from any core
* since we are in a critical section and xTaskIncrementTick itself
* protects itself within a critical section . Suspending the scheduler
2024-01-05 04:14:26 -05:00
* from any core causes xTaskIncrementTick to increment uxPendedCounts . */
2022-02-24 07:14:22 -05:00
{
TickType_t xPendedCounts = xPendedTicks ; /* Non-volatile copy. */
if ( xPendedCounts > ( TickType_t ) 0U )
{
do
{
if ( xTaskIncrementTick ( ) ! = pdFALSE )
{
2024-01-05 04:14:26 -05:00
/* Other cores are interrupted from
2022-02-24 07:14:22 -05:00
* within xTaskIncrementTick ( ) . */
xYieldPendings [ xCoreID ] = pdTRUE ;
}
else
{
mtCOVERAGE_TEST_MARKER ( ) ;
}
- - xPendedCounts ;
} while ( xPendedCounts > ( TickType_t ) 0U ) ;
xPendedTicks = 0 ;
}
else
{
mtCOVERAGE_TEST_MARKER ( ) ;
}
}
if ( xYieldPendings [ xCoreID ] ! = pdFALSE )
{
2024-01-05 04:14:26 -05:00
# if ( configUSE_PREEMPTION != 0 )
{
xAlreadyYielded = pdTRUE ;
}
# endif /* #if ( configUSE_PREEMPTION != 0 ) */
# if ( configNUMBER_OF_CORES == 1 )
{
taskYIELD_TASK_CORE_IF_USING_PREEMPTION ( pxCurrentTCB ) ;
}
# endif /* #if ( configNUMBER_OF_CORES == 1 ) */
}
else
{
mtCOVERAGE_TEST_MARKER ( ) ;
2022-02-24 07:14:22 -05:00
}
}
}
else
{
mtCOVERAGE_TEST_MARKER ( ) ;
}
}
taskEXIT_CRITICAL ( ) ;
}
2024-01-05 04:14:26 -05:00
traceRETURN_xTaskResumeAll ( xAlreadyYielded ) ;
2022-02-24 07:14:22 -05:00
return xAlreadyYielded ;
}
/*-----------------------------------------------------------*/
TickType_t xTaskGetTickCount ( void )
{
TickType_t xTicks ;
2024-01-05 04:14:26 -05:00
traceENTER_xTaskGetTickCount ( ) ;
2022-02-24 07:14:22 -05:00
/* Critical section required if running on a 16 bit processor. */
portTICK_TYPE_ENTER_CRITICAL ( ) ;
{
xTicks = xTickCount ;
}
portTICK_TYPE_EXIT_CRITICAL ( ) ;
2024-01-05 04:14:26 -05:00
traceRETURN_xTaskGetTickCount ( xTicks ) ;
2022-02-24 07:14:22 -05:00
return xTicks ;
}
/*-----------------------------------------------------------*/
TickType_t xTaskGetTickCountFromISR ( void )
{
TickType_t xReturn ;
UBaseType_t uxSavedInterruptStatus ;
2024-01-05 04:14:26 -05:00
traceENTER_xTaskGetTickCountFromISR ( ) ;
2022-02-24 07:14:22 -05:00
/* RTOS ports that support interrupt nesting have the concept of a maximum
* system call ( or maximum API call ) interrupt priority . Interrupts that are
* above the maximum system call priority are kept permanently enabled , even
* when the RTOS kernel is in a critical section , but cannot make any calls to
* FreeRTOS API functions . If configASSERT ( ) is defined in FreeRTOSConfig . h
* then portASSERT_IF_INTERRUPT_PRIORITY_INVALID ( ) will result in an assertion
* failure if a FreeRTOS API function is called from an interrupt that has been
* assigned a priority above the configured maximum system call priority .
* Only FreeRTOS functions that end in FromISR can be called from interrupts
* that have been assigned a priority at or ( logically ) below the maximum
* system call interrupt priority . FreeRTOS maintains a separate interrupt
* safe API to ensure interrupt entry is as fast and as simple as possible .
* More information ( albeit Cortex - M specific ) is provided on the following
* link : https : //www.FreeRTOS.org/RTOS-Cortex-M3-M4.html */
portASSERT_IF_INTERRUPT_PRIORITY_INVALID ( ) ;
uxSavedInterruptStatus = portTICK_TYPE_SET_INTERRUPT_MASK_FROM_ISR ( ) ;
{
xReturn = xTickCount ;
}
portTICK_TYPE_CLEAR_INTERRUPT_MASK_FROM_ISR ( uxSavedInterruptStatus ) ;
2024-01-05 04:14:26 -05:00
traceRETURN_xTaskGetTickCountFromISR ( xReturn ) ;
2022-02-24 07:14:22 -05:00
return xReturn ;
}
/*-----------------------------------------------------------*/
UBaseType_t uxTaskGetNumberOfTasks ( void )
{
2024-01-05 04:14:26 -05:00
traceENTER_uxTaskGetNumberOfTasks ( ) ;
2022-02-24 07:14:22 -05:00
/* A critical section is not required because the variables are of type
* BaseType_t . */
2024-01-05 04:14:26 -05:00
traceRETURN_uxTaskGetNumberOfTasks ( uxCurrentNumberOfTasks ) ;
2022-02-24 07:14:22 -05:00
return uxCurrentNumberOfTasks ;
}
/*-----------------------------------------------------------*/
2024-01-05 04:14:26 -05:00
char * pcTaskGetName ( TaskHandle_t xTaskToQuery )
2022-02-24 07:14:22 -05:00
{
TCB_t * pxTCB ;
2024-01-05 04:14:26 -05:00
traceENTER_pcTaskGetName ( xTaskToQuery ) ;
2022-02-24 07:14:22 -05:00
/* If null is passed in here then the name of the calling task is being
* queried . */
pxTCB = prvGetTCBFromHandle ( xTaskToQuery ) ;
configASSERT ( pxTCB ) ;
2024-01-05 04:14:26 -05:00
traceRETURN_pcTaskGetName ( & ( pxTCB - > pcTaskName [ 0 ] ) ) ;
2022-02-24 07:14:22 -05:00
return & ( pxTCB - > pcTaskName [ 0 ] ) ;
}
/*-----------------------------------------------------------*/
# if ( INCLUDE_xTaskGetHandle == 1 )
2024-01-05 04:14:26 -05:00
# if ( configNUMBER_OF_CORES == 1 )
static TCB_t * prvSearchForNameWithinSingleList ( List_t * pxList ,
const char pcNameToQuery [ ] )
2022-02-24 07:14:22 -05:00
{
2024-01-05 04:14:26 -05:00
TCB_t * pxNextTCB ;
TCB_t * pxFirstTCB ;
TCB_t * pxReturn = NULL ;
UBaseType_t x ;
char cNextChar ;
BaseType_t xBreakLoop ;
2022-02-24 07:14:22 -05:00
2024-01-05 04:14:26 -05:00
/* This function is called with the scheduler suspended. */
2022-02-24 07:14:22 -05:00
2024-01-05 04:14:26 -05:00
if ( listCURRENT_LIST_LENGTH ( pxList ) > ( UBaseType_t ) 0 )
{
/* MISRA Ref 11.5.3 [Void pointer assignment] */
/* More details at: https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/MISRA.md#rule-115 */
/* coverity[misra_c_2012_rule_11_5_violation] */
listGET_OWNER_OF_NEXT_ENTRY ( pxFirstTCB , pxList ) ;
2022-02-24 07:14:22 -05:00
2024-01-05 04:14:26 -05:00
do
2022-02-24 07:14:22 -05:00
{
2024-01-05 04:14:26 -05:00
/* MISRA Ref 11.5.3 [Void pointer assignment] */
/* More details at: https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/MISRA.md#rule-115 */
/* coverity[misra_c_2012_rule_11_5_violation] */
listGET_OWNER_OF_NEXT_ENTRY ( pxNextTCB , pxList ) ;
/* Check each character in the name looking for a match or
* mismatch . */
xBreakLoop = pdFALSE ;
2022-02-24 07:14:22 -05:00
2024-01-05 04:14:26 -05:00
for ( x = ( UBaseType_t ) 0 ; x < ( UBaseType_t ) configMAX_TASK_NAME_LEN ; x + + )
2022-02-24 07:14:22 -05:00
{
2024-01-05 04:14:26 -05:00
cNextChar = pxNextTCB - > pcTaskName [ x ] ;
if ( cNextChar ! = pcNameToQuery [ x ] )
{
/* Characters didn't match. */
xBreakLoop = pdTRUE ;
}
else if ( cNextChar = = ( char ) 0x00 )
{
/* Both strings terminated, a match must have been
* found . */
pxReturn = pxNextTCB ;
xBreakLoop = pdTRUE ;
}
else
{
mtCOVERAGE_TEST_MARKER ( ) ;
}
if ( xBreakLoop ! = pdFALSE )
{
break ;
}
2022-02-24 07:14:22 -05:00
}
2024-01-05 04:14:26 -05:00
if ( pxReturn ! = NULL )
2022-02-24 07:14:22 -05:00
{
2024-01-05 04:14:26 -05:00
/* The handle has been found. */
break ;
2022-02-24 07:14:22 -05:00
}
2024-01-05 04:14:26 -05:00
} while ( pxNextTCB ! = pxFirstTCB ) ;
}
else
{
mtCOVERAGE_TEST_MARKER ( ) ;
}
return pxReturn ;
}
# else /* if ( configNUMBER_OF_CORES == 1 ) */
static TCB_t * prvSearchForNameWithinSingleList ( List_t * pxList ,
const char pcNameToQuery [ ] )
{
TCB_t * pxReturn = NULL ;
UBaseType_t x ;
char cNextChar ;
BaseType_t xBreakLoop ;
const ListItem_t * pxEndMarker = listGET_END_MARKER ( pxList ) ;
ListItem_t * pxIterator ;
/* This function is called with the scheduler suspended. */
if ( listCURRENT_LIST_LENGTH ( pxList ) > ( UBaseType_t ) 0 )
{
for ( pxIterator = listGET_HEAD_ENTRY ( pxList ) ; pxIterator ! = pxEndMarker ; pxIterator = listGET_NEXT ( pxIterator ) )
{
/* MISRA Ref 11.5.3 [Void pointer assignment] */
/* More details at: https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/MISRA.md#rule-115 */
/* coverity[misra_c_2012_rule_11_5_violation] */
TCB_t * pxTCB = listGET_LIST_ITEM_OWNER ( pxIterator ) ;
/* Check each character in the name looking for a match or
* mismatch . */
xBreakLoop = pdFALSE ;
for ( x = ( UBaseType_t ) 0 ; x < ( UBaseType_t ) configMAX_TASK_NAME_LEN ; x + + )
2022-02-24 07:14:22 -05:00
{
2024-01-05 04:14:26 -05:00
cNextChar = pxTCB - > pcTaskName [ x ] ;
if ( cNextChar ! = pcNameToQuery [ x ] )
{
/* Characters didn't match. */
xBreakLoop = pdTRUE ;
}
else if ( cNextChar = = ( char ) 0x00 )
{
/* Both strings terminated, a match must have been
* found . */
pxReturn = pxTCB ;
xBreakLoop = pdTRUE ;
}
else
{
mtCOVERAGE_TEST_MARKER ( ) ;
}
if ( xBreakLoop ! = pdFALSE )
{
break ;
}
2022-02-24 07:14:22 -05:00
}
2024-01-05 04:14:26 -05:00
if ( pxReturn ! = NULL )
2022-02-24 07:14:22 -05:00
{
2024-01-05 04:14:26 -05:00
/* The handle has been found. */
2022-02-24 07:14:22 -05:00
break ;
}
}
2024-01-05 04:14:26 -05:00
}
else
{
mtCOVERAGE_TEST_MARKER ( ) ;
}
2022-02-24 07:14:22 -05:00
2024-01-05 04:14:26 -05:00
return pxReturn ;
2022-02-24 07:14:22 -05:00
}
2024-01-05 04:14:26 -05:00
# endif /* #if ( configNUMBER_OF_CORES == 1 ) */
2022-02-24 07:14:22 -05:00
# endif /* INCLUDE_xTaskGetHandle */
/*-----------------------------------------------------------*/
# if ( INCLUDE_xTaskGetHandle == 1 )
2024-01-05 04:14:26 -05:00
TaskHandle_t xTaskGetHandle ( const char * pcNameToQuery )
2022-02-24 07:14:22 -05:00
{
UBaseType_t uxQueue = configMAX_PRIORITIES ;
TCB_t * pxTCB ;
2024-01-05 04:14:26 -05:00
traceENTER_xTaskGetHandle ( pcNameToQuery ) ;
2022-02-24 07:14:22 -05:00
/* Task names will be truncated to configMAX_TASK_NAME_LEN - 1 bytes. */
configASSERT ( strlen ( pcNameToQuery ) < configMAX_TASK_NAME_LEN ) ;
vTaskSuspendAll ( ) ;
{
/* Search the ready lists. */
do
{
uxQueue - - ;
pxTCB = prvSearchForNameWithinSingleList ( ( List_t * ) & ( pxReadyTasksLists [ uxQueue ] ) , pcNameToQuery ) ;
if ( pxTCB ! = NULL )
{
/* Found the handle. */
break ;
}
2024-01-05 04:14:26 -05:00
} while ( uxQueue > ( UBaseType_t ) tskIDLE_PRIORITY ) ;
2022-02-24 07:14:22 -05:00
/* Search the delayed lists. */
if ( pxTCB = = NULL )
{
pxTCB = prvSearchForNameWithinSingleList ( ( List_t * ) pxDelayedTaskList , pcNameToQuery ) ;
}
if ( pxTCB = = NULL )
{
pxTCB = prvSearchForNameWithinSingleList ( ( List_t * ) pxOverflowDelayedTaskList , pcNameToQuery ) ;
}
# if ( INCLUDE_vTaskSuspend == 1 )
2024-01-05 04:14:26 -05:00
{
if ( pxTCB = = NULL )
2022-02-24 07:14:22 -05:00
{
2024-01-05 04:14:26 -05:00
/* Search the suspended list. */
pxTCB = prvSearchForNameWithinSingleList ( & xSuspendedTaskList , pcNameToQuery ) ;
2022-02-24 07:14:22 -05:00
}
2024-01-05 04:14:26 -05:00
}
2022-02-24 07:14:22 -05:00
# endif
# if ( INCLUDE_vTaskDelete == 1 )
2024-01-05 04:14:26 -05:00
{
if ( pxTCB = = NULL )
2022-02-24 07:14:22 -05:00
{
2024-01-05 04:14:26 -05:00
/* Search the deleted list. */
pxTCB = prvSearchForNameWithinSingleList ( & xTasksWaitingTermination , pcNameToQuery ) ;
2022-02-24 07:14:22 -05:00
}
2024-01-05 04:14:26 -05:00
}
2022-02-24 07:14:22 -05:00
# endif
}
( void ) xTaskResumeAll ( ) ;
2024-01-05 04:14:26 -05:00
traceRETURN_xTaskGetHandle ( pxTCB ) ;
2022-02-24 07:14:22 -05:00
return pxTCB ;
}
# endif /* INCLUDE_xTaskGetHandle */
/*-----------------------------------------------------------*/
2023-03-21 09:29:52 -04:00
# if ( configSUPPORT_STATIC_ALLOCATION == 1 )
BaseType_t xTaskGetStaticBuffers ( TaskHandle_t xTask ,
StackType_t * * ppuxStackBuffer ,
StaticTask_t * * ppxTaskBuffer )
{
BaseType_t xReturn ;
TCB_t * pxTCB ;
2024-01-05 04:14:26 -05:00
traceENTER_xTaskGetStaticBuffers ( xTask , ppuxStackBuffer , ppxTaskBuffer ) ;
2023-03-21 09:29:52 -04:00
configASSERT ( ppuxStackBuffer ! = NULL ) ;
configASSERT ( ppxTaskBuffer ! = NULL ) ;
pxTCB = prvGetTCBFromHandle ( xTask ) ;
# if ( tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE == 1 )
{
if ( pxTCB - > ucStaticallyAllocated = = tskSTATICALLY_ALLOCATED_STACK_AND_TCB )
{
* ppuxStackBuffer = pxTCB - > pxStack ;
2024-01-05 04:14:26 -05:00
/* MISRA Ref 11.3.1 [Misaligned access] */
/* More details at: https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/MISRA.md#rule-113 */
/* coverity[misra_c_2012_rule_11_3_violation] */
2023-03-21 09:29:52 -04:00
* ppxTaskBuffer = ( StaticTask_t * ) pxTCB ;
xReturn = pdTRUE ;
}
else if ( pxTCB - > ucStaticallyAllocated = = tskSTATICALLY_ALLOCATED_STACK_ONLY )
{
* ppuxStackBuffer = pxTCB - > pxStack ;
* ppxTaskBuffer = NULL ;
xReturn = pdTRUE ;
}
else
{
xReturn = pdFALSE ;
}
}
# else /* tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE == 1 */
{
* ppuxStackBuffer = pxTCB - > pxStack ;
* ppxTaskBuffer = ( StaticTask_t * ) pxTCB ;
xReturn = pdTRUE ;
}
# endif /* tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE == 1 */
2024-01-05 04:14:26 -05:00
traceRETURN_xTaskGetStaticBuffers ( xReturn ) ;
2023-03-21 09:29:52 -04:00
return xReturn ;
}
# endif /* configSUPPORT_STATIC_ALLOCATION */
/*-----------------------------------------------------------*/
2022-02-24 07:14:22 -05:00
# if ( configUSE_TRACE_FACILITY == 1 )
UBaseType_t uxTaskGetSystemState ( TaskStatus_t * const pxTaskStatusArray ,
const UBaseType_t uxArraySize ,
2024-01-05 04:14:26 -05:00
configRUN_TIME_COUNTER_TYPE * const pulTotalRunTime )
2022-02-24 07:14:22 -05:00
{
UBaseType_t uxTask = 0 , uxQueue = configMAX_PRIORITIES ;
2024-01-05 04:14:26 -05:00
traceENTER_uxTaskGetSystemState ( pxTaskStatusArray , uxArraySize , pulTotalRunTime ) ;
2022-02-24 07:14:22 -05:00
vTaskSuspendAll ( ) ;
{
/* Is there a space in the array for each task in the system? */
if ( uxArraySize > = uxCurrentNumberOfTasks )
{
/* Fill in an TaskStatus_t structure with information on each
* task in the Ready state . */
do
{
uxQueue - - ;
2024-01-05 04:14:26 -05:00
uxTask = ( UBaseType_t ) ( uxTask + prvListTasksWithinSingleList ( & ( pxTaskStatusArray [ uxTask ] ) , & ( pxReadyTasksLists [ uxQueue ] ) , eReady ) ) ;
} while ( uxQueue > ( UBaseType_t ) tskIDLE_PRIORITY ) ;
2022-02-24 07:14:22 -05:00
/* Fill in an TaskStatus_t structure with information on each
* task in the Blocked state . */
2024-01-05 04:14:26 -05:00
uxTask = ( UBaseType_t ) ( uxTask + prvListTasksWithinSingleList ( & ( pxTaskStatusArray [ uxTask ] ) , ( List_t * ) pxDelayedTaskList , eBlocked ) ) ;
uxTask = ( UBaseType_t ) ( uxTask + prvListTasksWithinSingleList ( & ( pxTaskStatusArray [ uxTask ] ) , ( List_t * ) pxOverflowDelayedTaskList , eBlocked ) ) ;
2022-02-24 07:14:22 -05:00
# if ( INCLUDE_vTaskDelete == 1 )
2024-01-05 04:14:26 -05:00
{
/* Fill in an TaskStatus_t structure with information on
* each task that has been deleted but not yet cleaned up . */
uxTask = ( UBaseType_t ) ( uxTask + prvListTasksWithinSingleList ( & ( pxTaskStatusArray [ uxTask ] ) , & xTasksWaitingTermination , eDeleted ) ) ;
}
2022-02-24 07:14:22 -05:00
# endif
# if ( INCLUDE_vTaskSuspend == 1 )
2024-01-05 04:14:26 -05:00
{
/* Fill in an TaskStatus_t structure with information on
* each task in the Suspended state . */
uxTask = ( UBaseType_t ) ( uxTask + prvListTasksWithinSingleList ( & ( pxTaskStatusArray [ uxTask ] ) , & xSuspendedTaskList , eSuspended ) ) ;
}
2022-02-24 07:14:22 -05:00
# endif
# if ( configGENERATE_RUN_TIME_STATS == 1 )
2024-01-05 04:14:26 -05:00
{
if ( pulTotalRunTime ! = NULL )
2022-02-24 07:14:22 -05:00
{
2024-01-05 04:14:26 -05:00
# ifdef portALT_GET_RUN_TIME_COUNTER_VALUE
portALT_GET_RUN_TIME_COUNTER_VALUE ( ( * pulTotalRunTime ) ) ;
# else
* pulTotalRunTime = ( configRUN_TIME_COUNTER_TYPE ) portGET_RUN_TIME_COUNTER_VALUE ( ) ;
# endif
2022-02-24 07:14:22 -05:00
}
2024-01-05 04:14:26 -05:00
}
2022-02-24 07:14:22 -05:00
# else /* if ( configGENERATE_RUN_TIME_STATS == 1 ) */
2024-01-05 04:14:26 -05:00
{
if ( pulTotalRunTime ! = NULL )
2022-02-24 07:14:22 -05:00
{
2024-01-05 04:14:26 -05:00
* pulTotalRunTime = 0 ;
2022-02-24 07:14:22 -05:00
}
2024-01-05 04:14:26 -05:00
}
2022-02-24 07:14:22 -05:00
# endif /* if ( configGENERATE_RUN_TIME_STATS == 1 ) */
}
else
{
mtCOVERAGE_TEST_MARKER ( ) ;
}
}
( void ) xTaskResumeAll ( ) ;
2024-01-05 04:14:26 -05:00
traceRETURN_uxTaskGetSystemState ( uxTask ) ;
2022-02-24 07:14:22 -05:00
return uxTask ;
}
# endif /* configUSE_TRACE_FACILITY */
/*----------------------------------------------------------*/
# if ( INCLUDE_xTaskGetIdleTaskHandle == 1 )
2024-01-05 04:14:26 -05:00
# if ( configNUMBER_OF_CORES == 1 )
TaskHandle_t xTaskGetIdleTaskHandle ( void )
{
traceENTER_xTaskGetIdleTaskHandle ( ) ;
/* If xTaskGetIdleTaskHandle() is called before the scheduler has been
* started , then xIdleTaskHandles will be NULL . */
configASSERT ( ( xIdleTaskHandles [ 0 ] ! = NULL ) ) ;
traceRETURN_xTaskGetIdleTaskHandle ( xIdleTaskHandles [ 0 ] ) ;
return xIdleTaskHandles [ 0 ] ;
}
# endif /* if ( configNUMBER_OF_CORES == 1 ) */
TaskHandle_t xTaskGetIdleTaskHandleForCore ( BaseType_t xCoreID )
2022-02-24 07:14:22 -05:00
{
2024-01-05 04:14:26 -05:00
traceENTER_xTaskGetIdleTaskHandleForCore ( xCoreID ) ;
/* Ensure the core ID is valid. */
configASSERT ( taskVALID_CORE_ID ( xCoreID ) = = pdTRUE ) ;
2022-02-24 07:14:22 -05:00
/* If xTaskGetIdleTaskHandle() is called before the scheduler has been
2024-01-05 04:14:26 -05:00
* started , then xIdleTaskHandles will be NULL . */
configASSERT ( ( xIdleTaskHandles [ xCoreID ] ! = NULL ) ) ;
traceRETURN_xTaskGetIdleTaskHandleForCore ( xIdleTaskHandles [ xCoreID ] ) ;
return xIdleTaskHandles [ xCoreID ] ;
2022-02-24 07:14:22 -05:00
}
# endif /* INCLUDE_xTaskGetIdleTaskHandle */
/*----------------------------------------------------------*/
/* This conditional compilation should use inequality to 0, not equality to 1.
* This is to ensure vTaskStepTick ( ) is available when user defined low power mode
* implementations require configUSE_TICKLESS_IDLE to be set to a value other than
* 1. */
# if ( configUSE_TICKLESS_IDLE != 0 )
2024-01-05 04:14:26 -05:00
void vTaskStepTick ( TickType_t xTicksToJump )
2022-02-24 07:14:22 -05:00
{
2024-01-05 04:14:26 -05:00
TickType_t xUpdatedTickCount ;
traceENTER_vTaskStepTick ( xTicksToJump ) ;
2022-02-24 07:14:22 -05:00
/* Correct the tick count value after a period during which the tick
* was suppressed . Note this does * not * call the tick hook function for
* each stepped tick . */
2024-01-05 04:14:26 -05:00
xUpdatedTickCount = xTickCount + xTicksToJump ;
configASSERT ( xUpdatedTickCount < = xNextTaskUnblockTime ) ;
if ( xUpdatedTickCount = = xNextTaskUnblockTime )
{
/* Arrange for xTickCount to reach xNextTaskUnblockTime in
* xTaskIncrementTick ( ) when the scheduler resumes . This ensures
* that any delayed tasks are resumed at the correct time . */
configASSERT ( uxSchedulerSuspended ! = ( UBaseType_t ) 0U ) ;
configASSERT ( xTicksToJump ! = ( TickType_t ) 0 ) ;
/* Prevent the tick interrupt modifying xPendedTicks simultaneously. */
taskENTER_CRITICAL ( ) ;
{
xPendedTicks + + ;
}
taskEXIT_CRITICAL ( ) ;
xTicksToJump - - ;
}
else
{
mtCOVERAGE_TEST_MARKER ( ) ;
}
2022-02-24 07:14:22 -05:00
xTickCount + = xTicksToJump ;
2024-01-05 04:14:26 -05:00
2022-02-24 07:14:22 -05:00
traceINCREASE_TICK_COUNT ( xTicksToJump ) ;
2024-01-05 04:14:26 -05:00
traceRETURN_vTaskStepTick ( ) ;
2022-02-24 07:14:22 -05:00
}
# endif /* configUSE_TICKLESS_IDLE */
/*----------------------------------------------------------*/
BaseType_t xTaskCatchUpTicks ( TickType_t xTicksToCatchUp )
{
BaseType_t xYieldOccurred ;
2024-01-05 04:14:26 -05:00
traceENTER_xTaskCatchUpTicks ( xTicksToCatchUp ) ;
2022-02-24 07:14:22 -05:00
/* Must not be called with the scheduler suspended as the implementation
* relies on xPendedTicks being wound down to 0 in xTaskResumeAll ( ) . */
2024-01-05 04:14:26 -05:00
configASSERT ( uxSchedulerSuspended = = ( UBaseType_t ) 0U ) ;
2022-02-24 07:14:22 -05:00
/* Use xPendedTicks to mimic xTicksToCatchUp number of ticks occurring when
* the scheduler is suspended so the ticks are executed in xTaskResumeAll ( ) . */
vTaskSuspendAll ( ) ;
2024-01-05 04:14:26 -05:00
/* Prevent the tick interrupt modifying xPendedTicks simultaneously. */
taskENTER_CRITICAL ( ) ;
{
xPendedTicks + = xTicksToCatchUp ;
}
taskEXIT_CRITICAL ( ) ;
2022-02-24 07:14:22 -05:00
xYieldOccurred = xTaskResumeAll ( ) ;
2024-01-05 04:14:26 -05:00
traceRETURN_xTaskCatchUpTicks ( xYieldOccurred ) ;
2022-02-24 07:14:22 -05:00
return xYieldOccurred ;
}
/*----------------------------------------------------------*/
# if ( INCLUDE_xTaskAbortDelay == 1 )
BaseType_t xTaskAbortDelay ( TaskHandle_t xTask )
{
TCB_t * pxTCB = xTask ;
BaseType_t xReturn ;
2024-01-05 04:14:26 -05:00
traceENTER_xTaskAbortDelay ( xTask ) ;
2022-02-24 07:14:22 -05:00
configASSERT ( pxTCB ) ;
vTaskSuspendAll ( ) ;
{
/* A task can only be prematurely removed from the Blocked state if
* it is actually in the Blocked state . */
if ( eTaskGetState ( xTask ) = = eBlocked )
{
xReturn = pdPASS ;
/* Remove the reference to the task from the blocked list. An
* interrupt won ' t touch the xStateListItem because the
* scheduler is suspended . */
( void ) uxListRemove ( & ( pxTCB - > xStateListItem ) ) ;
/* Is the task waiting on an event also? If so remove it from
* the event list too . Interrupts can touch the event list item ,
* even though the scheduler is suspended , so a critical section
* is used . */
taskENTER_CRITICAL ( ) ;
{
if ( listLIST_ITEM_CONTAINER ( & ( pxTCB - > xEventListItem ) ) ! = NULL )
{
( void ) uxListRemove ( & ( pxTCB - > xEventListItem ) ) ;
/* This lets the task know it was forcibly removed from the
* blocked state so it should not re - evaluate its block time and
* then block again . */
pxTCB - > ucDelayAborted = pdTRUE ;
}
else
{
mtCOVERAGE_TEST_MARKER ( ) ;
}
}
taskEXIT_CRITICAL ( ) ;
/* Place the unblocked task into the appropriate ready list. */
prvAddTaskToReadyList ( pxTCB ) ;
/* A task being unblocked cannot cause an immediate context
* switch if preemption is turned off . */
# if ( configUSE_PREEMPTION == 1 )
2024-01-05 04:14:26 -05:00
{
# if ( configNUMBER_OF_CORES == 1 )
{
/* Preemption is on, but a context switch should only be
* performed if the unblocked task has a priority that is
* higher than the currently executing task . */
if ( pxTCB - > uxPriority > pxCurrentTCB - > uxPriority )
{
/* Pend the yield to be performed when the scheduler
* is unsuspended . */
xYieldPendings [ 0 ] = pdTRUE ;
}
else
{
mtCOVERAGE_TEST_MARKER ( ) ;
}
}
# else /* #if ( configNUMBER_OF_CORES == 1 ) */
2022-02-24 07:14:22 -05:00
{
taskENTER_CRITICAL ( ) ;
{
2024-01-05 04:14:26 -05:00
prvYieldForTask ( pxTCB ) ;
2022-02-24 07:14:22 -05:00
}
taskEXIT_CRITICAL ( ) ;
}
2024-01-05 04:14:26 -05:00
# endif /* #if ( configNUMBER_OF_CORES == 1 ) */
}
# endif /* #if ( configUSE_PREEMPTION == 1 ) */
2022-02-24 07:14:22 -05:00
}
else
{
xReturn = pdFAIL ;
}
}
( void ) xTaskResumeAll ( ) ;
2024-01-05 04:14:26 -05:00
traceRETURN_xTaskAbortDelay ( xReturn ) ;
2022-02-24 07:14:22 -05:00
return xReturn ;
}
# endif /* INCLUDE_xTaskAbortDelay */
/*----------------------------------------------------------*/
BaseType_t xTaskIncrementTick ( void )
{
TCB_t * pxTCB ;
TickType_t xItemValue ;
BaseType_t xSwitchRequired = pdFALSE ;
2024-01-05 04:14:26 -05:00
# if ( configUSE_PREEMPTION == 1 ) && ( configNUMBER_OF_CORES > 1 )
BaseType_t xYieldRequiredForCore [ configNUMBER_OF_CORES ] = { pdFALSE } ;
# endif /* #if ( configUSE_PREEMPTION == 1 ) && ( configNUMBER_OF_CORES > 1 ) */
2022-02-24 07:14:22 -05:00
2024-01-05 04:14:26 -05:00
traceENTER_xTaskIncrementTick ( ) ;
2022-02-24 07:14:22 -05:00
2024-01-05 04:14:26 -05:00
/* Called by the portable layer each time a tick interrupt occurs.
* Increments the tick then checks to see if the new tick value will cause any
* tasks to be unblocked . */
traceTASK_INCREMENT_TICK ( xTickCount ) ;
2022-02-24 07:14:22 -05:00
2024-01-05 04:14:26 -05:00
/* Tick increment should occur on every kernel timer event. Core 0 has the
* responsibility to increment the tick , or increment the pended ticks if the
* scheduler is suspended . If pended ticks is greater than zero , the core that
* calls xTaskResumeAll has the responsibility to increment the tick . */
if ( uxSchedulerSuspended = = ( UBaseType_t ) 0U )
{
/* Minor optimisation. The tick count cannot change in this
* block . */
const TickType_t xConstTickCount = xTickCount + ( TickType_t ) 1 ;
2022-02-24 07:14:22 -05:00
2024-01-05 04:14:26 -05:00
/* Increment the RTOS tick, switching the delayed and overflowed
* delayed lists if it wraps to 0. */
xTickCount = xConstTickCount ;
if ( xConstTickCount = = ( TickType_t ) 0U )
{
taskSWITCH_DELAYED_LISTS ( ) ;
}
else
{
mtCOVERAGE_TEST_MARKER ( ) ;
}
2022-02-24 07:14:22 -05:00
2024-01-05 04:14:26 -05:00
/* See if this tick has made a timeout expire. Tasks are stored in
* the queue in the order of their wake time - meaning once one task
* has been found whose block time has not expired there is no need to
* look any further down the list . */
if ( xConstTickCount > = xNextTaskUnblockTime )
{
for ( ; ; )
2022-02-24 07:14:22 -05:00
{
2024-01-05 04:14:26 -05:00
if ( listLIST_IS_EMPTY ( pxDelayedTaskList ) ! = pdFALSE )
{
/* The delayed list is empty. Set xNextTaskUnblockTime
* to the maximum possible value so it is extremely
* unlikely that the
* if ( xTickCount > = xNextTaskUnblockTime ) test will pass
* next time through . */
xNextTaskUnblockTime = portMAX_DELAY ;
break ;
}
else
2022-02-24 07:14:22 -05:00
{
2024-01-05 04:14:26 -05:00
/* The delayed list is not empty, get the value of the
* item at the head of the delayed list . This is the time
* at which the task at the head of the delayed list must
* be removed from the Blocked state . */
/* MISRA Ref 11.5.3 [Void pointer assignment] */
/* More details at: https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/MISRA.md#rule-115 */
/* coverity[misra_c_2012_rule_11_5_violation] */
pxTCB = listGET_OWNER_OF_HEAD_ENTRY ( pxDelayedTaskList ) ;
xItemValue = listGET_LIST_ITEM_VALUE ( & ( pxTCB - > xStateListItem ) ) ;
if ( xConstTickCount < xItemValue )
2022-02-24 07:14:22 -05:00
{
2024-01-05 04:14:26 -05:00
/* It is not time to unblock this item yet, but the
* item value is the time at which the task at the head
* of the blocked list must be removed from the Blocked
* state - so record the item value in
* xNextTaskUnblockTime . */
xNextTaskUnblockTime = xItemValue ;
2022-02-24 07:14:22 -05:00
break ;
}
else
{
2024-01-05 04:14:26 -05:00
mtCOVERAGE_TEST_MARKER ( ) ;
}
2022-02-24 07:14:22 -05:00
2024-01-05 04:14:26 -05:00
/* It is time to remove the item from the Blocked state. */
listREMOVE_ITEM ( & ( pxTCB - > xStateListItem ) ) ;
2022-02-24 07:14:22 -05:00
2024-01-05 04:14:26 -05:00
/* Is the task waiting on an event also? If so remove
* it from the event list . */
if ( listLIST_ITEM_CONTAINER ( & ( pxTCB - > xEventListItem ) ) ! = NULL )
{
listREMOVE_ITEM ( & ( pxTCB - > xEventListItem ) ) ;
}
else
{
mtCOVERAGE_TEST_MARKER ( ) ;
}
2022-02-24 07:14:22 -05:00
2024-01-05 04:14:26 -05:00
/* Place the unblocked task into the appropriate ready
* list . */
prvAddTaskToReadyList ( pxTCB ) ;
2022-02-24 07:14:22 -05:00
2024-01-05 04:14:26 -05:00
/* A task being unblocked cannot cause an immediate
* context switch if preemption is turned off . */
# if ( configUSE_PREEMPTION == 1 )
{
# if ( configNUMBER_OF_CORES == 1 )
{
/* Preemption is on, but a context switch should
* only be performed if the unblocked task ' s
* priority is higher than the currently executing
* task .
* The case of equal priority tasks sharing
* processing time ( which happens when both
* preemption and time slicing are on ) is
* handled below . */
if ( pxTCB - > uxPriority > pxCurrentTCB - > uxPriority )
{
xSwitchRequired = pdTRUE ;
}
else
2022-02-24 07:14:22 -05:00
{
2024-01-05 04:14:26 -05:00
mtCOVERAGE_TEST_MARKER ( ) ;
2022-02-24 07:14:22 -05:00
}
2024-01-05 04:14:26 -05:00
}
# else /* #if( configNUMBER_OF_CORES == 1 ) */
{
prvYieldForTask ( pxTCB ) ;
}
# endif /* #if( configNUMBER_OF_CORES == 1 ) */
2022-02-24 07:14:22 -05:00
}
2024-01-05 04:14:26 -05:00
# endif /* #if ( configUSE_PREEMPTION == 1 ) */
2022-02-24 07:14:22 -05:00
}
}
2024-01-05 04:14:26 -05:00
}
2022-02-24 07:14:22 -05:00
2024-01-05 04:14:26 -05:00
/* Tasks of equal priority to the currently running task will share
* processing time ( time slice ) if preemption is on , and the application
* writer has not explicitly turned time slicing off . */
# if ( ( configUSE_PREEMPTION == 1 ) && ( configUSE_TIME_SLICING == 1 ) )
{
# if ( configNUMBER_OF_CORES == 1 )
{
if ( listCURRENT_LIST_LENGTH ( & ( pxReadyTasksLists [ pxCurrentTCB - > uxPriority ] ) ) > 1U )
2022-02-24 07:14:22 -05:00
{
2024-01-05 04:14:26 -05:00
xSwitchRequired = pdTRUE ;
}
else
{
mtCOVERAGE_TEST_MARKER ( ) ;
2022-02-24 07:14:22 -05:00
}
2024-01-05 04:14:26 -05:00
}
# else /* #if ( configNUMBER_OF_CORES == 1 ) */
{
BaseType_t xCoreID ;
2022-02-24 07:14:22 -05:00
2024-01-05 04:14:26 -05:00
for ( xCoreID = 0 ; xCoreID < ( ( BaseType_t ) configNUMBER_OF_CORES ) ; xCoreID + + )
2022-02-24 07:14:22 -05:00
{
2024-01-05 04:14:26 -05:00
if ( listCURRENT_LIST_LENGTH ( & ( pxReadyTasksLists [ pxCurrentTCBs [ xCoreID ] - > uxPriority ] ) ) > 1U )
2022-02-24 07:14:22 -05:00
{
2024-01-05 04:14:26 -05:00
xYieldRequiredForCore [ xCoreID ] = pdTRUE ;
2022-02-24 07:14:22 -05:00
}
else
{
mtCOVERAGE_TEST_MARKER ( ) ;
}
}
2024-01-05 04:14:26 -05:00
}
# endif /* #if ( configNUMBER_OF_CORES == 1 ) */
}
# endif /* #if ( ( configUSE_PREEMPTION == 1 ) && ( configUSE_TIME_SLICING == 1 ) ) */
# if ( configUSE_TICK_HOOK == 1 )
{
/* Guard against the tick hook being called when the pended tick
* count is being unwound ( when the scheduler is being unlocked ) . */
if ( xPendedTicks = = ( TickType_t ) 0 )
{
vApplicationTickHook ( ) ;
}
else
{
mtCOVERAGE_TEST_MARKER ( ) ;
}
}
# endif /* configUSE_TICK_HOOK */
2022-02-24 07:14:22 -05:00
2024-01-05 04:14:26 -05:00
# if ( configUSE_PREEMPTION == 1 )
{
# if ( configNUMBER_OF_CORES == 1 )
{
/* For single core the core ID is always 0. */
if ( xYieldPendings [ 0 ] ! = pdFALSE )
2022-02-24 07:14:22 -05:00
{
2024-01-05 04:14:26 -05:00
xSwitchRequired = pdTRUE ;
2022-02-24 07:14:22 -05:00
}
2024-01-05 04:14:26 -05:00
else
2022-02-24 07:14:22 -05:00
{
2024-01-05 04:14:26 -05:00
mtCOVERAGE_TEST_MARKER ( ) ;
}
}
# else /* #if ( configNUMBER_OF_CORES == 1 ) */
{
BaseType_t xCoreID , xCurrentCoreID ;
xCurrentCoreID = ( BaseType_t ) portGET_CORE_ID ( ) ;
2022-02-24 07:14:22 -05:00
2024-01-05 04:14:26 -05:00
for ( xCoreID = 0 ; xCoreID < ( BaseType_t ) configNUMBER_OF_CORES ; xCoreID + + )
{
# if ( configUSE_TASK_PREEMPTION_DISABLE == 1 )
if ( pxCurrentTCBs [ xCoreID ] - > xPreemptionDisable = = pdFALSE )
# endif
2022-02-24 07:14:22 -05:00
{
2024-01-05 04:14:26 -05:00
if ( ( xYieldRequiredForCore [ xCoreID ] ! = pdFALSE ) | | ( xYieldPendings [ xCoreID ] ! = pdFALSE ) )
2022-02-24 07:14:22 -05:00
{
2024-01-05 04:14:26 -05:00
if ( xCoreID = = xCurrentCoreID )
2022-02-24 07:14:22 -05:00
{
2024-01-05 04:14:26 -05:00
xSwitchRequired = pdTRUE ;
2022-02-24 07:14:22 -05:00
}
else
{
2024-01-05 04:14:26 -05:00
prvYieldCore ( xCoreID ) ;
2022-02-24 07:14:22 -05:00
}
}
2024-01-05 04:14:26 -05:00
else
{
mtCOVERAGE_TEST_MARKER ( ) ;
}
2022-02-24 07:14:22 -05:00
}
}
2024-01-05 04:14:26 -05:00
}
# endif /* #if ( configNUMBER_OF_CORES == 1 ) */
2022-02-24 07:14:22 -05:00
}
2024-01-05 04:14:26 -05:00
# endif /* #if ( configUSE_PREEMPTION == 1 ) */
}
else
{
+ + xPendedTicks ;
2022-02-24 07:14:22 -05:00
2024-01-05 04:14:26 -05:00
/* The tick hook gets called at regular intervals, even if the
* scheduler is locked . */
# if ( configUSE_TICK_HOOK == 1 )
{
vApplicationTickHook ( ) ;
2022-02-24 07:14:22 -05:00
}
2024-01-05 04:14:26 -05:00
# endif
2022-02-24 07:14:22 -05:00
}
2024-01-05 04:14:26 -05:00
traceRETURN_xTaskIncrementTick ( xSwitchRequired ) ;
2022-02-24 07:14:22 -05:00
return xSwitchRequired ;
}
/*-----------------------------------------------------------*/
# if ( configUSE_APPLICATION_TASK_TAG == 1 )
void vTaskSetApplicationTaskTag ( TaskHandle_t xTask ,
TaskHookFunction_t pxHookFunction )
{
TCB_t * xTCB ;
2024-01-05 04:14:26 -05:00
traceENTER_vTaskSetApplicationTaskTag ( xTask , pxHookFunction ) ;
2022-02-24 07:14:22 -05:00
/* If xTask is NULL then it is the task hook of the calling task that is
* getting set . */
if ( xTask = = NULL )
{
xTCB = ( TCB_t * ) pxCurrentTCB ;
}
else
{
xTCB = xTask ;
}
/* Save the hook function in the TCB. A critical section is required as
* the value can be accessed from an interrupt . */
taskENTER_CRITICAL ( ) ;
{
xTCB - > pxTaskTag = pxHookFunction ;
}
taskEXIT_CRITICAL ( ) ;
2024-01-05 04:14:26 -05:00
traceRETURN_vTaskSetApplicationTaskTag ( ) ;
2022-02-24 07:14:22 -05:00
}
# endif /* configUSE_APPLICATION_TASK_TAG */
/*-----------------------------------------------------------*/
# if ( configUSE_APPLICATION_TASK_TAG == 1 )
TaskHookFunction_t xTaskGetApplicationTaskTag ( TaskHandle_t xTask )
{
TCB_t * pxTCB ;
TaskHookFunction_t xReturn ;
2024-01-05 04:14:26 -05:00
traceENTER_xTaskGetApplicationTaskTag ( xTask ) ;
2022-02-24 07:14:22 -05:00
/* 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 = pxTCB - > pxTaskTag ;
}
taskEXIT_CRITICAL ( ) ;
2024-01-05 04:14:26 -05:00
traceRETURN_xTaskGetApplicationTaskTag ( xReturn ) ;
2022-02-24 07:14:22 -05:00
return xReturn ;
}
# 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 ;
2024-01-05 04:14:26 -05:00
traceENTER_xTaskGetApplicationTaskTagFromISR ( xTask ) ;
2022-02-24 07:14:22 -05:00
/* 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 . */
2024-01-05 04:14:26 -05:00
uxSavedInterruptStatus = taskENTER_CRITICAL_FROM_ISR ( ) ;
2022-02-24 07:14:22 -05:00
{
xReturn = pxTCB - > pxTaskTag ;
}
2024-01-05 04:14:26 -05:00
taskEXIT_CRITICAL_FROM_ISR ( uxSavedInterruptStatus ) ;
traceRETURN_xTaskGetApplicationTaskTagFromISR ( xReturn ) ;
2022-02-24 07:14:22 -05:00
return xReturn ;
}
# endif /* configUSE_APPLICATION_TASK_TAG */
/*-----------------------------------------------------------*/
# if ( configUSE_APPLICATION_TASK_TAG == 1 )
BaseType_t xTaskCallApplicationTaskHook ( TaskHandle_t xTask ,
void * pvParameter )
{
TCB_t * xTCB ;
BaseType_t xReturn ;
2024-01-05 04:14:26 -05:00
traceENTER_xTaskCallApplicationTaskHook ( xTask , pvParameter ) ;
2022-02-24 07:14:22 -05:00
/* If xTask is NULL then we are calling our own task hook. */
if ( xTask = = NULL )
{
xTCB = pxCurrentTCB ;
}
else
{
xTCB = xTask ;
}
if ( xTCB - > pxTaskTag ! = NULL )
{
xReturn = xTCB - > pxTaskTag ( pvParameter ) ;
}
else
{
xReturn = pdFAIL ;
}
2024-01-05 04:14:26 -05:00
traceRETURN_xTaskCallApplicationTaskHook ( xReturn ) ;
2022-02-24 07:14:22 -05:00
return xReturn ;
}
# endif /* configUSE_APPLICATION_TASK_TAG */
/*-----------------------------------------------------------*/
2024-01-05 04:14:26 -05:00
# if ( configNUMBER_OF_CORES == 1 )
void vTaskSwitchContext ( void )
2022-02-24 07:14:22 -05:00
{
2024-01-05 04:14:26 -05:00
traceENTER_vTaskSwitchContext ( ) ;
2022-02-24 07:14:22 -05:00
2024-01-05 04:14:26 -05:00
if ( uxSchedulerSuspended ! = ( UBaseType_t ) 0U )
2022-02-24 07:14:22 -05:00
{
/* The scheduler is currently suspended - do not allow a context
* switch . */
2024-01-05 04:14:26 -05:00
xYieldPendings [ 0 ] = pdTRUE ;
2022-02-24 07:14:22 -05:00
}
else
{
2024-01-05 04:14:26 -05:00
xYieldPendings [ 0 ] = pdFALSE ;
2022-02-24 07:14:22 -05:00
traceTASK_SWITCHED_OUT ( ) ;
# if ( configGENERATE_RUN_TIME_STATS == 1 )
2024-01-05 04:14:26 -05:00
{
# ifdef portALT_GET_RUN_TIME_COUNTER_VALUE
portALT_GET_RUN_TIME_COUNTER_VALUE ( ulTotalRunTime [ 0 ] ) ;
# else
ulTotalRunTime [ 0 ] = 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 [ 0 ] > ulTaskSwitchedInTime [ 0 ] )
{
pxCurrentTCB - > ulRunTimeCounter + = ( ulTotalRunTime [ 0 ] - ulTaskSwitchedInTime [ 0 ] ) ;
}
else
{
mtCOVERAGE_TEST_MARKER ( ) ;
}
ulTaskSwitchedInTime [ 0 ] = ulTotalRunTime [ 0 ] ;
}
# 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 . */
/* MISRA Ref 11.5.3 [Void pointer assignment] */
/* More details at: https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/MISRA.md#rule-115 */
/* coverity[misra_c_2012_rule_11_5_violation] */
taskSELECT_HIGHEST_PRIORITY_TASK ( ) ;
traceTASK_SWITCHED_IN ( ) ;
/* Macro to inject port specific behaviour immediately after
* switching tasks , such as setting an end of stack watchpoint
* or reconfiguring the MPU . */
portTASK_SWITCH_HOOK ( pxCurrentTCB ) ;
/* After the new task is switched in, update the global errno. */
# if ( configUSE_POSIX_ERRNO == 1 )
{
FreeRTOS_errno = pxCurrentTCB - > iTaskErrno ;
}
# endif
# if ( configUSE_C_RUNTIME_TLS_SUPPORT == 1 )
{
/* Switch C-Runtime's TLS Block to point to the TLS
* Block specific to this task . */
configSET_TLS_BLOCK ( pxCurrentTCB - > xTLSBlock ) ;
}
# endif
}
traceRETURN_vTaskSwitchContext ( ) ;
}
# else /* if ( configNUMBER_OF_CORES == 1 ) */
void vTaskSwitchContext ( BaseType_t xCoreID )
{
traceENTER_vTaskSwitchContext ( ) ;
/* Acquire both locks:
* - The ISR lock protects the ready list from simultaneous access by
* both other ISRs and tasks .
* - We also take the task lock to pause here in case another core has
* suspended the scheduler . We don ' t want to simply set xYieldPending
* and move on if another core suspended the scheduler . We should only
* do that if the current core has suspended the scheduler . */
portGET_TASK_LOCK ( ) ; /* Must always acquire the task lock first. */
portGET_ISR_LOCK ( ) ;
{
/* vTaskSwitchContext() must never be called from within a critical section.
* This is not necessarily true for single core FreeRTOS , but it is for this
* SMP port . */
configASSERT ( portGET_CRITICAL_NESTING_COUNT ( ) = = 0 ) ;
if ( uxSchedulerSuspended ! = ( UBaseType_t ) 0U )
{
/* The scheduler is currently suspended - do not allow a context
* switch . */
xYieldPendings [ xCoreID ] = pdTRUE ;
}
else
{
xYieldPendings [ xCoreID ] = pdFALSE ;
traceTASK_SWITCHED_OUT ( ) ;
# if ( configGENERATE_RUN_TIME_STATS == 1 )
2022-02-24 07:14:22 -05:00
{
# ifdef portALT_GET_RUN_TIME_COUNTER_VALUE
2024-01-05 04:14:26 -05:00
portALT_GET_RUN_TIME_COUNTER_VALUE ( ulTotalRunTime [ xCoreID ] ) ;
2022-02-24 07:14:22 -05:00
# else
2024-01-05 04:14:26 -05:00
ulTotalRunTime [ xCoreID ] = portGET_RUN_TIME_COUNTER_VALUE ( ) ;
2022-02-24 07:14:22 -05:00
# 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 . */
2024-01-05 04:14:26 -05:00
if ( ulTotalRunTime [ xCoreID ] > ulTaskSwitchedInTime [ xCoreID ] )
2022-02-24 07:14:22 -05:00
{
2024-01-05 04:14:26 -05:00
pxCurrentTCBs [ xCoreID ] - > ulRunTimeCounter + = ( ulTotalRunTime [ xCoreID ] - ulTaskSwitchedInTime [ xCoreID ] ) ;
2022-02-24 07:14:22 -05:00
}
else
{
mtCOVERAGE_TEST_MARKER ( ) ;
}
2024-01-05 04:14:26 -05:00
ulTaskSwitchedInTime [ xCoreID ] = ulTotalRunTime [ xCoreID ] ;
2022-02-24 07:14:22 -05:00
}
2024-01-05 04:14:26 -05:00
# endif /* configGENERATE_RUN_TIME_STATS */
2022-02-24 07:14:22 -05:00
2024-01-05 04:14:26 -05:00
/* Check for stack overflow, if configured. */
taskCHECK_FOR_STACK_OVERFLOW ( ) ;
2022-02-24 07:14:22 -05:00
2024-01-05 04:14:26 -05:00
/* Before the currently running task is switched out, save its errno. */
# if ( configUSE_POSIX_ERRNO == 1 )
2022-02-24 07:14:22 -05:00
{
2024-01-05 04:14:26 -05:00
pxCurrentTCBs [ xCoreID ] - > iTaskErrno = FreeRTOS_errno ;
2022-02-24 07:14:22 -05:00
}
2024-01-05 04:14:26 -05:00
# endif
2022-02-24 07:14:22 -05:00
2024-01-05 04:14:26 -05:00
/* Select a new task to run. */
taskSELECT_HIGHEST_PRIORITY_TASK ( xCoreID ) ;
traceTASK_SWITCHED_IN ( ) ;
2022-02-24 07:14:22 -05:00
2024-01-05 04:14:26 -05:00
/* Macro to inject port specific behaviour immediately after
* switching tasks , such as setting an end of stack watchpoint
* or reconfiguring the MPU . */
portTASK_SWITCH_HOOK ( pxCurrentTCBs [ portGET_CORE_ID ( ) ] ) ;
/* After the new task is switched in, update the global errno. */
# if ( configUSE_POSIX_ERRNO == 1 )
2022-02-24 07:14:22 -05:00
{
2024-01-05 04:14:26 -05:00
FreeRTOS_errno = pxCurrentTCBs [ xCoreID ] - > iTaskErrno ;
2022-02-24 07:14:22 -05:00
}
2024-01-05 04:14:26 -05:00
# endif
2022-02-24 07:14:22 -05:00
2024-01-05 04:14:26 -05:00
# if ( configUSE_C_RUNTIME_TLS_SUPPORT == 1 )
2022-02-24 07:14:22 -05:00
{
2024-01-05 04:14:26 -05:00
/* Switch C-Runtime's TLS Block to point to the TLS
* Block specific to this task . */
configSET_TLS_BLOCK ( pxCurrentTCBs [ xCoreID ] - > xTLSBlock ) ;
2022-02-24 07:14:22 -05:00
}
2024-01-05 04:14:26 -05:00
# endif
}
2022-02-24 07:14:22 -05:00
}
2024-01-05 04:14:26 -05:00
portRELEASE_ISR_LOCK ( ) ;
portRELEASE_TASK_LOCK ( ) ;
traceRETURN_vTaskSwitchContext ( ) ;
2022-02-24 07:14:22 -05:00
}
2024-01-05 04:14:26 -05:00
# endif /* if ( configNUMBER_OF_CORES > 1 ) */
2022-02-24 07:14:22 -05:00
/*-----------------------------------------------------------*/
void vTaskPlaceOnEventList ( List_t * const pxEventList ,
const TickType_t xTicksToWait )
{
2024-01-05 04:14:26 -05:00
traceENTER_vTaskPlaceOnEventList ( pxEventList , xTicksToWait ) ;
2022-02-24 07:14:22 -05:00
configASSERT ( pxEventList ) ;
2024-01-05 04:14:26 -05:00
/* THIS FUNCTION MUST BE CALLED WITH THE
2022-02-24 07:14:22 -05:00
* SCHEDULER SUSPENDED AND THE QUEUE BEING ACCESSED LOCKED . */
/* Place the event list item of the TCB in the appropriate event list.
* This is placed in the list in priority order so the highest priority task
2024-01-05 04:14:26 -05:00
* is the first to be woken by the event .
*
* Note : Lists are sorted in ascending order by ListItem_t . xItemValue .
* Normally , the xItemValue of a TCB ' s ListItem_t members is :
* xItemValue = ( configMAX_PRIORITIES - uxPriority )
* Therefore , the event list is sorted in descending priority order .
*
* The queue that contains the event list is locked , preventing
* simultaneous access from interrupts . */
2022-02-24 07:14:22 -05:00
vListInsert ( pxEventList , & ( pxCurrentTCB - > xEventListItem ) ) ;
prvAddCurrentTaskToDelayedList ( xTicksToWait , pdTRUE ) ;
2024-01-05 04:14:26 -05:00
traceRETURN_vTaskPlaceOnEventList ( ) ;
2022-02-24 07:14:22 -05:00
}
/*-----------------------------------------------------------*/
void vTaskPlaceOnUnorderedEventList ( List_t * pxEventList ,
const TickType_t xItemValue ,
const TickType_t xTicksToWait )
{
2024-01-05 04:14:26 -05:00
traceENTER_vTaskPlaceOnUnorderedEventList ( pxEventList , xItemValue , xTicksToWait ) ;
2022-02-24 07:14:22 -05:00
configASSERT ( pxEventList ) ;
/* THIS FUNCTION MUST BE CALLED WITH THE SCHEDULER SUSPENDED. It is used by
* the event groups implementation . */
2024-01-05 04:14:26 -05:00
configASSERT ( uxSchedulerSuspended ! = ( UBaseType_t ) 0U ) ;
2022-02-24 07:14:22 -05:00
/* Store the item value in the event list item. It is safe to access the
* event list item here as interrupts won ' t access the event list item of a
* task that is not in the Blocked state . */
listSET_LIST_ITEM_VALUE ( & ( pxCurrentTCB - > xEventListItem ) , xItemValue | taskEVENT_LIST_ITEM_VALUE_IN_USE ) ;
/* Place the event list item of the TCB at the end of the appropriate event
* list . It is safe to access the event list here because it is part of an
* event group implementation - and interrupts don ' t access event groups
* directly ( instead they access them indirectly by pending function calls to
* the task level ) . */
2024-01-05 04:14:26 -05:00
listINSERT_END ( pxEventList , & ( pxCurrentTCB - > xEventListItem ) ) ;
2022-02-24 07:14:22 -05:00
prvAddCurrentTaskToDelayedList ( xTicksToWait , pdTRUE ) ;
2024-01-05 04:14:26 -05:00
traceRETURN_vTaskPlaceOnUnorderedEventList ( ) ;
2022-02-24 07:14:22 -05:00
}
/*-----------------------------------------------------------*/
# if ( configUSE_TIMERS == 1 )
void vTaskPlaceOnEventListRestricted ( List_t * const pxEventList ,
TickType_t xTicksToWait ,
const BaseType_t xWaitIndefinitely )
{
2024-01-05 04:14:26 -05:00
traceENTER_vTaskPlaceOnEventListRestricted ( pxEventList , xTicksToWait , xWaitIndefinitely ) ;
2022-02-24 07:14:22 -05:00
configASSERT ( pxEventList ) ;
/* This function should not be called by application code hence the
* ' Restricted ' in its name . It is not part of the public API . It is
* designed for use by kernel code , and has special calling requirements -
* it should be called with the scheduler suspended . */
/* Place the event list item of the TCB in the appropriate event list.
* In this case it is assume that this is the only task that is going to
* be waiting on this event list , so the faster vListInsertEnd ( ) function
* can be used in place of vListInsert . */
2024-01-05 04:14:26 -05:00
listINSERT_END ( pxEventList , & ( pxCurrentTCB - > xEventListItem ) ) ;
2022-02-24 07:14:22 -05:00
/* If the task should block indefinitely then set the block time to a
* value that will be recognised as an indefinite delay inside the
* prvAddCurrentTaskToDelayedList ( ) function . */
if ( xWaitIndefinitely ! = pdFALSE )
{
xTicksToWait = portMAX_DELAY ;
}
traceTASK_DELAY_UNTIL ( ( xTickCount + xTicksToWait ) ) ;
prvAddCurrentTaskToDelayedList ( xTicksToWait , xWaitIndefinitely ) ;
2024-01-05 04:14:26 -05:00
traceRETURN_vTaskPlaceOnEventListRestricted ( ) ;
2022-02-24 07:14:22 -05:00
}
# endif /* configUSE_TIMERS */
/*-----------------------------------------------------------*/
BaseType_t xTaskRemoveFromEventList ( const List_t * const pxEventList )
{
TCB_t * pxUnblockedTCB ;
BaseType_t xReturn ;
2024-01-05 04:14:26 -05:00
traceENTER_xTaskRemoveFromEventList ( pxEventList ) ;
2022-02-24 07:14:22 -05:00
/* THIS FUNCTION MUST BE CALLED FROM A CRITICAL SECTION. It can also be
* called from a critical section within an ISR . */
/* The event list is sorted in priority order, so the first in the list can
* be removed as it is known to be the highest priority . Remove the TCB from
* the delayed list , and add it to the ready list .
*
* If an event is for a queue that is locked then this function will never
* get called - the lock count on the queue will get modified instead . This
* means exclusive access to the event list is guaranteed here .
*
* This function assumes that a check has already been made to ensure that
* pxEventList is not empty . */
2024-01-05 04:14:26 -05:00
/* MISRA Ref 11.5.3 [Void pointer assignment] */
/* More details at: https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/MISRA.md#rule-115 */
/* coverity[misra_c_2012_rule_11_5_violation] */
pxUnblockedTCB = listGET_OWNER_OF_HEAD_ENTRY ( pxEventList ) ;
2022-02-24 07:14:22 -05:00
configASSERT ( pxUnblockedTCB ) ;
2024-01-05 04:14:26 -05:00
listREMOVE_ITEM ( & ( pxUnblockedTCB - > xEventListItem ) ) ;
2022-02-24 07:14:22 -05:00
2024-01-05 04:14:26 -05:00
if ( uxSchedulerSuspended = = ( UBaseType_t ) 0U )
2022-02-24 07:14:22 -05:00
{
2024-01-05 04:14:26 -05:00
listREMOVE_ITEM ( & ( pxUnblockedTCB - > xStateListItem ) ) ;
2022-02-24 07:14:22 -05:00
prvAddTaskToReadyList ( pxUnblockedTCB ) ;
# if ( configUSE_TICKLESS_IDLE != 0 )
2024-01-05 04:14:26 -05:00
{
/* 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 ( ) ;
}
2022-02-24 07:14:22 -05:00
# endif
}
else
{
/* The delayed and ready lists cannot be accessed, so hold this task
* pending until the scheduler is resumed . */
2024-01-05 04:14:26 -05:00
listINSERT_END ( & ( xPendingReadyList ) , & ( pxUnblockedTCB - > xEventListItem ) ) ;
2022-02-24 07:14:22 -05:00
}
2024-01-05 04:14:26 -05:00
# if ( configNUMBER_OF_CORES == 1 )
{
if ( pxUnblockedTCB - > uxPriority > pxCurrentTCB - > uxPriority )
2022-02-24 07:14:22 -05:00
{
2024-01-05 04:14:26 -05:00
/* Return true if the task removed from the event list has a higher
* priority than the calling task . This allows the calling task to know if
* it should force a context switch now . */
2022-02-24 07:14:22 -05:00
xReturn = pdTRUE ;
2024-01-05 04:14:26 -05:00
/* Mark that a yield is pending in case the user is not using the
* " xHigherPriorityTaskWoken " parameter to an ISR safe FreeRTOS function . */
xYieldPendings [ 0 ] = pdTRUE ;
2022-02-24 07:14:22 -05:00
}
2024-01-05 04:14:26 -05:00
else
{
xReturn = pdFALSE ;
}
}
# else /* #if ( configNUMBER_OF_CORES == 1 ) */
{
xReturn = pdFALSE ;
# if ( configUSE_PREEMPTION == 1 )
{
prvYieldForTask ( pxUnblockedTCB ) ;
if ( xYieldPendings [ portGET_CORE_ID ( ) ] ! = pdFALSE )
{
xReturn = pdTRUE ;
}
}
# endif /* #if ( configUSE_PREEMPTION == 1 ) */
}
# endif /* #if ( configNUMBER_OF_CORES == 1 ) */
2022-02-24 07:14:22 -05:00
2024-01-05 04:14:26 -05:00
traceRETURN_xTaskRemoveFromEventList ( xReturn ) ;
2022-02-24 07:14:22 -05:00
return xReturn ;
}
/*-----------------------------------------------------------*/
void vTaskRemoveFromUnorderedEventList ( ListItem_t * pxEventListItem ,
const TickType_t xItemValue )
{
TCB_t * pxUnblockedTCB ;
2024-01-05 04:14:26 -05:00
traceENTER_vTaskRemoveFromUnorderedEventList ( pxEventListItem , xItemValue ) ;
2022-02-24 07:14:22 -05:00
/* THIS FUNCTION MUST BE CALLED WITH THE SCHEDULER SUSPENDED. It is used by
* the event flags implementation . */
2024-01-05 04:14:26 -05:00
configASSERT ( uxSchedulerSuspended ! = ( UBaseType_t ) 0U ) ;
2022-02-24 07:14:22 -05:00
/* Store the new item value in the event list. */
listSET_LIST_ITEM_VALUE ( pxEventListItem , xItemValue | taskEVENT_LIST_ITEM_VALUE_IN_USE ) ;
/* Remove the event list form the event flag. Interrupts do not access
* event flags . */
2024-01-05 04:14:26 -05:00
/* MISRA Ref 11.5.3 [Void pointer assignment] */
/* More details at: https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/MISRA.md#rule-115 */
/* coverity[misra_c_2012_rule_11_5_violation] */
pxUnblockedTCB = listGET_LIST_ITEM_OWNER ( pxEventListItem ) ;
2022-02-24 07:14:22 -05:00
configASSERT ( pxUnblockedTCB ) ;
2024-01-05 04:14:26 -05:00
listREMOVE_ITEM ( pxEventListItem ) ;
2022-02-24 07:14:22 -05:00
# if ( configUSE_TICKLESS_IDLE != 0 )
2024-01-05 04:14:26 -05:00
{
/* 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 ( ) ;
}
2022-02-24 07:14:22 -05:00
# endif
/* Remove the task from the delayed list and add it to the ready list. The
* scheduler is suspended so interrupts will not be accessing the ready
* lists . */
2024-01-05 04:14:26 -05:00
listREMOVE_ITEM ( & ( pxUnblockedTCB - > xStateListItem ) ) ;
2022-02-24 07:14:22 -05:00
prvAddTaskToReadyList ( pxUnblockedTCB ) ;
2024-01-05 04:14:26 -05:00
# if ( configNUMBER_OF_CORES == 1 )
{
if ( pxUnblockedTCB - > uxPriority > pxCurrentTCB - > uxPriority )
2022-02-24 07:14:22 -05:00
{
2024-01-05 04:14:26 -05:00
/* The unblocked task has a priority above that of the calling task, so
* a context switch is required . This function is called with the
* scheduler suspended so xYieldPending is set so the context switch
* occurs immediately that the scheduler is resumed ( unsuspended ) . */
xYieldPendings [ 0 ] = pdTRUE ;
2022-02-24 07:14:22 -05:00
}
2024-01-05 04:14:26 -05:00
}
# else /* #if ( configNUMBER_OF_CORES == 1 ) */
{
# if ( configUSE_PREEMPTION == 1 )
{
taskENTER_CRITICAL ( ) ;
{
prvYieldForTask ( pxUnblockedTCB ) ;
}
taskEXIT_CRITICAL ( ) ;
}
# endif
}
# endif /* #if ( configNUMBER_OF_CORES == 1 ) */
traceRETURN_vTaskRemoveFromUnorderedEventList ( ) ;
2022-02-24 07:14:22 -05:00
}
/*-----------------------------------------------------------*/
void vTaskSetTimeOutState ( TimeOut_t * const pxTimeOut )
{
2024-01-05 04:14:26 -05:00
traceENTER_vTaskSetTimeOutState ( pxTimeOut ) ;
2022-02-24 07:14:22 -05:00
configASSERT ( pxTimeOut ) ;
taskENTER_CRITICAL ( ) ;
{
pxTimeOut - > xOverflowCount = xNumOfOverflows ;
pxTimeOut - > xTimeOnEntering = xTickCount ;
}
taskEXIT_CRITICAL ( ) ;
2024-01-05 04:14:26 -05:00
traceRETURN_vTaskSetTimeOutState ( ) ;
2022-02-24 07:14:22 -05:00
}
/*-----------------------------------------------------------*/
void vTaskInternalSetTimeOutState ( TimeOut_t * const pxTimeOut )
{
2024-01-05 04:14:26 -05:00
traceENTER_vTaskInternalSetTimeOutState ( pxTimeOut ) ;
2022-02-24 07:14:22 -05:00
/* For internal use only as it does not use a critical section. */
pxTimeOut - > xOverflowCount = xNumOfOverflows ;
pxTimeOut - > xTimeOnEntering = xTickCount ;
2024-01-05 04:14:26 -05:00
traceRETURN_vTaskInternalSetTimeOutState ( ) ;
2022-02-24 07:14:22 -05:00
}
/*-----------------------------------------------------------*/
BaseType_t xTaskCheckForTimeOut ( TimeOut_t * const pxTimeOut ,
TickType_t * const pxTicksToWait )
{
BaseType_t xReturn ;
2024-01-05 04:14:26 -05:00
traceENTER_xTaskCheckForTimeOut ( pxTimeOut , pxTicksToWait ) ;
2022-02-24 07:14:22 -05:00
configASSERT ( pxTimeOut ) ;
configASSERT ( pxTicksToWait ) ;
taskENTER_CRITICAL ( ) ;
{
/* Minor optimisation. The tick count cannot change in this block. */
const TickType_t xConstTickCount = xTickCount ;
const TickType_t xElapsedTime = xConstTickCount - pxTimeOut - > xTimeOnEntering ;
# if ( INCLUDE_xTaskAbortDelay == 1 )
if ( pxCurrentTCB - > ucDelayAborted ! = ( uint8_t ) pdFALSE )
{
/* The delay was aborted, which is not the same as a time out,
* but has the same result . */
pxCurrentTCB - > ucDelayAborted = pdFALSE ;
xReturn = pdTRUE ;
}
else
# endif
# if ( INCLUDE_vTaskSuspend == 1 )
if ( * pxTicksToWait = = portMAX_DELAY )
{
/* If INCLUDE_vTaskSuspend is set to 1 and the block time
* specified is the maximum block time then the task should block
* indefinitely , and therefore never time out . */
xReturn = pdFALSE ;
}
else
# endif
2024-01-05 04:14:26 -05:00
if ( ( xNumOfOverflows ! = pxTimeOut - > xOverflowCount ) & & ( xConstTickCount > = pxTimeOut - > xTimeOnEntering ) )
2022-02-24 07:14:22 -05:00
{
/* The tick count is greater than the time at which
* vTaskSetTimeout ( ) was called , but has also overflowed since
* vTaskSetTimeOut ( ) was called . It must have wrapped all the way
* around and gone past again . This passed since vTaskSetTimeout ( )
* was called . */
xReturn = pdTRUE ;
* pxTicksToWait = ( TickType_t ) 0 ;
}
2024-01-05 04:14:26 -05:00
else if ( xElapsedTime < * pxTicksToWait )
2022-02-24 07:14:22 -05:00
{
/* Not a genuine timeout. Adjust parameters for time remaining. */
* pxTicksToWait - = xElapsedTime ;
vTaskInternalSetTimeOutState ( pxTimeOut ) ;
xReturn = pdFALSE ;
}
else
{
* pxTicksToWait = ( TickType_t ) 0 ;
xReturn = pdTRUE ;
}
}
taskEXIT_CRITICAL ( ) ;
2024-01-05 04:14:26 -05:00
traceRETURN_xTaskCheckForTimeOut ( xReturn ) ;
2022-02-24 07:14:22 -05:00
return xReturn ;
}
/*-----------------------------------------------------------*/
void vTaskMissedYield ( void )
{
2024-01-05 04:14:26 -05:00
traceENTER_vTaskMissedYield ( ) ;
/* Must be called from within a critical section. */
2022-02-24 07:14:22 -05:00
xYieldPendings [ portGET_CORE_ID ( ) ] = pdTRUE ;
2024-01-05 04:14:26 -05:00
traceRETURN_vTaskMissedYield ( ) ;
2022-02-24 07:14:22 -05:00
}
/*-----------------------------------------------------------*/
# if ( configUSE_TRACE_FACILITY == 1 )
UBaseType_t uxTaskGetTaskNumber ( TaskHandle_t xTask )
{
UBaseType_t uxReturn ;
TCB_t const * pxTCB ;
2024-01-05 04:14:26 -05:00
traceENTER_uxTaskGetTaskNumber ( xTask ) ;
2022-02-24 07:14:22 -05:00
if ( xTask ! = NULL )
{
pxTCB = xTask ;
uxReturn = pxTCB - > uxTaskNumber ;
}
else
{
uxReturn = 0U ;
}
2024-01-05 04:14:26 -05:00
traceRETURN_uxTaskGetTaskNumber ( uxReturn ) ;
2022-02-24 07:14:22 -05:00
return uxReturn ;
}
# endif /* configUSE_TRACE_FACILITY */
/*-----------------------------------------------------------*/
# if ( configUSE_TRACE_FACILITY == 1 )
void vTaskSetTaskNumber ( TaskHandle_t xTask ,
const UBaseType_t uxHandle )
{
TCB_t * pxTCB ;
2024-01-05 04:14:26 -05:00
traceENTER_vTaskSetTaskNumber ( xTask , uxHandle ) ;
2022-02-24 07:14:22 -05:00
if ( xTask ! = NULL )
{
pxTCB = xTask ;
pxTCB - > uxTaskNumber = uxHandle ;
}
2024-01-05 04:14:26 -05:00
traceRETURN_vTaskSetTaskNumber ( ) ;
2022-02-24 07:14:22 -05:00
}
# endif /* configUSE_TRACE_FACILITY */
2024-01-05 04:14:26 -05:00
/*-----------------------------------------------------------*/
2022-02-24 07:14:22 -05:00
/*
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
2024-01-05 04:14:26 -05:00
* The passive idle task .
2022-02-24 07:14:22 -05:00
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
*
2024-01-05 04:14:26 -05:00
* The passive idle task is used for all the additional cores in a SMP
* system . There must be only 1 active idle task and the rest are passive
* idle tasks .
*
* The portTASK_FUNCTION ( ) macro is used to allow port / compiler specific
* language extensions . The equivalent prototype for this function is :
2022-02-24 07:14:22 -05:00
*
2024-01-05 04:14:26 -05:00
* void prvPassiveIdleTask ( void * pvParameters ) ;
2022-02-24 07:14:22 -05:00
*/
2024-01-05 04:14:26 -05:00
# if ( configNUMBER_OF_CORES > 1 )
static portTASK_FUNCTION ( prvPassiveIdleTask , pvParameters )
2022-02-24 07:14:22 -05:00
{
2024-01-05 04:14:26 -05:00
( void ) pvParameters ;
2022-02-24 07:14:22 -05:00
taskYIELD ( ) ;
2024-01-05 04:14:26 -05:00
for ( ; configCONTROL_INFINITE_LOOP ( ) ; )
2022-02-24 07:14:22 -05:00
{
# if ( configUSE_PREEMPTION == 0 )
2024-01-05 04:14:26 -05:00
{
/* If we are not using preemption we keep forcing a task switch to
* see if any other task has become available . If we are using
* preemption we don ' t need to do this as any task becoming available
* will automatically get the processor anyway . */
taskYIELD ( ) ;
}
2022-02-24 07:14:22 -05:00
# endif /* configUSE_PREEMPTION */
# if ( ( configUSE_PREEMPTION == 1 ) && ( configIDLE_SHOULD_YIELD == 1 ) )
2024-01-05 04:14:26 -05:00
{
/* When using preemption tasks of equal priority will be
* timesliced . If a task that is sharing the idle priority is ready
* to run then the idle task should yield before the end of the
* timeslice .
*
* A critical region is not required here as we are just reading from
* the list , and an occasional incorrect value will not matter . If
* the ready list at the idle priority contains one more task than the
* number of idle tasks , which is equal to the configured numbers of cores
* then a task other than the idle task is ready to execute . */
if ( listCURRENT_LIST_LENGTH ( & ( pxReadyTasksLists [ tskIDLE_PRIORITY ] ) ) > ( UBaseType_t ) configNUMBER_OF_CORES )
2022-02-24 07:14:22 -05:00
{
2024-01-05 04:14:26 -05:00
taskYIELD ( ) ;
2022-02-24 07:14:22 -05:00
}
2024-01-05 04:14:26 -05:00
else
2022-02-24 07:14:22 -05:00
{
2024-01-05 04:14:26 -05:00
mtCOVERAGE_TEST_MARKER ( ) ;
2022-02-24 07:14:22 -05:00
}
2024-01-05 04:14:26 -05:00
}
# endif /* ( ( configUSE_PREEMPTION == 1 ) && ( configIDLE_SHOULD_YIELD == 1 ) ) */
# if ( configUSE_PASSIVE_IDLE_HOOK == 1 )
{
/* Call the user defined function from within the idle task. This
* allows the application designer to add background functionality
* without the overhead of a separate task .
*
* This hook is intended to manage core activity such as disabling cores that go idle .
*
* NOTE : vApplicationPassiveIdleHook ( ) MUST NOT , UNDER ANY CIRCUMSTANCES ,
* CALL A FUNCTION THAT MIGHT BLOCK . */
vApplicationPassiveIdleHook ( ) ;
}
# endif /* configUSE_PASSIVE_IDLE_HOOK */
2022-02-24 07:14:22 -05:00
}
}
2024-01-05 04:14:26 -05:00
# endif /* #if ( configNUMBER_OF_CORES > 1 ) */
2022-02-24 07:14:22 -05:00
/*
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
2024-01-05 04:14:26 -05:00
* The idle task .
2022-02-24 07:14:22 -05:00
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
*
2024-01-05 04:14:26 -05:00
* The portTASK_FUNCTION ( ) macro is used to allow port / compiler specific
* language extensions . The equivalent prototype for this function is :
*
* void prvIdleTask ( void * pvParameters ) ;
2022-02-24 07:14:22 -05:00
*
*/
2024-01-05 04:14:26 -05:00
2022-02-24 07:14:22 -05:00
static portTASK_FUNCTION ( prvIdleTask , pvParameters )
{
/* Stop warnings. */
( void ) pvParameters ;
/** THIS IS THE RTOS IDLE TASK - WHICH IS CREATED AUTOMATICALLY WHEN THE
* SCHEDULER IS STARTED . * */
/* 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 . */
portALLOCATE_SECURE_CONTEXT ( configMINIMAL_SECURE_STACK_SIZE ) ;
2024-01-05 04:14:26 -05:00
# if ( configNUMBER_OF_CORES > 1 )
{
/* SMP all cores start up in the idle task. This initial yield gets the application
* tasks started . */
taskYIELD ( ) ;
}
# endif /* #if ( configNUMBER_OF_CORES > 1 ) */
2022-02-24 07:14:22 -05:00
2024-01-05 04:14:26 -05:00
for ( ; configCONTROL_INFINITE_LOOP ( ) ; )
2022-02-24 07:14:22 -05:00
{
/* See if any tasks have deleted themselves - if so then the idle task
* is responsible for freeing the deleted task ' s TCB and stack . */
prvCheckTasksWaitingTermination ( ) ;
# if ( configUSE_PREEMPTION == 0 )
2024-01-05 04:14:26 -05:00
{
/* If we are not using preemption we keep forcing a task switch to
* see if any other task has become available . If we are using
* preemption we don ' t need to do this as any task becoming available
* will automatically get the processor anyway . */
taskYIELD ( ) ;
}
2022-02-24 07:14:22 -05:00
# endif /* configUSE_PREEMPTION */
# if ( ( configUSE_PREEMPTION == 1 ) && ( configIDLE_SHOULD_YIELD == 1 ) )
2024-01-05 04:14:26 -05:00
{
/* When using preemption tasks of equal priority will be
* timesliced . If a task that is sharing the idle priority is ready
* to run then the idle task should yield before the end of the
* timeslice .
*
* A critical region is not required here as we are just reading from
* the list , and an occasional incorrect value will not matter . If
* the ready list at the idle priority contains one more task than the
* number of idle tasks , which is equal to the configured numbers of cores
* then a task other than the idle task is ready to execute . */
if ( listCURRENT_LIST_LENGTH ( & ( pxReadyTasksLists [ tskIDLE_PRIORITY ] ) ) > ( UBaseType_t ) configNUMBER_OF_CORES )
2022-02-24 07:14:22 -05:00
{
2024-01-05 04:14:26 -05:00
taskYIELD ( ) ;
}
else
{
mtCOVERAGE_TEST_MARKER ( ) ;
2022-02-24 07:14:22 -05:00
}
2024-01-05 04:14:26 -05:00
}
2022-02-24 07:14:22 -05:00
# endif /* ( ( configUSE_PREEMPTION == 1 ) && ( configIDLE_SHOULD_YIELD == 1 ) ) */
# if ( configUSE_IDLE_HOOK == 1 )
2024-01-05 04:14:26 -05:00
{
/* Call the user defined function from within the idle task. */
vApplicationIdleHook ( ) ;
}
2022-02-24 07:14:22 -05:00
# endif /* configUSE_IDLE_HOOK */
/* This conditional compilation should use inequality to 0, not equality
* to 1. This is to ensure portSUPPRESS_TICKS_AND_SLEEP ( ) is called when
* user defined low power mode implementations require
* configUSE_TICKLESS_IDLE to be set to a value other than 1. */
# if ( configUSE_TICKLESS_IDLE != 0 )
2024-01-05 04:14:26 -05:00
{
TickType_t xExpectedIdleTime ;
2022-02-24 07:14:22 -05:00
2024-01-05 04:14:26 -05:00
/* It is not desirable to suspend then resume the scheduler on
* each iteration of the idle task . Therefore , a preliminary
* test of the expected idle time is performed without the
* scheduler suspended . The result here is not necessarily
* valid . */
xExpectedIdleTime = prvGetExpectedIdleTime ( ) ;
2022-02-24 07:14:22 -05:00
2024-01-05 04:14:26 -05:00
if ( xExpectedIdleTime > = ( TickType_t ) configEXPECTED_IDLE_TIME_BEFORE_SLEEP )
{
vTaskSuspendAll ( ) ;
2022-02-24 07:14:22 -05:00
{
2024-01-05 04:14:26 -05:00
/* Now the scheduler is suspended, the expected idle
* time can be sampled again , and this time its value can
* be used . */
configASSERT ( xNextTaskUnblockTime > = xTickCount ) ;
xExpectedIdleTime = prvGetExpectedIdleTime ( ) ;
/* Define the following macro to set xExpectedIdleTime to 0
* if the application does not want
* portSUPPRESS_TICKS_AND_SLEEP ( ) to be called . */
configPRE_SUPPRESS_TICKS_AND_SLEEP_PROCESSING ( xExpectedIdleTime ) ;
if ( xExpectedIdleTime > = ( TickType_t ) configEXPECTED_IDLE_TIME_BEFORE_SLEEP )
2022-02-24 07:14:22 -05:00
{
2024-01-05 04:14:26 -05:00
traceLOW_POWER_IDLE_BEGIN ( ) ;
portSUPPRESS_TICKS_AND_SLEEP ( xExpectedIdleTime ) ;
traceLOW_POWER_IDLE_END ( ) ;
}
else
{
mtCOVERAGE_TEST_MARKER ( ) ;
2022-02-24 07:14:22 -05:00
}
}
2024-01-05 04:14:26 -05:00
( void ) xTaskResumeAll ( ) ;
2022-02-24 07:14:22 -05:00
}
2024-01-05 04:14:26 -05:00
else
2022-02-24 07:14:22 -05:00
{
2024-01-05 04:14:26 -05:00
mtCOVERAGE_TEST_MARKER ( ) ;
2022-02-24 07:14:22 -05:00
}
2024-01-05 04:14:26 -05:00
}
# endif /* configUSE_TICKLESS_IDLE */
# if ( ( configNUMBER_OF_CORES > 1 ) && ( configUSE_PASSIVE_IDLE_HOOK == 1 ) )
{
/* Call the user defined function from within the idle task. This
* allows the application designer to add background functionality
* without the overhead of a separate task .
*
* This hook is intended to manage core activity such as disabling cores that go idle .
*
* NOTE : vApplicationPassiveIdleHook ( ) MUST NOT , UNDER ANY CIRCUMSTANCES ,
* CALL A FUNCTION THAT MIGHT BLOCK . */
vApplicationPassiveIdleHook ( ) ;
}
# endif /* #if ( ( configNUMBER_OF_CORES > 1 ) && ( configUSE_PASSIVE_IDLE_HOOK == 1 ) ) */
2022-02-24 07:14:22 -05:00
}
}
/*-----------------------------------------------------------*/
# if ( configUSE_TICKLESS_IDLE != 0 )
eSleepModeStatus eTaskConfirmSleepModeStatus ( void )
{
2024-01-05 04:14:26 -05:00
# if ( INCLUDE_vTaskSuspend == 1 )
/* The idle task exists in addition to the application tasks. */
const UBaseType_t uxNonApplicationTasks = configNUMBER_OF_CORES ;
# endif /* INCLUDE_vTaskSuspend */
2022-02-24 07:14:22 -05:00
eSleepModeStatus eReturn = eStandardSleep ;
2024-01-05 04:14:26 -05:00
traceENTER_eTaskConfirmSleepModeStatus ( ) ;
2022-02-24 07:14:22 -05:00
/* This function must be called from a critical section. */
2024-01-05 04:14:26 -05:00
if ( listCURRENT_LIST_LENGTH ( & xPendingReadyList ) ! = 0U )
2022-02-24 07:14:22 -05:00
{
/* A task was made ready while the scheduler was suspended. */
eReturn = eAbortSleep ;
}
2024-01-05 04:14:26 -05:00
else if ( xYieldPendings [ portGET_CORE_ID ( ) ] ! = pdFALSE )
2022-02-24 07:14:22 -05:00
{
/* A yield was pended while the scheduler was suspended. */
eReturn = eAbortSleep ;
}
2024-01-05 04:14:26 -05:00
else if ( xPendedTicks ! = 0U )
2022-02-24 07:14:22 -05:00
{
/* A tick interrupt has already occurred but was held pending
* because the scheduler is suspended . */
eReturn = eAbortSleep ;
}
2024-01-05 04:14:26 -05:00
# if ( INCLUDE_vTaskSuspend == 1 )
else if ( listCURRENT_LIST_LENGTH ( & xSuspendedTaskList ) = = ( uxCurrentNumberOfTasks - uxNonApplicationTasks ) )
2022-02-24 07:14:22 -05:00
{
2024-01-05 04:14:26 -05:00
/* If all the tasks are in the suspended list (which might mean they
* have an infinite block time rather than actually being suspended )
* then it is safe to turn all clocks off and just wait for external
* interrupts . */
2022-02-24 07:14:22 -05:00
eReturn = eNoTasksWaitingTimeout ;
}
2024-01-05 04:14:26 -05:00
# endif /* INCLUDE_vTaskSuspend */
else
{
mtCOVERAGE_TEST_MARKER ( ) ;
2022-02-24 07:14:22 -05:00
}
2024-01-05 04:14:26 -05:00
traceRETURN_eTaskConfirmSleepModeStatus ( eReturn ) ;
2022-02-24 07:14:22 -05:00
return eReturn ;
}
# endif /* configUSE_TICKLESS_IDLE */
/*-----------------------------------------------------------*/
# if ( configNUM_THREAD_LOCAL_STORAGE_POINTERS != 0 )
void vTaskSetThreadLocalStoragePointer ( TaskHandle_t xTaskToSet ,
BaseType_t xIndex ,
void * pvValue )
{
TCB_t * pxTCB ;
2024-01-05 04:14:26 -05:00
traceENTER_vTaskSetThreadLocalStoragePointer ( xTaskToSet , xIndex , pvValue ) ;
if ( ( xIndex > = 0 ) & &
( xIndex < ( BaseType_t ) configNUM_THREAD_LOCAL_STORAGE_POINTERS ) )
2022-02-24 07:14:22 -05:00
{
pxTCB = prvGetTCBFromHandle ( xTaskToSet ) ;
configASSERT ( pxTCB ! = NULL ) ;
pxTCB - > pvThreadLocalStoragePointers [ xIndex ] = pvValue ;
}
2024-01-05 04:14:26 -05:00
traceRETURN_vTaskSetThreadLocalStoragePointer ( ) ;
2022-02-24 07:14:22 -05:00
}
# endif /* configNUM_THREAD_LOCAL_STORAGE_POINTERS */
/*-----------------------------------------------------------*/
# if ( configNUM_THREAD_LOCAL_STORAGE_POINTERS != 0 )
void * pvTaskGetThreadLocalStoragePointer ( TaskHandle_t xTaskToQuery ,
BaseType_t xIndex )
{
void * pvReturn = NULL ;
TCB_t * pxTCB ;
2024-01-05 04:14:26 -05:00
traceENTER_pvTaskGetThreadLocalStoragePointer ( xTaskToQuery , xIndex ) ;
if ( ( xIndex > = 0 ) & &
( xIndex < ( BaseType_t ) configNUM_THREAD_LOCAL_STORAGE_POINTERS ) )
2022-02-24 07:14:22 -05:00
{
pxTCB = prvGetTCBFromHandle ( xTaskToQuery ) ;
pvReturn = pxTCB - > pvThreadLocalStoragePointers [ xIndex ] ;
}
else
{
pvReturn = NULL ;
}
2024-01-05 04:14:26 -05:00
traceRETURN_pvTaskGetThreadLocalStoragePointer ( pvReturn ) ;
2022-02-24 07:14:22 -05:00
return pvReturn ;
}
# endif /* configNUM_THREAD_LOCAL_STORAGE_POINTERS */
/*-----------------------------------------------------------*/
# if ( portUSING_MPU_WRAPPERS == 1 )
void vTaskAllocateMPURegions ( TaskHandle_t xTaskToModify ,
2024-01-05 04:14:26 -05:00
const MemoryRegion_t * const pxRegions )
2022-02-24 07:14:22 -05:00
{
TCB_t * pxTCB ;
2024-01-05 04:14:26 -05:00
traceENTER_vTaskAllocateMPURegions ( xTaskToModify , pxRegions ) ;
2022-02-24 07:14:22 -05:00
/* If null is passed in here then we are modifying the MPU settings of
* the calling task . */
pxTCB = prvGetTCBFromHandle ( xTaskToModify ) ;
2024-01-05 04:14:26 -05:00
vPortStoreTaskMPUSettings ( & ( pxTCB - > xMPUSettings ) , pxRegions , NULL , 0 ) ;
traceRETURN_vTaskAllocateMPURegions ( ) ;
2022-02-24 07:14:22 -05:00
}
# endif /* portUSING_MPU_WRAPPERS */
/*-----------------------------------------------------------*/
static void prvInitialiseTaskLists ( void )
{
UBaseType_t uxPriority ;
for ( uxPriority = ( UBaseType_t ) 0U ; uxPriority < ( UBaseType_t ) configMAX_PRIORITIES ; uxPriority + + )
{
vListInitialise ( & ( pxReadyTasksLists [ uxPriority ] ) ) ;
}
vListInitialise ( & xDelayedTaskList1 ) ;
vListInitialise ( & xDelayedTaskList2 ) ;
vListInitialise ( & xPendingReadyList ) ;
# if ( INCLUDE_vTaskDelete == 1 )
2024-01-05 04:14:26 -05:00
{
vListInitialise ( & xTasksWaitingTermination ) ;
}
2022-02-24 07:14:22 -05:00
# endif /* INCLUDE_vTaskDelete */
# if ( INCLUDE_vTaskSuspend == 1 )
2024-01-05 04:14:26 -05:00
{
vListInitialise ( & xSuspendedTaskList ) ;
}
2022-02-24 07:14:22 -05:00
# endif /* INCLUDE_vTaskSuspend */
/* Start with pxDelayedTaskList using list1 and the pxOverflowDelayedTaskList
* using list2 . */
pxDelayedTaskList = & xDelayedTaskList1 ;
pxOverflowDelayedTaskList = & xDelayedTaskList2 ;
}
/*-----------------------------------------------------------*/
static void prvCheckTasksWaitingTermination ( void )
{
/** THIS FUNCTION IS CALLED FROM THE RTOS IDLE TASK **/
# if ( INCLUDE_vTaskDelete == 1 )
2024-01-05 04:14:26 -05:00
{
TCB_t * pxTCB ;
/* uxDeletedTasksWaitingCleanUp is used to prevent taskENTER_CRITICAL()
* being called too often in the idle task . */
while ( uxDeletedTasksWaitingCleanUp > ( UBaseType_t ) 0U )
2022-02-24 07:14:22 -05:00
{
2024-01-05 04:14:26 -05:00
# if ( configNUMBER_OF_CORES == 1 )
{
taskENTER_CRITICAL ( ) ;
{
{
/* MISRA Ref 11.5.3 [Void pointer assignment] */
/* More details at: https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/MISRA.md#rule-115 */
/* coverity[misra_c_2012_rule_11_5_violation] */
pxTCB = listGET_OWNER_OF_HEAD_ENTRY ( ( & xTasksWaitingTermination ) ) ;
( void ) uxListRemove ( & ( pxTCB - > xStateListItem ) ) ;
- - uxCurrentNumberOfTasks ;
- - uxDeletedTasksWaitingCleanUp ;
}
}
taskEXIT_CRITICAL ( ) ;
2022-02-24 07:14:22 -05:00
2024-01-05 04:14:26 -05:00
prvDeleteTCB ( pxTCB ) ;
}
# else /* #if( configNUMBER_OF_CORES == 1 ) */
2022-02-24 07:14:22 -05:00
{
2024-01-05 04:14:26 -05:00
pxTCB = NULL ;
2022-02-24 07:14:22 -05:00
taskENTER_CRITICAL ( ) ;
{
2024-01-05 04:14:26 -05:00
/* For SMP, multiple idles can be running simultaneously
2022-02-24 07:14:22 -05:00
* and we need to check that other idles did not cleanup while we were
2024-01-05 04:14:26 -05:00
* waiting to enter the critical section . */
2022-02-24 07:14:22 -05:00
if ( uxDeletedTasksWaitingCleanUp > ( UBaseType_t ) 0U )
{
2024-01-05 04:14:26 -05:00
/* MISRA Ref 11.5.3 [Void pointer assignment] */
/* More details at: https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/MISRA.md#rule-115 */
/* coverity[misra_c_2012_rule_11_5_violation] */
pxTCB = listGET_OWNER_OF_HEAD_ENTRY ( ( & xTasksWaitingTermination ) ) ;
2022-02-24 07:14:22 -05:00
if ( pxTCB - > xTaskRunState = = taskTASK_NOT_RUNNING )
{
( void ) uxListRemove ( & ( pxTCB - > xStateListItem ) ) ;
- - uxCurrentNumberOfTasks ;
- - uxDeletedTasksWaitingCleanUp ;
}
else
{
/* The TCB to be deleted still has not yet been switched out
* by the scheduler , so we will just exit this loop early and
* try again next time . */
taskEXIT_CRITICAL ( ) ;
break ;
}
}
}
taskEXIT_CRITICAL ( ) ;
2024-01-05 04:14:26 -05:00
if ( pxTCB ! = NULL )
{
prvDeleteTCB ( pxTCB ) ;
}
2022-02-24 07:14:22 -05:00
}
2024-01-05 04:14:26 -05:00
# endif /* #if( configNUMBER_OF_CORES == 1 ) */
2022-02-24 07:14:22 -05:00
}
2024-01-05 04:14:26 -05:00
}
2022-02-24 07:14:22 -05:00
# endif /* INCLUDE_vTaskDelete */
}
/*-----------------------------------------------------------*/
# if ( configUSE_TRACE_FACILITY == 1 )
void vTaskGetInfo ( TaskHandle_t xTask ,
TaskStatus_t * pxTaskStatus ,
BaseType_t xGetFreeStackSpace ,
eTaskState eState )
{
TCB_t * pxTCB ;
2024-01-05 04:14:26 -05:00
traceENTER_vTaskGetInfo ( xTask , pxTaskStatus , xGetFreeStackSpace , eState ) ;
2022-02-24 07:14:22 -05:00
/* xTask is NULL then get the state of the calling task. */
pxTCB = prvGetTCBFromHandle ( xTask ) ;
2024-01-05 04:14:26 -05:00
pxTaskStatus - > xHandle = pxTCB ;
2022-02-24 07:14:22 -05:00
pxTaskStatus - > pcTaskName = ( const char * ) & ( pxTCB - > pcTaskName [ 0 ] ) ;
pxTaskStatus - > uxCurrentPriority = pxTCB - > uxPriority ;
pxTaskStatus - > pxStackBase = pxTCB - > pxStack ;
2024-01-05 04:14:26 -05:00
# if ( ( portSTACK_GROWTH > 0 ) || ( configRECORD_STACK_HIGH_ADDRESS == 1 ) )
pxTaskStatus - > pxTopOfStack = ( StackType_t * ) pxTCB - > pxTopOfStack ;
pxTaskStatus - > pxEndOfStack = pxTCB - > pxEndOfStack ;
# endif
2022-02-24 07:14:22 -05:00
pxTaskStatus - > xTaskNumber = pxTCB - > uxTCBNumber ;
2024-01-05 04:14:26 -05:00
# if ( ( configUSE_CORE_AFFINITY == 1 ) && ( configNUMBER_OF_CORES > 1 ) )
{
pxTaskStatus - > uxCoreAffinityMask = pxTCB - > uxCoreAffinityMask ;
}
2022-11-02 10:00:47 -04:00
# endif
2022-02-24 07:14:22 -05:00
# if ( configUSE_MUTEXES == 1 )
2024-01-05 04:14:26 -05:00
{
pxTaskStatus - > uxBasePriority = pxTCB - > uxBasePriority ;
}
2022-02-24 07:14:22 -05:00
# else
2024-01-05 04:14:26 -05:00
{
pxTaskStatus - > uxBasePriority = 0 ;
}
2022-02-24 07:14:22 -05:00
# endif
# if ( configGENERATE_RUN_TIME_STATS == 1 )
2024-01-05 04:14:26 -05:00
{
pxTaskStatus - > ulRunTimeCounter = pxTCB - > ulRunTimeCounter ;
}
2022-02-24 07:14:22 -05:00
# else
2024-01-05 04:14:26 -05:00
{
pxTaskStatus - > ulRunTimeCounter = ( configRUN_TIME_COUNTER_TYPE ) 0 ;
}
2022-02-24 07:14:22 -05:00
# endif
/* Obtaining the task state is a little fiddly, so is only done if the
* value of eState passed into this function is eInvalid - otherwise the
* state is just set to whatever is passed in . */
if ( eState ! = eInvalid )
{
2024-01-05 04:14:26 -05:00
if ( taskTASK_IS_RUNNING ( pxTCB ) = = pdTRUE )
2022-02-24 07:14:22 -05:00
{
pxTaskStatus - > eCurrentState = eRunning ;
}
else
{
pxTaskStatus - > eCurrentState = eState ;
# if ( INCLUDE_vTaskSuspend == 1 )
2024-01-05 04:14:26 -05:00
{
/* If the task is in the suspended list then there is a
* chance it is actually just blocked indefinitely - so really
* it should be reported as being in the Blocked state . */
if ( eState = = eSuspended )
2022-02-24 07:14:22 -05:00
{
2024-01-05 04:14:26 -05:00
vTaskSuspendAll ( ) ;
2022-02-24 07:14:22 -05:00
{
2024-01-05 04:14:26 -05:00
if ( listLIST_ITEM_CONTAINER ( & ( pxTCB - > xEventListItem ) ) ! = NULL )
{
pxTaskStatus - > eCurrentState = eBlocked ;
}
else
2022-02-24 07:14:22 -05:00
{
2024-01-05 04:14:26 -05:00
BaseType_t x ;
/* The task does not appear on the event list item of
* and of the RTOS objects , but could still be in the
* blocked state if it is waiting on its notification
* rather than waiting on an object . If not , is
* suspended . */
for ( x = ( BaseType_t ) 0 ; x < ( BaseType_t ) configTASK_NOTIFICATION_ARRAY_ENTRIES ; x + + )
2022-02-24 07:14:22 -05:00
{
2024-01-05 04:14:26 -05:00
if ( pxTCB - > ucNotifyState [ x ] = = taskWAITING_NOTIFICATION )
{
pxTaskStatus - > eCurrentState = eBlocked ;
break ;
}
2022-02-24 07:14:22 -05:00
}
}
}
2024-01-05 04:14:26 -05:00
( void ) xTaskResumeAll ( ) ;
2022-02-24 07:14:22 -05:00
}
2024-01-05 04:14:26 -05:00
}
2022-02-24 07:14:22 -05:00
# endif /* INCLUDE_vTaskSuspend */
2024-01-05 04:14:26 -05:00
/* Tasks can be in pending ready list and other state list at the
* same time . These tasks are in ready state no matter what state
* list the task is in . */
taskENTER_CRITICAL ( ) ;
{
if ( listIS_CONTAINED_WITHIN ( & xPendingReadyList , & ( pxTCB - > xEventListItem ) ) ! = pdFALSE )
{
pxTaskStatus - > eCurrentState = eReady ;
}
}
taskEXIT_CRITICAL ( ) ;
2022-02-24 07:14:22 -05:00
}
}
else
{
pxTaskStatus - > eCurrentState = eTaskGetState ( pxTCB ) ;
}
/* Obtaining the stack space takes some time, so the xGetFreeStackSpace
* parameter is provided to allow it to be skipped . */
if ( xGetFreeStackSpace ! = pdFALSE )
{
# if ( portSTACK_GROWTH > 0 )
2024-01-05 04:14:26 -05:00
{
pxTaskStatus - > usStackHighWaterMark = prvTaskCheckFreeStackSpace ( ( uint8_t * ) pxTCB - > pxEndOfStack ) ;
}
2022-02-24 07:14:22 -05:00
# else
2024-01-05 04:14:26 -05:00
{
pxTaskStatus - > usStackHighWaterMark = prvTaskCheckFreeStackSpace ( ( uint8_t * ) pxTCB - > pxStack ) ;
}
2022-02-24 07:14:22 -05:00
# endif
}
else
{
pxTaskStatus - > usStackHighWaterMark = 0 ;
}
2024-01-05 04:14:26 -05:00
traceRETURN_vTaskGetInfo ( ) ;
2022-02-24 07:14:22 -05:00
}
# endif /* configUSE_TRACE_FACILITY */
/*-----------------------------------------------------------*/
# if ( configUSE_TRACE_FACILITY == 1 )
static UBaseType_t prvListTasksWithinSingleList ( TaskStatus_t * pxTaskStatusArray ,
List_t * pxList ,
eTaskState eState )
{
2024-01-05 04:14:26 -05:00
configLIST_VOLATILE TCB_t * pxNextTCB ;
configLIST_VOLATILE TCB_t * pxFirstTCB ;
2022-02-24 07:14:22 -05:00
UBaseType_t uxTask = 0 ;
if ( listCURRENT_LIST_LENGTH ( pxList ) > ( UBaseType_t ) 0 )
{
2024-01-05 04:14:26 -05:00
/* MISRA Ref 11.5.3 [Void pointer assignment] */
/* More details at: https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/MISRA.md#rule-115 */
/* coverity[misra_c_2012_rule_11_5_violation] */
listGET_OWNER_OF_NEXT_ENTRY ( pxFirstTCB , pxList ) ;
2022-02-24 07:14:22 -05:00
/* Populate an TaskStatus_t structure within the
* pxTaskStatusArray array for each task that is referenced from
* pxList . See the definition of TaskStatus_t in task . h for the
* meaning of each TaskStatus_t structure member . */
do
{
2024-01-05 04:14:26 -05:00
/* MISRA Ref 11.5.3 [Void pointer assignment] */
/* More details at: https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/MISRA.md#rule-115 */
/* coverity[misra_c_2012_rule_11_5_violation] */
listGET_OWNER_OF_NEXT_ENTRY ( pxNextTCB , pxList ) ;
2022-02-24 07:14:22 -05:00
vTaskGetInfo ( ( TaskHandle_t ) pxNextTCB , & ( pxTaskStatusArray [ uxTask ] ) , pdTRUE , eState ) ;
uxTask + + ;
} while ( pxNextTCB ! = pxFirstTCB ) ;
}
else
{
mtCOVERAGE_TEST_MARKER ( ) ;
}
return uxTask ;
}
# endif /* configUSE_TRACE_FACILITY */
/*-----------------------------------------------------------*/
# if ( ( configUSE_TRACE_FACILITY == 1 ) || ( INCLUDE_uxTaskGetStackHighWaterMark == 1 ) || ( INCLUDE_uxTaskGetStackHighWaterMark2 == 1 ) )
static configSTACK_DEPTH_TYPE prvTaskCheckFreeStackSpace ( const uint8_t * pucStackByte )
{
uint32_t ulCount = 0U ;
while ( * pucStackByte = = ( uint8_t ) tskSTACK_FILL_BYTE )
{
pucStackByte - = portSTACK_GROWTH ;
ulCount + + ;
}
2024-01-05 04:14:26 -05:00
ulCount / = ( uint32_t ) sizeof ( StackType_t ) ;
2022-02-24 07:14:22 -05:00
return ( configSTACK_DEPTH_TYPE ) ulCount ;
}
# 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 ;
2024-01-05 04:14:26 -05:00
traceENTER_uxTaskGetStackHighWaterMark2 ( xTask ) ;
2022-02-24 07:14:22 -05:00
/* 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
2024-01-05 04:14:26 -05:00
{
pucEndOfStack = ( uint8_t * ) pxTCB - > pxStack ;
}
2022-02-24 07:14:22 -05:00
# else
2024-01-05 04:14:26 -05:00
{
pucEndOfStack = ( uint8_t * ) pxTCB - > pxEndOfStack ;
}
2022-02-24 07:14:22 -05:00
# endif
uxReturn = prvTaskCheckFreeStackSpace ( pucEndOfStack ) ;
2024-01-05 04:14:26 -05:00
traceRETURN_uxTaskGetStackHighWaterMark2 ( uxReturn ) ;
2022-02-24 07:14:22 -05:00
return uxReturn ;
}
# endif /* INCLUDE_uxTaskGetStackHighWaterMark2 */
/*-----------------------------------------------------------*/
# if ( INCLUDE_uxTaskGetStackHighWaterMark == 1 )
UBaseType_t uxTaskGetStackHighWaterMark ( TaskHandle_t xTask )
{
TCB_t * pxTCB ;
uint8_t * pucEndOfStack ;
UBaseType_t uxReturn ;
2024-01-05 04:14:26 -05:00
traceENTER_uxTaskGetStackHighWaterMark ( xTask ) ;
2022-02-24 07:14:22 -05:00
pxTCB = prvGetTCBFromHandle ( xTask ) ;
# if portSTACK_GROWTH < 0
2024-01-05 04:14:26 -05:00
{
pucEndOfStack = ( uint8_t * ) pxTCB - > pxStack ;
}
2022-02-24 07:14:22 -05:00
# else
2024-01-05 04:14:26 -05:00
{
pucEndOfStack = ( uint8_t * ) pxTCB - > pxEndOfStack ;
}
2022-02-24 07:14:22 -05:00
# endif
uxReturn = ( UBaseType_t ) prvTaskCheckFreeStackSpace ( pucEndOfStack ) ;
2024-01-05 04:14:26 -05:00
traceRETURN_uxTaskGetStackHighWaterMark ( uxReturn ) ;
2022-02-24 07:14:22 -05:00
return uxReturn ;
}
# endif /* INCLUDE_uxTaskGetStackHighWaterMark */
/*-----------------------------------------------------------*/
# if ( INCLUDE_vTaskDelete == 1 )
static void prvDeleteTCB ( TCB_t * pxTCB )
{
/* This call is required specifically for the TriCore port. It must be
* above the vPortFree ( ) calls . The call is also used by ports / demos that
* want to allocate and clean RAM statically . */
portCLEAN_UP_TCB ( pxTCB ) ;
2024-01-05 04:14:26 -05:00
# if ( configUSE_C_RUNTIME_TLS_SUPPORT == 1 )
{
/* Free up the memory allocated for the task's TLS Block. */
configDEINIT_TLS_BLOCK ( pxTCB - > xTLSBlock ) ;
}
# endif
2022-02-24 07:14:22 -05:00
# if ( ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 0 ) && ( portUSING_MPU_WRAPPERS == 0 ) )
2024-01-05 04:14:26 -05:00
{
/* The task can only have been allocated dynamically - free both
* the stack and TCB . */
vPortFreeStack ( pxTCB - > pxStack ) ;
vPortFree ( pxTCB ) ;
}
# elif ( tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE != 0 )
{
/* The task could have been allocated statically or dynamically, so
* check what was statically allocated before trying to free the
* memory . */
if ( pxTCB - > ucStaticallyAllocated = = tskDYNAMICALLY_ALLOCATED_STACK_AND_TCB )
2022-02-24 07:14:22 -05:00
{
2024-01-05 04:14:26 -05:00
/* Both the stack and TCB were allocated dynamically, so both
* must be freed . */
2022-02-24 07:14:22 -05:00
vPortFreeStack ( pxTCB - > pxStack ) ;
vPortFree ( pxTCB ) ;
}
2024-01-05 04:14:26 -05:00
else if ( pxTCB - > ucStaticallyAllocated = = tskSTATICALLY_ALLOCATED_STACK_ONLY )
{
/* Only the stack was statically allocated, so the TCB is the
* only memory that must be freed . */
vPortFree ( pxTCB ) ;
}
else
2022-02-24 07:14:22 -05:00
{
2024-01-05 04:14:26 -05:00
/* Neither the stack nor the TCB were allocated dynamically, so
* nothing needs to be freed . */
configASSERT ( pxTCB - > ucStaticallyAllocated = = tskSTATICALLY_ALLOCATED_STACK_AND_TCB ) ;
mtCOVERAGE_TEST_MARKER ( ) ;
2022-02-24 07:14:22 -05:00
}
2024-01-05 04:14:26 -05:00
}
2022-02-24 07:14:22 -05:00
# endif /* configSUPPORT_DYNAMIC_ALLOCATION */
}
# endif /* INCLUDE_vTaskDelete */
/*-----------------------------------------------------------*/
static void prvResetNextTaskUnblockTime ( void )
{
if ( listLIST_IS_EMPTY ( pxDelayedTaskList ) ! = pdFALSE )
{
/* The new current delayed list is empty. Set xNextTaskUnblockTime to
* the maximum possible value so it is extremely unlikely that the
* if ( xTickCount > = xNextTaskUnblockTime ) test will pass until
* there is an item in the delayed list . */
xNextTaskUnblockTime = portMAX_DELAY ;
}
else
{
/* The new current delayed list is not empty, get the value of
* the item at the head of the delayed list . This is the time at
* which the task at the head of the delayed list should be removed
* from the Blocked state . */
xNextTaskUnblockTime = listGET_ITEM_VALUE_OF_HEAD_ENTRY ( pxDelayedTaskList ) ;
}
}
/*-----------------------------------------------------------*/
2024-01-05 04:14:26 -05:00
# if ( ( INCLUDE_xTaskGetCurrentTaskHandle == 1 ) || ( configUSE_MUTEXES == 1 ) ) || ( configNUMBER_OF_CORES > 1 )
2022-02-24 07:14:22 -05:00
2024-01-05 04:14:26 -05:00
# if ( configNUMBER_OF_CORES == 1 )
TaskHandle_t xTaskGetCurrentTaskHandle ( void )
{
TaskHandle_t xReturn ;
2022-02-24 07:14:22 -05:00
2024-01-05 04:14:26 -05:00
traceENTER_xTaskGetCurrentTaskHandle ( ) ;
2022-02-24 07:14:22 -05:00
2024-01-05 04:14:26 -05:00
/* A critical section is not required as this is not called from
* an interrupt and the current TCB will always be the same for any
* individual execution thread . */
xReturn = pxCurrentTCB ;
2022-02-24 07:14:22 -05:00
2024-01-05 04:14:26 -05:00
traceRETURN_xTaskGetCurrentTaskHandle ( xReturn ) ;
2022-02-24 07:14:22 -05:00
2024-01-05 04:14:26 -05:00
return xReturn ;
}
# else /* #if ( configNUMBER_OF_CORES == 1 ) */
TaskHandle_t xTaskGetCurrentTaskHandle ( void )
2022-02-24 07:14:22 -05:00
{
2024-01-05 04:14:26 -05:00
TaskHandle_t xReturn ;
UBaseType_t uxSavedInterruptStatus ;
traceENTER_xTaskGetCurrentTaskHandle ( ) ;
uxSavedInterruptStatus = portSET_INTERRUPT_MASK ( ) ;
{
xReturn = pxCurrentTCBs [ portGET_CORE_ID ( ) ] ;
}
portCLEAR_INTERRUPT_MASK ( uxSavedInterruptStatus ) ;
traceRETURN_xTaskGetCurrentTaskHandle ( xReturn ) ;
return xReturn ;
2022-02-24 07:14:22 -05:00
}
2024-02-02 10:33:27 -05:00
# endif /* #if ( configNUMBER_OF_CORES == 1 ) */
2022-02-24 07:14:22 -05:00
2024-02-02 10:33:27 -05:00
TaskHandle_t xTaskGetCurrentTaskHandleForCore ( BaseType_t xCoreID )
{
TaskHandle_t xReturn = NULL ;
2024-01-05 04:14:26 -05:00
2024-02-02 10:33:27 -05:00
traceENTER_xTaskGetCurrentTaskHandleForCore ( xCoreID ) ;
2024-01-05 04:14:26 -05:00
2024-02-02 10:33:27 -05:00
if ( taskVALID_CORE_ID ( xCoreID ) ! = pdFALSE )
{
# if ( configNUMBER_OF_CORES == 1 )
xReturn = pxCurrentTCB ;
# else /* #if ( configNUMBER_OF_CORES == 1 ) */
2024-01-05 04:14:26 -05:00
xReturn = pxCurrentTCBs [ xCoreID ] ;
2024-02-02 10:33:27 -05:00
# endif /* #if ( configNUMBER_OF_CORES == 1 ) */
}
2024-01-05 04:14:26 -05:00
2024-02-02 10:33:27 -05:00
traceRETURN_xTaskGetCurrentTaskHandleForCore ( xReturn ) ;
2024-01-05 04:14:26 -05:00
2024-02-02 10:33:27 -05:00
return xReturn ;
}
2022-02-24 07:14:22 -05:00
# endif /* ( ( INCLUDE_xTaskGetCurrentTaskHandle == 1 ) || ( configUSE_MUTEXES == 1 ) ) */
/*-----------------------------------------------------------*/
# if ( ( INCLUDE_xTaskGetSchedulerState == 1 ) || ( configUSE_TIMERS == 1 ) )
BaseType_t xTaskGetSchedulerState ( void )
{
BaseType_t xReturn ;
2024-01-05 04:14:26 -05:00
traceENTER_xTaskGetSchedulerState ( ) ;
2022-02-24 07:14:22 -05:00
if ( xSchedulerRunning = = pdFALSE )
{
xReturn = taskSCHEDULER_NOT_STARTED ;
}
else
{
2024-01-05 04:14:26 -05:00
# if ( configNUMBER_OF_CORES > 1 )
taskENTER_CRITICAL ( ) ;
# endif
2022-02-24 07:14:22 -05:00
{
2024-01-05 04:14:26 -05:00
if ( uxSchedulerSuspended = = ( UBaseType_t ) 0U )
2022-02-24 07:14:22 -05:00
{
xReturn = taskSCHEDULER_RUNNING ;
}
else
{
xReturn = taskSCHEDULER_SUSPENDED ;
}
}
2024-01-05 04:14:26 -05:00
# if ( configNUMBER_OF_CORES > 1 )
taskEXIT_CRITICAL ( ) ;
# endif
2022-02-24 07:14:22 -05:00
}
2024-01-05 04:14:26 -05:00
traceRETURN_xTaskGetSchedulerState ( xReturn ) ;
2022-02-24 07:14:22 -05:00
return xReturn ;
}
# endif /* ( ( INCLUDE_xTaskGetSchedulerState == 1 ) || ( configUSE_TIMERS == 1 ) ) */
/*-----------------------------------------------------------*/
# if ( configUSE_MUTEXES == 1 )
BaseType_t xTaskPriorityInherit ( TaskHandle_t const pxMutexHolder )
{
TCB_t * const pxMutexHolderTCB = pxMutexHolder ;
BaseType_t xReturn = pdFALSE ;
2024-01-05 04:14:26 -05:00
traceENTER_xTaskPriorityInherit ( pxMutexHolder ) ;
/* If the mutex is taken by an interrupt, the mutex holder is NULL. Priority
* inheritance is not applied in this scenario . */
2022-02-24 07:14:22 -05:00
if ( pxMutexHolder ! = NULL )
{
/* If the holder of the mutex has a priority below the priority of
* the task attempting to obtain the mutex then it will temporarily
* inherit the priority of the task attempting to obtain the mutex . */
if ( pxMutexHolderTCB - > uxPriority < pxCurrentTCB - > uxPriority )
{
/* Adjust the mutex holder state to account for its new
* priority . Only reset the event list item value if the value is
* not being used for anything else . */
2024-01-05 04:14:26 -05:00
if ( ( listGET_LIST_ITEM_VALUE ( & ( pxMutexHolderTCB - > xEventListItem ) ) & taskEVENT_LIST_ITEM_VALUE_IN_USE ) = = ( ( TickType_t ) 0UL ) )
2022-02-24 07:14:22 -05:00
{
2024-01-05 04:14:26 -05:00
listSET_LIST_ITEM_VALUE ( & ( pxMutexHolderTCB - > xEventListItem ) , ( TickType_t ) configMAX_PRIORITIES - ( TickType_t ) pxCurrentTCB - > uxPriority ) ;
2022-02-24 07:14:22 -05:00
}
else
{
mtCOVERAGE_TEST_MARKER ( ) ;
}
/* If the task being modified is in the ready state it will need
* to be moved into a new list . */
if ( listIS_CONTAINED_WITHIN ( & ( pxReadyTasksLists [ pxMutexHolderTCB - > uxPriority ] ) , & ( pxMutexHolderTCB - > xStateListItem ) ) ! = pdFALSE )
{
if ( uxListRemove ( & ( pxMutexHolderTCB - > xStateListItem ) ) = = ( UBaseType_t ) 0 )
{
/* It is known that the task is in its ready list so
* there is no need to check again and the port level
* reset macro can be called directly . */
portRESET_READY_PRIORITY ( pxMutexHolderTCB - > uxPriority , uxTopReadyPriority ) ;
}
else
{
mtCOVERAGE_TEST_MARKER ( ) ;
}
/* Inherit the priority before being moved into the new list. */
pxMutexHolderTCB - > uxPriority = pxCurrentTCB - > uxPriority ;
prvAddTaskToReadyList ( pxMutexHolderTCB ) ;
2024-01-05 04:14:26 -05:00
# if ( configNUMBER_OF_CORES > 1 )
{
/* The priority of the task is raised. Yield for this task
* if it is not running . */
if ( taskTASK_IS_RUNNING ( pxMutexHolderTCB ) ! = pdTRUE )
{
prvYieldForTask ( pxMutexHolderTCB ) ;
}
}
# endif /* if ( configNUMBER_OF_CORES > 1 ) */
2022-02-24 07:14:22 -05:00
}
else
{
/* Just inherit the priority. */
pxMutexHolderTCB - > uxPriority = pxCurrentTCB - > uxPriority ;
}
traceTASK_PRIORITY_INHERIT ( pxMutexHolderTCB , pxCurrentTCB - > uxPriority ) ;
/* Inheritance occurred. */
xReturn = pdTRUE ;
}
else
{
if ( pxMutexHolderTCB - > uxBasePriority < pxCurrentTCB - > uxPriority )
{
/* The base priority of the mutex holder is lower than the
* priority of the task attempting to take the mutex , but the
* current priority of the mutex holder is not lower than the
* priority of the task attempting to take the mutex .
* Therefore the mutex holder must have already inherited a
* priority , but inheritance would have occurred if that had
* not been the case . */
xReturn = pdTRUE ;
}
else
{
mtCOVERAGE_TEST_MARKER ( ) ;
}
}
}
else
{
mtCOVERAGE_TEST_MARKER ( ) ;
}
2024-01-05 04:14:26 -05:00
traceRETURN_xTaskPriorityInherit ( xReturn ) ;
2022-02-24 07:14:22 -05:00
return xReturn ;
}
# endif /* configUSE_MUTEXES */
/*-----------------------------------------------------------*/
# if ( configUSE_MUTEXES == 1 )
BaseType_t xTaskPriorityDisinherit ( TaskHandle_t const pxMutexHolder )
{
TCB_t * const pxTCB = pxMutexHolder ;
BaseType_t xReturn = pdFALSE ;
2024-01-05 04:14:26 -05:00
traceENTER_xTaskPriorityDisinherit ( pxMutexHolder ) ;
2022-02-24 07:14:22 -05:00
if ( pxMutexHolder ! = NULL )
{
/* A task can only have an inherited priority if it holds the mutex.
* If the mutex is held by a task then it cannot be given from an
* interrupt , and if a mutex is given by the holding task then it must
* be the running state task . */
configASSERT ( pxTCB = = pxCurrentTCB ) ;
configASSERT ( pxTCB - > uxMutexesHeld ) ;
( pxTCB - > uxMutexesHeld ) - - ;
/* Has the holder of the mutex inherited the priority of another
* task ? */
if ( pxTCB - > uxPriority ! = pxTCB - > uxBasePriority )
{
/* Only disinherit if no other mutexes are held. */
if ( pxTCB - > uxMutexesHeld = = ( UBaseType_t ) 0 )
{
/* A task can only have an inherited priority if it holds
* the mutex . If the mutex is held by a task then it cannot be
* given from an interrupt , and if a mutex is given by the
* holding task then it must be the running state task . Remove
* the holding task from the ready list . */
if ( uxListRemove ( & ( pxTCB - > xStateListItem ) ) = = ( UBaseType_t ) 0 )
{
portRESET_READY_PRIORITY ( pxTCB - > uxPriority , uxTopReadyPriority ) ;
}
else
{
mtCOVERAGE_TEST_MARKER ( ) ;
}
/* Disinherit the priority before adding the task into the
* new ready list . */
traceTASK_PRIORITY_DISINHERIT ( pxTCB , pxTCB - > uxBasePriority ) ;
pxTCB - > uxPriority = pxTCB - > uxBasePriority ;
/* Reset the event list item value. It cannot be in use for
* any other purpose if this task is running , and it must be
* running to give back the mutex . */
2024-01-05 04:14:26 -05:00
listSET_LIST_ITEM_VALUE ( & ( pxTCB - > xEventListItem ) , ( TickType_t ) configMAX_PRIORITIES - ( TickType_t ) pxTCB - > uxPriority ) ;
2022-02-24 07:14:22 -05:00
prvAddTaskToReadyList ( pxTCB ) ;
2024-01-05 04:14:26 -05:00
# if ( configNUMBER_OF_CORES > 1 )
{
/* The priority of the task is dropped. Yield the core on
* which the task is running . */
if ( taskTASK_IS_RUNNING ( pxTCB ) = = pdTRUE )
{
prvYieldCore ( pxTCB - > xTaskRunState ) ;
}
}
# endif /* if ( configNUMBER_OF_CORES > 1 ) */
2022-02-24 07:14:22 -05:00
/* Return true to indicate that a context switch is required.
* This is only actually required in the corner case whereby
* multiple mutexes were held and the mutexes were given back
* in an order different to that in which they were taken .
* If a context switch did not occur when the first mutex was
* returned , even if a task was waiting on it , then a context
* switch should occur when the last mutex is returned whether
* a task is waiting on it or not . */
xReturn = pdTRUE ;
}
else
{
mtCOVERAGE_TEST_MARKER ( ) ;
}
}
else
{
mtCOVERAGE_TEST_MARKER ( ) ;
}
}
else
{
mtCOVERAGE_TEST_MARKER ( ) ;
}
2024-01-05 04:14:26 -05:00
traceRETURN_xTaskPriorityDisinherit ( xReturn ) ;
2022-02-24 07:14:22 -05:00
return xReturn ;
}
# endif /* configUSE_MUTEXES */
/*-----------------------------------------------------------*/
# if ( configUSE_MUTEXES == 1 )
void vTaskPriorityDisinheritAfterTimeout ( TaskHandle_t const pxMutexHolder ,
UBaseType_t uxHighestPriorityWaitingTask )
{
TCB_t * const pxTCB = pxMutexHolder ;
UBaseType_t uxPriorityUsedOnEntry , uxPriorityToUse ;
const UBaseType_t uxOnlyOneMutexHeld = ( UBaseType_t ) 1 ;
2024-01-05 04:14:26 -05:00
traceENTER_vTaskPriorityDisinheritAfterTimeout ( pxMutexHolder , uxHighestPriorityWaitingTask ) ;
2022-02-24 07:14:22 -05:00
if ( pxMutexHolder ! = NULL )
{
/* If pxMutexHolder is not NULL then the holder must hold at least
* one mutex . */
configASSERT ( pxTCB - > uxMutexesHeld ) ;
/* Determine the priority to which the priority of the task that
* holds the mutex should be set . This will be the greater of the
* holding task ' s base priority and the priority of the highest
* priority task that is waiting to obtain the mutex . */
if ( pxTCB - > uxBasePriority < uxHighestPriorityWaitingTask )
{
uxPriorityToUse = uxHighestPriorityWaitingTask ;
}
else
{
uxPriorityToUse = pxTCB - > uxBasePriority ;
}
/* Does the priority need to change? */
if ( pxTCB - > uxPriority ! = uxPriorityToUse )
{
/* Only disinherit if no other mutexes are held. This is a
* simplification in the priority inheritance implementation . If
* the task that holds the mutex is also holding other mutexes then
* the other mutexes may have caused the priority inheritance . */
if ( pxTCB - > uxMutexesHeld = = uxOnlyOneMutexHeld )
{
/* If a task has timed out because it already holds the
* mutex it was trying to obtain then it cannot of inherited
* its own priority . */
configASSERT ( pxTCB ! = pxCurrentTCB ) ;
/* Disinherit the priority, remembering the previous
* priority to facilitate determining the subject task ' s
* state . */
traceTASK_PRIORITY_DISINHERIT ( pxTCB , uxPriorityToUse ) ;
uxPriorityUsedOnEntry = pxTCB - > uxPriority ;
pxTCB - > uxPriority = uxPriorityToUse ;
/* Only reset the event list item value if the value is not
* being used for anything else . */
2024-01-05 04:14:26 -05:00
if ( ( listGET_LIST_ITEM_VALUE ( & ( pxTCB - > xEventListItem ) ) & taskEVENT_LIST_ITEM_VALUE_IN_USE ) = = ( ( TickType_t ) 0UL ) )
2022-02-24 07:14:22 -05:00
{
2024-01-05 04:14:26 -05:00
listSET_LIST_ITEM_VALUE ( & ( pxTCB - > xEventListItem ) , ( TickType_t ) configMAX_PRIORITIES - ( TickType_t ) uxPriorityToUse ) ;
2022-02-24 07:14:22 -05:00
}
else
{
mtCOVERAGE_TEST_MARKER ( ) ;
}
/* If the running task is not the task that holds the mutex
* then the task that holds the mutex could be in either the
* Ready , Blocked or Suspended states . Only remove the task
* from its current state list if it is in the Ready state as
* the task ' s priority is going to change and there is one
* Ready list per priority . */
if ( listIS_CONTAINED_WITHIN ( & ( pxReadyTasksLists [ uxPriorityUsedOnEntry ] ) , & ( pxTCB - > xStateListItem ) ) ! = pdFALSE )
{
if ( uxListRemove ( & ( pxTCB - > xStateListItem ) ) = = ( UBaseType_t ) 0 )
{
/* It is known that the task is in its ready list so
* there is no need to check again and the port level
* reset macro can be called directly . */
portRESET_READY_PRIORITY ( pxTCB - > uxPriority , uxTopReadyPriority ) ;
}
else
{
mtCOVERAGE_TEST_MARKER ( ) ;
}
prvAddTaskToReadyList ( pxTCB ) ;
2024-01-05 04:14:26 -05:00
# if ( configNUMBER_OF_CORES > 1 )
{
/* The priority of the task is dropped. Yield the core on
* which the task is running . */
if ( taskTASK_IS_RUNNING ( pxTCB ) = = pdTRUE )
{
prvYieldCore ( pxTCB - > xTaskRunState ) ;
}
}
# endif /* if ( configNUMBER_OF_CORES > 1 ) */
2022-02-24 07:14:22 -05:00
}
else
{
mtCOVERAGE_TEST_MARKER ( ) ;
}
}
else
{
mtCOVERAGE_TEST_MARKER ( ) ;
}
}
else
{
mtCOVERAGE_TEST_MARKER ( ) ;
}
}
else
{
mtCOVERAGE_TEST_MARKER ( ) ;
}
2024-01-05 04:14:26 -05:00
traceRETURN_vTaskPriorityDisinheritAfterTimeout ( ) ;
2022-02-24 07:14:22 -05:00
}
# endif /* configUSE_MUTEXES */
/*-----------------------------------------------------------*/
2024-01-05 04:14:26 -05:00
# if ( configNUMBER_OF_CORES > 1 )
/* If not in a critical section then yield immediately.
* Otherwise set xYieldPendings to true to wait to
2022-02-24 07:14:22 -05:00
* yield until exiting the critical section .
*/
2024-01-05 04:14:26 -05:00
void vTaskYieldWithinAPI ( void )
2022-02-24 07:14:22 -05:00
{
2024-01-05 04:14:26 -05:00
traceENTER_vTaskYieldWithinAPI ( ) ;
if ( portGET_CRITICAL_NESTING_COUNT ( ) = = 0U )
{
portYIELD ( ) ;
}
else
{
xYieldPendings [ portGET_CORE_ID ( ) ] = pdTRUE ;
}
traceRETURN_vTaskYieldWithinAPI ( ) ;
2022-02-24 07:14:22 -05:00
}
2024-01-05 04:14:26 -05:00
# endif /* #if ( configNUMBER_OF_CORES > 1 ) */
/*-----------------------------------------------------------*/
# if ( ( portCRITICAL_NESTING_IN_TCB == 1 ) && ( configNUMBER_OF_CORES == 1 ) )
void vTaskEnterCritical ( void )
2022-02-24 07:14:22 -05:00
{
2024-01-05 04:14:26 -05:00
traceENTER_vTaskEnterCritical ( ) ;
portDISABLE_INTERRUPTS ( ) ;
if ( xSchedulerRunning ! = pdFALSE )
{
( pxCurrentTCB - > uxCriticalNesting ) + + ;
/* This is not the interrupt safe version of the enter critical
* function so assert ( ) if it is being called from an interrupt
* context . Only API functions that end in " FromISR " can be used in an
* interrupt . Only assert if the critical nesting count is 1 to
* protect against recursive calls if the assert function also uses a
* critical section . */
if ( pxCurrentTCB - > uxCriticalNesting = = 1U )
{
portASSERT_IF_IN_ISR ( ) ;
}
}
else
{
mtCOVERAGE_TEST_MARKER ( ) ;
}
traceRETURN_vTaskEnterCritical ( ) ;
2022-02-24 07:14:22 -05:00
}
2024-01-05 04:14:26 -05:00
# endif /* #if ( ( portCRITICAL_NESTING_IN_TCB == 1 ) && ( configNUMBER_OF_CORES == 1 ) ) */
2022-02-24 07:14:22 -05:00
/*-----------------------------------------------------------*/
2024-01-05 04:14:26 -05:00
# if ( configNUMBER_OF_CORES > 1 )
2022-02-24 07:14:22 -05:00
void vTaskEnterCritical ( void )
{
2024-01-05 04:14:26 -05:00
traceENTER_vTaskEnterCritical ( ) ;
2022-02-24 07:14:22 -05:00
portDISABLE_INTERRUPTS ( ) ;
if ( xSchedulerRunning ! = pdFALSE )
{
2024-01-05 04:14:26 -05:00
if ( portGET_CRITICAL_NESTING_COUNT ( ) = = 0U )
{
portGET_TASK_LOCK ( ) ;
portGET_ISR_LOCK ( ) ;
}
portINCREMENT_CRITICAL_NESTING_COUNT ( ) ;
/* This is not the interrupt safe version of the enter critical
* function so assert ( ) if it is being called from an interrupt
* context . Only API functions that end in " FromISR " can be used in an
* interrupt . Only assert if the critical nesting count is 1 to
* protect against recursive calls if the assert function also uses a
* critical section . */
if ( portGET_CRITICAL_NESTING_COUNT ( ) = = 1U )
2022-02-24 07:14:22 -05:00
{
2024-01-05 04:14:26 -05:00
portASSERT_IF_IN_ISR ( ) ;
if ( uxSchedulerSuspended = = 0U )
2022-02-24 07:14:22 -05:00
{
2024-01-05 04:14:26 -05:00
/* The only time there would be a problem is if this is called
* before a context switch and vTaskExitCritical ( ) is called
* after pxCurrentTCB changes . Therefore this should not be
* used within vTaskSwitchContext ( ) . */
prvCheckForRunStateChange ( ) ;
2022-02-24 07:14:22 -05:00
}
}
2024-01-05 04:14:26 -05:00
}
else
{
mtCOVERAGE_TEST_MARKER ( ) ;
}
2022-02-24 07:14:22 -05:00
2024-01-05 04:14:26 -05:00
traceRETURN_vTaskEnterCritical ( ) ;
}
# endif /* #if ( configNUMBER_OF_CORES > 1 ) */
/*-----------------------------------------------------------*/
# if ( configNUMBER_OF_CORES > 1 )
UBaseType_t vTaskEnterCriticalFromISR ( void )
{
UBaseType_t uxSavedInterruptStatus = 0 ;
2022-02-24 07:14:22 -05:00
2024-01-05 04:14:26 -05:00
traceENTER_vTaskEnterCriticalFromISR ( ) ;
2022-02-24 07:14:22 -05:00
2024-01-05 04:14:26 -05:00
if ( xSchedulerRunning ! = pdFALSE )
{
uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR ( ) ;
if ( portGET_CRITICAL_NESTING_COUNT ( ) = = 0U )
2022-02-24 07:14:22 -05:00
{
2024-01-05 04:14:26 -05:00
portGET_ISR_LOCK ( ) ;
2022-02-24 07:14:22 -05:00
}
2024-01-05 04:14:26 -05:00
portINCREMENT_CRITICAL_NESTING_COUNT ( ) ;
2022-02-24 07:14:22 -05:00
}
else
{
mtCOVERAGE_TEST_MARKER ( ) ;
}
2024-01-05 04:14:26 -05:00
traceRETURN_vTaskEnterCriticalFromISR ( uxSavedInterruptStatus ) ;
return uxSavedInterruptStatus ;
2022-02-24 07:14:22 -05:00
}
2024-01-05 04:14:26 -05:00
# endif /* #if ( configNUMBER_OF_CORES > 1 ) */
2022-02-24 07:14:22 -05:00
/*-----------------------------------------------------------*/
2024-01-05 04:14:26 -05:00
# if ( ( portCRITICAL_NESTING_IN_TCB == 1 ) && ( configNUMBER_OF_CORES == 1 ) )
2022-02-24 07:14:22 -05:00
void vTaskExitCritical ( void )
{
2024-01-05 04:14:26 -05:00
traceENTER_vTaskExitCritical ( ) ;
2022-02-24 07:14:22 -05:00
if ( xSchedulerRunning ! = pdFALSE )
{
/* If pxCurrentTCB->uxCriticalNesting is zero then this function
* does not match a previous call to vTaskEnterCritical ( ) . */
configASSERT ( pxCurrentTCB - > uxCriticalNesting > 0U ) ;
2024-01-05 04:14:26 -05:00
/* This function should not be called in ISR. Use vTaskExitCriticalFromISR
* to exit critical section from ISR . */
portASSERT_IF_IN_ISR ( ) ;
2022-02-24 07:14:22 -05:00
if ( pxCurrentTCB - > uxCriticalNesting > 0U )
{
( pxCurrentTCB - > uxCriticalNesting ) - - ;
if ( pxCurrentTCB - > uxCriticalNesting = = 0U )
{
2024-01-05 04:14:26 -05:00
portENABLE_INTERRUPTS ( ) ;
}
else
{
mtCOVERAGE_TEST_MARKER ( ) ;
}
}
else
{
mtCOVERAGE_TEST_MARKER ( ) ;
}
}
else
{
mtCOVERAGE_TEST_MARKER ( ) ;
}
2022-02-24 07:14:22 -05:00
2024-01-05 04:14:26 -05:00
traceRETURN_vTaskExitCritical ( ) ;
}
# endif /* #if ( ( portCRITICAL_NESTING_IN_TCB == 1 ) && ( configNUMBER_OF_CORES == 1 ) ) */
/*-----------------------------------------------------------*/
# if ( configNUMBER_OF_CORES > 1 )
void vTaskExitCritical ( void )
{
traceENTER_vTaskExitCritical ( ) ;
if ( xSchedulerRunning ! = pdFALSE )
{
/* If critical nesting count is zero then this function
* does not match a previous call to vTaskEnterCritical ( ) . */
configASSERT ( portGET_CRITICAL_NESTING_COUNT ( ) > 0U ) ;
/* This function should not be called in ISR. Use vTaskExitCriticalFromISR
* to exit critical section from ISR . */
portASSERT_IF_IN_ISR ( ) ;
if ( portGET_CRITICAL_NESTING_COUNT ( ) > 0U )
{
portDECREMENT_CRITICAL_NESTING_COUNT ( ) ;
if ( portGET_CRITICAL_NESTING_COUNT ( ) = = 0U )
{
BaseType_t xYieldCurrentTask ;
/* Get the xYieldPending stats inside the critical section. */
xYieldCurrentTask = xYieldPendings [ portGET_CORE_ID ( ) ] ;
portRELEASE_ISR_LOCK ( ) ;
portRELEASE_TASK_LOCK ( ) ;
portENABLE_INTERRUPTS ( ) ;
/* When a task yields in a critical section it just sets
* xYieldPending to true . So now that we have exited the
* critical section check if xYieldPending is true , and
* if so yield . */
if ( xYieldCurrentTask ! = pdFALSE )
2022-02-24 07:14:22 -05:00
{
2024-01-05 04:14:26 -05:00
portYIELD ( ) ;
2022-02-24 07:14:22 -05:00
}
}
else
{
mtCOVERAGE_TEST_MARKER ( ) ;
}
}
else
{
mtCOVERAGE_TEST_MARKER ( ) ;
}
}
else
{
mtCOVERAGE_TEST_MARKER ( ) ;
}
2024-01-05 04:14:26 -05:00
traceRETURN_vTaskExitCritical ( ) ;
2022-02-24 07:14:22 -05:00
}
2024-01-05 04:14:26 -05:00
# endif /* #if ( configNUMBER_OF_CORES > 1 ) */
2022-02-24 07:14:22 -05:00
/*-----------------------------------------------------------*/
2024-01-05 04:14:26 -05:00
# if ( configNUMBER_OF_CORES > 1 )
void vTaskExitCriticalFromISR ( UBaseType_t uxSavedInterruptStatus )
{
traceENTER_vTaskExitCriticalFromISR ( uxSavedInterruptStatus ) ;
if ( xSchedulerRunning ! = pdFALSE )
{
/* If critical nesting count is zero then this function
* does not match a previous call to vTaskEnterCritical ( ) . */
configASSERT ( portGET_CRITICAL_NESTING_COUNT ( ) > 0U ) ;
if ( portGET_CRITICAL_NESTING_COUNT ( ) > 0U )
{
portDECREMENT_CRITICAL_NESTING_COUNT ( ) ;
if ( portGET_CRITICAL_NESTING_COUNT ( ) = = 0U )
{
portRELEASE_ISR_LOCK ( ) ;
portCLEAR_INTERRUPT_MASK_FROM_ISR ( uxSavedInterruptStatus ) ;
}
else
{
mtCOVERAGE_TEST_MARKER ( ) ;
}
}
else
{
mtCOVERAGE_TEST_MARKER ( ) ;
}
}
else
{
mtCOVERAGE_TEST_MARKER ( ) ;
}
traceRETURN_vTaskExitCriticalFromISR ( ) ;
}
# endif /* #if ( configNUMBER_OF_CORES > 1 ) */
/*-----------------------------------------------------------*/
# if ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 )
2022-02-24 07:14:22 -05:00
static char * prvWriteNameToBuffer ( char * pcBuffer ,
const char * pcTaskName )
{
size_t x ;
/* Start by copying the entire string. */
2024-01-05 04:14:26 -05:00
( void ) strcpy ( pcBuffer , pcTaskName ) ;
2022-02-24 07:14:22 -05:00
/* Pad the end of the string with spaces to ensure columns line up when
* printed out . */
2024-01-05 04:14:26 -05:00
for ( x = strlen ( pcBuffer ) ; x < ( size_t ) ( ( size_t ) configMAX_TASK_NAME_LEN - 1U ) ; x + + )
2022-02-24 07:14:22 -05:00
{
pcBuffer [ x ] = ' ' ;
}
/* Terminate. */
pcBuffer [ x ] = ( char ) 0x00 ;
/* Return the new end of string. */
return & ( pcBuffer [ x ] ) ;
}
2024-01-05 04:14:26 -05:00
# endif /* ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 ) */
2022-02-24 07:14:22 -05:00
/*-----------------------------------------------------------*/
2024-01-05 04:14:26 -05:00
# if ( ( configUSE_TRACE_FACILITY == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 ) )
2022-02-24 07:14:22 -05:00
2024-01-05 04:14:26 -05:00
void vTaskListTasks ( char * pcWriteBuffer ,
size_t uxBufferLength )
2022-02-24 07:14:22 -05:00
{
TaskStatus_t * pxTaskStatusArray ;
2024-01-05 04:14:26 -05:00
size_t uxConsumedBufferLength = 0 ;
size_t uxCharsWrittenBySnprintf ;
int iSnprintfReturnValue ;
BaseType_t xOutputBufferFull = pdFALSE ;
2022-02-24 07:14:22 -05:00
UBaseType_t uxArraySize , x ;
char cStatus ;
2024-01-05 04:14:26 -05:00
traceENTER_vTaskListTasks ( pcWriteBuffer , uxBufferLength ) ;
2022-02-24 07:14:22 -05:00
/*
* PLEASE NOTE :
*
* This function is provided for convenience only , and is used by many
* of the demo applications . Do not consider it to be part of the
* scheduler .
*
2024-01-05 04:14:26 -05:00
* vTaskListTasks ( ) calls uxTaskGetSystemState ( ) , then formats part of the
2022-02-24 07:14:22 -05:00
* uxTaskGetSystemState ( ) output into a human readable table that
* displays task : names , states , priority , stack usage and task number .
* Stack usage specified as the number of unused StackType_t words stack can hold
* on top of stack - not the number of bytes .
*
2024-01-05 04:14:26 -05:00
* vTaskListTasks ( ) has a dependency on the snprintf ( ) C library function that
2022-02-24 07:14:22 -05:00
* might bloat the code size , use a lot of stack , and provide different
* results on different platforms . An alternative , tiny , third party ,
2024-01-05 04:14:26 -05:00
* and limited functionality implementation of snprintf ( ) is provided in
2022-02-24 07:14:22 -05:00
* many of the FreeRTOS / Demo sub - directories in a file called
* printf - stdarg . c ( note printf - stdarg . c does not provide a full
* snprintf ( ) implementation ! ) .
*
* It is recommended that production systems call uxTaskGetSystemState ( )
* directly to get access to raw stats data , rather than indirectly
2024-01-05 04:14:26 -05:00
* through a call to vTaskListTasks ( ) .
2022-02-24 07:14:22 -05:00
*/
/* Make sure the write buffer does not contain a string. */
* pcWriteBuffer = ( char ) 0x00 ;
/* Take a snapshot of the number of tasks in case it changes while this
* function is executing . */
uxArraySize = uxCurrentNumberOfTasks ;
/* Allocate an array index for each task. NOTE! if
* configSUPPORT_DYNAMIC_ALLOCATION is set to 0 then pvPortMalloc ( ) will
* equate to NULL . */
2024-01-05 04:14:26 -05:00
/* MISRA Ref 11.5.1 [Malloc memory assignment] */
/* More details at: https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/MISRA.md#rule-115 */
/* coverity[misra_c_2012_rule_11_5_violation] */
pxTaskStatusArray = pvPortMalloc ( uxCurrentNumberOfTasks * sizeof ( TaskStatus_t ) ) ;
2022-02-24 07:14:22 -05:00
if ( pxTaskStatusArray ! = NULL )
{
/* Generate the (binary) data. */
uxArraySize = uxTaskGetSystemState ( pxTaskStatusArray , uxArraySize , NULL ) ;
/* Create a human readable table from the binary data. */
for ( x = 0 ; x < uxArraySize ; x + + )
{
switch ( pxTaskStatusArray [ x ] . eCurrentState )
{
case eRunning :
cStatus = tskRUNNING_CHAR ;
break ;
case eReady :
cStatus = tskREADY_CHAR ;
break ;
case eBlocked :
cStatus = tskBLOCKED_CHAR ;
break ;
case eSuspended :
cStatus = tskSUSPENDED_CHAR ;
break ;
case eDeleted :
cStatus = tskDELETED_CHAR ;
break ;
case eInvalid : /* Fall through. */
default : /* Should not get here, but it is included
* to prevent static checking errors . */
cStatus = ( char ) 0x00 ;
break ;
}
2024-01-05 04:14:26 -05:00
/* Is there enough space in the buffer to hold task name? */
if ( ( uxConsumedBufferLength + configMAX_TASK_NAME_LEN ) < = uxBufferLength )
{
/* Write the task name to the string, padding with spaces so it
* can be printed in tabular form more easily . */
pcWriteBuffer = prvWriteNameToBuffer ( pcWriteBuffer , pxTaskStatusArray [ x ] . pcTaskName ) ;
/* Do not count the terminating null character. */
uxConsumedBufferLength = uxConsumedBufferLength + ( configMAX_TASK_NAME_LEN - 1U ) ;
/* Is there space left in the buffer? -1 is done because snprintf
* writes a terminating null character . So we are essentially
* checking if the buffer has space to write at least one non - null
* character . */
if ( uxConsumedBufferLength < ( uxBufferLength - 1U ) )
{
/* Write the rest of the string. */
# if ( ( configUSE_CORE_AFFINITY == 1 ) && ( configNUMBER_OF_CORES > 1 ) )
/* MISRA Ref 21.6.1 [snprintf for utility] */
/* More details at: https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/MISRA.md#rule-216 */
/* coverity[misra_c_2012_rule_21_6_violation] */
iSnprintfReturnValue = snprintf ( pcWriteBuffer ,
uxBufferLength - uxConsumedBufferLength ,
" \t %c \t %u \t %u \t %u \t 0x%x \r \n " ,
cStatus ,
( unsigned int ) pxTaskStatusArray [ x ] . uxCurrentPriority ,
( unsigned int ) pxTaskStatusArray [ x ] . usStackHighWaterMark ,
( unsigned int ) pxTaskStatusArray [ x ] . xTaskNumber ,
( unsigned int ) pxTaskStatusArray [ x ] . uxCoreAffinityMask ) ;
# else /* ( ( configUSE_CORE_AFFINITY == 1 ) && ( configNUMBER_OF_CORES > 1 ) ) */
/* MISRA Ref 21.6.1 [snprintf for utility] */
/* More details at: https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/MISRA.md#rule-216 */
/* coverity[misra_c_2012_rule_21_6_violation] */
iSnprintfReturnValue = snprintf ( pcWriteBuffer ,
uxBufferLength - uxConsumedBufferLength ,
" \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 ) ;
# endif /* ( ( configUSE_CORE_AFFINITY == 1 ) && ( configNUMBER_OF_CORES > 1 ) ) */
uxCharsWrittenBySnprintf = prvSnprintfReturnValueToCharsWritten ( iSnprintfReturnValue , uxBufferLength - uxConsumedBufferLength ) ;
uxConsumedBufferLength + = uxCharsWrittenBySnprintf ;
pcWriteBuffer + = uxCharsWrittenBySnprintf ;
}
else
{
xOutputBufferFull = pdTRUE ;
}
}
else
{
xOutputBufferFull = pdTRUE ;
}
2022-02-24 07:14:22 -05:00
2024-01-05 04:14:26 -05:00
if ( xOutputBufferFull = = pdTRUE )
{
break ;
}
2022-02-24 07:14:22 -05:00
}
/* Free the array again. NOTE! If configSUPPORT_DYNAMIC_ALLOCATION
* is 0 then vPortFree ( ) will be # defined to nothing . */
vPortFree ( pxTaskStatusArray ) ;
}
else
{
mtCOVERAGE_TEST_MARKER ( ) ;
}
2024-01-05 04:14:26 -05:00
traceRETURN_vTaskListTasks ( ) ;
2022-02-24 07:14:22 -05:00
}
2024-01-05 04:14:26 -05:00
# endif /* ( ( configUSE_TRACE_FACILITY == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 ) ) */
2022-02-24 07:14:22 -05:00
/*----------------------------------------------------------*/
2024-01-05 04:14:26 -05:00
# if ( ( configGENERATE_RUN_TIME_STATS == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 ) && ( configUSE_TRACE_FACILITY == 1 ) )
2022-02-24 07:14:22 -05:00
2024-01-05 04:14:26 -05:00
void vTaskGetRunTimeStatistics ( char * pcWriteBuffer ,
size_t uxBufferLength )
2022-02-24 07:14:22 -05:00
{
TaskStatus_t * pxTaskStatusArray ;
2024-01-05 04:14:26 -05:00
size_t uxConsumedBufferLength = 0 ;
size_t uxCharsWrittenBySnprintf ;
int iSnprintfReturnValue ;
BaseType_t xOutputBufferFull = pdFALSE ;
2022-02-24 07:14:22 -05:00
UBaseType_t uxArraySize , x ;
2024-01-05 04:14:26 -05:00
configRUN_TIME_COUNTER_TYPE ulTotalTime = 0 ;
configRUN_TIME_COUNTER_TYPE ulStatsAsPercentage ;
2022-02-24 07:14:22 -05:00
2024-01-05 04:14:26 -05:00
traceENTER_vTaskGetRunTimeStatistics ( pcWriteBuffer , uxBufferLength ) ;
2022-02-24 07:14:22 -05:00
/*
* PLEASE NOTE :
*
* This function is provided for convenience only , and is used by many
* of the demo applications . Do not consider it to be part of the
* scheduler .
*
2024-01-05 04:14:26 -05:00
* vTaskGetRunTimeStatistics ( ) calls uxTaskGetSystemState ( ) , then formats part
2022-02-24 07:14:22 -05:00
* of the uxTaskGetSystemState ( ) output into a human readable table that
* displays the amount of time each task has spent in the Running state
* in both absolute and percentage terms .
*
2024-01-05 04:14:26 -05:00
* vTaskGetRunTimeStatistics ( ) has a dependency on the snprintf ( ) C library
2022-02-24 07:14:22 -05:00
* function that might bloat the code size , use a lot of stack , and
* provide different results on different platforms . An alternative ,
* tiny , third party , and limited functionality implementation of
2024-01-05 04:14:26 -05:00
* snprintf ( ) is provided in many of the FreeRTOS / Demo sub - directories in
2022-02-24 07:14:22 -05:00
* a file called printf - stdarg . c ( note printf - stdarg . c does not provide
* a full snprintf ( ) implementation ! ) .
*
* It is recommended that production systems call uxTaskGetSystemState ( )
* directly to get access to raw stats data , rather than indirectly
2024-01-05 04:14:26 -05:00
* through a call to vTaskGetRunTimeStatistics ( ) .
2022-02-24 07:14:22 -05:00
*/
/* Make sure the write buffer does not contain a string. */
* pcWriteBuffer = ( char ) 0x00 ;
/* Take a snapshot of the number of tasks in case it changes while this
* function is executing . */
uxArraySize = uxCurrentNumberOfTasks ;
/* Allocate an array index for each task. NOTE! If
* configSUPPORT_DYNAMIC_ALLOCATION is set to 0 then pvPortMalloc ( ) will
* equate to NULL . */
2024-01-05 04:14:26 -05:00
/* MISRA Ref 11.5.1 [Malloc memory assignment] */
/* More details at: https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/MISRA.md#rule-115 */
/* coverity[misra_c_2012_rule_11_5_violation] */
pxTaskStatusArray = pvPortMalloc ( uxCurrentNumberOfTasks * sizeof ( TaskStatus_t ) ) ;
2022-02-24 07:14:22 -05:00
if ( pxTaskStatusArray ! = NULL )
{
/* Generate the (binary) data. */
uxArraySize = uxTaskGetSystemState ( pxTaskStatusArray , uxArraySize , & ulTotalTime ) ;
/* For percentage calculations. */
2024-01-05 04:14:26 -05:00
ulTotalTime / = ( ( configRUN_TIME_COUNTER_TYPE ) 100UL ) ;
2022-02-24 07:14:22 -05:00
/* Avoid divide by zero errors. */
if ( ulTotalTime > 0UL )
{
/* Create a human readable table from the binary data. */
for ( x = 0 ; x < uxArraySize ; x + + )
{
/* What percentage of the total run time has the task used?
* This will always be rounded down to the nearest integer .
2024-01-05 04:14:26 -05:00
* ulTotalRunTime has already been divided by 100. */
2022-02-24 07:14:22 -05:00
ulStatsAsPercentage = pxTaskStatusArray [ x ] . ulRunTimeCounter / ulTotalTime ;
2024-01-05 04:14:26 -05:00
/* Is there enough space in the buffer to hold task name? */
if ( ( uxConsumedBufferLength + configMAX_TASK_NAME_LEN ) < = uxBufferLength )
2022-02-24 07:14:22 -05:00
{
2024-01-05 04:14:26 -05:00
/* Write the task name to the string, padding with
* spaces so it can be printed in tabular form more
* easily . */
pcWriteBuffer = prvWriteNameToBuffer ( pcWriteBuffer , pxTaskStatusArray [ x ] . pcTaskName ) ;
/* Do not count the terminating null character. */
uxConsumedBufferLength = uxConsumedBufferLength + ( configMAX_TASK_NAME_LEN - 1U ) ;
/* Is there space left in the buffer? -1 is done because snprintf
* writes a terminating null character . So we are essentially
* checking if the buffer has space to write at least one non - null
* character . */
if ( uxConsumedBufferLength < ( uxBufferLength - 1U ) )
{
if ( ulStatsAsPercentage > 0UL )
2022-02-24 07:14:22 -05:00
{
2024-01-05 04:14:26 -05:00
# ifdef portLU_PRINTF_SPECIFIER_REQUIRED
{
/* MISRA Ref 21.6.1 [snprintf for utility] */
/* More details at: https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/MISRA.md#rule-216 */
/* coverity[misra_c_2012_rule_21_6_violation] */
iSnprintfReturnValue = snprintf ( pcWriteBuffer ,
uxBufferLength - uxConsumedBufferLength ,
" \t %lu \t \t %lu%% \r \n " ,
pxTaskStatusArray [ x ] . ulRunTimeCounter ,
ulStatsAsPercentage ) ;
}
# else /* ifdef portLU_PRINTF_SPECIFIER_REQUIRED */
{
/* sizeof( int ) == sizeof( long ) so a smaller
* printf ( ) library can be used . */
/* MISRA Ref 21.6.1 [snprintf for utility] */
/* More details at: https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/MISRA.md#rule-216 */
/* coverity[misra_c_2012_rule_21_6_violation] */
iSnprintfReturnValue = snprintf ( pcWriteBuffer ,
uxBufferLength - uxConsumedBufferLength ,
" \t %u \t \t %u%% \r \n " ,
( unsigned int ) pxTaskStatusArray [ x ] . ulRunTimeCounter ,
( unsigned int ) ulStatsAsPercentage ) ;
}
# endif /* ifdef portLU_PRINTF_SPECIFIER_REQUIRED */
2022-02-24 07:14:22 -05:00
}
2024-01-05 04:14:26 -05:00
else
2022-02-24 07:14:22 -05:00
{
2024-01-05 04:14:26 -05:00
/* If the percentage is zero here then the task has
* consumed less than 1 % of the total run time . */
# ifdef portLU_PRINTF_SPECIFIER_REQUIRED
{
/* MISRA Ref 21.6.1 [snprintf for utility] */
/* More details at: https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/MISRA.md#rule-216 */
/* coverity[misra_c_2012_rule_21_6_violation] */
iSnprintfReturnValue = snprintf ( pcWriteBuffer ,
uxBufferLength - uxConsumedBufferLength ,
" \t %lu \t \t <1%% \r \n " ,
pxTaskStatusArray [ x ] . ulRunTimeCounter ) ;
}
# else
{
/* sizeof( int ) == sizeof( long ) so a smaller
* printf ( ) library can be used . */
/* MISRA Ref 21.6.1 [snprintf for utility] */
/* More details at: https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/MISRA.md#rule-216 */
/* coverity[misra_c_2012_rule_21_6_violation] */
iSnprintfReturnValue = snprintf ( pcWriteBuffer ,
uxBufferLength - uxConsumedBufferLength ,
" \t %u \t \t <1%% \r \n " ,
( unsigned int ) pxTaskStatusArray [ x ] . ulRunTimeCounter ) ;
}
# endif /* ifdef portLU_PRINTF_SPECIFIER_REQUIRED */
2022-02-24 07:14:22 -05:00
}
2024-01-05 04:14:26 -05:00
uxCharsWrittenBySnprintf = prvSnprintfReturnValueToCharsWritten ( iSnprintfReturnValue , uxBufferLength - uxConsumedBufferLength ) ;
uxConsumedBufferLength + = uxCharsWrittenBySnprintf ;
pcWriteBuffer + = uxCharsWrittenBySnprintf ;
}
else
{
xOutputBufferFull = pdTRUE ;
}
2022-02-24 07:14:22 -05:00
}
else
{
2024-01-05 04:14:26 -05:00
xOutputBufferFull = pdTRUE ;
2022-02-24 07:14:22 -05:00
}
2024-01-05 04:14:26 -05:00
if ( xOutputBufferFull = = pdTRUE )
{
break ;
}
2022-02-24 07:14:22 -05:00
}
}
else
{
mtCOVERAGE_TEST_MARKER ( ) ;
}
/* Free the array again. NOTE! If configSUPPORT_DYNAMIC_ALLOCATION
* is 0 then vPortFree ( ) will be # defined to nothing . */
vPortFree ( pxTaskStatusArray ) ;
}
else
{
mtCOVERAGE_TEST_MARKER ( ) ;
}
2024-01-05 04:14:26 -05:00
traceRETURN_vTaskGetRunTimeStatistics ( ) ;
2022-02-24 07:14:22 -05:00
}
2024-01-05 04:14:26 -05:00
# endif /* ( ( configGENERATE_RUN_TIME_STATS == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 ) ) */
2022-02-24 07:14:22 -05:00
/*-----------------------------------------------------------*/
TickType_t uxTaskResetEventItemValue ( void )
{
TickType_t uxReturn ;
2024-01-05 04:14:26 -05:00
traceENTER_uxTaskResetEventItemValue ( ) ;
2022-02-24 07:14:22 -05:00
uxReturn = listGET_LIST_ITEM_VALUE ( & ( pxCurrentTCB - > xEventListItem ) ) ;
/* Reset the event list item to its normal value - so it can be used with
* queues and semaphores . */
2024-01-05 04:14:26 -05:00
listSET_LIST_ITEM_VALUE ( & ( pxCurrentTCB - > xEventListItem ) , ( ( TickType_t ) configMAX_PRIORITIES - ( TickType_t ) pxCurrentTCB - > uxPriority ) ) ;
traceRETURN_uxTaskResetEventItemValue ( uxReturn ) ;
2022-02-24 07:14:22 -05:00
return uxReturn ;
}
/*-----------------------------------------------------------*/
# if ( configUSE_MUTEXES == 1 )
2024-01-05 04:14:26 -05:00
TaskHandle_t pvTaskIncrementMutexHeldCount ( void )
{
TCB_t * pxTCB ;
traceENTER_pvTaskIncrementMutexHeldCount ( ) ;
pxTCB = pxCurrentTCB ;
2022-02-24 07:14:22 -05:00
/* If xSemaphoreCreateMutex() is called before any tasks have been created
* then pxCurrentTCB will be NULL . */
2024-01-05 04:14:26 -05:00
if ( pxTCB ! = NULL )
2022-02-24 07:14:22 -05:00
{
2024-01-05 04:14:26 -05:00
( pxTCB - > uxMutexesHeld ) + + ;
2022-02-24 07:14:22 -05:00
}
2024-01-05 04:14:26 -05:00
traceRETURN_pvTaskIncrementMutexHeldCount ( pxTCB ) ;
return pxTCB ;
2022-02-24 07:14:22 -05:00
}
# endif /* configUSE_MUTEXES */
/*-----------------------------------------------------------*/
# if ( configUSE_TASK_NOTIFICATIONS == 1 )
2024-01-05 04:14:26 -05:00
uint32_t ulTaskGenericNotifyTake ( UBaseType_t uxIndexToWaitOn ,
2022-02-24 07:14:22 -05:00
BaseType_t xClearCountOnExit ,
TickType_t xTicksToWait )
{
uint32_t ulReturn ;
2024-01-05 04:14:26 -05:00
BaseType_t xAlreadyYielded ;
traceENTER_ulTaskGenericNotifyTake ( uxIndexToWaitOn , xClearCountOnExit , xTicksToWait ) ;
2022-02-24 07:14:22 -05:00
2024-01-05 04:14:26 -05:00
configASSERT ( uxIndexToWaitOn < configTASK_NOTIFICATION_ARRAY_ENTRIES ) ;
2022-02-24 07:14:22 -05:00
taskENTER_CRITICAL ( ) ;
2024-01-05 04:14:26 -05:00
/* Only block if the notification count is not already non-zero. */
if ( pxCurrentTCB - > ulNotifiedValue [ uxIndexToWaitOn ] = = 0UL )
2022-02-24 07:14:22 -05:00
{
2024-01-05 04:14:26 -05:00
/* Mark this task as waiting for a notification. */
pxCurrentTCB - > ucNotifyState [ uxIndexToWaitOn ] = taskWAITING_NOTIFICATION ;
if ( xTicksToWait > ( TickType_t ) 0 )
2022-02-24 07:14:22 -05:00
{
2024-01-05 04:14:26 -05:00
traceTASK_NOTIFY_TAKE_BLOCK ( uxIndexToWaitOn ) ;
2022-02-24 07:14:22 -05:00
2024-01-05 04:14:26 -05:00
/* We MUST suspend the scheduler before exiting the critical
* section ( i . e . before enabling interrupts ) .
*
* If we do not do so , a notification sent from an ISR , which
* happens after exiting the critical section and before
* suspending the scheduler , will get lost . The sequence of
* events will be :
* 1. Exit critical section .
* 2. Interrupt - ISR calls xTaskNotifyFromISR which adds the
* task to the Ready list .
* 3. Suspend scheduler .
* 4. prvAddCurrentTaskToDelayedList moves the task to the
* delayed or suspended list .
* 5. Resume scheduler does not touch the task ( because it is
* not on the pendingReady list ) , effectively losing the
* notification from the ISR .
*
* The same does not happen when we suspend the scheduler before
* exiting the critical section . The sequence of events in this
* case will be :
* 1. Suspend scheduler .
* 2. Exit critical section .
* 3. Interrupt - ISR calls xTaskNotifyFromISR which adds the
* task to the pendingReady list as the scheduler is
* suspended .
* 4. prvAddCurrentTaskToDelayedList adds the task to delayed or
* suspended list . Note that this operation does not nullify
* the add to pendingReady list done in the above step because
* a different list item , namely xEventListItem , is used for
* adding the task to the pendingReady list . In other words ,
* the task still remains on the pendingReady list .
* 5. Resume scheduler moves the task from pendingReady list to
* the Ready list .
*/
vTaskSuspendAll ( ) ;
2022-02-24 07:14:22 -05:00
{
2024-01-05 04:14:26 -05:00
taskEXIT_CRITICAL ( ) ;
2022-02-24 07:14:22 -05:00
prvAddCurrentTaskToDelayedList ( xTicksToWait , pdTRUE ) ;
2024-01-05 04:14:26 -05:00
}
xAlreadyYielded = xTaskResumeAll ( ) ;
2022-02-24 07:14:22 -05:00
2024-01-05 04:14:26 -05:00
if ( xAlreadyYielded = = pdFALSE )
{
taskYIELD_WITHIN_API ( ) ;
2022-02-24 07:14:22 -05:00
}
else
{
mtCOVERAGE_TEST_MARKER ( ) ;
}
}
else
{
2024-01-05 04:14:26 -05:00
taskEXIT_CRITICAL ( ) ;
2022-02-24 07:14:22 -05:00
}
}
2024-01-05 04:14:26 -05:00
else
{
taskEXIT_CRITICAL ( ) ;
}
2022-02-24 07:14:22 -05:00
taskENTER_CRITICAL ( ) ;
{
2024-01-05 04:14:26 -05:00
traceTASK_NOTIFY_TAKE ( uxIndexToWaitOn ) ;
ulReturn = pxCurrentTCB - > ulNotifiedValue [ uxIndexToWaitOn ] ;
2022-02-24 07:14:22 -05:00
if ( ulReturn ! = 0UL )
{
if ( xClearCountOnExit ! = pdFALSE )
{
2024-01-05 04:14:26 -05:00
pxCurrentTCB - > ulNotifiedValue [ uxIndexToWaitOn ] = ( uint32_t ) 0UL ;
2022-02-24 07:14:22 -05:00
}
else
{
2024-01-05 04:14:26 -05:00
pxCurrentTCB - > ulNotifiedValue [ uxIndexToWaitOn ] = ulReturn - ( uint32_t ) 1 ;
2022-02-24 07:14:22 -05:00
}
}
else
{
mtCOVERAGE_TEST_MARKER ( ) ;
}
2024-01-05 04:14:26 -05:00
pxCurrentTCB - > ucNotifyState [ uxIndexToWaitOn ] = taskNOT_WAITING_NOTIFICATION ;
2022-02-24 07:14:22 -05:00
}
taskEXIT_CRITICAL ( ) ;
2024-01-05 04:14:26 -05:00
traceRETURN_ulTaskGenericNotifyTake ( ulReturn ) ;
2022-02-24 07:14:22 -05:00
return ulReturn ;
}
# endif /* configUSE_TASK_NOTIFICATIONS */
/*-----------------------------------------------------------*/
# if ( configUSE_TASK_NOTIFICATIONS == 1 )
2024-01-05 04:14:26 -05:00
BaseType_t xTaskGenericNotifyWait ( UBaseType_t uxIndexToWaitOn ,
2022-02-24 07:14:22 -05:00
uint32_t ulBitsToClearOnEntry ,
uint32_t ulBitsToClearOnExit ,
uint32_t * pulNotificationValue ,
TickType_t xTicksToWait )
{
2024-01-05 04:14:26 -05:00
BaseType_t xReturn , xAlreadyYielded ;
2022-02-24 07:14:22 -05:00
2024-01-05 04:14:26 -05:00
traceENTER_xTaskGenericNotifyWait ( uxIndexToWaitOn , ulBitsToClearOnEntry , ulBitsToClearOnExit , pulNotificationValue , xTicksToWait ) ;
configASSERT ( uxIndexToWaitOn < configTASK_NOTIFICATION_ARRAY_ENTRIES ) ;
2022-02-24 07:14:22 -05:00
taskENTER_CRITICAL ( ) ;
2024-01-05 04:14:26 -05:00
/* Only block if a notification is not already pending. */
if ( pxCurrentTCB - > ucNotifyState [ uxIndexToWaitOn ] ! = taskNOTIFICATION_RECEIVED )
2022-02-24 07:14:22 -05:00
{
2024-01-05 04:14:26 -05:00
/* Clear bits in the task's notification value as bits may get
* set by the notifying task or interrupt . This can be used to
* clear the value to zero . */
pxCurrentTCB - > ulNotifiedValue [ uxIndexToWaitOn ] & = ~ ulBitsToClearOnEntry ;
/* Mark this task as waiting for a notification. */
pxCurrentTCB - > ucNotifyState [ uxIndexToWaitOn ] = taskWAITING_NOTIFICATION ;
2022-02-24 07:14:22 -05:00
2024-01-05 04:14:26 -05:00
if ( xTicksToWait > ( TickType_t ) 0 )
{
traceTASK_NOTIFY_WAIT_BLOCK ( uxIndexToWaitOn ) ;
2022-02-24 07:14:22 -05:00
2024-01-05 04:14:26 -05:00
/* We MUST suspend the scheduler before exiting the critical
* section ( i . e . before enabling interrupts ) .
*
* If we do not do so , a notification sent from an ISR , which
* happens after exiting the critical section and before
* suspending the scheduler , will get lost . The sequence of
* events will be :
* 1. Exit critical section .
* 2. Interrupt - ISR calls xTaskNotifyFromISR which adds the
* task to the Ready list .
* 3. Suspend scheduler .
* 4. prvAddCurrentTaskToDelayedList moves the task to the
* delayed or suspended list .
* 5. Resume scheduler does not touch the task ( because it is
* not on the pendingReady list ) , effectively losing the
* notification from the ISR .
*
* The same does not happen when we suspend the scheduler before
* exiting the critical section . The sequence of events in this
* case will be :
* 1. Suspend scheduler .
* 2. Exit critical section .
* 3. Interrupt - ISR calls xTaskNotifyFromISR which adds the
* task to the pendingReady list as the scheduler is
* suspended .
* 4. prvAddCurrentTaskToDelayedList adds the task to delayed or
* suspended list . Note that this operation does not nullify
* the add to pendingReady list done in the above step because
* a different list item , namely xEventListItem , is used for
* adding the task to the pendingReady list . In other words ,
* the task still remains on the pendingReady list .
* 5. Resume scheduler moves the task from pendingReady list to
* the Ready list .
*/
vTaskSuspendAll ( ) ;
2022-02-24 07:14:22 -05:00
{
2024-01-05 04:14:26 -05:00
taskEXIT_CRITICAL ( ) ;
2022-02-24 07:14:22 -05:00
prvAddCurrentTaskToDelayedList ( xTicksToWait , pdTRUE ) ;
2024-01-05 04:14:26 -05:00
}
xAlreadyYielded = xTaskResumeAll ( ) ;
2022-02-24 07:14:22 -05:00
2024-01-05 04:14:26 -05:00
if ( xAlreadyYielded = = pdFALSE )
{
taskYIELD_WITHIN_API ( ) ;
2022-02-24 07:14:22 -05:00
}
else
{
mtCOVERAGE_TEST_MARKER ( ) ;
}
}
else
{
2024-01-05 04:14:26 -05:00
taskEXIT_CRITICAL ( ) ;
2022-02-24 07:14:22 -05:00
}
}
2024-01-05 04:14:26 -05:00
else
{
taskEXIT_CRITICAL ( ) ;
}
2022-02-24 07:14:22 -05:00
taskENTER_CRITICAL ( ) ;
{
2024-01-05 04:14:26 -05:00
traceTASK_NOTIFY_WAIT ( uxIndexToWaitOn ) ;
2022-02-24 07:14:22 -05:00
if ( pulNotificationValue ! = NULL )
{
/* Output the current notification value, which may or may not
* have changed . */
2024-01-05 04:14:26 -05:00
* pulNotificationValue = pxCurrentTCB - > ulNotifiedValue [ uxIndexToWaitOn ] ;
2022-02-24 07:14:22 -05:00
}
/* If ucNotifyValue is set then either the task never entered the
* blocked state ( because a notification was already pending ) or the
* task unblocked because of a notification . Otherwise the task
* unblocked because of a timeout . */
2024-01-05 04:14:26 -05:00
if ( pxCurrentTCB - > ucNotifyState [ uxIndexToWaitOn ] ! = taskNOTIFICATION_RECEIVED )
2022-02-24 07:14:22 -05:00
{
/* A notification was not received. */
xReturn = pdFALSE ;
}
else
{
/* A notification was already pending or a notification was
* received while the task was waiting . */
2024-01-05 04:14:26 -05:00
pxCurrentTCB - > ulNotifiedValue [ uxIndexToWaitOn ] & = ~ ulBitsToClearOnExit ;
2022-02-24 07:14:22 -05:00
xReturn = pdTRUE ;
}
2024-01-05 04:14:26 -05:00
pxCurrentTCB - > ucNotifyState [ uxIndexToWaitOn ] = taskNOT_WAITING_NOTIFICATION ;
2022-02-24 07:14:22 -05:00
}
taskEXIT_CRITICAL ( ) ;
2024-01-05 04:14:26 -05:00
traceRETURN_xTaskGenericNotifyWait ( xReturn ) ;
2022-02-24 07:14:22 -05:00
return xReturn ;
}
# endif /* configUSE_TASK_NOTIFICATIONS */
/*-----------------------------------------------------------*/
# if ( configUSE_TASK_NOTIFICATIONS == 1 )
BaseType_t xTaskGenericNotify ( TaskHandle_t xTaskToNotify ,
UBaseType_t uxIndexToNotify ,
uint32_t ulValue ,
eNotifyAction eAction ,
uint32_t * pulPreviousNotificationValue )
{
TCB_t * pxTCB ;
BaseType_t xReturn = pdPASS ;
uint8_t ucOriginalNotifyState ;
2024-01-05 04:14:26 -05:00
traceENTER_xTaskGenericNotify ( xTaskToNotify , uxIndexToNotify , ulValue , eAction , pulPreviousNotificationValue ) ;
2022-02-24 07:14:22 -05:00
configASSERT ( uxIndexToNotify < configTASK_NOTIFICATION_ARRAY_ENTRIES ) ;
configASSERT ( xTaskToNotify ) ;
pxTCB = xTaskToNotify ;
taskENTER_CRITICAL ( ) ;
{
if ( pulPreviousNotificationValue ! = NULL )
{
* pulPreviousNotificationValue = pxTCB - > ulNotifiedValue [ uxIndexToNotify ] ;
}
ucOriginalNotifyState = pxTCB - > ucNotifyState [ uxIndexToNotify ] ;
pxTCB - > ucNotifyState [ uxIndexToNotify ] = taskNOTIFICATION_RECEIVED ;
switch ( eAction )
{
case eSetBits :
pxTCB - > ulNotifiedValue [ uxIndexToNotify ] | = ulValue ;
break ;
case eIncrement :
( pxTCB - > ulNotifiedValue [ uxIndexToNotify ] ) + + ;
break ;
case eSetValueWithOverwrite :
pxTCB - > ulNotifiedValue [ uxIndexToNotify ] = ulValue ;
break ;
case eSetValueWithoutOverwrite :
if ( ucOriginalNotifyState ! = taskNOTIFICATION_RECEIVED )
{
pxTCB - > ulNotifiedValue [ uxIndexToNotify ] = ulValue ;
}
else
{
/* The value could not be written to the task. */
xReturn = pdFAIL ;
}
break ;
case eNoAction :
/* The task is being notified without its notify value being
* updated . */
break ;
default :
/* Should not get here if all enums are handled.
* Artificially force an assert by testing a value the
* compiler can ' t assume is const . */
configASSERT ( xTickCount = = ( TickType_t ) 0 ) ;
break ;
}
traceTASK_NOTIFY ( uxIndexToNotify ) ;
/* If the task is in the blocked state specifically to wait for a
* notification then unblock it now . */
if ( ucOriginalNotifyState = = taskWAITING_NOTIFICATION )
{
2024-01-05 04:14:26 -05:00
listREMOVE_ITEM ( & ( pxTCB - > xStateListItem ) ) ;
2022-02-24 07:14:22 -05:00
prvAddTaskToReadyList ( pxTCB ) ;
/* The task should not have been on an event list. */
configASSERT ( listLIST_ITEM_CONTAINER ( & ( pxTCB - > xEventListItem ) ) = = NULL ) ;
# if ( configUSE_TICKLESS_IDLE != 0 )
2024-01-05 04:14:26 -05:00
{
/* If a task is blocked waiting for a notification 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 will automatically get 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 ( ) ;
}
2022-02-24 07:14:22 -05:00
# endif
2024-01-05 04:14:26 -05:00
/* Check if the notified task has a priority above the currently
* executing task . */
taskYIELD_ANY_CORE_IF_USING_PREEMPTION ( pxTCB ) ;
2022-02-24 07:14:22 -05:00
}
else
{
mtCOVERAGE_TEST_MARKER ( ) ;
}
}
taskEXIT_CRITICAL ( ) ;
2024-01-05 04:14:26 -05:00
traceRETURN_xTaskGenericNotify ( xReturn ) ;
2022-02-24 07:14:22 -05:00
return xReturn ;
}
# endif /* configUSE_TASK_NOTIFICATIONS */
/*-----------------------------------------------------------*/
# if ( configUSE_TASK_NOTIFICATIONS == 1 )
BaseType_t xTaskGenericNotifyFromISR ( TaskHandle_t xTaskToNotify ,
UBaseType_t uxIndexToNotify ,
uint32_t ulValue ,
eNotifyAction eAction ,
uint32_t * pulPreviousNotificationValue ,
BaseType_t * pxHigherPriorityTaskWoken )
{
TCB_t * pxTCB ;
uint8_t ucOriginalNotifyState ;
BaseType_t xReturn = pdPASS ;
UBaseType_t uxSavedInterruptStatus ;
2024-01-05 04:14:26 -05:00
traceENTER_xTaskGenericNotifyFromISR ( xTaskToNotify , uxIndexToNotify , ulValue , eAction , pulPreviousNotificationValue , pxHigherPriorityTaskWoken ) ;
2022-02-24 07:14:22 -05:00
configASSERT ( xTaskToNotify ) ;
configASSERT ( uxIndexToNotify < configTASK_NOTIFICATION_ARRAY_ENTRIES ) ;
/* RTOS ports that support interrupt nesting have the concept of a
* maximum system call ( or maximum API call ) interrupt priority .
* Interrupts that are above the maximum system call priority are keep
* permanently enabled , even when the RTOS kernel is in a critical section ,
* but cannot make any calls to FreeRTOS API functions . If configASSERT ( )
* is defined in FreeRTOSConfig . h then
* portASSERT_IF_INTERRUPT_PRIORITY_INVALID ( ) will result in an assertion
* failure if a FreeRTOS API function is called from an interrupt that has
* been assigned a priority above the configured maximum system call
* priority . Only FreeRTOS functions that end in FromISR can be called
* from interrupts that have been assigned a priority at or ( logically )
* below the maximum system call interrupt priority . FreeRTOS maintains a
* separate interrupt safe API to ensure interrupt entry is as fast and as
* simple as possible . More information ( albeit Cortex - M specific ) is
* provided on the following link :
* https : //www.FreeRTOS.org/RTOS-Cortex-M3-M4.html */
portASSERT_IF_INTERRUPT_PRIORITY_INVALID ( ) ;
pxTCB = xTaskToNotify ;
2024-01-05 04:14:26 -05:00
uxSavedInterruptStatus = taskENTER_CRITICAL_FROM_ISR ( ) ;
2022-02-24 07:14:22 -05:00
{
if ( pulPreviousNotificationValue ! = NULL )
{
* pulPreviousNotificationValue = pxTCB - > ulNotifiedValue [ uxIndexToNotify ] ;
}
ucOriginalNotifyState = pxTCB - > ucNotifyState [ uxIndexToNotify ] ;
pxTCB - > ucNotifyState [ uxIndexToNotify ] = taskNOTIFICATION_RECEIVED ;
switch ( eAction )
{
case eSetBits :
pxTCB - > ulNotifiedValue [ uxIndexToNotify ] | = ulValue ;
break ;
case eIncrement :
( pxTCB - > ulNotifiedValue [ uxIndexToNotify ] ) + + ;
break ;
case eSetValueWithOverwrite :
pxTCB - > ulNotifiedValue [ uxIndexToNotify ] = ulValue ;
break ;
case eSetValueWithoutOverwrite :
if ( ucOriginalNotifyState ! = taskNOTIFICATION_RECEIVED )
{
pxTCB - > ulNotifiedValue [ uxIndexToNotify ] = ulValue ;
}
else
{
/* The value could not be written to the task. */
xReturn = pdFAIL ;
}
break ;
case eNoAction :
/* The task is being notified without its notify value being
* updated . */
break ;
default :
/* Should not get here if all enums are handled.
* Artificially force an assert by testing a value the
* compiler can ' t assume is const . */
configASSERT ( xTickCount = = ( TickType_t ) 0 ) ;
break ;
}
traceTASK_NOTIFY_FROM_ISR ( uxIndexToNotify ) ;
/* If the task is in the blocked state specifically to wait for a
* notification then unblock it now . */
if ( ucOriginalNotifyState = = taskWAITING_NOTIFICATION )
{
/* The task should not have been on an event list. */
configASSERT ( listLIST_ITEM_CONTAINER ( & ( pxTCB - > xEventListItem ) ) = = NULL ) ;
2024-01-05 04:14:26 -05:00
if ( uxSchedulerSuspended = = ( UBaseType_t ) 0U )
2022-02-24 07:14:22 -05:00
{
2024-01-05 04:14:26 -05:00
listREMOVE_ITEM ( & ( pxTCB - > xStateListItem ) ) ;
2022-02-24 07:14:22 -05:00
prvAddTaskToReadyList ( pxTCB ) ;
}
else
{
/* The delayed and ready lists cannot be accessed, so hold
* this task pending until the scheduler is resumed . */
2024-01-05 04:14:26 -05:00
listINSERT_END ( & ( xPendingReadyList ) , & ( pxTCB - > xEventListItem ) ) ;
2022-02-24 07:14:22 -05:00
}
2024-01-05 04:14:26 -05:00
# if ( configNUMBER_OF_CORES == 1 )
{
if ( pxTCB - > uxPriority > pxCurrentTCB - > uxPriority )
2022-02-24 07:14:22 -05:00
{
2024-01-05 04:14:26 -05:00
/* The notified task has a priority above the currently
* executing task so a yield is required . */
2022-02-24 07:14:22 -05:00
if ( pxHigherPriorityTaskWoken ! = NULL )
{
* pxHigherPriorityTaskWoken = pdTRUE ;
}
2024-01-05 04:14:26 -05:00
/* Mark that a yield is pending in case the user is not
* using the " xHigherPriorityTaskWoken " parameter to an ISR
* safe FreeRTOS function . */
xYieldPendings [ 0 ] = pdTRUE ;
}
else
{
mtCOVERAGE_TEST_MARKER ( ) ;
}
}
# else /* #if ( configNUMBER_OF_CORES == 1 ) */
{
# if ( configUSE_PREEMPTION == 1 )
{
prvYieldForTask ( pxTCB ) ;
if ( xYieldPendings [ portGET_CORE_ID ( ) ] = = pdTRUE )
{
if ( pxHigherPriorityTaskWoken ! = NULL )
{
* pxHigherPriorityTaskWoken = pdTRUE ;
}
}
2022-02-24 07:14:22 -05:00
}
2024-01-05 04:14:26 -05:00
# endif /* if ( configUSE_PREEMPTION == 1 ) */
}
# endif /* #if ( configNUMBER_OF_CORES == 1 ) */
2022-02-24 07:14:22 -05:00
}
}
2024-01-05 04:14:26 -05:00
taskEXIT_CRITICAL_FROM_ISR ( uxSavedInterruptStatus ) ;
traceRETURN_xTaskGenericNotifyFromISR ( xReturn ) ;
2022-02-24 07:14:22 -05:00
return xReturn ;
}
# endif /* configUSE_TASK_NOTIFICATIONS */
/*-----------------------------------------------------------*/
# if ( configUSE_TASK_NOTIFICATIONS == 1 )
void vTaskGenericNotifyGiveFromISR ( TaskHandle_t xTaskToNotify ,
UBaseType_t uxIndexToNotify ,
BaseType_t * pxHigherPriorityTaskWoken )
{
TCB_t * pxTCB ;
uint8_t ucOriginalNotifyState ;
UBaseType_t uxSavedInterruptStatus ;
2024-01-05 04:14:26 -05:00
traceENTER_vTaskGenericNotifyGiveFromISR ( xTaskToNotify , uxIndexToNotify , pxHigherPriorityTaskWoken ) ;
2022-02-24 07:14:22 -05:00
configASSERT ( xTaskToNotify ) ;
configASSERT ( uxIndexToNotify < configTASK_NOTIFICATION_ARRAY_ENTRIES ) ;
/* RTOS ports that support interrupt nesting have the concept of a
* maximum system call ( or maximum API call ) interrupt priority .
* Interrupts that are above the maximum system call priority are keep
* permanently enabled , even when the RTOS kernel is in a critical section ,
* but cannot make any calls to FreeRTOS API functions . If configASSERT ( )
* is defined in FreeRTOSConfig . h then
* portASSERT_IF_INTERRUPT_PRIORITY_INVALID ( ) will result in an assertion
* failure if a FreeRTOS API function is called from an interrupt that has
* been assigned a priority above the configured maximum system call
* priority . Only FreeRTOS functions that end in FromISR can be called
* from interrupts that have been assigned a priority at or ( logically )
* below the maximum system call interrupt priority . FreeRTOS maintains a
* separate interrupt safe API to ensure interrupt entry is as fast and as
* simple as possible . More information ( albeit Cortex - M specific ) is
* provided on the following link :
* https : //www.FreeRTOS.org/RTOS-Cortex-M3-M4.html */
portASSERT_IF_INTERRUPT_PRIORITY_INVALID ( ) ;
pxTCB = xTaskToNotify ;
2024-01-05 04:14:26 -05:00
uxSavedInterruptStatus = taskENTER_CRITICAL_FROM_ISR ( ) ;
2022-02-24 07:14:22 -05:00
{
ucOriginalNotifyState = pxTCB - > ucNotifyState [ uxIndexToNotify ] ;
pxTCB - > ucNotifyState [ uxIndexToNotify ] = taskNOTIFICATION_RECEIVED ;
/* 'Giving' is equivalent to incrementing a count in a counting
* semaphore . */
( pxTCB - > ulNotifiedValue [ uxIndexToNotify ] ) + + ;
traceTASK_NOTIFY_GIVE_FROM_ISR ( uxIndexToNotify ) ;
/* If the task is in the blocked state specifically to wait for a
* notification then unblock it now . */
if ( ucOriginalNotifyState = = taskWAITING_NOTIFICATION )
{
/* The task should not have been on an event list. */
configASSERT ( listLIST_ITEM_CONTAINER ( & ( pxTCB - > xEventListItem ) ) = = NULL ) ;
2024-01-05 04:14:26 -05:00
if ( uxSchedulerSuspended = = ( UBaseType_t ) 0U )
2022-02-24 07:14:22 -05:00
{
2024-01-05 04:14:26 -05:00
listREMOVE_ITEM ( & ( pxTCB - > xStateListItem ) ) ;
2022-02-24 07:14:22 -05:00
prvAddTaskToReadyList ( pxTCB ) ;
}
else
{
/* The delayed and ready lists cannot be accessed, so hold
* this task pending until the scheduler is resumed . */
2024-01-05 04:14:26 -05:00
listINSERT_END ( & ( xPendingReadyList ) , & ( pxTCB - > xEventListItem ) ) ;
2022-02-24 07:14:22 -05:00
}
2024-01-05 04:14:26 -05:00
# if ( configNUMBER_OF_CORES == 1 )
{
if ( pxTCB - > uxPriority > pxCurrentTCB - > uxPriority )
2022-02-24 07:14:22 -05:00
{
2024-01-05 04:14:26 -05:00
/* The notified task has a priority above the currently
* executing task so a yield is required . */
2022-02-24 07:14:22 -05:00
if ( pxHigherPriorityTaskWoken ! = NULL )
{
* pxHigherPriorityTaskWoken = pdTRUE ;
}
2024-01-05 04:14:26 -05:00
/* Mark that a yield is pending in case the user is not
* using the " xHigherPriorityTaskWoken " parameter in an ISR
* safe FreeRTOS function . */
xYieldPendings [ 0 ] = pdTRUE ;
2022-02-24 07:14:22 -05:00
}
2024-01-05 04:14:26 -05:00
else
{
mtCOVERAGE_TEST_MARKER ( ) ;
}
}
# else /* #if ( configNUMBER_OF_CORES == 1 ) */
{
# if ( configUSE_PREEMPTION == 1 )
{
prvYieldForTask ( pxTCB ) ;
if ( xYieldPendings [ portGET_CORE_ID ( ) ] = = pdTRUE )
{
if ( pxHigherPriorityTaskWoken ! = NULL )
{
* pxHigherPriorityTaskWoken = pdTRUE ;
}
}
}
# endif /* #if ( configUSE_PREEMPTION == 1 ) */
}
# endif /* #if ( configNUMBER_OF_CORES == 1 ) */
2022-02-24 07:14:22 -05:00
}
}
2024-01-05 04:14:26 -05:00
taskEXIT_CRITICAL_FROM_ISR ( uxSavedInterruptStatus ) ;
traceRETURN_vTaskGenericNotifyGiveFromISR ( ) ;
2022-02-24 07:14:22 -05:00
}
# endif /* configUSE_TASK_NOTIFICATIONS */
/*-----------------------------------------------------------*/
# if ( configUSE_TASK_NOTIFICATIONS == 1 )
BaseType_t xTaskGenericNotifyStateClear ( TaskHandle_t xTask ,
UBaseType_t uxIndexToClear )
{
TCB_t * pxTCB ;
BaseType_t xReturn ;
2024-01-05 04:14:26 -05:00
traceENTER_xTaskGenericNotifyStateClear ( xTask , uxIndexToClear ) ;
2022-02-24 07:14:22 -05:00
configASSERT ( uxIndexToClear < configTASK_NOTIFICATION_ARRAY_ENTRIES ) ;
/* If null is passed in here then it is the calling task that is having
* its notification state cleared . */
pxTCB = prvGetTCBFromHandle ( xTask ) ;
taskENTER_CRITICAL ( ) ;
{
if ( pxTCB - > ucNotifyState [ uxIndexToClear ] = = taskNOTIFICATION_RECEIVED )
{
pxTCB - > ucNotifyState [ uxIndexToClear ] = taskNOT_WAITING_NOTIFICATION ;
xReturn = pdPASS ;
}
else
{
xReturn = pdFAIL ;
}
}
taskEXIT_CRITICAL ( ) ;
2024-01-05 04:14:26 -05:00
traceRETURN_xTaskGenericNotifyStateClear ( xReturn ) ;
2022-02-24 07:14:22 -05:00
return xReturn ;
}
# endif /* configUSE_TASK_NOTIFICATIONS */
/*-----------------------------------------------------------*/
# if ( configUSE_TASK_NOTIFICATIONS == 1 )
uint32_t ulTaskGenericNotifyValueClear ( TaskHandle_t xTask ,
UBaseType_t uxIndexToClear ,
uint32_t ulBitsToClear )
{
TCB_t * pxTCB ;
uint32_t ulReturn ;
2024-01-05 04:14:26 -05:00
traceENTER_ulTaskGenericNotifyValueClear ( xTask , uxIndexToClear , ulBitsToClear ) ;
configASSERT ( uxIndexToClear < configTASK_NOTIFICATION_ARRAY_ENTRIES ) ;
2022-02-24 07:14:22 -05:00
/* If null is passed in here then it is the calling task that is having
* its notification state cleared . */
pxTCB = prvGetTCBFromHandle ( xTask ) ;
taskENTER_CRITICAL ( ) ;
{
/* Return the notification as it was before the bits were cleared,
* then clear the bit mask . */
ulReturn = pxTCB - > ulNotifiedValue [ uxIndexToClear ] ;
pxTCB - > ulNotifiedValue [ uxIndexToClear ] & = ~ ulBitsToClear ;
}
taskEXIT_CRITICAL ( ) ;
2024-01-05 04:14:26 -05:00
traceRETURN_ulTaskGenericNotifyValueClear ( ulReturn ) ;
2022-02-24 07:14:22 -05:00
return ulReturn ;
}
# endif /* configUSE_TASK_NOTIFICATIONS */
/*-----------------------------------------------------------*/
2024-01-05 04:14:26 -05:00
# if ( configGENERATE_RUN_TIME_STATS == 1 )
configRUN_TIME_COUNTER_TYPE ulTaskGetRunTimeCounter ( const TaskHandle_t xTask )
{
TCB_t * pxTCB ;
traceENTER_ulTaskGetRunTimeCounter ( xTask ) ;
pxTCB = prvGetTCBFromHandle ( xTask ) ;
traceRETURN_ulTaskGetRunTimeCounter ( pxTCB - > ulRunTimeCounter ) ;
return pxTCB - > ulRunTimeCounter ;
}
# endif /* if ( configGENERATE_RUN_TIME_STATS == 1 ) */
/*-----------------------------------------------------------*/
# if ( configGENERATE_RUN_TIME_STATS == 1 )
configRUN_TIME_COUNTER_TYPE ulTaskGetRunTimePercent ( const TaskHandle_t xTask )
{
TCB_t * pxTCB ;
configRUN_TIME_COUNTER_TYPE ulTotalTime , ulReturn ;
traceENTER_ulTaskGetRunTimePercent ( xTask ) ;
ulTotalTime = ( configRUN_TIME_COUNTER_TYPE ) portGET_RUN_TIME_COUNTER_VALUE ( ) ;
/* For percentage calculations. */
ulTotalTime / = ( configRUN_TIME_COUNTER_TYPE ) 100 ;
/* Avoid divide by zero errors. */
if ( ulTotalTime > ( configRUN_TIME_COUNTER_TYPE ) 0 )
{
pxTCB = prvGetTCBFromHandle ( xTask ) ;
ulReturn = pxTCB - > ulRunTimeCounter / ulTotalTime ;
}
else
{
ulReturn = 0 ;
}
traceRETURN_ulTaskGetRunTimePercent ( ulReturn ) ;
return ulReturn ;
}
# endif /* if ( configGENERATE_RUN_TIME_STATS == 1 ) */
/*-----------------------------------------------------------*/
# if ( ( configGENERATE_RUN_TIME_STATS == 1 ) && ( INCLUDE_xTaskGetIdleTaskHandle == 1 ) )
configRUN_TIME_COUNTER_TYPE ulTaskGetIdleRunTimeCounter ( void )
{
configRUN_TIME_COUNTER_TYPE ulReturn = 0 ;
BaseType_t i ;
traceENTER_ulTaskGetIdleRunTimeCounter ( ) ;
for ( i = 0 ; i < ( BaseType_t ) configNUMBER_OF_CORES ; i + + )
{
ulReturn + = xIdleTaskHandles [ i ] - > ulRunTimeCounter ;
}
traceRETURN_ulTaskGetIdleRunTimeCounter ( ulReturn ) ;
return ulReturn ;
}
# endif /* if ( ( configGENERATE_RUN_TIME_STATS == 1 ) && ( INCLUDE_xTaskGetIdleTaskHandle == 1 ) ) */
/*-----------------------------------------------------------*/
2022-02-24 07:14:22 -05:00
# if ( ( configGENERATE_RUN_TIME_STATS == 1 ) && ( INCLUDE_xTaskGetIdleTaskHandle == 1 ) )
2024-01-05 04:14:26 -05:00
configRUN_TIME_COUNTER_TYPE ulTaskGetIdleRunTimePercent ( void )
2022-02-24 07:14:22 -05:00
{
2024-01-05 04:14:26 -05:00
configRUN_TIME_COUNTER_TYPE ulTotalTime , ulReturn ;
configRUN_TIME_COUNTER_TYPE ulRunTimeCounter = 0 ;
BaseType_t i ;
2022-02-24 07:14:22 -05:00
2024-01-05 04:14:26 -05:00
traceENTER_ulTaskGetIdleRunTimePercent ( ) ;
ulTotalTime = portGET_RUN_TIME_COUNTER_VALUE ( ) * configNUMBER_OF_CORES ;
/* For percentage calculations. */
ulTotalTime / = ( configRUN_TIME_COUNTER_TYPE ) 100 ;
/* Avoid divide by zero errors. */
if ( ulTotalTime > ( configRUN_TIME_COUNTER_TYPE ) 0 )
{
for ( i = 0 ; i < ( BaseType_t ) configNUMBER_OF_CORES ; i + + )
{
ulRunTimeCounter + = xIdleTaskHandles [ i ] - > ulRunTimeCounter ;
}
ulReturn = ulRunTimeCounter / ulTotalTime ;
}
else
2022-02-24 07:14:22 -05:00
{
2024-01-05 04:14:26 -05:00
ulReturn = 0 ;
2022-02-24 07:14:22 -05:00
}
2024-01-05 04:14:26 -05:00
traceRETURN_ulTaskGetIdleRunTimePercent ( ulReturn ) ;
2022-02-24 07:14:22 -05:00
return ulReturn ;
}
# endif /* if ( ( configGENERATE_RUN_TIME_STATS == 1 ) && ( INCLUDE_xTaskGetIdleTaskHandle == 1 ) ) */
/*-----------------------------------------------------------*/
static void prvAddCurrentTaskToDelayedList ( TickType_t xTicksToWait ,
const BaseType_t xCanBlockIndefinitely )
{
TickType_t xTimeToWake ;
const TickType_t xConstTickCount = xTickCount ;
2024-01-05 04:14:26 -05:00
List_t * const pxDelayedList = pxDelayedTaskList ;
List_t * const pxOverflowDelayedList = pxOverflowDelayedTaskList ;
2022-02-24 07:14:22 -05:00
# if ( INCLUDE_xTaskAbortDelay == 1 )
2024-01-05 04:14:26 -05:00
{
/* About to enter a delayed list, so ensure the ucDelayAborted flag is
* reset to pdFALSE so it can be detected as having been set to pdTRUE
* when the task leaves the Blocked state . */
pxCurrentTCB - > ucDelayAborted = pdFALSE ;
}
2022-02-24 07:14:22 -05:00
# endif
/* Remove the task from the ready list before adding it to the blocked list
* as the same list item is used for both lists . */
if ( uxListRemove ( & ( pxCurrentTCB - > xStateListItem ) ) = = ( UBaseType_t ) 0 )
{
/* The current task must be in a ready list, so there is no need to
* check , and the port reset macro can be called directly . */
2024-01-05 04:14:26 -05:00
portRESET_READY_PRIORITY ( pxCurrentTCB - > uxPriority , uxTopReadyPriority ) ;
2022-02-24 07:14:22 -05:00
}
else
{
mtCOVERAGE_TEST_MARKER ( ) ;
}
# if ( INCLUDE_vTaskSuspend == 1 )
2024-01-05 04:14:26 -05:00
{
if ( ( xTicksToWait = = portMAX_DELAY ) & & ( xCanBlockIndefinitely ! = pdFALSE ) )
2022-02-24 07:14:22 -05:00
{
2024-01-05 04:14:26 -05:00
/* Add the task to the suspended task list instead of a delayed task
* list to ensure it is not woken by a timing event . It will block
* indefinitely . */
listINSERT_END ( & xSuspendedTaskList , & ( pxCurrentTCB - > xStateListItem ) ) ;
2022-02-24 07:14:22 -05:00
}
2024-01-05 04:14:26 -05:00
else
2022-02-24 07:14:22 -05:00
{
/* Calculate the time at which the task should be woken if the event
2024-01-05 04:14:26 -05:00
* does not occur . This may overflow but this doesn ' t matter , the
* kernel will manage it correctly . */
2022-02-24 07:14:22 -05:00
xTimeToWake = xConstTickCount + xTicksToWait ;
/* The list item will be inserted in wake time order. */
listSET_LIST_ITEM_VALUE ( & ( pxCurrentTCB - > xStateListItem ) , xTimeToWake ) ;
if ( xTimeToWake < xConstTickCount )
{
2024-01-05 04:14:26 -05:00
/* Wake time has overflowed. Place this item in the overflow
* list . */
traceMOVED_TASK_TO_OVERFLOW_DELAYED_LIST ( ) ;
vListInsert ( pxOverflowDelayedList , & ( pxCurrentTCB - > xStateListItem ) ) ;
2022-02-24 07:14:22 -05:00
}
else
{
2024-01-05 04:14:26 -05:00
/* The wake time has not overflowed, so the current block list
* is used . */
traceMOVED_TASK_TO_DELAYED_LIST ( ) ;
vListInsert ( pxDelayedList , & ( pxCurrentTCB - > xStateListItem ) ) ;
2022-02-24 07:14:22 -05:00
2024-01-05 04:14:26 -05:00
/* If the task entering the blocked state was placed at the
* head of the list of blocked tasks then xNextTaskUnblockTime
* needs to be updated too . */
2022-02-24 07:14:22 -05:00
if ( xTimeToWake < xNextTaskUnblockTime )
{
xNextTaskUnblockTime = xTimeToWake ;
}
else
{
mtCOVERAGE_TEST_MARKER ( ) ;
}
}
2024-01-05 04:14:26 -05:00
}
}
# else /* INCLUDE_vTaskSuspend */
{
/* Calculate the time at which the task should be woken if the event
* does not occur . This may overflow but this doesn ' t matter , the kernel
* will manage it correctly . */
xTimeToWake = xConstTickCount + xTicksToWait ;
/* The list item will be inserted in wake time order. */
listSET_LIST_ITEM_VALUE ( & ( pxCurrentTCB - > xStateListItem ) , xTimeToWake ) ;
if ( xTimeToWake < xConstTickCount )
{
traceMOVED_TASK_TO_OVERFLOW_DELAYED_LIST ( ) ;
/* Wake time has overflowed. Place this item in the overflow list. */
vListInsert ( pxOverflowDelayedList , & ( pxCurrentTCB - > xStateListItem ) ) ;
}
else
{
traceMOVED_TASK_TO_DELAYED_LIST ( ) ;
/* The wake time has not overflowed, so the current block list is used. */
vListInsert ( pxDelayedList , & ( pxCurrentTCB - > xStateListItem ) ) ;
2022-02-24 07:14:22 -05:00
2024-01-05 04:14:26 -05:00
/* If the task entering the blocked state was placed at the head of the
* list of blocked tasks then xNextTaskUnblockTime needs to be updated
* too . */
if ( xTimeToWake < xNextTaskUnblockTime )
{
xNextTaskUnblockTime = xTimeToWake ;
}
else
{
mtCOVERAGE_TEST_MARKER ( ) ;
}
2022-02-24 07:14:22 -05:00
}
2024-01-05 04:14:26 -05:00
/* Avoid compiler warning when INCLUDE_vTaskSuspend is not 1. */
( void ) xCanBlockIndefinitely ;
}
2022-02-24 07:14:22 -05:00
# endif /* INCLUDE_vTaskSuspend */
}
2024-01-05 04:14:26 -05:00
/*-----------------------------------------------------------*/
# if ( portUSING_MPU_WRAPPERS == 1 )
xMPU_SETTINGS * xTaskGetMPUSettings ( TaskHandle_t xTask )
{
TCB_t * pxTCB ;
traceENTER_xTaskGetMPUSettings ( xTask ) ;
pxTCB = prvGetTCBFromHandle ( xTask ) ;
traceRETURN_xTaskGetMPUSettings ( & ( pxTCB - > xMPUSettings ) ) ;
return & ( pxTCB - > xMPUSettings ) ;
}
# endif /* portUSING_MPU_WRAPPERS */
/*-----------------------------------------------------------*/
2022-02-24 07:14:22 -05:00
/* Code below here allows additional code to be inserted into this source file,
* especially where access to file scope functions and data is needed ( for example
* when performing module tests ) . */
# ifdef FREERTOS_MODULE_TEST
# include "tasks_test_access_functions.h"
# endif
# if ( configINCLUDE_FREERTOS_TASK_C_ADDITIONS_H == 1 )
# include "freertos_tasks_c_additions.h"
# ifdef FREERTOS_TASKS_C_ADDITIONS_INIT
static void freertos_tasks_c_additions_init ( void )
{
FREERTOS_TASKS_C_ADDITIONS_INIT ( ) ;
}
# endif
# endif /* if ( configINCLUDE_FREERTOS_TASK_C_ADDITIONS_H == 1 ) */
2024-01-05 04:14:26 -05:00
/*-----------------------------------------------------------*/
# if ( ( configSUPPORT_STATIC_ALLOCATION == 1 ) && ( configKERNEL_PROVIDED_STATIC_MEMORY == 1 ) && ( portUSING_MPU_WRAPPERS == 0 ) )
/*
* This is the kernel provided implementation of vApplicationGetIdleTaskMemory ( )
* to provide the memory that is used by the Idle task . It is used when
* configKERNEL_PROVIDED_STATIC_MEMORY is set to 1. The application can provide
* it ' s own implementation of vApplicationGetIdleTaskMemory by setting
* configKERNEL_PROVIDED_STATIC_MEMORY to 0 or leaving it undefined .
*/
void vApplicationGetIdleTaskMemory ( StaticTask_t * * ppxIdleTaskTCBBuffer ,
StackType_t * * ppxIdleTaskStackBuffer ,
uint32_t * pulIdleTaskStackSize )
{
static StaticTask_t xIdleTaskTCB ;
static StackType_t uxIdleTaskStack [ configMINIMAL_STACK_SIZE ] ;
* ppxIdleTaskTCBBuffer = & ( xIdleTaskTCB ) ;
* ppxIdleTaskStackBuffer = & ( uxIdleTaskStack [ 0 ] ) ;
* pulIdleTaskStackSize = configMINIMAL_STACK_SIZE ;
}
# if ( configNUMBER_OF_CORES > 1 )
void vApplicationGetPassiveIdleTaskMemory ( StaticTask_t * * ppxIdleTaskTCBBuffer ,
StackType_t * * ppxIdleTaskStackBuffer ,
uint32_t * pulIdleTaskStackSize ,
BaseType_t xPassiveIdleTaskIndex )
{
static StaticTask_t xIdleTaskTCBs [ configNUMBER_OF_CORES - 1 ] ;
static StackType_t uxIdleTaskStacks [ configNUMBER_OF_CORES - 1 ] [ configMINIMAL_STACK_SIZE ] ;
* ppxIdleTaskTCBBuffer = & ( xIdleTaskTCBs [ xPassiveIdleTaskIndex ] ) ;
* ppxIdleTaskStackBuffer = & ( uxIdleTaskStacks [ xPassiveIdleTaskIndex ] [ 0 ] ) ;
* pulIdleTaskStackSize = configMINIMAL_STACK_SIZE ;
}
# endif /* #if ( configNUMBER_OF_CORES > 1 ) */
# endif /* #if ( ( configSUPPORT_STATIC_ALLOCATION == 1 ) && ( configKERNEL_PROVIDED_STATIC_MEMORY == 1 ) && ( portUSING_MPU_WRAPPERS == 0 ) ) */
/*-----------------------------------------------------------*/
# if ( ( configSUPPORT_STATIC_ALLOCATION == 1 ) && ( configKERNEL_PROVIDED_STATIC_MEMORY == 1 ) && ( portUSING_MPU_WRAPPERS == 0 ) )
/*
* This is the kernel provided implementation of vApplicationGetTimerTaskMemory ( )
* to provide the memory that is used by the Timer service task . It is used when
* configKERNEL_PROVIDED_STATIC_MEMORY is set to 1. The application can provide
* it ' s own implementation of vApplicationGetTimerTaskMemory by setting
* configKERNEL_PROVIDED_STATIC_MEMORY to 0 or leaving it undefined .
*/
void vApplicationGetTimerTaskMemory ( StaticTask_t * * ppxTimerTaskTCBBuffer ,
StackType_t * * ppxTimerTaskStackBuffer ,
uint32_t * pulTimerTaskStackSize )
{
static StaticTask_t xTimerTaskTCB ;
static StackType_t uxTimerTaskStack [ configTIMER_TASK_STACK_DEPTH ] ;
* ppxTimerTaskTCBBuffer = & ( xTimerTaskTCB ) ;
* ppxTimerTaskStackBuffer = & ( uxTimerTaskStack [ 0 ] ) ;
* pulTimerTaskStackSize = configTIMER_TASK_STACK_DEPTH ;
}
# endif /* #if ( ( configSUPPORT_STATIC_ALLOCATION == 1 ) && ( configKERNEL_PROVIDED_STATIC_MEMORY == 1 ) && ( portUSING_MPU_WRAPPERS == 0 ) ) */
/*-----------------------------------------------------------*/