]> begriffs open source - freertos/blob - tasks.c
Fix spelling typos (#1168)
[freertos] / tasks.c
1 /*
2  * FreeRTOS Kernel <DEVELOPMENT BRANCH>
3  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
4  *
5  * SPDX-License-Identifier: MIT
6  *
7  * Permission is hereby granted, free of charge, to any person obtaining a copy of
8  * this software and associated documentation files (the "Software"), to deal in
9  * the Software without restriction, including without limitation the rights to
10  * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
11  * the Software, and to permit persons to whom the Software is furnished to do so,
12  * subject to the following conditions:
13  *
14  * The above copyright notice and this permission notice shall be included in all
15  * copies or substantial portions of the Software.
16  *
17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
19  * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
20  * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
21  * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23  *
24  * https://www.FreeRTOS.org
25  * https://github.com/FreeRTOS
26  *
27  */
28
29 /* Standard includes. */
30 #include <stdlib.h>
31 #include <string.h>
32
33 /* Defining MPU_WRAPPERS_INCLUDED_FROM_API_FILE prevents task.h from redefining
34  * all the API functions to use the MPU wrappers.  That should only be done when
35  * task.h is included from an application file. */
36 #define MPU_WRAPPERS_INCLUDED_FROM_API_FILE
37
38 /* FreeRTOS includes. */
39 #include "FreeRTOS.h"
40 #include "task.h"
41 #include "timers.h"
42 #include "stack_macros.h"
43
44 /* The default definitions are only available for non-MPU ports. The
45  * reason is that the stack alignment requirements vary for different
46  * architectures.*/
47 #if ( ( configSUPPORT_STATIC_ALLOCATION == 1 ) && ( configKERNEL_PROVIDED_STATIC_MEMORY == 1 ) && ( portUSING_MPU_WRAPPERS != 0 ) )
48     #error configKERNEL_PROVIDED_STATIC_MEMORY cannot be set to 1 when using an MPU port. The vApplicationGet*TaskMemory() functions must be provided manually.
49 #endif
50
51 /* The MPU ports require MPU_WRAPPERS_INCLUDED_FROM_API_FILE to be defined
52  * for the header files above, but not in this file, in order to generate the
53  * correct privileged Vs unprivileged linkage and placement. */
54 #undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE
55
56 /* Set configUSE_STATS_FORMATTING_FUNCTIONS to 2 to include the stats formatting
57  * functions but without including stdio.h here. */
58 #if ( configUSE_STATS_FORMATTING_FUNCTIONS == 1 )
59
60 /* At the bottom of this file are two optional functions that can be used
61  * to generate human readable text from the raw data generated by the
62  * uxTaskGetSystemState() function.  Note the formatting functions are provided
63  * for convenience only, and are NOT considered part of the kernel. */
64     #include <stdio.h>
65 #endif /* configUSE_STATS_FORMATTING_FUNCTIONS == 1 ) */
66
67 #if ( configUSE_PREEMPTION == 0 )
68
69 /* If the cooperative scheduler is being used then a yield should not be
70  * performed just because a higher priority task has been woken. */
71     #define taskYIELD_TASK_CORE_IF_USING_PREEMPTION( pxTCB )
72     #define taskYIELD_ANY_CORE_IF_USING_PREEMPTION( pxTCB )
73 #else
74
75     #if ( configNUMBER_OF_CORES == 1 )
76
77 /* This macro requests the running task pxTCB to yield. In single core
78  * scheduler, a running task always runs on core 0 and portYIELD_WITHIN_API()
79  * can be used to request the task running on core 0 to yield. Therefore, pxTCB
80  * is not used in this macro. */
81         #define taskYIELD_TASK_CORE_IF_USING_PREEMPTION( pxTCB ) \
82     do {                                                         \
83         ( void ) ( pxTCB );                                      \
84         portYIELD_WITHIN_API();                                  \
85     } while( 0 )
86
87         #define taskYIELD_ANY_CORE_IF_USING_PREEMPTION( pxTCB ) \
88     do {                                                        \
89         if( pxCurrentTCB->uxPriority < ( pxTCB )->uxPriority )  \
90         {                                                       \
91             portYIELD_WITHIN_API();                             \
92         }                                                       \
93         else                                                    \
94         {                                                       \
95             mtCOVERAGE_TEST_MARKER();                           \
96         }                                                       \
97     } while( 0 )
98
99     #else /* if ( configNUMBER_OF_CORES == 1 ) */
100
101 /* Yield the core on which this task is running. */
102         #define taskYIELD_TASK_CORE_IF_USING_PREEMPTION( pxTCB )    prvYieldCore( ( pxTCB )->xTaskRunState )
103
104 /* Yield for the task if a running task has priority lower than this task. */
105         #define taskYIELD_ANY_CORE_IF_USING_PREEMPTION( pxTCB )     prvYieldForTask( pxTCB )
106
107     #endif /* #if ( configNUMBER_OF_CORES == 1 ) */
108
109 #endif /* if ( configUSE_PREEMPTION == 0 ) */
110
111 /* Values that can be assigned to the ucNotifyState member of the TCB. */
112 #define taskNOT_WAITING_NOTIFICATION              ( ( uint8_t ) 0 ) /* Must be zero as it is the initialised value. */
113 #define taskWAITING_NOTIFICATION                  ( ( uint8_t ) 1 )
114 #define taskNOTIFICATION_RECEIVED                 ( ( uint8_t ) 2 )
115
116 /*
117  * The value used to fill the stack of a task when the task is created.  This
118  * is used purely for checking the high water mark for tasks.
119  */
120 #define tskSTACK_FILL_BYTE                        ( 0xa5U )
121
122 /* Bits used to record how a task's stack and TCB were allocated. */
123 #define tskDYNAMICALLY_ALLOCATED_STACK_AND_TCB    ( ( uint8_t ) 0 )
124 #define tskSTATICALLY_ALLOCATED_STACK_ONLY        ( ( uint8_t ) 1 )
125 #define tskSTATICALLY_ALLOCATED_STACK_AND_TCB     ( ( uint8_t ) 2 )
126
127 /* If any of the following are set then task stacks are filled with a known
128  * value so the high water mark can be determined.  If none of the following are
129  * set then don't fill the stack so there is no unnecessary dependency on memset. */
130 #if ( ( configCHECK_FOR_STACK_OVERFLOW > 1 ) || ( configUSE_TRACE_FACILITY == 1 ) || ( INCLUDE_uxTaskGetStackHighWaterMark == 1 ) || ( INCLUDE_uxTaskGetStackHighWaterMark2 == 1 ) )
131     #define tskSET_NEW_STACKS_TO_KNOWN_VALUE    1
132 #else
133     #define tskSET_NEW_STACKS_TO_KNOWN_VALUE    0
134 #endif
135
136 /*
137  * Macros used by vListTask to indicate which state a task is in.
138  */
139 #define tskRUNNING_CHAR      ( 'X' )
140 #define tskBLOCKED_CHAR      ( 'B' )
141 #define tskREADY_CHAR        ( 'R' )
142 #define tskDELETED_CHAR      ( 'D' )
143 #define tskSUSPENDED_CHAR    ( 'S' )
144
145 /*
146  * Some kernel aware debuggers require the data the debugger needs access to be
147  * global, rather than file scope.
148  */
149 #ifdef portREMOVE_STATIC_QUALIFIER
150     #define static
151 #endif
152
153 /* The name allocated to the Idle task.  This can be overridden by defining
154  * configIDLE_TASK_NAME in FreeRTOSConfig.h. */
155 #ifndef configIDLE_TASK_NAME
156     #define configIDLE_TASK_NAME    "IDLE"
157 #endif
158
159 #if ( configUSE_PORT_OPTIMISED_TASK_SELECTION == 0 )
160
161 /* If configUSE_PORT_OPTIMISED_TASK_SELECTION is 0 then task selection is
162  * performed in a generic way that is not optimised to any particular
163  * microcontroller architecture. */
164
165 /* uxTopReadyPriority holds the priority of the highest priority ready
166  * state task. */
167     #define taskRECORD_READY_PRIORITY( uxPriority ) \
168     do {                                            \
169         if( ( uxPriority ) > uxTopReadyPriority )   \
170         {                                           \
171             uxTopReadyPriority = ( uxPriority );    \
172         }                                           \
173     } while( 0 ) /* taskRECORD_READY_PRIORITY */
174
175 /*-----------------------------------------------------------*/
176
177     #if ( configNUMBER_OF_CORES == 1 )
178         #define taskSELECT_HIGHEST_PRIORITY_TASK()                                       \
179     do {                                                                                 \
180         UBaseType_t uxTopPriority = uxTopReadyPriority;                                  \
181                                                                                          \
182         /* Find the highest priority queue that contains ready tasks. */                 \
183         while( listLIST_IS_EMPTY( &( pxReadyTasksLists[ uxTopPriority ] ) ) != pdFALSE ) \
184         {                                                                                \
185             configASSERT( uxTopPriority );                                               \
186             --uxTopPriority;                                                             \
187         }                                                                                \
188                                                                                          \
189         /* listGET_OWNER_OF_NEXT_ENTRY indexes through the list, so the tasks of \
190          * the  same priority get an equal share of the processor time. */                    \
191         listGET_OWNER_OF_NEXT_ENTRY( pxCurrentTCB, &( pxReadyTasksLists[ uxTopPriority ] ) ); \
192         uxTopReadyPriority = uxTopPriority;                                                   \
193     } while( 0 ) /* taskSELECT_HIGHEST_PRIORITY_TASK */
194     #else /* if ( configNUMBER_OF_CORES == 1 ) */
195
196         #define taskSELECT_HIGHEST_PRIORITY_TASK( xCoreID )    prvSelectHighestPriorityTask( xCoreID )
197
198     #endif /* if ( configNUMBER_OF_CORES == 1 ) */
199
200 /*-----------------------------------------------------------*/
201
202 /* Define away taskRESET_READY_PRIORITY() and portRESET_READY_PRIORITY() as
203  * they are only required when a port optimised method of task selection is
204  * being used. */
205     #define taskRESET_READY_PRIORITY( uxPriority )
206     #define portRESET_READY_PRIORITY( uxPriority, uxTopReadyPriority )
207
208 #else /* configUSE_PORT_OPTIMISED_TASK_SELECTION */
209
210 /* If configUSE_PORT_OPTIMISED_TASK_SELECTION is 1 then task selection is
211  * performed in a way that is tailored to the particular microcontroller
212  * architecture being used. */
213
214 /* A port optimised version is provided.  Call the port defined macros. */
215     #define taskRECORD_READY_PRIORITY( uxPriority )    portRECORD_READY_PRIORITY( ( uxPriority ), uxTopReadyPriority )
216
217 /*-----------------------------------------------------------*/
218
219     #define taskSELECT_HIGHEST_PRIORITY_TASK()                                                  \
220     do {                                                                                        \
221         UBaseType_t uxTopPriority;                                                              \
222                                                                                                 \
223         /* Find the highest priority list that contains ready tasks. */                         \
224         portGET_HIGHEST_PRIORITY( uxTopPriority, uxTopReadyPriority );                          \
225         configASSERT( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ uxTopPriority ] ) ) > 0 ); \
226         listGET_OWNER_OF_NEXT_ENTRY( pxCurrentTCB, &( pxReadyTasksLists[ uxTopPriority ] ) );   \
227     } while( 0 )
228
229 /*-----------------------------------------------------------*/
230
231 /* A port optimised version is provided, call it only if the TCB being reset
232  * is being referenced from a ready list.  If it is referenced from a delayed
233  * or suspended list then it won't be in a ready list. */
234     #define taskRESET_READY_PRIORITY( uxPriority )                                                     \
235     do {                                                                                               \
236         if( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ ( uxPriority ) ] ) ) == ( UBaseType_t ) 0 ) \
237         {                                                                                              \
238             portRESET_READY_PRIORITY( ( uxPriority ), ( uxTopReadyPriority ) );                        \
239         }                                                                                              \
240     } while( 0 )
241
242 #endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */
243
244 /*-----------------------------------------------------------*/
245
246 /* pxDelayedTaskList and pxOverflowDelayedTaskList are switched when the tick
247  * count overflows. */
248 #define taskSWITCH_DELAYED_LISTS()                                                \
249     do {                                                                          \
250         List_t * pxTemp;                                                          \
251                                                                                   \
252         /* The delayed tasks list should be empty when the lists are switched. */ \
253         configASSERT( ( listLIST_IS_EMPTY( pxDelayedTaskList ) ) );               \
254                                                                                   \
255         pxTemp = pxDelayedTaskList;                                               \
256         pxDelayedTaskList = pxOverflowDelayedTaskList;                            \
257         pxOverflowDelayedTaskList = pxTemp;                                       \
258         xNumOfOverflows = ( BaseType_t ) ( xNumOfOverflows + 1 );                 \
259         prvResetNextTaskUnblockTime();                                            \
260     } while( 0 )
261
262 /*-----------------------------------------------------------*/
263
264 /*
265  * Place the task represented by pxTCB into the appropriate ready list for
266  * the task.  It is inserted at the end of the list.
267  */
268 #define prvAddTaskToReadyList( pxTCB )                                                                     \
269     do {                                                                                                   \
270         traceMOVED_TASK_TO_READY_STATE( pxTCB );                                                           \
271         taskRECORD_READY_PRIORITY( ( pxTCB )->uxPriority );                                                \
272         listINSERT_END( &( pxReadyTasksLists[ ( pxTCB )->uxPriority ] ), &( ( pxTCB )->xStateListItem ) ); \
273         tracePOST_MOVED_TASK_TO_READY_STATE( pxTCB );                                                      \
274     } while( 0 )
275 /*-----------------------------------------------------------*/
276
277 /*
278  * Several functions take a TaskHandle_t parameter that can optionally be NULL,
279  * where NULL is used to indicate that the handle of the currently executing
280  * task should be used in place of the parameter.  This macro simply checks to
281  * see if the parameter is NULL and returns a pointer to the appropriate TCB.
282  */
283 #define prvGetTCBFromHandle( pxHandle )    ( ( ( pxHandle ) == NULL ) ? pxCurrentTCB : ( pxHandle ) )
284
285 /* The item value of the event list item is normally used to hold the priority
286  * of the task to which it belongs (coded to allow it to be held in reverse
287  * priority order).  However, it is occasionally borrowed for other purposes.  It
288  * is important its value is not updated due to a task priority change while it is
289  * being used for another purpose.  The following bit definition is used to inform
290  * the scheduler that the value should not be changed - in which case it is the
291  * responsibility of whichever module is using the value to ensure it gets set back
292  * to its original value when it is released. */
293 #if ( configTICK_TYPE_WIDTH_IN_BITS == TICK_TYPE_WIDTH_16_BITS )
294     #define taskEVENT_LIST_ITEM_VALUE_IN_USE    ( ( uint16_t ) 0x8000U )
295 #elif ( configTICK_TYPE_WIDTH_IN_BITS == TICK_TYPE_WIDTH_32_BITS )
296     #define taskEVENT_LIST_ITEM_VALUE_IN_USE    ( ( uint32_t ) 0x80000000U )
297 #elif ( configTICK_TYPE_WIDTH_IN_BITS == TICK_TYPE_WIDTH_64_BITS )
298     #define taskEVENT_LIST_ITEM_VALUE_IN_USE    ( ( uint64_t ) 0x8000000000000000U )
299 #endif
300
301 /* Indicates that the task is not actively running on any core. */
302 #define taskTASK_NOT_RUNNING           ( ( BaseType_t ) ( -1 ) )
303
304 /* Indicates that the task is actively running but scheduled to yield. */
305 #define taskTASK_SCHEDULED_TO_YIELD    ( ( BaseType_t ) ( -2 ) )
306
307 /* Returns pdTRUE if the task is actively running and not scheduled to yield. */
308 #if ( configNUMBER_OF_CORES == 1 )
309     #define taskTASK_IS_RUNNING( pxTCB )                          ( ( ( pxTCB ) == pxCurrentTCB ) ? ( pdTRUE ) : ( pdFALSE ) )
310     #define taskTASK_IS_RUNNING_OR_SCHEDULED_TO_YIELD( pxTCB )    ( ( ( pxTCB ) == pxCurrentTCB ) ? ( pdTRUE ) : ( pdFALSE ) )
311 #else
312     #define taskTASK_IS_RUNNING( pxTCB )                          ( ( ( ( pxTCB )->xTaskRunState >= ( BaseType_t ) 0 ) && ( ( pxTCB )->xTaskRunState < ( BaseType_t ) configNUMBER_OF_CORES ) ) ? ( pdTRUE ) : ( pdFALSE ) )
313     #define taskTASK_IS_RUNNING_OR_SCHEDULED_TO_YIELD( pxTCB )    ( ( ( pxTCB )->xTaskRunState != taskTASK_NOT_RUNNING ) ? ( pdTRUE ) : ( pdFALSE ) )
314 #endif
315
316 /* Indicates that the task is an Idle task. */
317 #define taskATTRIBUTE_IS_IDLE    ( UBaseType_t ) ( 1U << 0U )
318
319 #if ( ( configNUMBER_OF_CORES > 1 ) && ( portCRITICAL_NESTING_IN_TCB == 1 ) )
320     #define portGET_CRITICAL_NESTING_COUNT()          ( pxCurrentTCBs[ portGET_CORE_ID() ]->uxCriticalNesting )
321     #define portSET_CRITICAL_NESTING_COUNT( x )       ( pxCurrentTCBs[ portGET_CORE_ID() ]->uxCriticalNesting = ( x ) )
322     #define portINCREMENT_CRITICAL_NESTING_COUNT()    ( pxCurrentTCBs[ portGET_CORE_ID() ]->uxCriticalNesting++ )
323     #define portDECREMENT_CRITICAL_NESTING_COUNT()    ( pxCurrentTCBs[ portGET_CORE_ID() ]->uxCriticalNesting-- )
324 #endif /* #if ( ( configNUMBER_OF_CORES > 1 ) && ( portCRITICAL_NESTING_IN_TCB == 1 ) ) */
325
326 #define taskBITS_PER_BYTE    ( ( size_t ) 8 )
327
328 #if ( configNUMBER_OF_CORES > 1 )
329
330 /* Yields the given core. This must be called from a critical section and xCoreID
331  * must be valid. This macro is not required in single core since there is only
332  * one core to yield. */
333     #define prvYieldCore( xCoreID )                                                          \
334     do {                                                                                     \
335         if( ( xCoreID ) == ( BaseType_t ) portGET_CORE_ID() )                                \
336         {                                                                                    \
337             /* Pending a yield for this core since it is in the critical section. */         \
338             xYieldPendings[ ( xCoreID ) ] = pdTRUE;                                          \
339         }                                                                                    \
340         else                                                                                 \
341         {                                                                                    \
342             /* Request other core to yield if it is not requested before. */                 \
343             if( pxCurrentTCBs[ ( xCoreID ) ]->xTaskRunState != taskTASK_SCHEDULED_TO_YIELD ) \
344             {                                                                                \
345                 portYIELD_CORE( xCoreID );                                                   \
346                 pxCurrentTCBs[ ( xCoreID ) ]->xTaskRunState = taskTASK_SCHEDULED_TO_YIELD;   \
347             }                                                                                \
348         }                                                                                    \
349     } while( 0 )
350 #endif /* #if ( configNUMBER_OF_CORES > 1 ) */
351 /*-----------------------------------------------------------*/
352
353 /*
354  * Task control block.  A task control block (TCB) is allocated for each task,
355  * and stores task state information, including a pointer to the task's context
356  * (the task's run time environment, including register values)
357  */
358 typedef struct tskTaskControlBlock       /* The old naming convention is used to prevent breaking kernel aware debuggers. */
359 {
360     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. */
361
362     #if ( portUSING_MPU_WRAPPERS == 1 )
363         xMPU_SETTINGS xMPUSettings; /**< The MPU settings are defined as part of the port layer.  THIS MUST BE THE SECOND MEMBER OF THE TCB STRUCT. */
364     #endif
365
366     #if ( configUSE_CORE_AFFINITY == 1 ) && ( configNUMBER_OF_CORES > 1 )
367         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. */
368     #endif
369
370     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 ). */
371     ListItem_t xEventListItem;                  /**< Used to reference a task from an event list. */
372     UBaseType_t uxPriority;                     /**< The priority of the task.  0 is the lowest priority. */
373     StackType_t * pxStack;                      /**< Points to the start of the stack. */
374     #if ( configNUMBER_OF_CORES > 1 )
375         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. */
376         UBaseType_t uxTaskAttributes;           /**< Task's attributes - currently used to identify the idle tasks. */
377     #endif
378     char pcTaskName[ configMAX_TASK_NAME_LEN ]; /**< Descriptive name given to the task when created.  Facilitates debugging only. */
379
380     #if ( configUSE_TASK_PREEMPTION_DISABLE == 1 )
381         BaseType_t xPreemptionDisable; /**< Used to prevent the task from being preempted. */
382     #endif
383
384     #if ( ( portSTACK_GROWTH > 0 ) || ( configRECORD_STACK_HIGH_ADDRESS == 1 ) )
385         StackType_t * pxEndOfStack; /**< Points to the highest valid address for the stack. */
386     #endif
387
388     #if ( portCRITICAL_NESTING_IN_TCB == 1 )
389         UBaseType_t uxCriticalNesting; /**< Holds the critical section nesting depth for ports that do not maintain their own count in the port layer. */
390     #endif
391
392     #if ( configUSE_TRACE_FACILITY == 1 )
393         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. */
394         UBaseType_t uxTaskNumber; /**< Stores a number specifically for use by third party trace code. */
395     #endif
396
397     #if ( configUSE_MUTEXES == 1 )
398         UBaseType_t uxBasePriority; /**< The priority last assigned to the task - used by the priority inheritance mechanism. */
399         UBaseType_t uxMutexesHeld;
400     #endif
401
402     #if ( configUSE_APPLICATION_TASK_TAG == 1 )
403         TaskHookFunction_t pxTaskTag;
404     #endif
405
406     #if ( configNUM_THREAD_LOCAL_STORAGE_POINTERS > 0 )
407         void * pvThreadLocalStoragePointers[ configNUM_THREAD_LOCAL_STORAGE_POINTERS ];
408     #endif
409
410     #if ( configGENERATE_RUN_TIME_STATS == 1 )
411         configRUN_TIME_COUNTER_TYPE ulRunTimeCounter; /**< Stores the amount of time the task has spent in the Running state. */
412     #endif
413
414     #if ( configUSE_C_RUNTIME_TLS_SUPPORT == 1 )
415         configTLS_BLOCK_TYPE xTLSBlock; /**< Memory block used as Thread Local Storage (TLS) Block for the task. */
416     #endif
417
418     #if ( configUSE_TASK_NOTIFICATIONS == 1 )
419         volatile uint32_t ulNotifiedValue[ configTASK_NOTIFICATION_ARRAY_ENTRIES ];
420         volatile uint8_t ucNotifyState[ configTASK_NOTIFICATION_ARRAY_ENTRIES ];
421     #endif
422
423     /* See the comments in FreeRTOS.h with the definition of
424      * tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE. */
425     #if ( tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE != 0 )
426         uint8_t ucStaticallyAllocated; /**< Set to pdTRUE if the task is a statically allocated to ensure no attempt is made to free the memory. */
427     #endif
428
429     #if ( INCLUDE_xTaskAbortDelay == 1 )
430         uint8_t ucDelayAborted;
431     #endif
432
433     #if ( configUSE_POSIX_ERRNO == 1 )
434         int iTaskErrno;
435     #endif
436 } tskTCB;
437
438 /* The old tskTCB name is maintained above then typedefed to the new TCB_t name
439  * below to enable the use of older kernel aware debuggers. */
440 typedef tskTCB TCB_t;
441
442 #if ( configNUMBER_OF_CORES == 1 )
443     /* MISRA Ref 8.4.1 [Declaration shall be visible] */
444     /* More details at: https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/MISRA.md#rule-84 */
445     /* coverity[misra_c_2012_rule_8_4_violation] */
446     portDONT_DISCARD PRIVILEGED_DATA TCB_t * volatile pxCurrentTCB = NULL;
447 #else
448     /* MISRA Ref 8.4.1 [Declaration shall be visible] */
449     /* More details at: https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/MISRA.md#rule-84 */
450     /* coverity[misra_c_2012_rule_8_4_violation] */
451     portDONT_DISCARD PRIVILEGED_DATA TCB_t * volatile pxCurrentTCBs[ configNUMBER_OF_CORES ];
452     #define pxCurrentTCB    xTaskGetCurrentTaskHandle()
453 #endif
454
455 /* Lists for ready and blocked tasks. --------------------
456  * xDelayedTaskList1 and xDelayedTaskList2 could be moved to function scope but
457  * doing so breaks some kernel aware debuggers and debuggers that rely on removing
458  * the static qualifier. */
459 PRIVILEGED_DATA static List_t pxReadyTasksLists[ configMAX_PRIORITIES ]; /**< Prioritised ready tasks. */
460 PRIVILEGED_DATA static List_t xDelayedTaskList1;                         /**< Delayed tasks. */
461 PRIVILEGED_DATA static List_t xDelayedTaskList2;                         /**< Delayed tasks (two lists are used - one for delays that have overflowed the current tick count. */
462 PRIVILEGED_DATA static List_t * volatile pxDelayedTaskList;              /**< Points to the delayed task list currently being used. */
463 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. */
464 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. */
465
466 #if ( INCLUDE_vTaskDelete == 1 )
467
468     PRIVILEGED_DATA static List_t xTasksWaitingTermination; /**< Tasks that have been deleted - but their memory not yet freed. */
469     PRIVILEGED_DATA static volatile UBaseType_t uxDeletedTasksWaitingCleanUp = ( UBaseType_t ) 0U;
470
471 #endif
472
473 #if ( INCLUDE_vTaskSuspend == 1 )
474
475     PRIVILEGED_DATA static List_t xSuspendedTaskList; /**< Tasks that are currently suspended. */
476
477 #endif
478
479 /* Global POSIX errno. Its value is changed upon context switching to match
480  * the errno of the currently running task. */
481 #if ( configUSE_POSIX_ERRNO == 1 )
482     int FreeRTOS_errno = 0;
483 #endif
484
485 /* Other file private variables. --------------------------------*/
486 PRIVILEGED_DATA static volatile UBaseType_t uxCurrentNumberOfTasks = ( UBaseType_t ) 0U;
487 PRIVILEGED_DATA static volatile TickType_t xTickCount = ( TickType_t ) configINITIAL_TICK_COUNT;
488 PRIVILEGED_DATA static volatile UBaseType_t uxTopReadyPriority = tskIDLE_PRIORITY;
489 PRIVILEGED_DATA static volatile BaseType_t xSchedulerRunning = pdFALSE;
490 PRIVILEGED_DATA static volatile TickType_t xPendedTicks = ( TickType_t ) 0U;
491 PRIVILEGED_DATA static volatile BaseType_t xYieldPendings[ configNUMBER_OF_CORES ] = { pdFALSE };
492 PRIVILEGED_DATA static volatile BaseType_t xNumOfOverflows = ( BaseType_t ) 0;
493 PRIVILEGED_DATA static UBaseType_t uxTaskNumber = ( UBaseType_t ) 0U;
494 PRIVILEGED_DATA static volatile TickType_t xNextTaskUnblockTime = ( TickType_t ) 0U; /* Initialised to portMAX_DELAY before the scheduler starts. */
495 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. */
496
497 /* Improve support for OpenOCD. The kernel tracks Ready tasks via priority lists.
498  * For tracking the state of remote threads, OpenOCD uses uxTopUsedPriority
499  * to determine the number of priority lists to read back from the remote target. */
500 static const volatile UBaseType_t uxTopUsedPriority = configMAX_PRIORITIES - 1U;
501
502 /* Context switches are held pending while the scheduler is suspended.  Also,
503  * interrupts must not manipulate the xStateListItem of a TCB, or any of the
504  * lists the xStateListItem can be referenced from, if the scheduler is suspended.
505  * If an interrupt needs to unblock a task while the scheduler is suspended then it
506  * moves the task's event list item into the xPendingReadyList, ready for the
507  * kernel to move the task from the pending ready list into the real ready list
508  * when the scheduler is unsuspended.  The pending ready list itself can only be
509  * accessed from a critical section.
510  *
511  * Updates to uxSchedulerSuspended must be protected by both the task lock and the ISR lock
512  * and must not be done from an ISR. Reads must be protected by either lock and may be done
513  * from either an ISR or a task. */
514 PRIVILEGED_DATA static volatile UBaseType_t uxSchedulerSuspended = ( UBaseType_t ) 0U;
515
516 #if ( configGENERATE_RUN_TIME_STATS == 1 )
517
518 /* Do not move these variables to function scope as doing so prevents the
519  * code working with debuggers that need to remove the static qualifier. */
520 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. */
521 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. */
522
523 #endif
524
525 /*-----------------------------------------------------------*/
526
527 /* File private functions. --------------------------------*/
528
529 /*
530  * Creates the idle tasks during scheduler start.
531  */
532 static BaseType_t prvCreateIdleTasks( void );
533
534 #if ( configNUMBER_OF_CORES > 1 )
535
536 /*
537  * Checks to see if another task moved the current task out of the ready
538  * list while it was waiting to enter a critical section and yields, if so.
539  */
540     static void prvCheckForRunStateChange( void );
541 #endif /* #if ( configNUMBER_OF_CORES > 1 ) */
542
543 #if ( configNUMBER_OF_CORES > 1 )
544
545 /*
546  * Yields a core, or cores if multiple priorities are not allowed to run
547  * simultaneously, to allow the task pxTCB to run.
548  */
549     static void prvYieldForTask( const TCB_t * pxTCB );
550 #endif /* #if ( configNUMBER_OF_CORES > 1 ) */
551
552 #if ( configNUMBER_OF_CORES > 1 )
553
554 /*
555  * Selects the highest priority available task for the given core.
556  */
557     static void prvSelectHighestPriorityTask( BaseType_t xCoreID );
558 #endif /* #if ( configNUMBER_OF_CORES > 1 ) */
559
560 /**
561  * Utility task that simply returns pdTRUE if the task referenced by xTask is
562  * currently in the Suspended state, or pdFALSE if the task referenced by xTask
563  * is in any other state.
564  */
565 #if ( INCLUDE_vTaskSuspend == 1 )
566
567     static BaseType_t prvTaskIsTaskSuspended( const TaskHandle_t xTask ) PRIVILEGED_FUNCTION;
568
569 #endif /* INCLUDE_vTaskSuspend */
570
571 /*
572  * Utility to ready all the lists used by the scheduler.  This is called
573  * automatically upon the creation of the first task.
574  */
575 static void prvInitialiseTaskLists( void ) PRIVILEGED_FUNCTION;
576
577 /*
578  * The idle task, which as all tasks is implemented as a never ending loop.
579  * The idle task is automatically created and added to the ready lists upon
580  * creation of the first user task.
581  *
582  * In the FreeRTOS SMP, configNUMBER_OF_CORES - 1 passive idle tasks are also
583  * created to ensure that each core has an idle task to run when no other
584  * task is available to run.
585  *
586  * The portTASK_FUNCTION_PROTO() macro is used to allow port/compiler specific
587  * language extensions.  The equivalent prototype for these functions are:
588  *
589  * void prvIdleTask( void *pvParameters );
590  * void prvPassiveIdleTask( void *pvParameters );
591  *
592  */
593 static portTASK_FUNCTION_PROTO( prvIdleTask, pvParameters ) PRIVILEGED_FUNCTION;
594 #if ( configNUMBER_OF_CORES > 1 )
595     static portTASK_FUNCTION_PROTO( prvPassiveIdleTask, pvParameters ) PRIVILEGED_FUNCTION;
596 #endif
597
598 /*
599  * Utility to free all memory allocated by the scheduler to hold a TCB,
600  * including the stack pointed to by the TCB.
601  *
602  * This does not free memory allocated by the task itself (i.e. memory
603  * allocated by calls to pvPortMalloc from within the tasks application code).
604  */
605 #if ( INCLUDE_vTaskDelete == 1 )
606
607     static void prvDeleteTCB( TCB_t * pxTCB ) PRIVILEGED_FUNCTION;
608
609 #endif
610
611 /*
612  * Used only by the idle task.  This checks to see if anything has been placed
613  * in the list of tasks waiting to be deleted.  If so the task is cleaned up
614  * and its TCB deleted.
615  */
616 static void prvCheckTasksWaitingTermination( void ) PRIVILEGED_FUNCTION;
617
618 /*
619  * The currently executing task is entering the Blocked state.  Add the task to
620  * either the current or the overflow delayed task list.
621  */
622 static void prvAddCurrentTaskToDelayedList( TickType_t xTicksToWait,
623                                             const BaseType_t xCanBlockIndefinitely ) PRIVILEGED_FUNCTION;
624
625 /*
626  * Fills an TaskStatus_t structure with information on each task that is
627  * referenced from the pxList list (which may be a ready list, a delayed list,
628  * a suspended list, etc.).
629  *
630  * THIS FUNCTION IS INTENDED FOR DEBUGGING ONLY, AND SHOULD NOT BE CALLED FROM
631  * NORMAL APPLICATION CODE.
632  */
633 #if ( configUSE_TRACE_FACILITY == 1 )
634
635     static UBaseType_t prvListTasksWithinSingleList( TaskStatus_t * pxTaskStatusArray,
636                                                      List_t * pxList,
637                                                      eTaskState eState ) PRIVILEGED_FUNCTION;
638
639 #endif
640
641 /*
642  * Searches pxList for a task with name pcNameToQuery - returning a handle to
643  * the task if it is found, or NULL if the task is not found.
644  */
645 #if ( INCLUDE_xTaskGetHandle == 1 )
646
647     static TCB_t * prvSearchForNameWithinSingleList( List_t * pxList,
648                                                      const char pcNameToQuery[] ) PRIVILEGED_FUNCTION;
649
650 #endif
651
652 /*
653  * When a task is created, the stack of the task is filled with a known value.
654  * This function determines the 'high water mark' of the task stack by
655  * determining how much of the stack remains at the original preset value.
656  */
657 #if ( ( configUSE_TRACE_FACILITY == 1 ) || ( INCLUDE_uxTaskGetStackHighWaterMark == 1 ) || ( INCLUDE_uxTaskGetStackHighWaterMark2 == 1 ) )
658
659     static configSTACK_DEPTH_TYPE prvTaskCheckFreeStackSpace( const uint8_t * pucStackByte ) PRIVILEGED_FUNCTION;
660
661 #endif
662
663 /*
664  * Return the amount of time, in ticks, that will pass before the kernel will
665  * next move a task from the Blocked state to the Running state or before the
666  * tick count overflows (whichever is earlier).
667  *
668  * This conditional compilation should use inequality to 0, not equality to 1.
669  * This is to ensure portSUPPRESS_TICKS_AND_SLEEP() can be called when user
670  * defined low power mode implementations require configUSE_TICKLESS_IDLE to be
671  * set to a value other than 1.
672  */
673 #if ( configUSE_TICKLESS_IDLE != 0 )
674
675     static TickType_t prvGetExpectedIdleTime( void ) PRIVILEGED_FUNCTION;
676
677 #endif
678
679 /*
680  * Set xNextTaskUnblockTime to the time at which the next Blocked state task
681  * will exit the Blocked state.
682  */
683 static void prvResetNextTaskUnblockTime( void ) PRIVILEGED_FUNCTION;
684
685 #if ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 )
686
687 /*
688  * Helper function used to pad task names with spaces when printing out
689  * human readable tables of task information.
690  */
691     static char * prvWriteNameToBuffer( char * pcBuffer,
692                                         const char * pcTaskName ) PRIVILEGED_FUNCTION;
693
694 #endif
695
696 /*
697  * Called after a Task_t structure has been allocated either statically or
698  * dynamically to fill in the structure's members.
699  */
700 static void prvInitialiseNewTask( TaskFunction_t pxTaskCode,
701                                   const char * const pcName,
702                                   const configSTACK_DEPTH_TYPE uxStackDepth,
703                                   void * const pvParameters,
704                                   UBaseType_t uxPriority,
705                                   TaskHandle_t * const pxCreatedTask,
706                                   TCB_t * pxNewTCB,
707                                   const MemoryRegion_t * const xRegions ) PRIVILEGED_FUNCTION;
708
709 /*
710  * Called after a new task has been created and initialised to place the task
711  * under the control of the scheduler.
712  */
713 static void prvAddNewTaskToReadyList( TCB_t * pxNewTCB ) PRIVILEGED_FUNCTION;
714
715 /*
716  * Create a task with static buffer for both TCB and stack. Returns a handle to
717  * the task if it is created successfully. Otherwise, returns NULL.
718  */
719 #if ( configSUPPORT_STATIC_ALLOCATION == 1 )
720     static TCB_t * prvCreateStaticTask( TaskFunction_t pxTaskCode,
721                                         const char * const pcName,
722                                         const configSTACK_DEPTH_TYPE uxStackDepth,
723                                         void * const pvParameters,
724                                         UBaseType_t uxPriority,
725                                         StackType_t * const puxStackBuffer,
726                                         StaticTask_t * const pxTaskBuffer,
727                                         TaskHandle_t * const pxCreatedTask ) PRIVILEGED_FUNCTION;
728 #endif /* #if ( configSUPPORT_STATIC_ALLOCATION == 1 ) */
729
730 /*
731  * Create a restricted task with static buffer for both TCB and stack. Returns
732  * a handle to the task if it is created successfully. Otherwise, returns NULL.
733  */
734 #if ( ( portUSING_MPU_WRAPPERS == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 1 ) )
735     static TCB_t * prvCreateRestrictedStaticTask( const TaskParameters_t * const pxTaskDefinition,
736                                                   TaskHandle_t * const pxCreatedTask ) PRIVILEGED_FUNCTION;
737 #endif /* #if ( ( portUSING_MPU_WRAPPERS == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 1 ) ) */
738
739 /*
740  * Create a restricted task with static buffer for task stack and allocated buffer
741  * for TCB. Returns a handle to the task if it is created successfully. Otherwise,
742  * returns NULL.
743  */
744 #if ( ( portUSING_MPU_WRAPPERS == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) )
745     static TCB_t * prvCreateRestrictedTask( const TaskParameters_t * const pxTaskDefinition,
746                                             TaskHandle_t * const pxCreatedTask ) PRIVILEGED_FUNCTION;
747 #endif /* #if ( ( portUSING_MPU_WRAPPERS == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) ) */
748
749 /*
750  * Create a task with allocated buffer for both TCB and stack. Returns a handle to
751  * the task if it is created successfully. Otherwise, returns NULL.
752  */
753 #if ( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
754     static TCB_t * prvCreateTask( TaskFunction_t pxTaskCode,
755                                   const char * const pcName,
756                                   const configSTACK_DEPTH_TYPE uxStackDepth,
757                                   void * const pvParameters,
758                                   UBaseType_t uxPriority,
759                                   TaskHandle_t * const pxCreatedTask ) PRIVILEGED_FUNCTION;
760 #endif /* #if ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) */
761
762 /*
763  * freertos_tasks_c_additions_init() should only be called if the user definable
764  * macro FREERTOS_TASKS_C_ADDITIONS_INIT() is defined, as that is the only macro
765  * called by the function.
766  */
767 #ifdef FREERTOS_TASKS_C_ADDITIONS_INIT
768
769     static void freertos_tasks_c_additions_init( void ) PRIVILEGED_FUNCTION;
770
771 #endif
772
773 #if ( configUSE_PASSIVE_IDLE_HOOK == 1 )
774     extern void vApplicationPassiveIdleHook( void );
775 #endif /* #if ( configUSE_PASSIVE_IDLE_HOOK == 1 ) */
776
777 #if ( ( configUSE_TRACE_FACILITY == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 ) )
778
779 /*
780  * Convert the snprintf return value to the number of characters
781  * written. The following are the possible cases:
782  *
783  * 1. The buffer supplied to snprintf is large enough to hold the
784  *    generated string. The return value in this case is the number
785  *    of characters actually written, not counting the terminating
786  *    null character.
787  * 2. The buffer supplied to snprintf is NOT large enough to hold
788  *    the generated string. The return value in this case is the
789  *    number of characters that would have been written if the
790  *    buffer had been sufficiently large, not counting the
791  *    terminating null character.
792  * 3. Encoding error. The return value in this case is a negative
793  *    number.
794  *
795  * From 1 and 2 above ==> Only when the return value is non-negative
796  * and less than the supplied buffer length, the string has been
797  * completely written.
798  */
799     static size_t prvSnprintfReturnValueToCharsWritten( int iSnprintfReturnValue,
800                                                         size_t n );
801
802 #endif /* #if ( ( configUSE_TRACE_FACILITY == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 ) ) */
803 /*-----------------------------------------------------------*/
804
805 #if ( configNUMBER_OF_CORES > 1 )
806     static void prvCheckForRunStateChange( void )
807     {
808         UBaseType_t uxPrevCriticalNesting;
809         const TCB_t * pxThisTCB;
810
811         /* This must only be called from within a task. */
812         portASSERT_IF_IN_ISR();
813
814         /* This function is always called with interrupts disabled
815          * so this is safe. */
816         pxThisTCB = pxCurrentTCBs[ portGET_CORE_ID() ];
817
818         while( pxThisTCB->xTaskRunState == taskTASK_SCHEDULED_TO_YIELD )
819         {
820             /* We are only here if we just entered a critical section
821             * or if we just suspended the scheduler, and another task
822             * has requested that we yield.
823             *
824             * This is slightly complicated since we need to save and restore
825             * the suspension and critical nesting counts, as well as release
826             * and reacquire the correct locks. And then, do it all over again
827             * if our state changed again during the reacquisition. */
828             uxPrevCriticalNesting = portGET_CRITICAL_NESTING_COUNT();
829
830             if( uxPrevCriticalNesting > 0U )
831             {
832                 portSET_CRITICAL_NESTING_COUNT( 0U );
833                 portRELEASE_ISR_LOCK();
834             }
835             else
836             {
837                 /* The scheduler is suspended. uxSchedulerSuspended is updated
838                  * only when the task is not requested to yield. */
839                 mtCOVERAGE_TEST_MARKER();
840             }
841
842             portRELEASE_TASK_LOCK();
843             portMEMORY_BARRIER();
844             configASSERT( pxThisTCB->xTaskRunState == taskTASK_SCHEDULED_TO_YIELD );
845
846             portENABLE_INTERRUPTS();
847
848             /* Enabling interrupts should cause this core to immediately service
849              * the pending interrupt and yield. After servicing the pending interrupt,
850              * the task needs to re-evaluate its run state within this loop, as
851              * other cores may have requested this task to yield, potentially altering
852              * its run state. */
853
854             portDISABLE_INTERRUPTS();
855             portGET_TASK_LOCK();
856             portGET_ISR_LOCK();
857
858             portSET_CRITICAL_NESTING_COUNT( uxPrevCriticalNesting );
859
860             if( uxPrevCriticalNesting == 0U )
861             {
862                 portRELEASE_ISR_LOCK();
863             }
864         }
865     }
866 #endif /* #if ( configNUMBER_OF_CORES > 1 ) */
867
868 /*-----------------------------------------------------------*/
869
870 #if ( configNUMBER_OF_CORES > 1 )
871     static void prvYieldForTask( const TCB_t * pxTCB )
872     {
873         BaseType_t xLowestPriorityToPreempt;
874         BaseType_t xCurrentCoreTaskPriority;
875         BaseType_t xLowestPriorityCore = ( BaseType_t ) -1;
876         BaseType_t xCoreID;
877
878         #if ( configRUN_MULTIPLE_PRIORITIES == 0 )
879             BaseType_t xYieldCount = 0;
880         #endif /* #if ( configRUN_MULTIPLE_PRIORITIES == 0 ) */
881
882         /* This must be called from a critical section. */
883         configASSERT( portGET_CRITICAL_NESTING_COUNT() > 0U );
884
885         #if ( configRUN_MULTIPLE_PRIORITIES == 0 )
886
887             /* No task should yield for this one if it is a lower priority
888              * than priority level of currently ready tasks. */
889             if( pxTCB->uxPriority >= uxTopReadyPriority )
890         #else
891             /* Yield is not required for a task which is already running. */
892             if( taskTASK_IS_RUNNING( pxTCB ) == pdFALSE )
893         #endif
894         {
895             xLowestPriorityToPreempt = ( BaseType_t ) pxTCB->uxPriority;
896
897             /* xLowestPriorityToPreempt will be decremented to -1 if the priority of pxTCB
898              * is 0. This is ok as we will give system idle tasks a priority of -1 below. */
899             --xLowestPriorityToPreempt;
900
901             for( xCoreID = ( BaseType_t ) 0; xCoreID < ( BaseType_t ) configNUMBER_OF_CORES; xCoreID++ )
902             {
903                 xCurrentCoreTaskPriority = ( BaseType_t ) pxCurrentTCBs[ xCoreID ]->uxPriority;
904
905                 /* System idle tasks are being assigned a priority of tskIDLE_PRIORITY - 1 here. */
906                 if( ( pxCurrentTCBs[ xCoreID ]->uxTaskAttributes & taskATTRIBUTE_IS_IDLE ) != 0U )
907                 {
908                     xCurrentCoreTaskPriority = ( BaseType_t ) ( xCurrentCoreTaskPriority - 1 );
909                 }
910
911                 if( ( taskTASK_IS_RUNNING( pxCurrentTCBs[ xCoreID ] ) != pdFALSE ) && ( xYieldPendings[ xCoreID ] == pdFALSE ) )
912                 {
913                     #if ( configRUN_MULTIPLE_PRIORITIES == 0 )
914                         if( taskTASK_IS_RUNNING( pxTCB ) == pdFALSE )
915                     #endif
916                     {
917                         if( xCurrentCoreTaskPriority <= xLowestPriorityToPreempt )
918                         {
919                             #if ( configUSE_CORE_AFFINITY == 1 )
920                                 if( ( pxTCB->uxCoreAffinityMask & ( ( UBaseType_t ) 1U << ( UBaseType_t ) xCoreID ) ) != 0U )
921                             #endif
922                             {
923                                 #if ( configUSE_TASK_PREEMPTION_DISABLE == 1 )
924                                     if( pxCurrentTCBs[ xCoreID ]->xPreemptionDisable == pdFALSE )
925                                 #endif
926                                 {
927                                     xLowestPriorityToPreempt = xCurrentCoreTaskPriority;
928                                     xLowestPriorityCore = xCoreID;
929                                 }
930                             }
931                         }
932                         else
933                         {
934                             mtCOVERAGE_TEST_MARKER();
935                         }
936                     }
937
938                     #if ( configRUN_MULTIPLE_PRIORITIES == 0 )
939                     {
940                         /* Yield all currently running non-idle tasks with a priority lower than
941                          * the task that needs to run. */
942                         if( ( xCurrentCoreTaskPriority > ( ( BaseType_t ) tskIDLE_PRIORITY - 1 ) ) &&
943                             ( xCurrentCoreTaskPriority < ( BaseType_t ) pxTCB->uxPriority ) )
944                         {
945                             prvYieldCore( xCoreID );
946                             xYieldCount++;
947                         }
948                         else
949                         {
950                             mtCOVERAGE_TEST_MARKER();
951                         }
952                     }
953                     #endif /* #if ( configRUN_MULTIPLE_PRIORITIES == 0 ) */
954                 }
955                 else
956                 {
957                     mtCOVERAGE_TEST_MARKER();
958                 }
959             }
960
961             #if ( configRUN_MULTIPLE_PRIORITIES == 0 )
962                 if( ( xYieldCount == 0 ) && ( xLowestPriorityCore >= 0 ) )
963             #else /* #if ( configRUN_MULTIPLE_PRIORITIES == 0 ) */
964                 if( xLowestPriorityCore >= 0 )
965             #endif /* #if ( configRUN_MULTIPLE_PRIORITIES == 0 ) */
966             {
967                 prvYieldCore( xLowestPriorityCore );
968             }
969
970             #if ( configRUN_MULTIPLE_PRIORITIES == 0 )
971                 /* Verify that the calling core always yields to higher priority tasks. */
972                 if( ( ( pxCurrentTCBs[ portGET_CORE_ID() ]->uxTaskAttributes & taskATTRIBUTE_IS_IDLE ) == 0U ) &&
973                     ( pxTCB->uxPriority > pxCurrentTCBs[ portGET_CORE_ID() ]->uxPriority ) )
974                 {
975                     configASSERT( ( xYieldPendings[ portGET_CORE_ID() ] == pdTRUE ) ||
976                                   ( taskTASK_IS_RUNNING( pxCurrentTCBs[ portGET_CORE_ID() ] ) == pdFALSE ) );
977                 }
978             #endif
979         }
980     }
981 #endif /* #if ( configNUMBER_OF_CORES > 1 ) */
982 /*-----------------------------------------------------------*/
983
984 #if ( configNUMBER_OF_CORES > 1 )
985     static void prvSelectHighestPriorityTask( BaseType_t xCoreID )
986     {
987         UBaseType_t uxCurrentPriority = uxTopReadyPriority;
988         BaseType_t xTaskScheduled = pdFALSE;
989         BaseType_t xDecrementTopPriority = pdTRUE;
990         TCB_t * pxTCB = NULL;
991
992         #if ( configUSE_CORE_AFFINITY == 1 )
993             const TCB_t * pxPreviousTCB = NULL;
994         #endif
995         #if ( configRUN_MULTIPLE_PRIORITIES == 0 )
996             BaseType_t xPriorityDropped = pdFALSE;
997         #endif
998
999         /* This function should be called when scheduler is running. */
1000         configASSERT( xSchedulerRunning == pdTRUE );
1001
1002         /* A new task is created and a running task with the same priority yields
1003          * itself to run the new task. When a running task yields itself, it is still
1004          * in the ready list. This running task will be selected before the new task
1005          * since the new task is always added to the end of the ready list.
1006          * The other problem is that the running task still in the same position of
1007          * the ready list when it yields itself. It is possible that it will be selected
1008          * earlier then other tasks which waits longer than this task.
1009          *
1010          * To fix these problems, the running task should be put to the end of the
1011          * ready list before searching for the ready task in the ready list. */
1012         if( listIS_CONTAINED_WITHIN( &( pxReadyTasksLists[ pxCurrentTCBs[ xCoreID ]->uxPriority ] ),
1013                                      &pxCurrentTCBs[ xCoreID ]->xStateListItem ) == pdTRUE )
1014         {
1015             ( void ) uxListRemove( &pxCurrentTCBs[ xCoreID ]->xStateListItem );
1016             vListInsertEnd( &( pxReadyTasksLists[ pxCurrentTCBs[ xCoreID ]->uxPriority ] ),
1017                             &pxCurrentTCBs[ xCoreID ]->xStateListItem );
1018         }
1019
1020         while( xTaskScheduled == pdFALSE )
1021         {
1022             #if ( configRUN_MULTIPLE_PRIORITIES == 0 )
1023             {
1024                 if( uxCurrentPriority < uxTopReadyPriority )
1025                 {
1026                     /* We can't schedule any tasks, other than idle, that have a
1027                      * priority lower than the priority of a task currently running
1028                      * on another core. */
1029                     uxCurrentPriority = tskIDLE_PRIORITY;
1030                 }
1031             }
1032             #endif
1033
1034             if( listLIST_IS_EMPTY( &( pxReadyTasksLists[ uxCurrentPriority ] ) ) == pdFALSE )
1035             {
1036                 const List_t * const pxReadyList = &( pxReadyTasksLists[ uxCurrentPriority ] );
1037                 const ListItem_t * pxEndMarker = listGET_END_MARKER( pxReadyList );
1038                 ListItem_t * pxIterator;
1039
1040                 /* The ready task list for uxCurrentPriority is not empty, so uxTopReadyPriority
1041                  * must not be decremented any further. */
1042                 xDecrementTopPriority = pdFALSE;
1043
1044                 for( pxIterator = listGET_HEAD_ENTRY( pxReadyList ); pxIterator != pxEndMarker; pxIterator = listGET_NEXT( pxIterator ) )
1045                 {
1046                     /* MISRA Ref 11.5.3 [Void pointer assignment] */
1047                     /* More details at: https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/MISRA.md#rule-115 */
1048                     /* coverity[misra_c_2012_rule_11_5_violation] */
1049                     pxTCB = ( TCB_t * ) listGET_LIST_ITEM_OWNER( pxIterator );
1050
1051                     #if ( configRUN_MULTIPLE_PRIORITIES == 0 )
1052                     {
1053                         /* When falling back to the idle priority because only one priority
1054                          * level is allowed to run at a time, we should ONLY schedule the true
1055                          * idle tasks, not user tasks at the idle priority. */
1056                         if( uxCurrentPriority < uxTopReadyPriority )
1057                         {
1058                             if( ( pxTCB->uxTaskAttributes & taskATTRIBUTE_IS_IDLE ) == 0U )
1059                             {
1060                                 continue;
1061                             }
1062                         }
1063                     }
1064                     #endif /* #if ( configRUN_MULTIPLE_PRIORITIES == 0 ) */
1065
1066                     if( pxTCB->xTaskRunState == taskTASK_NOT_RUNNING )
1067                     {
1068                         #if ( configUSE_CORE_AFFINITY == 1 )
1069                             if( ( pxTCB->uxCoreAffinityMask & ( ( UBaseType_t ) 1U << ( UBaseType_t ) xCoreID ) ) != 0U )
1070                         #endif
1071                         {
1072                             /* If the task is not being executed by any core swap it in. */
1073                             pxCurrentTCBs[ xCoreID ]->xTaskRunState = taskTASK_NOT_RUNNING;
1074                             #if ( configUSE_CORE_AFFINITY == 1 )
1075                                 pxPreviousTCB = pxCurrentTCBs[ xCoreID ];
1076                             #endif
1077                             pxTCB->xTaskRunState = xCoreID;
1078                             pxCurrentTCBs[ xCoreID ] = pxTCB;
1079                             xTaskScheduled = pdTRUE;
1080                         }
1081                     }
1082                     else if( pxTCB == pxCurrentTCBs[ xCoreID ] )
1083                     {
1084                         configASSERT( ( pxTCB->xTaskRunState == xCoreID ) || ( pxTCB->xTaskRunState == taskTASK_SCHEDULED_TO_YIELD ) );
1085
1086                         #if ( configUSE_CORE_AFFINITY == 1 )
1087                             if( ( pxTCB->uxCoreAffinityMask & ( ( UBaseType_t ) 1U << ( UBaseType_t ) xCoreID ) ) != 0U )
1088                         #endif
1089                         {
1090                             /* The task is already running on this core, mark it as scheduled. */
1091                             pxTCB->xTaskRunState = xCoreID;
1092                             xTaskScheduled = pdTRUE;
1093                         }
1094                     }
1095                     else
1096                     {
1097                         /* This task is running on the core other than xCoreID. */
1098                         mtCOVERAGE_TEST_MARKER();
1099                     }
1100
1101                     if( xTaskScheduled != pdFALSE )
1102                     {
1103                         /* A task has been selected to run on this core. */
1104                         break;
1105                     }
1106                 }
1107             }
1108             else
1109             {
1110                 if( xDecrementTopPriority != pdFALSE )
1111                 {
1112                     uxTopReadyPriority--;
1113                     #if ( configRUN_MULTIPLE_PRIORITIES == 0 )
1114                     {
1115                         xPriorityDropped = pdTRUE;
1116                     }
1117                     #endif
1118                 }
1119             }
1120
1121             /* There are configNUMBER_OF_CORES Idle tasks created when scheduler started.
1122              * The scheduler should be able to select a task to run when uxCurrentPriority
1123              * is tskIDLE_PRIORITY. uxCurrentPriority is never decreased to value blow
1124              * tskIDLE_PRIORITY. */
1125             if( uxCurrentPriority > tskIDLE_PRIORITY )
1126             {
1127                 uxCurrentPriority--;
1128             }
1129             else
1130             {
1131                 /* This function is called when idle task is not created. Break the
1132                  * loop to prevent uxCurrentPriority overrun. */
1133                 break;
1134             }
1135         }
1136
1137         #if ( configRUN_MULTIPLE_PRIORITIES == 0 )
1138         {
1139             if( xTaskScheduled == pdTRUE )
1140             {
1141                 if( xPriorityDropped != pdFALSE )
1142                 {
1143                     /* There may be several ready tasks that were being prevented from running because there was
1144                      * a higher priority task running. Now that the last of the higher priority tasks is no longer
1145                      * running, make sure all the other idle tasks yield. */
1146                     BaseType_t x;
1147
1148                     for( x = ( BaseType_t ) 0; x < ( BaseType_t ) configNUMBER_OF_CORES; x++ )
1149                     {
1150                         if( ( pxCurrentTCBs[ x ]->uxTaskAttributes & taskATTRIBUTE_IS_IDLE ) != 0U )
1151                         {
1152                             prvYieldCore( x );
1153                         }
1154                     }
1155                 }
1156             }
1157         }
1158         #endif /* #if ( configRUN_MULTIPLE_PRIORITIES == 0 ) */
1159
1160         #if ( configUSE_CORE_AFFINITY == 1 )
1161         {
1162             if( xTaskScheduled == pdTRUE )
1163             {
1164                 if( ( pxPreviousTCB != NULL ) && ( listIS_CONTAINED_WITHIN( &( pxReadyTasksLists[ pxPreviousTCB->uxPriority ] ), &( pxPreviousTCB->xStateListItem ) ) != pdFALSE ) )
1165                 {
1166                     /* A ready task was just evicted from this core. See if it can be
1167                      * scheduled on any other core. */
1168                     UBaseType_t uxCoreMap = pxPreviousTCB->uxCoreAffinityMask;
1169                     BaseType_t xLowestPriority = ( BaseType_t ) pxPreviousTCB->uxPriority;
1170                     BaseType_t xLowestPriorityCore = -1;
1171                     BaseType_t x;
1172
1173                     if( ( pxPreviousTCB->uxTaskAttributes & taskATTRIBUTE_IS_IDLE ) != 0U )
1174                     {
1175                         xLowestPriority = xLowestPriority - 1;
1176                     }
1177
1178                     if( ( uxCoreMap & ( ( UBaseType_t ) 1U << ( UBaseType_t ) xCoreID ) ) != 0U )
1179                     {
1180                         /* pxPreviousTCB was removed from this core and this core is not excluded
1181                          * from it's core affinity mask.
1182                          *
1183                          * pxPreviousTCB is preempted by the new higher priority task
1184                          * pxCurrentTCBs[ xCoreID ]. When searching a new core for pxPreviousTCB,
1185                          * we do not need to look at the cores on which pxCurrentTCBs[ xCoreID ]
1186                          * is allowed to run. The reason is - when more than one cores are
1187                          * eligible for an incoming task, we preempt the core with the minimum
1188                          * priority task. Because this core (i.e. xCoreID) was preempted for
1189                          * pxCurrentTCBs[ xCoreID ], this means that all the others cores
1190                          * where pxCurrentTCBs[ xCoreID ] can run, are running tasks with priority
1191                          * no lower than pxPreviousTCB's priority. Therefore, the only cores where
1192                          * which can be preempted for pxPreviousTCB are the ones where
1193                          * pxCurrentTCBs[ xCoreID ] is not allowed to run (and obviously,
1194                          * pxPreviousTCB is allowed to run).
1195                          *
1196                          * This is an optimization which reduces the number of cores needed to be
1197                          * searched for pxPreviousTCB to run. */
1198                         uxCoreMap &= ~( pxCurrentTCBs[ xCoreID ]->uxCoreAffinityMask );
1199                     }
1200                     else
1201                     {
1202                         /* pxPreviousTCB's core affinity mask is changed and it is no longer
1203                          * allowed to run on this core. Searching all the cores in pxPreviousTCB's
1204                          * new core affinity mask to find a core on which it can run. */
1205                     }
1206
1207                     uxCoreMap &= ( ( 1U << configNUMBER_OF_CORES ) - 1U );
1208
1209                     for( x = ( ( BaseType_t ) configNUMBER_OF_CORES - 1 ); x >= ( BaseType_t ) 0; x-- )
1210                     {
1211                         UBaseType_t uxCore = ( UBaseType_t ) x;
1212                         BaseType_t xTaskPriority;
1213
1214                         if( ( uxCoreMap & ( ( UBaseType_t ) 1U << uxCore ) ) != 0U )
1215                         {
1216                             xTaskPriority = ( BaseType_t ) pxCurrentTCBs[ uxCore ]->uxPriority;
1217
1218                             if( ( pxCurrentTCBs[ uxCore ]->uxTaskAttributes & taskATTRIBUTE_IS_IDLE ) != 0U )
1219                             {
1220                                 xTaskPriority = xTaskPriority - ( BaseType_t ) 1;
1221                             }
1222
1223                             uxCoreMap &= ~( ( UBaseType_t ) 1U << uxCore );
1224
1225                             if( ( xTaskPriority < xLowestPriority ) &&
1226                                 ( taskTASK_IS_RUNNING( pxCurrentTCBs[ uxCore ] ) != pdFALSE ) &&
1227                                 ( xYieldPendings[ uxCore ] == pdFALSE ) )
1228                             {
1229                                 #if ( configUSE_TASK_PREEMPTION_DISABLE == 1 )
1230                                     if( pxCurrentTCBs[ uxCore ]->xPreemptionDisable == pdFALSE )
1231                                 #endif
1232                                 {
1233                                     xLowestPriority = xTaskPriority;
1234                                     xLowestPriorityCore = ( BaseType_t ) uxCore;
1235                                 }
1236                             }
1237                         }
1238                     }
1239
1240                     if( xLowestPriorityCore >= 0 )
1241                     {
1242                         prvYieldCore( xLowestPriorityCore );
1243                     }
1244                 }
1245             }
1246         }
1247         #endif /* #if ( configUSE_CORE_AFFINITY == 1 ) */
1248     }
1249
1250 #endif /* ( configNUMBER_OF_CORES > 1 ) */
1251
1252 /*-----------------------------------------------------------*/
1253
1254 #if ( configSUPPORT_STATIC_ALLOCATION == 1 )
1255
1256     static TCB_t * prvCreateStaticTask( TaskFunction_t pxTaskCode,
1257                                         const char * const pcName,
1258                                         const configSTACK_DEPTH_TYPE uxStackDepth,
1259                                         void * const pvParameters,
1260                                         UBaseType_t uxPriority,
1261                                         StackType_t * const puxStackBuffer,
1262                                         StaticTask_t * const pxTaskBuffer,
1263                                         TaskHandle_t * const pxCreatedTask )
1264     {
1265         TCB_t * pxNewTCB;
1266
1267         configASSERT( puxStackBuffer != NULL );
1268         configASSERT( pxTaskBuffer != NULL );
1269
1270         #if ( configASSERT_DEFINED == 1 )
1271         {
1272             /* Sanity check that the size of the structure used to declare a
1273              * variable of type StaticTask_t equals the size of the real task
1274              * structure. */
1275             volatile size_t xSize = sizeof( StaticTask_t );
1276             configASSERT( xSize == sizeof( TCB_t ) );
1277             ( void ) xSize; /* Prevent unused variable warning when configASSERT() is not used. */
1278         }
1279         #endif /* configASSERT_DEFINED */
1280
1281         if( ( pxTaskBuffer != NULL ) && ( puxStackBuffer != NULL ) )
1282         {
1283             /* The memory used for the task's TCB and stack are passed into this
1284              * function - use them. */
1285             /* MISRA Ref 11.3.1 [Misaligned access] */
1286             /* More details at: https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/MISRA.md#rule-113 */
1287             /* coverity[misra_c_2012_rule_11_3_violation] */
1288             pxNewTCB = ( TCB_t * ) pxTaskBuffer;
1289             ( void ) memset( ( void * ) pxNewTCB, 0x00, sizeof( TCB_t ) );
1290             pxNewTCB->pxStack = ( StackType_t * ) puxStackBuffer;
1291
1292             #if ( tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE != 0 )
1293             {
1294                 /* Tasks can be created statically or dynamically, so note this
1295                  * task was created statically in case the task is later deleted. */
1296                 pxNewTCB->ucStaticallyAllocated = tskSTATICALLY_ALLOCATED_STACK_AND_TCB;
1297             }
1298             #endif /* tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE */
1299
1300             prvInitialiseNewTask( pxTaskCode, pcName, uxStackDepth, pvParameters, uxPriority, pxCreatedTask, pxNewTCB, NULL );
1301         }
1302         else
1303         {
1304             pxNewTCB = NULL;
1305         }
1306
1307         return pxNewTCB;
1308     }
1309 /*-----------------------------------------------------------*/
1310
1311     TaskHandle_t xTaskCreateStatic( TaskFunction_t pxTaskCode,
1312                                     const char * const pcName,
1313                                     const configSTACK_DEPTH_TYPE uxStackDepth,
1314                                     void * const pvParameters,
1315                                     UBaseType_t uxPriority,
1316                                     StackType_t * const puxStackBuffer,
1317                                     StaticTask_t * const pxTaskBuffer )
1318     {
1319         TaskHandle_t xReturn = NULL;
1320         TCB_t * pxNewTCB;
1321
1322         traceENTER_xTaskCreateStatic( pxTaskCode, pcName, uxStackDepth, pvParameters, uxPriority, puxStackBuffer, pxTaskBuffer );
1323
1324         pxNewTCB = prvCreateStaticTask( pxTaskCode, pcName, uxStackDepth, pvParameters, uxPriority, puxStackBuffer, pxTaskBuffer, &xReturn );
1325
1326         if( pxNewTCB != NULL )
1327         {
1328             #if ( ( configNUMBER_OF_CORES > 1 ) && ( configUSE_CORE_AFFINITY == 1 ) )
1329             {
1330                 /* Set the task's affinity before scheduling it. */
1331                 pxNewTCB->uxCoreAffinityMask = configTASK_DEFAULT_CORE_AFFINITY;
1332             }
1333             #endif
1334
1335             prvAddNewTaskToReadyList( pxNewTCB );
1336         }
1337         else
1338         {
1339             mtCOVERAGE_TEST_MARKER();
1340         }
1341
1342         traceRETURN_xTaskCreateStatic( xReturn );
1343
1344         return xReturn;
1345     }
1346 /*-----------------------------------------------------------*/
1347
1348     #if ( ( configNUMBER_OF_CORES > 1 ) && ( configUSE_CORE_AFFINITY == 1 ) )
1349         TaskHandle_t xTaskCreateStaticAffinitySet( TaskFunction_t pxTaskCode,
1350                                                    const char * const pcName,
1351                                                    const configSTACK_DEPTH_TYPE uxStackDepth,
1352                                                    void * const pvParameters,
1353                                                    UBaseType_t uxPriority,
1354                                                    StackType_t * const puxStackBuffer,
1355                                                    StaticTask_t * const pxTaskBuffer,
1356                                                    UBaseType_t uxCoreAffinityMask )
1357         {
1358             TaskHandle_t xReturn = NULL;
1359             TCB_t * pxNewTCB;
1360
1361             traceENTER_xTaskCreateStaticAffinitySet( pxTaskCode, pcName, uxStackDepth, pvParameters, uxPriority, puxStackBuffer, pxTaskBuffer, uxCoreAffinityMask );
1362
1363             pxNewTCB = prvCreateStaticTask( pxTaskCode, pcName, uxStackDepth, pvParameters, uxPriority, puxStackBuffer, pxTaskBuffer, &xReturn );
1364
1365             if( pxNewTCB != NULL )
1366             {
1367                 /* Set the task's affinity before scheduling it. */
1368                 pxNewTCB->uxCoreAffinityMask = uxCoreAffinityMask;
1369
1370                 prvAddNewTaskToReadyList( pxNewTCB );
1371             }
1372             else
1373             {
1374                 mtCOVERAGE_TEST_MARKER();
1375             }
1376
1377             traceRETURN_xTaskCreateStaticAffinitySet( xReturn );
1378
1379             return xReturn;
1380         }
1381     #endif /* #if ( ( configNUMBER_OF_CORES > 1 ) && ( configUSE_CORE_AFFINITY == 1 ) ) */
1382
1383 #endif /* SUPPORT_STATIC_ALLOCATION */
1384 /*-----------------------------------------------------------*/
1385
1386 #if ( ( portUSING_MPU_WRAPPERS == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 1 ) )
1387     static TCB_t * prvCreateRestrictedStaticTask( const TaskParameters_t * const pxTaskDefinition,
1388                                                   TaskHandle_t * const pxCreatedTask )
1389     {
1390         TCB_t * pxNewTCB;
1391
1392         configASSERT( pxTaskDefinition->puxStackBuffer != NULL );
1393         configASSERT( pxTaskDefinition->pxTaskBuffer != NULL );
1394
1395         if( ( pxTaskDefinition->puxStackBuffer != NULL ) && ( pxTaskDefinition->pxTaskBuffer != NULL ) )
1396         {
1397             /* Allocate space for the TCB.  Where the memory comes from depends
1398              * on the implementation of the port malloc function and whether or
1399              * not static allocation is being used. */
1400             pxNewTCB = ( TCB_t * ) pxTaskDefinition->pxTaskBuffer;
1401             ( void ) memset( ( void * ) pxNewTCB, 0x00, sizeof( TCB_t ) );
1402
1403             /* Store the stack location in the TCB. */
1404             pxNewTCB->pxStack = pxTaskDefinition->puxStackBuffer;
1405
1406             #if ( tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE != 0 )
1407             {
1408                 /* Tasks can be created statically or dynamically, so note this
1409                  * task was created statically in case the task is later deleted. */
1410                 pxNewTCB->ucStaticallyAllocated = tskSTATICALLY_ALLOCATED_STACK_AND_TCB;
1411             }
1412             #endif /* tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE */
1413
1414             prvInitialiseNewTask( pxTaskDefinition->pvTaskCode,
1415                                   pxTaskDefinition->pcName,
1416                                   pxTaskDefinition->usStackDepth,
1417                                   pxTaskDefinition->pvParameters,
1418                                   pxTaskDefinition->uxPriority,
1419                                   pxCreatedTask, pxNewTCB,
1420                                   pxTaskDefinition->xRegions );
1421         }
1422         else
1423         {
1424             pxNewTCB = NULL;
1425         }
1426
1427         return pxNewTCB;
1428     }
1429 /*-----------------------------------------------------------*/
1430
1431     BaseType_t xTaskCreateRestrictedStatic( const TaskParameters_t * const pxTaskDefinition,
1432                                             TaskHandle_t * pxCreatedTask )
1433     {
1434         TCB_t * pxNewTCB;
1435         BaseType_t xReturn;
1436
1437         traceENTER_xTaskCreateRestrictedStatic( pxTaskDefinition, pxCreatedTask );
1438
1439         configASSERT( pxTaskDefinition != NULL );
1440
1441         pxNewTCB = prvCreateRestrictedStaticTask( pxTaskDefinition, pxCreatedTask );
1442
1443         if( pxNewTCB != NULL )
1444         {
1445             #if ( ( configNUMBER_OF_CORES > 1 ) && ( configUSE_CORE_AFFINITY == 1 ) )
1446             {
1447                 /* Set the task's affinity before scheduling it. */
1448                 pxNewTCB->uxCoreAffinityMask = configTASK_DEFAULT_CORE_AFFINITY;
1449             }
1450             #endif
1451
1452             prvAddNewTaskToReadyList( pxNewTCB );
1453             xReturn = pdPASS;
1454         }
1455         else
1456         {
1457             xReturn = errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY;
1458         }
1459
1460         traceRETURN_xTaskCreateRestrictedStatic( xReturn );
1461
1462         return xReturn;
1463     }
1464 /*-----------------------------------------------------------*/
1465
1466     #if ( ( configNUMBER_OF_CORES > 1 ) && ( configUSE_CORE_AFFINITY == 1 ) )
1467         BaseType_t xTaskCreateRestrictedStaticAffinitySet( const TaskParameters_t * const pxTaskDefinition,
1468                                                            UBaseType_t uxCoreAffinityMask,
1469                                                            TaskHandle_t * pxCreatedTask )
1470         {
1471             TCB_t * pxNewTCB;
1472             BaseType_t xReturn;
1473
1474             traceENTER_xTaskCreateRestrictedStaticAffinitySet( pxTaskDefinition, uxCoreAffinityMask, pxCreatedTask );
1475
1476             configASSERT( pxTaskDefinition != NULL );
1477
1478             pxNewTCB = prvCreateRestrictedStaticTask( pxTaskDefinition, pxCreatedTask );
1479
1480             if( pxNewTCB != NULL )
1481             {
1482                 /* Set the task's affinity before scheduling it. */
1483                 pxNewTCB->uxCoreAffinityMask = uxCoreAffinityMask;
1484
1485                 prvAddNewTaskToReadyList( pxNewTCB );
1486                 xReturn = pdPASS;
1487             }
1488             else
1489             {
1490                 xReturn = errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY;
1491             }
1492
1493             traceRETURN_xTaskCreateRestrictedStaticAffinitySet( xReturn );
1494
1495             return xReturn;
1496         }
1497     #endif /* #if ( ( configNUMBER_OF_CORES > 1 ) && ( configUSE_CORE_AFFINITY == 1 ) ) */
1498
1499 #endif /* ( portUSING_MPU_WRAPPERS == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 1 ) */
1500 /*-----------------------------------------------------------*/
1501
1502 #if ( ( portUSING_MPU_WRAPPERS == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) )
1503     static TCB_t * prvCreateRestrictedTask( const TaskParameters_t * const pxTaskDefinition,
1504                                             TaskHandle_t * const pxCreatedTask )
1505     {
1506         TCB_t * pxNewTCB;
1507
1508         configASSERT( pxTaskDefinition->puxStackBuffer );
1509
1510         if( pxTaskDefinition->puxStackBuffer != NULL )
1511         {
1512             /* MISRA Ref 11.5.1 [Malloc memory assignment] */
1513             /* More details at: https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/MISRA.md#rule-115 */
1514             /* coverity[misra_c_2012_rule_11_5_violation] */
1515             pxNewTCB = ( TCB_t * ) pvPortMalloc( sizeof( TCB_t ) );
1516
1517             if( pxNewTCB != NULL )
1518             {
1519                 ( void ) memset( ( void * ) pxNewTCB, 0x00, sizeof( TCB_t ) );
1520
1521                 /* Store the stack location in the TCB. */
1522                 pxNewTCB->pxStack = pxTaskDefinition->puxStackBuffer;
1523
1524                 #if ( tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE != 0 )
1525                 {
1526                     /* Tasks can be created statically or dynamically, so note
1527                      * this task had a statically allocated stack in case it is
1528                      * later deleted.  The TCB was allocated dynamically. */
1529                     pxNewTCB->ucStaticallyAllocated = tskSTATICALLY_ALLOCATED_STACK_ONLY;
1530                 }
1531                 #endif /* tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE */
1532
1533                 prvInitialiseNewTask( pxTaskDefinition->pvTaskCode,
1534                                       pxTaskDefinition->pcName,
1535                                       pxTaskDefinition->usStackDepth,
1536                                       pxTaskDefinition->pvParameters,
1537                                       pxTaskDefinition->uxPriority,
1538                                       pxCreatedTask, pxNewTCB,
1539                                       pxTaskDefinition->xRegions );
1540             }
1541         }
1542         else
1543         {
1544             pxNewTCB = NULL;
1545         }
1546
1547         return pxNewTCB;
1548     }
1549 /*-----------------------------------------------------------*/
1550
1551     BaseType_t xTaskCreateRestricted( const TaskParameters_t * const pxTaskDefinition,
1552                                       TaskHandle_t * pxCreatedTask )
1553     {
1554         TCB_t * pxNewTCB;
1555         BaseType_t xReturn;
1556
1557         traceENTER_xTaskCreateRestricted( pxTaskDefinition, pxCreatedTask );
1558
1559         pxNewTCB = prvCreateRestrictedTask( pxTaskDefinition, pxCreatedTask );
1560
1561         if( pxNewTCB != NULL )
1562         {
1563             #if ( ( configNUMBER_OF_CORES > 1 ) && ( configUSE_CORE_AFFINITY == 1 ) )
1564             {
1565                 /* Set the task's affinity before scheduling it. */
1566                 pxNewTCB->uxCoreAffinityMask = configTASK_DEFAULT_CORE_AFFINITY;
1567             }
1568             #endif /* #if ( ( configNUMBER_OF_CORES > 1 ) && ( configUSE_CORE_AFFINITY == 1 ) ) */
1569
1570             prvAddNewTaskToReadyList( pxNewTCB );
1571
1572             xReturn = pdPASS;
1573         }
1574         else
1575         {
1576             xReturn = errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY;
1577         }
1578
1579         traceRETURN_xTaskCreateRestricted( xReturn );
1580
1581         return xReturn;
1582     }
1583 /*-----------------------------------------------------------*/
1584
1585     #if ( ( configNUMBER_OF_CORES > 1 ) && ( configUSE_CORE_AFFINITY == 1 ) )
1586         BaseType_t xTaskCreateRestrictedAffinitySet( const TaskParameters_t * const pxTaskDefinition,
1587                                                      UBaseType_t uxCoreAffinityMask,
1588                                                      TaskHandle_t * pxCreatedTask )
1589         {
1590             TCB_t * pxNewTCB;
1591             BaseType_t xReturn;
1592
1593             traceENTER_xTaskCreateRestrictedAffinitySet( pxTaskDefinition, uxCoreAffinityMask, pxCreatedTask );
1594
1595             pxNewTCB = prvCreateRestrictedTask( pxTaskDefinition, pxCreatedTask );
1596
1597             if( pxNewTCB != NULL )
1598             {
1599                 /* Set the task's affinity before scheduling it. */
1600                 pxNewTCB->uxCoreAffinityMask = uxCoreAffinityMask;
1601
1602                 prvAddNewTaskToReadyList( pxNewTCB );
1603
1604                 xReturn = pdPASS;
1605             }
1606             else
1607             {
1608                 xReturn = errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY;
1609             }
1610
1611             traceRETURN_xTaskCreateRestrictedAffinitySet( xReturn );
1612
1613             return xReturn;
1614         }
1615     #endif /* #if ( ( configNUMBER_OF_CORES > 1 ) && ( configUSE_CORE_AFFINITY == 1 ) ) */
1616
1617
1618 #endif /* portUSING_MPU_WRAPPERS */
1619 /*-----------------------------------------------------------*/
1620
1621 #if ( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
1622     static TCB_t * prvCreateTask( TaskFunction_t pxTaskCode,
1623                                   const char * const pcName,
1624                                   const configSTACK_DEPTH_TYPE uxStackDepth,
1625                                   void * const pvParameters,
1626                                   UBaseType_t uxPriority,
1627                                   TaskHandle_t * const pxCreatedTask )
1628     {
1629         TCB_t * pxNewTCB;
1630
1631         /* If the stack grows down then allocate the stack then the TCB so the stack
1632          * does not grow into the TCB.  Likewise if the stack grows up then allocate
1633          * the TCB then the stack. */
1634         #if ( portSTACK_GROWTH > 0 )
1635         {
1636             /* Allocate space for the TCB.  Where the memory comes from depends on
1637              * the implementation of the port malloc function and whether or not static
1638              * allocation is being used. */
1639             /* MISRA Ref 11.5.1 [Malloc memory assignment] */
1640             /* More details at: https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/MISRA.md#rule-115 */
1641             /* coverity[misra_c_2012_rule_11_5_violation] */
1642             pxNewTCB = ( TCB_t * ) pvPortMalloc( sizeof( TCB_t ) );
1643
1644             if( pxNewTCB != NULL )
1645             {
1646                 ( void ) memset( ( void * ) pxNewTCB, 0x00, sizeof( TCB_t ) );
1647
1648                 /* Allocate space for the stack used by the task being created.
1649                  * The base of the stack memory stored in the TCB so the task can
1650                  * be deleted later if required. */
1651                 /* MISRA Ref 11.5.1 [Malloc memory assignment] */
1652                 /* More details at: https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/MISRA.md#rule-115 */
1653                 /* coverity[misra_c_2012_rule_11_5_violation] */
1654                 pxNewTCB->pxStack = ( StackType_t * ) pvPortMallocStack( ( ( ( size_t ) uxStackDepth ) * sizeof( StackType_t ) ) );
1655
1656                 if( pxNewTCB->pxStack == NULL )
1657                 {
1658                     /* Could not allocate the stack.  Delete the allocated TCB. */
1659                     vPortFree( pxNewTCB );
1660                     pxNewTCB = NULL;
1661                 }
1662             }
1663         }
1664         #else /* portSTACK_GROWTH */
1665         {
1666             StackType_t * pxStack;
1667
1668             /* Allocate space for the stack used by the task being created. */
1669             /* MISRA Ref 11.5.1 [Malloc memory assignment] */
1670             /* More details at: https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/MISRA.md#rule-115 */
1671             /* coverity[misra_c_2012_rule_11_5_violation] */
1672             pxStack = pvPortMallocStack( ( ( ( size_t ) uxStackDepth ) * sizeof( StackType_t ) ) );
1673
1674             if( pxStack != NULL )
1675             {
1676                 /* Allocate space for the TCB. */
1677                 /* MISRA Ref 11.5.1 [Malloc memory assignment] */
1678                 /* More details at: https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/MISRA.md#rule-115 */
1679                 /* coverity[misra_c_2012_rule_11_5_violation] */
1680                 pxNewTCB = ( TCB_t * ) pvPortMalloc( sizeof( TCB_t ) );
1681
1682                 if( pxNewTCB != NULL )
1683                 {
1684                     ( void ) memset( ( void * ) pxNewTCB, 0x00, sizeof( TCB_t ) );
1685
1686                     /* Store the stack location in the TCB. */
1687                     pxNewTCB->pxStack = pxStack;
1688                 }
1689                 else
1690                 {
1691                     /* The stack cannot be used as the TCB was not created.  Free
1692                      * it again. */
1693                     vPortFreeStack( pxStack );
1694                 }
1695             }
1696             else
1697             {
1698                 pxNewTCB = NULL;
1699             }
1700         }
1701         #endif /* portSTACK_GROWTH */
1702
1703         if( pxNewTCB != NULL )
1704         {
1705             #if ( tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE != 0 )
1706             {
1707                 /* Tasks can be created statically or dynamically, so note this
1708                  * task was created dynamically in case it is later deleted. */
1709                 pxNewTCB->ucStaticallyAllocated = tskDYNAMICALLY_ALLOCATED_STACK_AND_TCB;
1710             }
1711             #endif /* tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE */
1712
1713             prvInitialiseNewTask( pxTaskCode, pcName, uxStackDepth, pvParameters, uxPriority, pxCreatedTask, pxNewTCB, NULL );
1714         }
1715
1716         return pxNewTCB;
1717     }
1718 /*-----------------------------------------------------------*/
1719
1720     BaseType_t xTaskCreate( TaskFunction_t pxTaskCode,
1721                             const char * const pcName,
1722                             const configSTACK_DEPTH_TYPE uxStackDepth,
1723                             void * const pvParameters,
1724                             UBaseType_t uxPriority,
1725                             TaskHandle_t * const pxCreatedTask )
1726     {
1727         TCB_t * pxNewTCB;
1728         BaseType_t xReturn;
1729
1730         traceENTER_xTaskCreate( pxTaskCode, pcName, uxStackDepth, pvParameters, uxPriority, pxCreatedTask );
1731
1732         pxNewTCB = prvCreateTask( pxTaskCode, pcName, uxStackDepth, pvParameters, uxPriority, pxCreatedTask );
1733
1734         if( pxNewTCB != NULL )
1735         {
1736             #if ( ( configNUMBER_OF_CORES > 1 ) && ( configUSE_CORE_AFFINITY == 1 ) )
1737             {
1738                 /* Set the task's affinity before scheduling it. */
1739                 pxNewTCB->uxCoreAffinityMask = configTASK_DEFAULT_CORE_AFFINITY;
1740             }
1741             #endif
1742
1743             prvAddNewTaskToReadyList( pxNewTCB );
1744             xReturn = pdPASS;
1745         }
1746         else
1747         {
1748             xReturn = errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY;
1749         }
1750
1751         traceRETURN_xTaskCreate( xReturn );
1752
1753         return xReturn;
1754     }
1755 /*-----------------------------------------------------------*/
1756
1757     #if ( ( configNUMBER_OF_CORES > 1 ) && ( configUSE_CORE_AFFINITY == 1 ) )
1758         BaseType_t xTaskCreateAffinitySet( TaskFunction_t pxTaskCode,
1759                                            const char * const pcName,
1760                                            const configSTACK_DEPTH_TYPE uxStackDepth,
1761                                            void * const pvParameters,
1762                                            UBaseType_t uxPriority,
1763                                            UBaseType_t uxCoreAffinityMask,
1764                                            TaskHandle_t * const pxCreatedTask )
1765         {
1766             TCB_t * pxNewTCB;
1767             BaseType_t xReturn;
1768
1769             traceENTER_xTaskCreateAffinitySet( pxTaskCode, pcName, uxStackDepth, pvParameters, uxPriority, uxCoreAffinityMask, pxCreatedTask );
1770
1771             pxNewTCB = prvCreateTask( pxTaskCode, pcName, uxStackDepth, pvParameters, uxPriority, pxCreatedTask );
1772
1773             if( pxNewTCB != NULL )
1774             {
1775                 /* Set the task's affinity before scheduling it. */
1776                 pxNewTCB->uxCoreAffinityMask = uxCoreAffinityMask;
1777
1778                 prvAddNewTaskToReadyList( pxNewTCB );
1779                 xReturn = pdPASS;
1780             }
1781             else
1782             {
1783                 xReturn = errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY;
1784             }
1785
1786             traceRETURN_xTaskCreateAffinitySet( xReturn );
1787
1788             return xReturn;
1789         }
1790     #endif /* #if ( ( configNUMBER_OF_CORES > 1 ) && ( configUSE_CORE_AFFINITY == 1 ) ) */
1791
1792 #endif /* configSUPPORT_DYNAMIC_ALLOCATION */
1793 /*-----------------------------------------------------------*/
1794
1795 static void prvInitialiseNewTask( TaskFunction_t pxTaskCode,
1796                                   const char * const pcName,
1797                                   const configSTACK_DEPTH_TYPE uxStackDepth,
1798                                   void * const pvParameters,
1799                                   UBaseType_t uxPriority,
1800                                   TaskHandle_t * const pxCreatedTask,
1801                                   TCB_t * pxNewTCB,
1802                                   const MemoryRegion_t * const xRegions )
1803 {
1804     StackType_t * pxTopOfStack;
1805     UBaseType_t x;
1806
1807     #if ( portUSING_MPU_WRAPPERS == 1 )
1808         /* Should the task be created in privileged mode? */
1809         BaseType_t xRunPrivileged;
1810
1811         if( ( uxPriority & portPRIVILEGE_BIT ) != 0U )
1812         {
1813             xRunPrivileged = pdTRUE;
1814         }
1815         else
1816         {
1817             xRunPrivileged = pdFALSE;
1818         }
1819         uxPriority &= ~portPRIVILEGE_BIT;
1820     #endif /* portUSING_MPU_WRAPPERS == 1 */
1821
1822     /* Avoid dependency on memset() if it is not required. */
1823     #if ( tskSET_NEW_STACKS_TO_KNOWN_VALUE == 1 )
1824     {
1825         /* Fill the stack with a known value to assist debugging. */
1826         ( void ) memset( pxNewTCB->pxStack, ( int ) tskSTACK_FILL_BYTE, ( size_t ) uxStackDepth * sizeof( StackType_t ) );
1827     }
1828     #endif /* tskSET_NEW_STACKS_TO_KNOWN_VALUE */
1829
1830     /* Calculate the top of stack address.  This depends on whether the stack
1831      * grows from high memory to low (as per the 80x86) or vice versa.
1832      * portSTACK_GROWTH is used to make the result positive or negative as required
1833      * by the port. */
1834     #if ( portSTACK_GROWTH < 0 )
1835     {
1836         pxTopOfStack = &( pxNewTCB->pxStack[ uxStackDepth - ( configSTACK_DEPTH_TYPE ) 1 ] );
1837         pxTopOfStack = ( StackType_t * ) ( ( ( portPOINTER_SIZE_TYPE ) pxTopOfStack ) & ( ~( ( portPOINTER_SIZE_TYPE ) portBYTE_ALIGNMENT_MASK ) ) );
1838
1839         /* Check the alignment of the calculated top of stack is correct. */
1840         configASSERT( ( ( ( portPOINTER_SIZE_TYPE ) pxTopOfStack & ( portPOINTER_SIZE_TYPE ) portBYTE_ALIGNMENT_MASK ) == 0U ) );
1841
1842         #if ( configRECORD_STACK_HIGH_ADDRESS == 1 )
1843         {
1844             /* Also record the stack's high address, which may assist
1845              * debugging. */
1846             pxNewTCB->pxEndOfStack = pxTopOfStack;
1847         }
1848         #endif /* configRECORD_STACK_HIGH_ADDRESS */
1849     }
1850     #else /* portSTACK_GROWTH */
1851     {
1852         pxTopOfStack = pxNewTCB->pxStack;
1853         pxTopOfStack = ( StackType_t * ) ( ( ( ( portPOINTER_SIZE_TYPE ) pxTopOfStack ) + portBYTE_ALIGNMENT_MASK ) & ( ~( ( portPOINTER_SIZE_TYPE ) portBYTE_ALIGNMENT_MASK ) ) );
1854
1855         /* Check the alignment of the calculated top of stack is correct. */
1856         configASSERT( ( ( ( portPOINTER_SIZE_TYPE ) pxTopOfStack & ( portPOINTER_SIZE_TYPE ) portBYTE_ALIGNMENT_MASK ) == 0U ) );
1857
1858         /* The other extreme of the stack space is required if stack checking is
1859          * performed. */
1860         pxNewTCB->pxEndOfStack = pxNewTCB->pxStack + ( uxStackDepth - ( configSTACK_DEPTH_TYPE ) 1 );
1861     }
1862     #endif /* portSTACK_GROWTH */
1863
1864     /* Store the task name in the TCB. */
1865     if( pcName != NULL )
1866     {
1867         for( x = ( UBaseType_t ) 0; x < ( UBaseType_t ) configMAX_TASK_NAME_LEN; x++ )
1868         {
1869             pxNewTCB->pcTaskName[ x ] = pcName[ x ];
1870
1871             /* Don't copy all configMAX_TASK_NAME_LEN if the string is shorter than
1872              * configMAX_TASK_NAME_LEN characters just in case the memory after the
1873              * string is not accessible (extremely unlikely). */
1874             if( pcName[ x ] == ( char ) 0x00 )
1875             {
1876                 break;
1877             }
1878             else
1879             {
1880                 mtCOVERAGE_TEST_MARKER();
1881             }
1882         }
1883
1884         /* Ensure the name string is terminated in the case that the string length
1885          * was greater or equal to configMAX_TASK_NAME_LEN. */
1886         pxNewTCB->pcTaskName[ configMAX_TASK_NAME_LEN - 1U ] = '\0';
1887     }
1888     else
1889     {
1890         mtCOVERAGE_TEST_MARKER();
1891     }
1892
1893     /* This is used as an array index so must ensure it's not too large. */
1894     configASSERT( uxPriority < configMAX_PRIORITIES );
1895
1896     if( uxPriority >= ( UBaseType_t ) configMAX_PRIORITIES )
1897     {
1898         uxPriority = ( UBaseType_t ) configMAX_PRIORITIES - ( UBaseType_t ) 1U;
1899     }
1900     else
1901     {
1902         mtCOVERAGE_TEST_MARKER();
1903     }
1904
1905     pxNewTCB->uxPriority = uxPriority;
1906     #if ( configUSE_MUTEXES == 1 )
1907     {
1908         pxNewTCB->uxBasePriority = uxPriority;
1909     }
1910     #endif /* configUSE_MUTEXES */
1911
1912     vListInitialiseItem( &( pxNewTCB->xStateListItem ) );
1913     vListInitialiseItem( &( pxNewTCB->xEventListItem ) );
1914
1915     /* Set the pxNewTCB as a link back from the ListItem_t.  This is so we can get
1916      * back to  the containing TCB from a generic item in a list. */
1917     listSET_LIST_ITEM_OWNER( &( pxNewTCB->xStateListItem ), pxNewTCB );
1918
1919     /* Event lists are always in priority order. */
1920     listSET_LIST_ITEM_VALUE( &( pxNewTCB->xEventListItem ), ( TickType_t ) configMAX_PRIORITIES - ( TickType_t ) uxPriority );
1921     listSET_LIST_ITEM_OWNER( &( pxNewTCB->xEventListItem ), pxNewTCB );
1922
1923     #if ( portUSING_MPU_WRAPPERS == 1 )
1924     {
1925         vPortStoreTaskMPUSettings( &( pxNewTCB->xMPUSettings ), xRegions, pxNewTCB->pxStack, uxStackDepth );
1926     }
1927     #else
1928     {
1929         /* Avoid compiler warning about unreferenced parameter. */
1930         ( void ) xRegions;
1931     }
1932     #endif
1933
1934     #if ( configUSE_C_RUNTIME_TLS_SUPPORT == 1 )
1935     {
1936         /* Allocate and initialize memory for the task's TLS Block. */
1937         configINIT_TLS_BLOCK( pxNewTCB->xTLSBlock, pxTopOfStack );
1938     }
1939     #endif
1940
1941     /* Initialize the TCB stack to look as if the task was already running,
1942      * but had been interrupted by the scheduler.  The return address is set
1943      * to the start of the task function. Once the stack has been initialised
1944      * the top of stack variable is updated. */
1945     #if ( portUSING_MPU_WRAPPERS == 1 )
1946     {
1947         /* If the port has capability to detect stack overflow,
1948          * pass the stack end address to the stack initialization
1949          * function as well. */
1950         #if ( portHAS_STACK_OVERFLOW_CHECKING == 1 )
1951         {
1952             #if ( portSTACK_GROWTH < 0 )
1953             {
1954                 pxNewTCB->pxTopOfStack = pxPortInitialiseStack( pxTopOfStack, pxNewTCB->pxStack, pxTaskCode, pvParameters, xRunPrivileged, &( pxNewTCB->xMPUSettings ) );
1955             }
1956             #else /* portSTACK_GROWTH */
1957             {
1958                 pxNewTCB->pxTopOfStack = pxPortInitialiseStack( pxTopOfStack, pxNewTCB->pxEndOfStack, pxTaskCode, pvParameters, xRunPrivileged, &( pxNewTCB->xMPUSettings ) );
1959             }
1960             #endif /* portSTACK_GROWTH */
1961         }
1962         #else /* portHAS_STACK_OVERFLOW_CHECKING */
1963         {
1964             pxNewTCB->pxTopOfStack = pxPortInitialiseStack( pxTopOfStack, pxTaskCode, pvParameters, xRunPrivileged, &( pxNewTCB->xMPUSettings ) );
1965         }
1966         #endif /* portHAS_STACK_OVERFLOW_CHECKING */
1967     }
1968     #else /* portUSING_MPU_WRAPPERS */
1969     {
1970         /* If the port has capability to detect stack overflow,
1971          * pass the stack end address to the stack initialization
1972          * function as well. */
1973         #if ( portHAS_STACK_OVERFLOW_CHECKING == 1 )
1974         {
1975             #if ( portSTACK_GROWTH < 0 )
1976             {
1977                 pxNewTCB->pxTopOfStack = pxPortInitialiseStack( pxTopOfStack, pxNewTCB->pxStack, pxTaskCode, pvParameters );
1978             }
1979             #else /* portSTACK_GROWTH */
1980             {
1981                 pxNewTCB->pxTopOfStack = pxPortInitialiseStack( pxTopOfStack, pxNewTCB->pxEndOfStack, pxTaskCode, pvParameters );
1982             }
1983             #endif /* portSTACK_GROWTH */
1984         }
1985         #else /* portHAS_STACK_OVERFLOW_CHECKING */
1986         {
1987             pxNewTCB->pxTopOfStack = pxPortInitialiseStack( pxTopOfStack, pxTaskCode, pvParameters );
1988         }
1989         #endif /* portHAS_STACK_OVERFLOW_CHECKING */
1990     }
1991     #endif /* portUSING_MPU_WRAPPERS */
1992
1993     /* Initialize task state and task attributes. */
1994     #if ( configNUMBER_OF_CORES > 1 )
1995     {
1996         pxNewTCB->xTaskRunState = taskTASK_NOT_RUNNING;
1997
1998         /* Is this an idle task? */
1999         if( ( ( TaskFunction_t ) pxTaskCode == ( TaskFunction_t ) prvIdleTask ) || ( ( TaskFunction_t ) pxTaskCode == ( TaskFunction_t ) prvPassiveIdleTask ) )
2000         {
2001             pxNewTCB->uxTaskAttributes |= taskATTRIBUTE_IS_IDLE;
2002         }
2003     }
2004     #endif /* #if ( configNUMBER_OF_CORES > 1 ) */
2005
2006     if( pxCreatedTask != NULL )
2007     {
2008         /* Pass the handle out in an anonymous way.  The handle can be used to
2009          * change the created task's priority, delete the created task, etc.*/
2010         *pxCreatedTask = ( TaskHandle_t ) pxNewTCB;
2011     }
2012     else
2013     {
2014         mtCOVERAGE_TEST_MARKER();
2015     }
2016 }
2017 /*-----------------------------------------------------------*/
2018
2019 #if ( configNUMBER_OF_CORES == 1 )
2020
2021     static void prvAddNewTaskToReadyList( TCB_t * pxNewTCB )
2022     {
2023         /* Ensure interrupts don't access the task lists while the lists are being
2024          * updated. */
2025         taskENTER_CRITICAL();
2026         {
2027             uxCurrentNumberOfTasks = ( UBaseType_t ) ( uxCurrentNumberOfTasks + 1U );
2028
2029             if( pxCurrentTCB == NULL )
2030             {
2031                 /* There are no other tasks, or all the other tasks are in
2032                  * the suspended state - make this the current task. */
2033                 pxCurrentTCB = pxNewTCB;
2034
2035                 if( uxCurrentNumberOfTasks == ( UBaseType_t ) 1 )
2036                 {
2037                     /* This is the first task to be created so do the preliminary
2038                      * initialisation required.  We will not recover if this call
2039                      * fails, but we will report the failure. */
2040                     prvInitialiseTaskLists();
2041                 }
2042                 else
2043                 {
2044                     mtCOVERAGE_TEST_MARKER();
2045                 }
2046             }
2047             else
2048             {
2049                 /* If the scheduler is not already running, make this task the
2050                  * current task if it is the highest priority task to be created
2051                  * so far. */
2052                 if( xSchedulerRunning == pdFALSE )
2053                 {
2054                     if( pxCurrentTCB->uxPriority <= pxNewTCB->uxPriority )
2055                     {
2056                         pxCurrentTCB = pxNewTCB;
2057                     }
2058                     else
2059                     {
2060                         mtCOVERAGE_TEST_MARKER();
2061                     }
2062                 }
2063                 else
2064                 {
2065                     mtCOVERAGE_TEST_MARKER();
2066                 }
2067             }
2068
2069             uxTaskNumber++;
2070
2071             #if ( configUSE_TRACE_FACILITY == 1 )
2072             {
2073                 /* Add a counter into the TCB for tracing only. */
2074                 pxNewTCB->uxTCBNumber = uxTaskNumber;
2075             }
2076             #endif /* configUSE_TRACE_FACILITY */
2077             traceTASK_CREATE( pxNewTCB );
2078
2079             prvAddTaskToReadyList( pxNewTCB );
2080
2081             portSETUP_TCB( pxNewTCB );
2082         }
2083         taskEXIT_CRITICAL();
2084
2085         if( xSchedulerRunning != pdFALSE )
2086         {
2087             /* If the created task is of a higher priority than the current task
2088              * then it should run now. */
2089             taskYIELD_ANY_CORE_IF_USING_PREEMPTION( pxNewTCB );
2090         }
2091         else
2092         {
2093             mtCOVERAGE_TEST_MARKER();
2094         }
2095     }
2096
2097 #else /* #if ( configNUMBER_OF_CORES == 1 ) */
2098
2099     static void prvAddNewTaskToReadyList( TCB_t * pxNewTCB )
2100     {
2101         /* Ensure interrupts don't access the task lists while the lists are being
2102          * updated. */
2103         taskENTER_CRITICAL();
2104         {
2105             uxCurrentNumberOfTasks++;
2106
2107             if( xSchedulerRunning == pdFALSE )
2108             {
2109                 if( uxCurrentNumberOfTasks == ( UBaseType_t ) 1 )
2110                 {
2111                     /* This is the first task to be created so do the preliminary
2112                      * initialisation required.  We will not recover if this call
2113                      * fails, but we will report the failure. */
2114                     prvInitialiseTaskLists();
2115                 }
2116                 else
2117                 {
2118                     mtCOVERAGE_TEST_MARKER();
2119                 }
2120
2121                 /* All the cores start with idle tasks before the SMP scheduler
2122                  * is running. Idle tasks are assigned to cores when they are
2123                  * created in prvCreateIdleTasks(). */
2124             }
2125
2126             uxTaskNumber++;
2127
2128             #if ( configUSE_TRACE_FACILITY == 1 )
2129             {
2130                 /* Add a counter into the TCB for tracing only. */
2131                 pxNewTCB->uxTCBNumber = uxTaskNumber;
2132             }
2133             #endif /* configUSE_TRACE_FACILITY */
2134             traceTASK_CREATE( pxNewTCB );
2135
2136             prvAddTaskToReadyList( pxNewTCB );
2137
2138             portSETUP_TCB( pxNewTCB );
2139
2140             if( xSchedulerRunning != pdFALSE )
2141             {
2142                 /* If the created task is of a higher priority than another
2143                  * currently running task and preemption is on then it should
2144                  * run now. */
2145                 taskYIELD_ANY_CORE_IF_USING_PREEMPTION( pxNewTCB );
2146             }
2147             else
2148             {
2149                 mtCOVERAGE_TEST_MARKER();
2150             }
2151         }
2152         taskEXIT_CRITICAL();
2153     }
2154
2155 #endif /* #if ( configNUMBER_OF_CORES == 1 ) */
2156 /*-----------------------------------------------------------*/
2157
2158 #if ( ( configUSE_TRACE_FACILITY == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 ) )
2159
2160     static size_t prvSnprintfReturnValueToCharsWritten( int iSnprintfReturnValue,
2161                                                         size_t n )
2162     {
2163         size_t uxCharsWritten;
2164
2165         if( iSnprintfReturnValue < 0 )
2166         {
2167             /* Encoding error - Return 0 to indicate that nothing
2168              * was written to the buffer. */
2169             uxCharsWritten = 0;
2170         }
2171         else if( iSnprintfReturnValue >= ( int ) n )
2172         {
2173             /* This is the case when the supplied buffer is not
2174              * large to hold the generated string. Return the
2175              * number of characters actually written without
2176              * counting the terminating NULL character. */
2177             uxCharsWritten = n - 1U;
2178         }
2179         else
2180         {
2181             /* Complete string was written to the buffer. */
2182             uxCharsWritten = ( size_t ) iSnprintfReturnValue;
2183         }
2184
2185         return uxCharsWritten;
2186     }
2187
2188 #endif /* #if ( ( configUSE_TRACE_FACILITY == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 ) ) */
2189 /*-----------------------------------------------------------*/
2190
2191 #if ( INCLUDE_vTaskDelete == 1 )
2192
2193     void vTaskDelete( TaskHandle_t xTaskToDelete )
2194     {
2195         TCB_t * pxTCB;
2196         BaseType_t xDeleteTCBInIdleTask = pdFALSE;
2197         BaseType_t xTaskIsRunningOrYielding;
2198
2199         traceENTER_vTaskDelete( xTaskToDelete );
2200
2201         taskENTER_CRITICAL();
2202         {
2203             /* If null is passed in here then it is the calling task that is
2204              * being deleted. */
2205             pxTCB = prvGetTCBFromHandle( xTaskToDelete );
2206
2207             /* Remove task from the ready/delayed list. */
2208             if( uxListRemove( &( pxTCB->xStateListItem ) ) == ( UBaseType_t ) 0 )
2209             {
2210                 taskRESET_READY_PRIORITY( pxTCB->uxPriority );
2211             }
2212             else
2213             {
2214                 mtCOVERAGE_TEST_MARKER();
2215             }
2216
2217             /* Is the task waiting on an event also? */
2218             if( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) != NULL )
2219             {
2220                 ( void ) uxListRemove( &( pxTCB->xEventListItem ) );
2221             }
2222             else
2223             {
2224                 mtCOVERAGE_TEST_MARKER();
2225             }
2226
2227             /* Increment the uxTaskNumber also so kernel aware debuggers can
2228              * detect that the task lists need re-generating.  This is done before
2229              * portPRE_TASK_DELETE_HOOK() as in the Windows port that macro will
2230              * not return. */
2231             uxTaskNumber++;
2232
2233             /* Use temp variable as distinct sequence points for reading volatile
2234              * variables prior to a logical operator to ensure compliance with
2235              * MISRA C 2012 Rule 13.5. */
2236             xTaskIsRunningOrYielding = taskTASK_IS_RUNNING_OR_SCHEDULED_TO_YIELD( pxTCB );
2237
2238             /* If the task is running (or yielding), we must add it to the
2239              * termination list so that an idle task can delete it when it is
2240              * no longer running. */
2241             if( ( xSchedulerRunning != pdFALSE ) && ( xTaskIsRunningOrYielding != pdFALSE ) )
2242             {
2243                 /* A running task or a task which is scheduled to yield is being
2244                  * deleted. This cannot complete when the task is still running
2245                  * on a core, as a context switch to another task is required.
2246                  * Place the task in the termination list. The idle task will check
2247                  * the termination list and free up any memory allocated by the
2248                  * scheduler for the TCB and stack of the deleted task. */
2249                 vListInsertEnd( &xTasksWaitingTermination, &( pxTCB->xStateListItem ) );
2250
2251                 /* Increment the ucTasksDeleted variable so the idle task knows
2252                  * there is a task that has been deleted and that it should therefore
2253                  * check the xTasksWaitingTermination list. */
2254                 ++uxDeletedTasksWaitingCleanUp;
2255
2256                 /* Call the delete hook before portPRE_TASK_DELETE_HOOK() as
2257                  * portPRE_TASK_DELETE_HOOK() does not return in the Win32 port. */
2258                 traceTASK_DELETE( pxTCB );
2259
2260                 /* Delete the task TCB in idle task. */
2261                 xDeleteTCBInIdleTask = pdTRUE;
2262
2263                 /* The pre-delete hook is primarily for the Windows simulator,
2264                  * in which Windows specific clean up operations are performed,
2265                  * after which it is not possible to yield away from this task -
2266                  * hence xYieldPending is used to latch that a context switch is
2267                  * required. */
2268                 #if ( configNUMBER_OF_CORES == 1 )
2269                     portPRE_TASK_DELETE_HOOK( pxTCB, &( xYieldPendings[ 0 ] ) );
2270                 #else
2271                     portPRE_TASK_DELETE_HOOK( pxTCB, &( xYieldPendings[ pxTCB->xTaskRunState ] ) );
2272                 #endif
2273
2274                 /* In the case of SMP, it is possible that the task being deleted
2275                  * is running on another core. We must evict the task before
2276                  * exiting the critical section to ensure that the task cannot
2277                  * take an action which puts it back on ready/state/event list,
2278                  * thereby nullifying the delete operation. Once evicted, the
2279                  * task won't be scheduled ever as it will no longer be on the
2280                  * ready list. */
2281                 #if ( configNUMBER_OF_CORES > 1 )
2282                 {
2283                     if( taskTASK_IS_RUNNING( pxTCB ) == pdTRUE )
2284                     {
2285                         if( pxTCB->xTaskRunState == ( BaseType_t ) portGET_CORE_ID() )
2286                         {
2287                             configASSERT( uxSchedulerSuspended == 0 );
2288                             taskYIELD_WITHIN_API();
2289                         }
2290                         else
2291                         {
2292                             prvYieldCore( pxTCB->xTaskRunState );
2293                         }
2294                     }
2295                 }
2296                 #endif /* #if ( configNUMBER_OF_CORES > 1 ) */
2297             }
2298             else
2299             {
2300                 --uxCurrentNumberOfTasks;
2301                 traceTASK_DELETE( pxTCB );
2302
2303                 /* Reset the next expected unblock time in case it referred to
2304                  * the task that has just been deleted. */
2305                 prvResetNextTaskUnblockTime();
2306             }
2307         }
2308         taskEXIT_CRITICAL();
2309
2310         /* If the task is not deleting itself, call prvDeleteTCB from outside of
2311          * critical section. If a task deletes itself, prvDeleteTCB is called
2312          * from prvCheckTasksWaitingTermination which is called from Idle task. */
2313         if( xDeleteTCBInIdleTask != pdTRUE )
2314         {
2315             prvDeleteTCB( pxTCB );
2316         }
2317
2318         /* Force a reschedule if it is the currently running task that has just
2319          * been deleted. */
2320         #if ( configNUMBER_OF_CORES == 1 )
2321         {
2322             if( xSchedulerRunning != pdFALSE )
2323             {
2324                 if( pxTCB == pxCurrentTCB )
2325                 {
2326                     configASSERT( uxSchedulerSuspended == 0 );
2327                     taskYIELD_WITHIN_API();
2328                 }
2329                 else
2330                 {
2331                     mtCOVERAGE_TEST_MARKER();
2332                 }
2333             }
2334         }
2335         #endif /* #if ( configNUMBER_OF_CORES == 1 ) */
2336
2337         traceRETURN_vTaskDelete();
2338     }
2339
2340 #endif /* INCLUDE_vTaskDelete */
2341 /*-----------------------------------------------------------*/
2342
2343 #if ( INCLUDE_xTaskDelayUntil == 1 )
2344
2345     BaseType_t xTaskDelayUntil( TickType_t * const pxPreviousWakeTime,
2346                                 const TickType_t xTimeIncrement )
2347     {
2348         TickType_t xTimeToWake;
2349         BaseType_t xAlreadyYielded, xShouldDelay = pdFALSE;
2350
2351         traceENTER_xTaskDelayUntil( pxPreviousWakeTime, xTimeIncrement );
2352
2353         configASSERT( pxPreviousWakeTime );
2354         configASSERT( ( xTimeIncrement > 0U ) );
2355
2356         vTaskSuspendAll();
2357         {
2358             /* Minor optimisation.  The tick count cannot change in this
2359              * block. */
2360             const TickType_t xConstTickCount = xTickCount;
2361
2362             configASSERT( uxSchedulerSuspended == 1U );
2363
2364             /* Generate the tick time at which the task wants to wake. */
2365             xTimeToWake = *pxPreviousWakeTime + xTimeIncrement;
2366
2367             if( xConstTickCount < *pxPreviousWakeTime )
2368             {
2369                 /* The tick count has overflowed since this function was
2370                  * lasted called.  In this case the only time we should ever
2371                  * actually delay is if the wake time has also  overflowed,
2372                  * and the wake time is greater than the tick time.  When this
2373                  * is the case it is as if neither time had overflowed. */
2374                 if( ( xTimeToWake < *pxPreviousWakeTime ) && ( xTimeToWake > xConstTickCount ) )
2375                 {
2376                     xShouldDelay = pdTRUE;
2377                 }
2378                 else
2379                 {
2380                     mtCOVERAGE_TEST_MARKER();
2381                 }
2382             }
2383             else
2384             {
2385                 /* The tick time has not overflowed.  In this case we will
2386                  * delay if either the wake time has overflowed, and/or the
2387                  * tick time is less than the wake time. */
2388                 if( ( xTimeToWake < *pxPreviousWakeTime ) || ( xTimeToWake > xConstTickCount ) )
2389                 {
2390                     xShouldDelay = pdTRUE;
2391                 }
2392                 else
2393                 {
2394                     mtCOVERAGE_TEST_MARKER();
2395                 }
2396             }
2397
2398             /* Update the wake time ready for the next call. */
2399             *pxPreviousWakeTime = xTimeToWake;
2400
2401             if( xShouldDelay != pdFALSE )
2402             {
2403                 traceTASK_DELAY_UNTIL( xTimeToWake );
2404
2405                 /* prvAddCurrentTaskToDelayedList() needs the block time, not
2406                  * the time to wake, so subtract the current tick count. */
2407                 prvAddCurrentTaskToDelayedList( xTimeToWake - xConstTickCount, pdFALSE );
2408             }
2409             else
2410             {
2411                 mtCOVERAGE_TEST_MARKER();
2412             }
2413         }
2414         xAlreadyYielded = xTaskResumeAll();
2415
2416         /* Force a reschedule if xTaskResumeAll has not already done so, we may
2417          * have put ourselves to sleep. */
2418         if( xAlreadyYielded == pdFALSE )
2419         {
2420             taskYIELD_WITHIN_API();
2421         }
2422         else
2423         {
2424             mtCOVERAGE_TEST_MARKER();
2425         }
2426
2427         traceRETURN_xTaskDelayUntil( xShouldDelay );
2428
2429         return xShouldDelay;
2430     }
2431
2432 #endif /* INCLUDE_xTaskDelayUntil */
2433 /*-----------------------------------------------------------*/
2434
2435 #if ( INCLUDE_vTaskDelay == 1 )
2436
2437     void vTaskDelay( const TickType_t xTicksToDelay )
2438     {
2439         BaseType_t xAlreadyYielded = pdFALSE;
2440
2441         traceENTER_vTaskDelay( xTicksToDelay );
2442
2443         /* A delay time of zero just forces a reschedule. */
2444         if( xTicksToDelay > ( TickType_t ) 0U )
2445         {
2446             vTaskSuspendAll();
2447             {
2448                 configASSERT( uxSchedulerSuspended == 1U );
2449
2450                 traceTASK_DELAY();
2451
2452                 /* A task that is removed from the event list while the
2453                  * scheduler is suspended will not get placed in the ready
2454                  * list or removed from the blocked list until the scheduler
2455                  * is resumed.
2456                  *
2457                  * This task cannot be in an event list as it is the currently
2458                  * executing task. */
2459                 prvAddCurrentTaskToDelayedList( xTicksToDelay, pdFALSE );
2460             }
2461             xAlreadyYielded = xTaskResumeAll();
2462         }
2463         else
2464         {
2465             mtCOVERAGE_TEST_MARKER();
2466         }
2467
2468         /* Force a reschedule if xTaskResumeAll has not already done so, we may
2469          * have put ourselves to sleep. */
2470         if( xAlreadyYielded == pdFALSE )
2471         {
2472             taskYIELD_WITHIN_API();
2473         }
2474         else
2475         {
2476             mtCOVERAGE_TEST_MARKER();
2477         }
2478
2479         traceRETURN_vTaskDelay();
2480     }
2481
2482 #endif /* INCLUDE_vTaskDelay */
2483 /*-----------------------------------------------------------*/
2484
2485 #if ( ( INCLUDE_eTaskGetState == 1 ) || ( configUSE_TRACE_FACILITY == 1 ) || ( INCLUDE_xTaskAbortDelay == 1 ) )
2486
2487     eTaskState eTaskGetState( TaskHandle_t xTask )
2488     {
2489         eTaskState eReturn;
2490         List_t const * pxStateList;
2491         List_t const * pxEventList;
2492         List_t const * pxDelayedList;
2493         List_t const * pxOverflowedDelayedList;
2494         const TCB_t * const pxTCB = xTask;
2495
2496         traceENTER_eTaskGetState( xTask );
2497
2498         configASSERT( pxTCB );
2499
2500         #if ( configNUMBER_OF_CORES == 1 )
2501             if( pxTCB == pxCurrentTCB )
2502             {
2503                 /* The task calling this function is querying its own state. */
2504                 eReturn = eRunning;
2505             }
2506             else
2507         #endif
2508         {
2509             taskENTER_CRITICAL();
2510             {
2511                 pxStateList = listLIST_ITEM_CONTAINER( &( pxTCB->xStateListItem ) );
2512                 pxEventList = listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) );
2513                 pxDelayedList = pxDelayedTaskList;
2514                 pxOverflowedDelayedList = pxOverflowDelayedTaskList;
2515             }
2516             taskEXIT_CRITICAL();
2517
2518             if( pxEventList == &xPendingReadyList )
2519             {
2520                 /* The task has been placed on the pending ready list, so its
2521                  * state is eReady regardless of what list the task's state list
2522                  * item is currently placed on. */
2523                 eReturn = eReady;
2524             }
2525             else if( ( pxStateList == pxDelayedList ) || ( pxStateList == pxOverflowedDelayedList ) )
2526             {
2527                 /* The task being queried is referenced from one of the Blocked
2528                  * lists. */
2529                 eReturn = eBlocked;
2530             }
2531
2532             #if ( INCLUDE_vTaskSuspend == 1 )
2533                 else if( pxStateList == &xSuspendedTaskList )
2534                 {
2535                     /* The task being queried is referenced from the suspended
2536                      * list.  Is it genuinely suspended or is it blocked
2537                      * indefinitely? */
2538                     if( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) == NULL )
2539                     {
2540                         #if ( configUSE_TASK_NOTIFICATIONS == 1 )
2541                         {
2542                             BaseType_t x;
2543
2544                             /* The task does not appear on the event list item of
2545                              * and of the RTOS objects, but could still be in the
2546                              * blocked state if it is waiting on its notification
2547                              * rather than waiting on an object.  If not, is
2548                              * suspended. */
2549                             eReturn = eSuspended;
2550
2551                             for( x = ( BaseType_t ) 0; x < ( BaseType_t ) configTASK_NOTIFICATION_ARRAY_ENTRIES; x++ )
2552                             {
2553                                 if( pxTCB->ucNotifyState[ x ] == taskWAITING_NOTIFICATION )
2554                                 {
2555                                     eReturn = eBlocked;
2556                                     break;
2557                                 }
2558                             }
2559                         }
2560                         #else /* if ( configUSE_TASK_NOTIFICATIONS == 1 ) */
2561                         {
2562                             eReturn = eSuspended;
2563                         }
2564                         #endif /* if ( configUSE_TASK_NOTIFICATIONS == 1 ) */
2565                     }
2566                     else
2567                     {
2568                         eReturn = eBlocked;
2569                     }
2570                 }
2571             #endif /* if ( INCLUDE_vTaskSuspend == 1 ) */
2572
2573             #if ( INCLUDE_vTaskDelete == 1 )
2574                 else if( ( pxStateList == &xTasksWaitingTermination ) || ( pxStateList == NULL ) )
2575                 {
2576                     /* The task being queried is referenced from the deleted
2577                      * tasks list, or it is not referenced from any lists at
2578                      * all. */
2579                     eReturn = eDeleted;
2580                 }
2581             #endif
2582
2583             else
2584             {
2585                 #if ( configNUMBER_OF_CORES == 1 )
2586                 {
2587                     /* If the task is not in any other state, it must be in the
2588                      * Ready (including pending ready) state. */
2589                     eReturn = eReady;
2590                 }
2591                 #else /* #if ( configNUMBER_OF_CORES == 1 ) */
2592                 {
2593                     if( taskTASK_IS_RUNNING( pxTCB ) == pdTRUE )
2594                     {
2595                         /* Is it actively running on a core? */
2596                         eReturn = eRunning;
2597                     }
2598                     else
2599                     {
2600                         /* If the task is not in any other state, it must be in the
2601                          * Ready (including pending ready) state. */
2602                         eReturn = eReady;
2603                     }
2604                 }
2605                 #endif /* #if ( configNUMBER_OF_CORES == 1 ) */
2606             }
2607         }
2608
2609         traceRETURN_eTaskGetState( eReturn );
2610
2611         return eReturn;
2612     }
2613
2614 #endif /* INCLUDE_eTaskGetState */
2615 /*-----------------------------------------------------------*/
2616
2617 #if ( INCLUDE_uxTaskPriorityGet == 1 )
2618
2619     UBaseType_t uxTaskPriorityGet( const TaskHandle_t xTask )
2620     {
2621         TCB_t const * pxTCB;
2622         UBaseType_t uxReturn;
2623
2624         traceENTER_uxTaskPriorityGet( xTask );
2625
2626         portBASE_TYPE_ENTER_CRITICAL();
2627         {
2628             /* If null is passed in here then it is the priority of the task
2629              * that called uxTaskPriorityGet() that is being queried. */
2630             pxTCB = prvGetTCBFromHandle( xTask );
2631             uxReturn = pxTCB->uxPriority;
2632         }
2633         portBASE_TYPE_EXIT_CRITICAL();
2634
2635         traceRETURN_uxTaskPriorityGet( uxReturn );
2636
2637         return uxReturn;
2638     }
2639
2640 #endif /* INCLUDE_uxTaskPriorityGet */
2641 /*-----------------------------------------------------------*/
2642
2643 #if ( INCLUDE_uxTaskPriorityGet == 1 )
2644
2645     UBaseType_t uxTaskPriorityGetFromISR( const TaskHandle_t xTask )
2646     {
2647         TCB_t const * pxTCB;
2648         UBaseType_t uxReturn;
2649         UBaseType_t uxSavedInterruptStatus;
2650
2651         traceENTER_uxTaskPriorityGetFromISR( xTask );
2652
2653         /* RTOS ports that support interrupt nesting have the concept of a
2654          * maximum  system call (or maximum API call) interrupt priority.
2655          * Interrupts that are  above the maximum system call priority are keep
2656          * permanently enabled, even when the RTOS kernel is in a critical section,
2657          * but cannot make any calls to FreeRTOS API functions.  If configASSERT()
2658          * is defined in FreeRTOSConfig.h then
2659          * portASSERT_IF_INTERRUPT_PRIORITY_INVALID() will result in an assertion
2660          * failure if a FreeRTOS API function is called from an interrupt that has
2661          * been assigned a priority above the configured maximum system call
2662          * priority.  Only FreeRTOS functions that end in FromISR can be called
2663          * from interrupts  that have been assigned a priority at or (logically)
2664          * below the maximum system call interrupt priority.  FreeRTOS maintains a
2665          * separate interrupt safe API to ensure interrupt entry is as fast and as
2666          * simple as possible.  More information (albeit Cortex-M specific) is
2667          * provided on the following link:
2668          * https://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html */
2669         portASSERT_IF_INTERRUPT_PRIORITY_INVALID();
2670
2671         /* MISRA Ref 4.7.1 [Return value shall be checked] */
2672         /* More details at: https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/MISRA.md#dir-47 */
2673         /* coverity[misra_c_2012_directive_4_7_violation] */
2674         uxSavedInterruptStatus = ( UBaseType_t ) taskENTER_CRITICAL_FROM_ISR();
2675         {
2676             /* If null is passed in here then it is the priority of the calling
2677              * task that is being queried. */
2678             pxTCB = prvGetTCBFromHandle( xTask );
2679             uxReturn = pxTCB->uxPriority;
2680         }
2681         taskEXIT_CRITICAL_FROM_ISR( uxSavedInterruptStatus );
2682
2683         traceRETURN_uxTaskPriorityGetFromISR( uxReturn );
2684
2685         return uxReturn;
2686     }
2687
2688 #endif /* INCLUDE_uxTaskPriorityGet */
2689 /*-----------------------------------------------------------*/
2690
2691 #if ( ( INCLUDE_uxTaskPriorityGet == 1 ) && ( configUSE_MUTEXES == 1 ) )
2692
2693     UBaseType_t uxTaskBasePriorityGet( const TaskHandle_t xTask )
2694     {
2695         TCB_t const * pxTCB;
2696         UBaseType_t uxReturn;
2697
2698         traceENTER_uxTaskBasePriorityGet( xTask );
2699
2700         portBASE_TYPE_ENTER_CRITICAL();
2701         {
2702             /* If null is passed in here then it is the base priority of the task
2703              * that called uxTaskBasePriorityGet() that is being queried. */
2704             pxTCB = prvGetTCBFromHandle( xTask );
2705             uxReturn = pxTCB->uxBasePriority;
2706         }
2707         portBASE_TYPE_EXIT_CRITICAL();
2708
2709         traceRETURN_uxTaskBasePriorityGet( uxReturn );
2710
2711         return uxReturn;
2712     }
2713
2714 #endif /* #if ( ( INCLUDE_uxTaskPriorityGet == 1 ) && ( configUSE_MUTEXES == 1 ) ) */
2715 /*-----------------------------------------------------------*/
2716
2717 #if ( ( INCLUDE_uxTaskPriorityGet == 1 ) && ( configUSE_MUTEXES == 1 ) )
2718
2719     UBaseType_t uxTaskBasePriorityGetFromISR( const TaskHandle_t xTask )
2720     {
2721         TCB_t const * pxTCB;
2722         UBaseType_t uxReturn;
2723         UBaseType_t uxSavedInterruptStatus;
2724
2725         traceENTER_uxTaskBasePriorityGetFromISR( xTask );
2726
2727         /* RTOS ports that support interrupt nesting have the concept of a
2728          * maximum  system call (or maximum API call) interrupt priority.
2729          * Interrupts that are  above the maximum system call priority are keep
2730          * permanently enabled, even when the RTOS kernel is in a critical section,
2731          * but cannot make any calls to FreeRTOS API functions.  If configASSERT()
2732          * is defined in FreeRTOSConfig.h then
2733          * portASSERT_IF_INTERRUPT_PRIORITY_INVALID() will result in an assertion
2734          * failure if a FreeRTOS API function is called from an interrupt that has
2735          * been assigned a priority above the configured maximum system call
2736          * priority.  Only FreeRTOS functions that end in FromISR can be called
2737          * from interrupts  that have been assigned a priority at or (logically)
2738          * below the maximum system call interrupt priority.  FreeRTOS maintains a
2739          * separate interrupt safe API to ensure interrupt entry is as fast and as
2740          * simple as possible.  More information (albeit Cortex-M specific) is
2741          * provided on the following link:
2742          * https://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html */
2743         portASSERT_IF_INTERRUPT_PRIORITY_INVALID();
2744
2745         /* MISRA Ref 4.7.1 [Return value shall be checked] */
2746         /* More details at: https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/MISRA.md#dir-47 */
2747         /* coverity[misra_c_2012_directive_4_7_violation] */
2748         uxSavedInterruptStatus = ( UBaseType_t ) taskENTER_CRITICAL_FROM_ISR();
2749         {
2750             /* If null is passed in here then it is the base priority of the calling
2751              * task that is being queried. */
2752             pxTCB = prvGetTCBFromHandle( xTask );
2753             uxReturn = pxTCB->uxBasePriority;
2754         }
2755         taskEXIT_CRITICAL_FROM_ISR( uxSavedInterruptStatus );
2756
2757         traceRETURN_uxTaskBasePriorityGetFromISR( uxReturn );
2758
2759         return uxReturn;
2760     }
2761
2762 #endif /* #if ( ( INCLUDE_uxTaskPriorityGet == 1 ) && ( configUSE_MUTEXES == 1 ) ) */
2763 /*-----------------------------------------------------------*/
2764
2765 #if ( INCLUDE_vTaskPrioritySet == 1 )
2766
2767     void vTaskPrioritySet( TaskHandle_t xTask,
2768                            UBaseType_t uxNewPriority )
2769     {
2770         TCB_t * pxTCB;
2771         UBaseType_t uxCurrentBasePriority, uxPriorityUsedOnEntry;
2772         BaseType_t xYieldRequired = pdFALSE;
2773
2774         #if ( configNUMBER_OF_CORES > 1 )
2775             BaseType_t xYieldForTask = pdFALSE;
2776         #endif
2777
2778         traceENTER_vTaskPrioritySet( xTask, uxNewPriority );
2779
2780         configASSERT( uxNewPriority < configMAX_PRIORITIES );
2781
2782         /* Ensure the new priority is valid. */
2783         if( uxNewPriority >= ( UBaseType_t ) configMAX_PRIORITIES )
2784         {
2785             uxNewPriority = ( UBaseType_t ) configMAX_PRIORITIES - ( UBaseType_t ) 1U;
2786         }
2787         else
2788         {
2789             mtCOVERAGE_TEST_MARKER();
2790         }
2791
2792         taskENTER_CRITICAL();
2793         {
2794             /* If null is passed in here then it is the priority of the calling
2795              * task that is being changed. */
2796             pxTCB = prvGetTCBFromHandle( xTask );
2797
2798             traceTASK_PRIORITY_SET( pxTCB, uxNewPriority );
2799
2800             #if ( configUSE_MUTEXES == 1 )
2801             {
2802                 uxCurrentBasePriority = pxTCB->uxBasePriority;
2803             }
2804             #else
2805             {
2806                 uxCurrentBasePriority = pxTCB->uxPriority;
2807             }
2808             #endif
2809
2810             if( uxCurrentBasePriority != uxNewPriority )
2811             {
2812                 /* The priority change may have readied a task of higher
2813                  * priority than a running task. */
2814                 if( uxNewPriority > uxCurrentBasePriority )
2815                 {
2816                     #if ( configNUMBER_OF_CORES == 1 )
2817                     {
2818                         if( pxTCB != pxCurrentTCB )
2819                         {
2820                             /* The priority of a task other than the currently
2821                              * running task is being raised.  Is the priority being
2822                              * raised above that of the running task? */
2823                             if( uxNewPriority > pxCurrentTCB->uxPriority )
2824                             {
2825                                 xYieldRequired = pdTRUE;
2826                             }
2827                             else
2828                             {
2829                                 mtCOVERAGE_TEST_MARKER();
2830                             }
2831                         }
2832                         else
2833                         {
2834                             /* The priority of the running task is being raised,
2835                              * but the running task must already be the highest
2836                              * priority task able to run so no yield is required. */
2837                         }
2838                     }
2839                     #else /* #if ( configNUMBER_OF_CORES == 1 ) */
2840                     {
2841                         /* The priority of a task is being raised so
2842                          * perform a yield for this task later. */
2843                         xYieldForTask = pdTRUE;
2844                     }
2845                     #endif /* #if ( configNUMBER_OF_CORES == 1 ) */
2846                 }
2847                 else if( taskTASK_IS_RUNNING( pxTCB ) == pdTRUE )
2848                 {
2849                     /* Setting the priority of a running task down means
2850                      * there may now be another task of higher priority that
2851                      * is ready to execute. */
2852                     #if ( configUSE_TASK_PREEMPTION_DISABLE == 1 )
2853                         if( pxTCB->xPreemptionDisable == pdFALSE )
2854                     #endif
2855                     {
2856                         xYieldRequired = pdTRUE;
2857                     }
2858                 }
2859                 else
2860                 {
2861                     /* Setting the priority of any other task down does not
2862                      * require a yield as the running task must be above the
2863                      * new priority of the task being modified. */
2864                 }
2865
2866                 /* Remember the ready list the task might be referenced from
2867                  * before its uxPriority member is changed so the
2868                  * taskRESET_READY_PRIORITY() macro can function correctly. */
2869                 uxPriorityUsedOnEntry = pxTCB->uxPriority;
2870
2871                 #if ( configUSE_MUTEXES == 1 )
2872                 {
2873                     /* Only change the priority being used if the task is not
2874                      * currently using an inherited priority or the new priority
2875                      * is bigger than the inherited priority. */
2876                     if( ( pxTCB->uxBasePriority == pxTCB->uxPriority ) || ( uxNewPriority > pxTCB->uxPriority ) )
2877                     {
2878                         pxTCB->uxPriority = uxNewPriority;
2879                     }
2880                     else
2881                     {
2882                         mtCOVERAGE_TEST_MARKER();
2883                     }
2884
2885                     /* The base priority gets set whatever. */
2886                     pxTCB->uxBasePriority = uxNewPriority;
2887                 }
2888                 #else /* if ( configUSE_MUTEXES == 1 ) */
2889                 {
2890                     pxTCB->uxPriority = uxNewPriority;
2891                 }
2892                 #endif /* if ( configUSE_MUTEXES == 1 ) */
2893
2894                 /* Only reset the event list item value if the value is not
2895                  * being used for anything else. */
2896                 if( ( listGET_LIST_ITEM_VALUE( &( pxTCB->xEventListItem ) ) & taskEVENT_LIST_ITEM_VALUE_IN_USE ) == ( ( TickType_t ) 0U ) )
2897                 {
2898                     listSET_LIST_ITEM_VALUE( &( pxTCB->xEventListItem ), ( ( TickType_t ) configMAX_PRIORITIES - ( TickType_t ) uxNewPriority ) );
2899                 }
2900                 else
2901                 {
2902                     mtCOVERAGE_TEST_MARKER();
2903                 }
2904
2905                 /* If the task is in the blocked or suspended list we need do
2906                  * nothing more than change its priority variable. However, if
2907                  * the task is in a ready list it needs to be removed and placed
2908                  * in the list appropriate to its new priority. */
2909                 if( listIS_CONTAINED_WITHIN( &( pxReadyTasksLists[ uxPriorityUsedOnEntry ] ), &( pxTCB->xStateListItem ) ) != pdFALSE )
2910                 {
2911                     /* The task is currently in its ready list - remove before
2912                      * adding it to its new ready list.  As we are in a critical
2913                      * section we can do this even if the scheduler is suspended. */
2914                     if( uxListRemove( &( pxTCB->xStateListItem ) ) == ( UBaseType_t ) 0 )
2915                     {
2916                         /* It is known that the task is in its ready list so
2917                          * there is no need to check again and the port level
2918                          * reset macro can be called directly. */
2919                         portRESET_READY_PRIORITY( uxPriorityUsedOnEntry, uxTopReadyPriority );
2920                     }
2921                     else
2922                     {
2923                         mtCOVERAGE_TEST_MARKER();
2924                     }
2925
2926                     prvAddTaskToReadyList( pxTCB );
2927                 }
2928                 else
2929                 {
2930                     #if ( configNUMBER_OF_CORES == 1 )
2931                     {
2932                         mtCOVERAGE_TEST_MARKER();
2933                     }
2934                     #else
2935                     {
2936                         /* It's possible that xYieldForTask was already set to pdTRUE because
2937                          * its priority is being raised. However, since it is not in a ready list
2938                          * we don't actually need to yield for it. */
2939                         xYieldForTask = pdFALSE;
2940                     }
2941                     #endif
2942                 }
2943
2944                 if( xYieldRequired != pdFALSE )
2945                 {
2946                     /* The running task priority is set down. Request the task to yield. */
2947                     taskYIELD_TASK_CORE_IF_USING_PREEMPTION( pxTCB );
2948                 }
2949                 else
2950                 {
2951                     #if ( configNUMBER_OF_CORES > 1 )
2952                         if( xYieldForTask != pdFALSE )
2953                         {
2954                             /* The priority of the task is being raised. If a running
2955                              * task has priority lower than this task, it should yield
2956                              * for this task. */
2957                             taskYIELD_ANY_CORE_IF_USING_PREEMPTION( pxTCB );
2958                         }
2959                         else
2960                     #endif /* if ( configNUMBER_OF_CORES > 1 ) */
2961                     {
2962                         mtCOVERAGE_TEST_MARKER();
2963                     }
2964                 }
2965
2966                 /* Remove compiler warning about unused variables when the port
2967                  * optimised task selection is not being used. */
2968                 ( void ) uxPriorityUsedOnEntry;
2969             }
2970         }
2971         taskEXIT_CRITICAL();
2972
2973         traceRETURN_vTaskPrioritySet();
2974     }
2975
2976 #endif /* INCLUDE_vTaskPrioritySet */
2977 /*-----------------------------------------------------------*/
2978
2979 #if ( ( configNUMBER_OF_CORES > 1 ) && ( configUSE_CORE_AFFINITY == 1 ) )
2980     void vTaskCoreAffinitySet( const TaskHandle_t xTask,
2981                                UBaseType_t uxCoreAffinityMask )
2982     {
2983         TCB_t * pxTCB;
2984         BaseType_t xCoreID;
2985
2986         traceENTER_vTaskCoreAffinitySet( xTask, uxCoreAffinityMask );
2987
2988         taskENTER_CRITICAL();
2989         {
2990             pxTCB = prvGetTCBFromHandle( xTask );
2991
2992             pxTCB->uxCoreAffinityMask = uxCoreAffinityMask;
2993
2994             if( xSchedulerRunning != pdFALSE )
2995             {
2996                 if( taskTASK_IS_RUNNING( pxTCB ) == pdTRUE )
2997                 {
2998                     xCoreID = ( BaseType_t ) pxTCB->xTaskRunState;
2999
3000                     /* If the task can no longer run on the core it was running,
3001                      * request the core to yield. */
3002                     if( ( uxCoreAffinityMask & ( ( UBaseType_t ) 1U << ( UBaseType_t ) xCoreID ) ) == 0U )
3003                     {
3004                         prvYieldCore( xCoreID );
3005                     }
3006                 }
3007                 else
3008                 {
3009                     #if ( configUSE_PREEMPTION == 1 )
3010                     {
3011                         /* The SMP scheduler requests a core to yield when a ready
3012                          * task is able to run. It is possible that the core affinity
3013                          * of the ready task is changed before the requested core
3014                          * can select it to run. In that case, the task may not be
3015                          * selected by the previously requested core due to core affinity
3016                          * constraint and the SMP scheduler must select a new core to
3017                          * yield for the task. */
3018                         prvYieldForTask( xTask );
3019                     }
3020                     #else /* #if( configUSE_PREEMPTION == 1 ) */
3021                     {
3022                         mtCOVERAGE_TEST_MARKER();
3023                     }
3024                     #endif /* #if( configUSE_PREEMPTION == 1 ) */
3025                 }
3026             }
3027         }
3028         taskEXIT_CRITICAL();
3029
3030         traceRETURN_vTaskCoreAffinitySet();
3031     }
3032 #endif /* #if ( ( configNUMBER_OF_CORES > 1 ) && ( configUSE_CORE_AFFINITY == 1 ) ) */
3033 /*-----------------------------------------------------------*/
3034
3035 #if ( ( configNUMBER_OF_CORES > 1 ) && ( configUSE_CORE_AFFINITY == 1 ) )
3036     UBaseType_t vTaskCoreAffinityGet( ConstTaskHandle_t xTask )
3037     {
3038         const TCB_t * pxTCB;
3039         UBaseType_t uxCoreAffinityMask;
3040
3041         traceENTER_vTaskCoreAffinityGet( xTask );
3042
3043         portBASE_TYPE_ENTER_CRITICAL();
3044         {
3045             pxTCB = prvGetTCBFromHandle( xTask );
3046             uxCoreAffinityMask = pxTCB->uxCoreAffinityMask;
3047         }
3048         portBASE_TYPE_EXIT_CRITICAL();
3049
3050         traceRETURN_vTaskCoreAffinityGet( uxCoreAffinityMask );
3051
3052         return uxCoreAffinityMask;
3053     }
3054 #endif /* #if ( ( configNUMBER_OF_CORES > 1 ) && ( configUSE_CORE_AFFINITY == 1 ) ) */
3055
3056 /*-----------------------------------------------------------*/
3057
3058 #if ( configUSE_TASK_PREEMPTION_DISABLE == 1 )
3059
3060     void vTaskPreemptionDisable( const TaskHandle_t xTask )
3061     {
3062         TCB_t * pxTCB;
3063
3064         traceENTER_vTaskPreemptionDisable( xTask );
3065
3066         taskENTER_CRITICAL();
3067         {
3068             pxTCB = prvGetTCBFromHandle( xTask );
3069
3070             pxTCB->xPreemptionDisable = pdTRUE;
3071         }
3072         taskEXIT_CRITICAL();
3073
3074         traceRETURN_vTaskPreemptionDisable();
3075     }
3076
3077 #endif /* #if ( configUSE_TASK_PREEMPTION_DISABLE == 1 ) */
3078 /*-----------------------------------------------------------*/
3079
3080 #if ( configUSE_TASK_PREEMPTION_DISABLE == 1 )
3081
3082     void vTaskPreemptionEnable( const TaskHandle_t xTask )
3083     {
3084         TCB_t * pxTCB;
3085         BaseType_t xCoreID;
3086
3087         traceENTER_vTaskPreemptionEnable( xTask );
3088
3089         taskENTER_CRITICAL();
3090         {
3091             pxTCB = prvGetTCBFromHandle( xTask );
3092
3093             pxTCB->xPreemptionDisable = pdFALSE;
3094
3095             if( xSchedulerRunning != pdFALSE )
3096             {
3097                 if( taskTASK_IS_RUNNING( pxTCB ) == pdTRUE )
3098                 {
3099                     xCoreID = ( BaseType_t ) pxTCB->xTaskRunState;
3100                     prvYieldCore( xCoreID );
3101                 }
3102             }
3103         }
3104         taskEXIT_CRITICAL();
3105
3106         traceRETURN_vTaskPreemptionEnable();
3107     }
3108
3109 #endif /* #if ( configUSE_TASK_PREEMPTION_DISABLE == 1 ) */
3110 /*-----------------------------------------------------------*/
3111
3112 #if ( INCLUDE_vTaskSuspend == 1 )
3113
3114     void vTaskSuspend( TaskHandle_t xTaskToSuspend )
3115     {
3116         TCB_t * pxTCB;
3117
3118         traceENTER_vTaskSuspend( xTaskToSuspend );
3119
3120         taskENTER_CRITICAL();
3121         {
3122             /* If null is passed in here then it is the running task that is
3123              * being suspended. */
3124             pxTCB = prvGetTCBFromHandle( xTaskToSuspend );
3125
3126             traceTASK_SUSPEND( pxTCB );
3127
3128             /* Remove task from the ready/delayed list and place in the
3129              * suspended list. */
3130             if( uxListRemove( &( pxTCB->xStateListItem ) ) == ( UBaseType_t ) 0 )
3131             {
3132                 taskRESET_READY_PRIORITY( pxTCB->uxPriority );
3133             }
3134             else
3135             {
3136                 mtCOVERAGE_TEST_MARKER();
3137             }
3138
3139             /* Is the task waiting on an event also? */
3140             if( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) != NULL )
3141             {
3142                 ( void ) uxListRemove( &( pxTCB->xEventListItem ) );
3143             }
3144             else
3145             {
3146                 mtCOVERAGE_TEST_MARKER();
3147             }
3148
3149             vListInsertEnd( &xSuspendedTaskList, &( pxTCB->xStateListItem ) );
3150
3151             #if ( configUSE_TASK_NOTIFICATIONS == 1 )
3152             {
3153                 BaseType_t x;
3154
3155                 for( x = ( BaseType_t ) 0; x < ( BaseType_t ) configTASK_NOTIFICATION_ARRAY_ENTRIES; x++ )
3156                 {
3157                     if( pxTCB->ucNotifyState[ x ] == taskWAITING_NOTIFICATION )
3158                     {
3159                         /* The task was blocked to wait for a notification, but is
3160                          * now suspended, so no notification was received. */
3161                         pxTCB->ucNotifyState[ x ] = taskNOT_WAITING_NOTIFICATION;
3162                     }
3163                 }
3164             }
3165             #endif /* if ( configUSE_TASK_NOTIFICATIONS == 1 ) */
3166
3167             /* In the case of SMP, it is possible that the task being suspended
3168              * is running on another core. We must evict the task before
3169              * exiting the critical section to ensure that the task cannot
3170              * take an action which puts it back on ready/state/event list,
3171              * thereby nullifying the suspend operation. Once evicted, the
3172              * task won't be scheduled before it is resumed as it will no longer
3173              * be on the ready list. */
3174             #if ( configNUMBER_OF_CORES > 1 )
3175             {
3176                 if( xSchedulerRunning != pdFALSE )
3177                 {
3178                     /* Reset the next expected unblock time in case it referred to the
3179                      * task that is now in the Suspended state. */
3180                     prvResetNextTaskUnblockTime();
3181
3182                     if( taskTASK_IS_RUNNING( pxTCB ) == pdTRUE )
3183                     {
3184                         if( pxTCB->xTaskRunState == ( BaseType_t ) portGET_CORE_ID() )
3185                         {
3186                             /* The current task has just been suspended. */
3187                             configASSERT( uxSchedulerSuspended == 0 );
3188                             vTaskYieldWithinAPI();
3189                         }
3190                         else
3191                         {
3192                             prvYieldCore( pxTCB->xTaskRunState );
3193                         }
3194                     }
3195                     else
3196                     {
3197                         mtCOVERAGE_TEST_MARKER();
3198                     }
3199                 }
3200                 else
3201                 {
3202                     mtCOVERAGE_TEST_MARKER();
3203                 }
3204             }
3205             #endif /* #if ( configNUMBER_OF_CORES > 1 ) */
3206         }
3207         taskEXIT_CRITICAL();
3208
3209         #if ( configNUMBER_OF_CORES == 1 )
3210         {
3211             UBaseType_t uxCurrentListLength;
3212
3213             if( xSchedulerRunning != pdFALSE )
3214             {
3215                 /* Reset the next expected unblock time in case it referred to the
3216                  * task that is now in the Suspended state. */
3217                 taskENTER_CRITICAL();
3218                 {
3219                     prvResetNextTaskUnblockTime();
3220                 }
3221                 taskEXIT_CRITICAL();
3222             }
3223             else
3224             {
3225                 mtCOVERAGE_TEST_MARKER();
3226             }
3227
3228             if( pxTCB == pxCurrentTCB )
3229             {
3230                 if( xSchedulerRunning != pdFALSE )
3231                 {
3232                     /* The current task has just been suspended. */
3233                     configASSERT( uxSchedulerSuspended == 0 );
3234                     portYIELD_WITHIN_API();
3235                 }
3236                 else
3237                 {
3238                     /* The scheduler is not running, but the task that was pointed
3239                      * to by pxCurrentTCB has just been suspended and pxCurrentTCB
3240                      * must be adjusted to point to a different task. */
3241
3242                     /* Use a temp variable as a distinct sequence point for reading
3243                      * volatile variables prior to a comparison to ensure compliance
3244                      * with MISRA C 2012 Rule 13.2. */
3245                     uxCurrentListLength = listCURRENT_LIST_LENGTH( &xSuspendedTaskList );
3246
3247                     if( uxCurrentListLength == uxCurrentNumberOfTasks )
3248                     {
3249                         /* No other tasks are ready, so set pxCurrentTCB back to
3250                          * NULL so when the next task is created pxCurrentTCB will
3251                          * be set to point to it no matter what its relative priority
3252                          * is. */
3253                         pxCurrentTCB = NULL;
3254                     }
3255                     else
3256                     {
3257                         vTaskSwitchContext();
3258                     }
3259                 }
3260             }
3261             else
3262             {
3263                 mtCOVERAGE_TEST_MARKER();
3264             }
3265         }
3266         #endif /* #if ( configNUMBER_OF_CORES == 1 ) */
3267
3268         traceRETURN_vTaskSuspend();
3269     }
3270
3271 #endif /* INCLUDE_vTaskSuspend */
3272 /*-----------------------------------------------------------*/
3273
3274 #if ( INCLUDE_vTaskSuspend == 1 )
3275
3276     static BaseType_t prvTaskIsTaskSuspended( const TaskHandle_t xTask )
3277     {
3278         BaseType_t xReturn = pdFALSE;
3279         const TCB_t * const pxTCB = xTask;
3280
3281         /* Accesses xPendingReadyList so must be called from a critical
3282          * section. */
3283
3284         /* It does not make sense to check if the calling task is suspended. */
3285         configASSERT( xTask );
3286
3287         /* Is the task being resumed actually in the suspended list? */
3288         if( listIS_CONTAINED_WITHIN( &xSuspendedTaskList, &( pxTCB->xStateListItem ) ) != pdFALSE )
3289         {
3290             /* Has the task already been resumed from within an ISR? */
3291             if( listIS_CONTAINED_WITHIN( &xPendingReadyList, &( pxTCB->xEventListItem ) ) == pdFALSE )
3292             {
3293                 /* Is it in the suspended list because it is in the Suspended
3294                  * state, or because it is blocked with no timeout? */
3295                 if( listIS_CONTAINED_WITHIN( NULL, &( pxTCB->xEventListItem ) ) != pdFALSE )
3296                 {
3297                     #if ( configUSE_TASK_NOTIFICATIONS == 1 )
3298                     {
3299                         BaseType_t x;
3300
3301                         /* The task does not appear on the event list item of
3302                          * and of the RTOS objects, but could still be in the
3303                          * blocked state if it is waiting on its notification
3304                          * rather than waiting on an object.  If not, is
3305                          * suspended. */
3306                         xReturn = pdTRUE;
3307
3308                         for( x = ( BaseType_t ) 0; x < ( BaseType_t ) configTASK_NOTIFICATION_ARRAY_ENTRIES; x++ )
3309                         {
3310                             if( pxTCB->ucNotifyState[ x ] == taskWAITING_NOTIFICATION )
3311                             {
3312                                 xReturn = pdFALSE;
3313                                 break;
3314                             }
3315                         }
3316                     }
3317                     #else /* if ( configUSE_TASK_NOTIFICATIONS == 1 ) */
3318                     {
3319                         xReturn = pdTRUE;
3320                     }
3321                     #endif /* if ( configUSE_TASK_NOTIFICATIONS == 1 ) */
3322                 }
3323                 else
3324                 {
3325                     mtCOVERAGE_TEST_MARKER();
3326                 }
3327             }
3328             else
3329             {
3330                 mtCOVERAGE_TEST_MARKER();
3331             }
3332         }
3333         else
3334         {
3335             mtCOVERAGE_TEST_MARKER();
3336         }
3337
3338         return xReturn;
3339     }
3340
3341 #endif /* INCLUDE_vTaskSuspend */
3342 /*-----------------------------------------------------------*/
3343
3344 #if ( INCLUDE_vTaskSuspend == 1 )
3345
3346     void vTaskResume( TaskHandle_t xTaskToResume )
3347     {
3348         TCB_t * const pxTCB = xTaskToResume;
3349
3350         traceENTER_vTaskResume( xTaskToResume );
3351
3352         /* It does not make sense to resume the calling task. */
3353         configASSERT( xTaskToResume );
3354
3355         #if ( configNUMBER_OF_CORES == 1 )
3356
3357             /* The parameter cannot be NULL as it is impossible to resume the
3358              * currently executing task. */
3359             if( ( pxTCB != pxCurrentTCB ) && ( pxTCB != NULL ) )
3360         #else
3361
3362             /* The parameter cannot be NULL as it is impossible to resume the
3363              * currently executing task. It is also impossible to resume a task
3364              * that is actively running on another core but it is not safe
3365              * to check their run state here. Therefore, we get into a critical
3366              * section and check if the task is actually suspended or not. */
3367             if( pxTCB != NULL )
3368         #endif
3369         {
3370             taskENTER_CRITICAL();
3371             {
3372                 if( prvTaskIsTaskSuspended( pxTCB ) != pdFALSE )
3373                 {
3374                     traceTASK_RESUME( pxTCB );
3375
3376                     /* The ready list can be accessed even if the scheduler is
3377                      * suspended because this is inside a critical section. */
3378                     ( void ) uxListRemove( &( pxTCB->xStateListItem ) );
3379                     prvAddTaskToReadyList( pxTCB );
3380
3381                     /* This yield may not cause the task just resumed to run,
3382                      * but will leave the lists in the correct state for the
3383                      * next yield. */
3384                     taskYIELD_ANY_CORE_IF_USING_PREEMPTION( pxTCB );
3385                 }
3386                 else
3387                 {
3388                     mtCOVERAGE_TEST_MARKER();
3389                 }
3390             }
3391             taskEXIT_CRITICAL();
3392         }
3393         else
3394         {
3395             mtCOVERAGE_TEST_MARKER();
3396         }
3397
3398         traceRETURN_vTaskResume();
3399     }
3400
3401 #endif /* INCLUDE_vTaskSuspend */
3402
3403 /*-----------------------------------------------------------*/
3404
3405 #if ( ( INCLUDE_xTaskResumeFromISR == 1 ) && ( INCLUDE_vTaskSuspend == 1 ) )
3406
3407     BaseType_t xTaskResumeFromISR( TaskHandle_t xTaskToResume )
3408     {
3409         BaseType_t xYieldRequired = pdFALSE;
3410         TCB_t * const pxTCB = xTaskToResume;
3411         UBaseType_t uxSavedInterruptStatus;
3412
3413         traceENTER_xTaskResumeFromISR( xTaskToResume );
3414
3415         configASSERT( xTaskToResume );
3416
3417         /* RTOS ports that support interrupt nesting have the concept of a
3418          * maximum  system call (or maximum API call) interrupt priority.
3419          * Interrupts that are  above the maximum system call priority are keep
3420          * permanently enabled, even when the RTOS kernel is in a critical section,
3421          * but cannot make any calls to FreeRTOS API functions.  If configASSERT()
3422          * is defined in FreeRTOSConfig.h then
3423          * portASSERT_IF_INTERRUPT_PRIORITY_INVALID() will result in an assertion
3424          * failure if a FreeRTOS API function is called from an interrupt that has
3425          * been assigned a priority above the configured maximum system call
3426          * priority.  Only FreeRTOS functions that end in FromISR can be called
3427          * from interrupts  that have been assigned a priority at or (logically)
3428          * below the maximum system call interrupt priority.  FreeRTOS maintains a
3429          * separate interrupt safe API to ensure interrupt entry is as fast and as
3430          * simple as possible.  More information (albeit Cortex-M specific) is
3431          * provided on the following link:
3432          * https://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html */
3433         portASSERT_IF_INTERRUPT_PRIORITY_INVALID();
3434
3435         /* MISRA Ref 4.7.1 [Return value shall be checked] */
3436         /* More details at: https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/MISRA.md#dir-47 */
3437         /* coverity[misra_c_2012_directive_4_7_violation] */
3438         uxSavedInterruptStatus = taskENTER_CRITICAL_FROM_ISR();
3439         {
3440             if( prvTaskIsTaskSuspended( pxTCB ) != pdFALSE )
3441             {
3442                 traceTASK_RESUME_FROM_ISR( pxTCB );
3443
3444                 /* Check the ready lists can be accessed. */
3445                 if( uxSchedulerSuspended == ( UBaseType_t ) 0U )
3446                 {
3447                     #if ( configNUMBER_OF_CORES == 1 )
3448                     {
3449                         /* Ready lists can be accessed so move the task from the
3450                          * suspended list to the ready list directly. */
3451                         if( pxTCB->uxPriority > pxCurrentTCB->uxPriority )
3452                         {
3453                             xYieldRequired = pdTRUE;
3454
3455                             /* Mark that a yield is pending in case the user is not
3456                              * using the return value to initiate a context switch
3457                              * from the ISR using the port specific portYIELD_FROM_ISR(). */
3458                             xYieldPendings[ 0 ] = pdTRUE;
3459                         }
3460                         else
3461                         {
3462                             mtCOVERAGE_TEST_MARKER();
3463                         }
3464                     }
3465                     #endif /* #if ( configNUMBER_OF_CORES == 1 ) */
3466
3467                     ( void ) uxListRemove( &( pxTCB->xStateListItem ) );
3468                     prvAddTaskToReadyList( pxTCB );
3469                 }
3470                 else
3471                 {
3472                     /* The delayed or ready lists cannot be accessed so the task
3473                      * is held in the pending ready list until the scheduler is
3474                      * unsuspended. */
3475                     vListInsertEnd( &( xPendingReadyList ), &( pxTCB->xEventListItem ) );
3476                 }
3477
3478                 #if ( ( configNUMBER_OF_CORES > 1 ) && ( configUSE_PREEMPTION == 1 ) )
3479                 {
3480                     prvYieldForTask( pxTCB );
3481
3482                     if( xYieldPendings[ portGET_CORE_ID() ] != pdFALSE )
3483                     {
3484                         xYieldRequired = pdTRUE;
3485                     }
3486                 }
3487                 #endif /* #if ( ( configNUMBER_OF_CORES > 1 ) && ( configUSE_PREEMPTION == 1 ) ) */
3488             }
3489             else
3490             {
3491                 mtCOVERAGE_TEST_MARKER();
3492             }
3493         }
3494         taskEXIT_CRITICAL_FROM_ISR( uxSavedInterruptStatus );
3495
3496         traceRETURN_xTaskResumeFromISR( xYieldRequired );
3497
3498         return xYieldRequired;
3499     }
3500
3501 #endif /* ( ( INCLUDE_xTaskResumeFromISR == 1 ) && ( INCLUDE_vTaskSuspend == 1 ) ) */
3502 /*-----------------------------------------------------------*/
3503
3504 static BaseType_t prvCreateIdleTasks( void )
3505 {
3506     BaseType_t xReturn = pdPASS;
3507     BaseType_t xCoreID;
3508     char cIdleName[ configMAX_TASK_NAME_LEN ];
3509     TaskFunction_t pxIdleTaskFunction = NULL;
3510     BaseType_t xIdleTaskNameIndex;
3511
3512     for( xIdleTaskNameIndex = ( BaseType_t ) 0; xIdleTaskNameIndex < ( BaseType_t ) configMAX_TASK_NAME_LEN; xIdleTaskNameIndex++ )
3513     {
3514         cIdleName[ xIdleTaskNameIndex ] = configIDLE_TASK_NAME[ xIdleTaskNameIndex ];
3515
3516         /* Don't copy all configMAX_TASK_NAME_LEN if the string is shorter than
3517          * configMAX_TASK_NAME_LEN characters just in case the memory after the
3518          * string is not accessible (extremely unlikely). */
3519         if( cIdleName[ xIdleTaskNameIndex ] == ( char ) 0x00 )
3520         {
3521             break;
3522         }
3523         else
3524         {
3525             mtCOVERAGE_TEST_MARKER();
3526         }
3527     }
3528
3529     /* Add each idle task at the lowest priority. */
3530     for( xCoreID = ( BaseType_t ) 0; xCoreID < ( BaseType_t ) configNUMBER_OF_CORES; xCoreID++ )
3531     {
3532         #if ( configNUMBER_OF_CORES == 1 )
3533         {
3534             pxIdleTaskFunction = prvIdleTask;
3535         }
3536         #else /* #if (  configNUMBER_OF_CORES == 1 ) */
3537         {
3538             /* In the FreeRTOS SMP, configNUMBER_OF_CORES - 1 passive idle tasks
3539              * are also created to ensure that each core has an idle task to
3540              * run when no other task is available to run. */
3541             if( xCoreID == 0 )
3542             {
3543                 pxIdleTaskFunction = prvIdleTask;
3544             }
3545             else
3546             {
3547                 pxIdleTaskFunction = prvPassiveIdleTask;
3548             }
3549         }
3550         #endif /* #if (  configNUMBER_OF_CORES == 1 ) */
3551
3552         /* Update the idle task name with suffix to differentiate the idle tasks.
3553          * This function is not required in single core FreeRTOS since there is
3554          * only one idle task. */
3555         #if ( configNUMBER_OF_CORES > 1 )
3556         {
3557             /* Append the idle task number to the end of the name if there is space. */
3558             if( xIdleTaskNameIndex < ( BaseType_t ) configMAX_TASK_NAME_LEN )
3559             {
3560                 cIdleName[ xIdleTaskNameIndex ] = ( char ) ( xCoreID + '0' );
3561
3562                 /* And append a null character if there is space. */
3563                 if( ( xIdleTaskNameIndex + 1 ) < ( BaseType_t ) configMAX_TASK_NAME_LEN )
3564                 {
3565                     cIdleName[ xIdleTaskNameIndex + 1 ] = '\0';
3566                 }
3567                 else
3568                 {
3569                     mtCOVERAGE_TEST_MARKER();
3570                 }
3571             }
3572             else
3573             {
3574                 mtCOVERAGE_TEST_MARKER();
3575             }
3576         }
3577         #endif /* if ( configNUMBER_OF_CORES > 1 ) */
3578
3579         #if ( configSUPPORT_STATIC_ALLOCATION == 1 )
3580         {
3581             StaticTask_t * pxIdleTaskTCBBuffer = NULL;
3582             StackType_t * pxIdleTaskStackBuffer = NULL;
3583             configSTACK_DEPTH_TYPE uxIdleTaskStackSize;
3584
3585             /* The Idle task is created using user provided RAM - obtain the
3586              * address of the RAM then create the idle task. */
3587             #if ( configNUMBER_OF_CORES == 1 )
3588             {
3589                 vApplicationGetIdleTaskMemory( &pxIdleTaskTCBBuffer, &pxIdleTaskStackBuffer, &uxIdleTaskStackSize );
3590             }
3591             #else
3592             {
3593                 if( xCoreID == 0 )
3594                 {
3595                     vApplicationGetIdleTaskMemory( &pxIdleTaskTCBBuffer, &pxIdleTaskStackBuffer, &uxIdleTaskStackSize );
3596                 }
3597                 else
3598                 {
3599                     vApplicationGetPassiveIdleTaskMemory( &pxIdleTaskTCBBuffer, &pxIdleTaskStackBuffer, &uxIdleTaskStackSize, ( BaseType_t ) ( xCoreID - 1 ) );
3600                 }
3601             }
3602             #endif /* if ( configNUMBER_OF_CORES == 1 ) */
3603             xIdleTaskHandles[ xCoreID ] = xTaskCreateStatic( pxIdleTaskFunction,
3604                                                              cIdleName,
3605                                                              uxIdleTaskStackSize,
3606                                                              ( void * ) NULL,
3607                                                              portPRIVILEGE_BIT, /* In effect ( tskIDLE_PRIORITY | portPRIVILEGE_BIT ), but tskIDLE_PRIORITY is zero. */
3608                                                              pxIdleTaskStackBuffer,
3609                                                              pxIdleTaskTCBBuffer );
3610
3611             if( xIdleTaskHandles[ xCoreID ] != NULL )
3612             {
3613                 xReturn = pdPASS;
3614             }
3615             else
3616             {
3617                 xReturn = pdFAIL;
3618             }
3619         }
3620         #else /* if ( configSUPPORT_STATIC_ALLOCATION == 1 ) */
3621         {
3622             /* The Idle task is being created using dynamically allocated RAM. */
3623             xReturn = xTaskCreate( pxIdleTaskFunction,
3624                                    cIdleName,
3625                                    configMINIMAL_STACK_SIZE,
3626                                    ( void * ) NULL,
3627                                    portPRIVILEGE_BIT, /* In effect ( tskIDLE_PRIORITY | portPRIVILEGE_BIT ), but tskIDLE_PRIORITY is zero. */
3628                                    &xIdleTaskHandles[ xCoreID ] );
3629         }
3630         #endif /* configSUPPORT_STATIC_ALLOCATION */
3631
3632         /* Break the loop if any of the idle task is failed to be created. */
3633         if( xReturn != pdPASS )
3634         {
3635             break;
3636         }
3637         else
3638         {
3639             #if ( configNUMBER_OF_CORES == 1 )
3640             {
3641                 mtCOVERAGE_TEST_MARKER();
3642             }
3643             #else
3644             {
3645                 /* Assign idle task to each core before SMP scheduler is running. */
3646                 xIdleTaskHandles[ xCoreID ]->xTaskRunState = xCoreID;
3647                 pxCurrentTCBs[ xCoreID ] = xIdleTaskHandles[ xCoreID ];
3648             }
3649             #endif
3650         }
3651     }
3652
3653     return xReturn;
3654 }
3655
3656 /*-----------------------------------------------------------*/
3657
3658 void vTaskStartScheduler( void )
3659 {
3660     BaseType_t xReturn;
3661
3662     traceENTER_vTaskStartScheduler();
3663
3664     #if ( configUSE_CORE_AFFINITY == 1 ) && ( configNUMBER_OF_CORES > 1 )
3665     {
3666         /* Sanity check that the UBaseType_t must have greater than or equal to
3667          * the number of bits as confNUMBER_OF_CORES. */
3668         configASSERT( ( sizeof( UBaseType_t ) * taskBITS_PER_BYTE ) >= configNUMBER_OF_CORES );
3669     }
3670     #endif /* #if ( configUSE_CORE_AFFINITY == 1 ) && ( configNUMBER_OF_CORES > 1 ) */
3671
3672     xReturn = prvCreateIdleTasks();
3673
3674     #if ( configUSE_TIMERS == 1 )
3675     {
3676         if( xReturn == pdPASS )
3677         {
3678             xReturn = xTimerCreateTimerTask();
3679         }
3680         else
3681         {
3682             mtCOVERAGE_TEST_MARKER();
3683         }
3684     }
3685     #endif /* configUSE_TIMERS */
3686
3687     if( xReturn == pdPASS )
3688     {
3689         /* freertos_tasks_c_additions_init() should only be called if the user
3690          * definable macro FREERTOS_TASKS_C_ADDITIONS_INIT() is defined, as that is
3691          * the only macro called by the function. */
3692         #ifdef FREERTOS_TASKS_C_ADDITIONS_INIT
3693         {
3694             freertos_tasks_c_additions_init();
3695         }
3696         #endif
3697
3698         /* Interrupts are turned off here, to ensure a tick does not occur
3699          * before or during the call to xPortStartScheduler().  The stacks of
3700          * the created tasks contain a status word with interrupts switched on
3701          * so interrupts will automatically get re-enabled when the first task
3702          * starts to run. */
3703         portDISABLE_INTERRUPTS();
3704
3705         #if ( configUSE_C_RUNTIME_TLS_SUPPORT == 1 )
3706         {
3707             /* Switch C-Runtime's TLS Block to point to the TLS
3708              * block specific to the task that will run first. */
3709             configSET_TLS_BLOCK( pxCurrentTCB->xTLSBlock );
3710         }
3711         #endif
3712
3713         xNextTaskUnblockTime = portMAX_DELAY;
3714         xSchedulerRunning = pdTRUE;
3715         xTickCount = ( TickType_t ) configINITIAL_TICK_COUNT;
3716
3717         /* If configGENERATE_RUN_TIME_STATS is defined then the following
3718          * macro must be defined to configure the timer/counter used to generate
3719          * the run time counter time base.   NOTE:  If configGENERATE_RUN_TIME_STATS
3720          * is set to 0 and the following line fails to build then ensure you do not
3721          * have portCONFIGURE_TIMER_FOR_RUN_TIME_STATS() defined in your
3722          * FreeRTOSConfig.h file. */
3723         portCONFIGURE_TIMER_FOR_RUN_TIME_STATS();
3724
3725         traceTASK_SWITCHED_IN();
3726
3727         traceSTARTING_SCHEDULER( xIdleTaskHandles );
3728
3729         /* Setting up the timer tick is hardware specific and thus in the
3730          * portable interface. */
3731
3732         /* The return value for xPortStartScheduler is not required
3733          * hence using a void datatype. */
3734         ( void ) xPortStartScheduler();
3735
3736         /* In most cases, xPortStartScheduler() will not return. If it
3737          * returns pdTRUE then there was not enough heap memory available
3738          * to create either the Idle or the Timer task. If it returned
3739          * pdFALSE, then the application called xTaskEndScheduler().
3740          * Most ports don't implement xTaskEndScheduler() as there is
3741          * nothing to return to. */
3742     }
3743     else
3744     {
3745         /* This line will only be reached if the kernel could not be started,
3746          * because there was not enough FreeRTOS heap to create the idle task
3747          * or the timer task. */
3748         configASSERT( xReturn != errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY );
3749     }
3750
3751     /* Prevent compiler warnings if INCLUDE_xTaskGetIdleTaskHandle is set to 0,
3752      * meaning xIdleTaskHandles are not used anywhere else. */
3753     ( void ) xIdleTaskHandles;
3754
3755     /* OpenOCD makes use of uxTopUsedPriority for thread debugging. Prevent uxTopUsedPriority
3756      * from getting optimized out as it is no longer used by the kernel. */
3757     ( void ) uxTopUsedPriority;
3758
3759     traceRETURN_vTaskStartScheduler();
3760 }
3761 /*-----------------------------------------------------------*/
3762
3763 void vTaskEndScheduler( void )
3764 {
3765     traceENTER_vTaskEndScheduler();
3766
3767     #if ( INCLUDE_vTaskDelete == 1 )
3768     {
3769         BaseType_t xCoreID;
3770
3771         #if ( configUSE_TIMERS == 1 )
3772         {
3773             /* Delete the timer task created by the kernel. */
3774             vTaskDelete( xTimerGetTimerDaemonTaskHandle() );
3775         }
3776         #endif /* #if ( configUSE_TIMERS == 1 ) */
3777
3778         /* Delete Idle tasks created by the kernel.*/
3779         for( xCoreID = 0; xCoreID < ( BaseType_t ) configNUMBER_OF_CORES; xCoreID++ )
3780         {
3781             vTaskDelete( xIdleTaskHandles[ xCoreID ] );
3782         }
3783
3784         /* Idle task is responsible for reclaiming the resources of the tasks in
3785          * xTasksWaitingTermination list. Since the idle task is now deleted and
3786          * no longer going to run, we need to reclaim resources of all the tasks
3787          * in the xTasksWaitingTermination list. */
3788         prvCheckTasksWaitingTermination();
3789     }
3790     #endif /* #if ( INCLUDE_vTaskDelete == 1 ) */
3791
3792     /* Stop the scheduler interrupts and call the portable scheduler end
3793      * routine so the original ISRs can be restored if necessary.  The port
3794      * layer must ensure interrupts enable  bit is left in the correct state. */
3795     portDISABLE_INTERRUPTS();
3796     xSchedulerRunning = pdFALSE;
3797
3798     /* This function must be called from a task and the application is
3799      * responsible for deleting that task after the scheduler is stopped. */
3800     vPortEndScheduler();
3801
3802     traceRETURN_vTaskEndScheduler();
3803 }
3804 /*----------------------------------------------------------*/
3805
3806 void vTaskSuspendAll( void )
3807 {
3808     traceENTER_vTaskSuspendAll();
3809
3810     #if ( configNUMBER_OF_CORES == 1 )
3811     {
3812         /* A critical section is not required as the variable is of type
3813          * BaseType_t. Each task maintains its own context, and a context switch
3814          * cannot occur if the variable is non zero. So, as long as the writing
3815          * from the register back into the memory is atomic, it is not a
3816          * problem.
3817          *
3818          * Consider the following scenario, which starts with
3819          * uxSchedulerSuspended at zero.
3820          *
3821          * 1. load uxSchedulerSuspended into register.
3822          * 2. Now a context switch causes another task to run, and the other
3823          *    task uses the same variable. The other task will see the variable
3824          *    as zero because the variable has not yet been updated by the
3825          *    original task. Eventually the original task runs again. **That can
3826          *    only happen when uxSchedulerSuspended is once again zero**. When
3827          *    the original task runs again, the contents of the CPU registers
3828          *    are restored to exactly how they were when it was switched out -
3829          *    therefore the value it read into the register still matches the
3830          *    value of the uxSchedulerSuspended variable.
3831          *
3832          * 3. increment register.
3833          * 4. store register into uxSchedulerSuspended. The value restored to
3834          *    uxSchedulerSuspended will be the correct value of 1, even though
3835          *    the variable was used by other tasks in the mean time.
3836          */
3837
3838         /* portSOFTWARE_BARRIER() is only implemented for emulated/simulated ports that
3839          * do not otherwise exhibit real time behaviour. */
3840         portSOFTWARE_BARRIER();
3841
3842         /* The scheduler is suspended if uxSchedulerSuspended is non-zero.  An increment
3843          * is used to allow calls to vTaskSuspendAll() to nest. */
3844         uxSchedulerSuspended = ( UBaseType_t ) ( uxSchedulerSuspended + 1U );
3845
3846         /* Enforces ordering for ports and optimised compilers that may otherwise place
3847          * the above increment elsewhere. */
3848         portMEMORY_BARRIER();
3849     }
3850     #else /* #if ( configNUMBER_OF_CORES == 1 ) */
3851     {
3852         UBaseType_t ulState;
3853
3854         /* This must only be called from within a task. */
3855         portASSERT_IF_IN_ISR();
3856
3857         if( xSchedulerRunning != pdFALSE )
3858         {
3859             /* Writes to uxSchedulerSuspended must be protected by both the task AND ISR locks.
3860              * We must disable interrupts before we grab the locks in the event that this task is
3861              * interrupted and switches context before incrementing uxSchedulerSuspended.
3862              * It is safe to re-enable interrupts after releasing the ISR lock and incrementing
3863              * uxSchedulerSuspended since that will prevent context switches. */
3864             ulState = portSET_INTERRUPT_MASK();
3865
3866             /* This must never be called from inside a critical section. */
3867             configASSERT( portGET_CRITICAL_NESTING_COUNT() == 0 );
3868
3869             /* portSOFRWARE_BARRIER() is only implemented for emulated/simulated ports that
3870              * do not otherwise exhibit real time behaviour. */
3871             portSOFTWARE_BARRIER();
3872
3873             portGET_TASK_LOCK();
3874
3875             /* uxSchedulerSuspended is increased after prvCheckForRunStateChange. The
3876              * purpose is to prevent altering the variable when fromISR APIs are readying
3877              * it. */
3878             if( uxSchedulerSuspended == 0U )
3879             {
3880                 prvCheckForRunStateChange();
3881             }
3882             else
3883             {
3884                 mtCOVERAGE_TEST_MARKER();
3885             }
3886
3887             portGET_ISR_LOCK();
3888
3889             /* The scheduler is suspended if uxSchedulerSuspended is non-zero. An increment
3890              * is used to allow calls to vTaskSuspendAll() to nest. */
3891             ++uxSchedulerSuspended;
3892             portRELEASE_ISR_LOCK();
3893
3894             portCLEAR_INTERRUPT_MASK( ulState );
3895         }
3896         else
3897         {
3898             mtCOVERAGE_TEST_MARKER();
3899         }
3900     }
3901     #endif /* #if ( configNUMBER_OF_CORES == 1 ) */
3902
3903     traceRETURN_vTaskSuspendAll();
3904 }
3905
3906 /*----------------------------------------------------------*/
3907
3908 #if ( configUSE_TICKLESS_IDLE != 0 )
3909
3910     static TickType_t prvGetExpectedIdleTime( void )
3911     {
3912         TickType_t xReturn;
3913         BaseType_t xHigherPriorityReadyTasks = pdFALSE;
3914
3915         /* xHigherPriorityReadyTasks takes care of the case where
3916          * configUSE_PREEMPTION is 0, so there may be tasks above the idle priority
3917          * task that are in the Ready state, even though the idle task is
3918          * running. */
3919         #if ( configUSE_PORT_OPTIMISED_TASK_SELECTION == 0 )
3920         {
3921             if( uxTopReadyPriority > tskIDLE_PRIORITY )
3922             {
3923                 xHigherPriorityReadyTasks = pdTRUE;
3924             }
3925         }
3926         #else
3927         {
3928             const UBaseType_t uxLeastSignificantBit = ( UBaseType_t ) 0x01;
3929
3930             /* When port optimised task selection is used the uxTopReadyPriority
3931              * variable is used as a bit map.  If bits other than the least
3932              * significant bit are set then there are tasks that have a priority
3933              * above the idle priority that are in the Ready state.  This takes
3934              * care of the case where the co-operative scheduler is in use. */
3935             if( uxTopReadyPriority > uxLeastSignificantBit )
3936             {
3937                 xHigherPriorityReadyTasks = pdTRUE;
3938             }
3939         }
3940         #endif /* if ( configUSE_PORT_OPTIMISED_TASK_SELECTION == 0 ) */
3941
3942         if( pxCurrentTCB->uxPriority > tskIDLE_PRIORITY )
3943         {
3944             xReturn = 0;
3945         }
3946         else if( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ tskIDLE_PRIORITY ] ) ) > 1U )
3947         {
3948             /* There are other idle priority tasks in the ready state.  If
3949              * time slicing is used then the very next tick interrupt must be
3950              * processed. */
3951             xReturn = 0;
3952         }
3953         else if( xHigherPriorityReadyTasks != pdFALSE )
3954         {
3955             /* There are tasks in the Ready state that have a priority above the
3956              * idle priority.  This path can only be reached if
3957              * configUSE_PREEMPTION is 0. */
3958             xReturn = 0;
3959         }
3960         else
3961         {
3962             xReturn = xNextTaskUnblockTime;
3963             xReturn -= xTickCount;
3964         }
3965
3966         return xReturn;
3967     }
3968
3969 #endif /* configUSE_TICKLESS_IDLE */
3970 /*----------------------------------------------------------*/
3971
3972 BaseType_t xTaskResumeAll( void )
3973 {
3974     TCB_t * pxTCB = NULL;
3975     BaseType_t xAlreadyYielded = pdFALSE;
3976
3977     traceENTER_xTaskResumeAll();
3978
3979     #if ( configNUMBER_OF_CORES > 1 )
3980         if( xSchedulerRunning != pdFALSE )
3981     #endif
3982     {
3983         /* It is possible that an ISR caused a task to be removed from an event
3984          * list while the scheduler was suspended.  If this was the case then the
3985          * removed task will have been added to the xPendingReadyList.  Once the
3986          * scheduler has been resumed it is safe to move all the pending ready
3987          * tasks from this list into their appropriate ready list. */
3988         taskENTER_CRITICAL();
3989         {
3990             BaseType_t xCoreID;
3991             xCoreID = ( BaseType_t ) portGET_CORE_ID();
3992
3993             /* If uxSchedulerSuspended is zero then this function does not match a
3994              * previous call to vTaskSuspendAll(). */
3995             configASSERT( uxSchedulerSuspended != 0U );
3996
3997             uxSchedulerSuspended = ( UBaseType_t ) ( uxSchedulerSuspended - 1U );
3998             portRELEASE_TASK_LOCK();
3999
4000             if( uxSchedulerSuspended == ( UBaseType_t ) 0U )
4001             {
4002                 if( uxCurrentNumberOfTasks > ( UBaseType_t ) 0U )
4003                 {
4004                     /* Move any readied tasks from the pending list into the
4005                      * appropriate ready list. */
4006                     while( listLIST_IS_EMPTY( &xPendingReadyList ) == pdFALSE )
4007                     {
4008                         /* MISRA Ref 11.5.3 [Void pointer assignment] */
4009                         /* More details at: https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/MISRA.md#rule-115 */
4010                         /* coverity[misra_c_2012_rule_11_5_violation] */
4011                         pxTCB = listGET_OWNER_OF_HEAD_ENTRY( ( &xPendingReadyList ) );
4012                         listREMOVE_ITEM( &( pxTCB->xEventListItem ) );
4013                         portMEMORY_BARRIER();
4014                         listREMOVE_ITEM( &( pxTCB->xStateListItem ) );
4015                         prvAddTaskToReadyList( pxTCB );
4016
4017                         #if ( configNUMBER_OF_CORES == 1 )
4018                         {
4019                             /* If the moved task has a priority higher than the current
4020                              * task then a yield must be performed. */
4021                             if( pxTCB->uxPriority > pxCurrentTCB->uxPriority )
4022                             {
4023                                 xYieldPendings[ xCoreID ] = pdTRUE;
4024                             }
4025                             else
4026                             {
4027                                 mtCOVERAGE_TEST_MARKER();
4028                             }
4029                         }
4030                         #else /* #if ( configNUMBER_OF_CORES == 1 ) */
4031                         {
4032                             /* All appropriate tasks yield at the moment a task is added to xPendingReadyList.
4033                              * If the current core yielded then vTaskSwitchContext() has already been called
4034                              * which sets xYieldPendings for the current core to pdTRUE. */
4035                         }
4036                         #endif /* #if ( configNUMBER_OF_CORES == 1 ) */
4037                     }
4038
4039                     if( pxTCB != NULL )
4040                     {
4041                         /* A task was unblocked while the scheduler was suspended,
4042                          * which may have prevented the next unblock time from being
4043                          * re-calculated, in which case re-calculate it now.  Mainly
4044                          * important for low power tickless implementations, where
4045                          * this can prevent an unnecessary exit from low power
4046                          * state. */
4047                         prvResetNextTaskUnblockTime();
4048                     }
4049
4050                     /* If any ticks occurred while the scheduler was suspended then
4051                      * they should be processed now.  This ensures the tick count does
4052                      * not  slip, and that any delayed tasks are resumed at the correct
4053                      * time.
4054                      *
4055                      * It should be safe to call xTaskIncrementTick here from any core
4056                      * since we are in a critical section and xTaskIncrementTick itself
4057                      * protects itself within a critical section. Suspending the scheduler
4058                      * from any core causes xTaskIncrementTick to increment uxPendedCounts. */
4059                     {
4060                         TickType_t xPendedCounts = xPendedTicks; /* Non-volatile copy. */
4061
4062                         if( xPendedCounts > ( TickType_t ) 0U )
4063                         {
4064                             do
4065                             {
4066                                 if( xTaskIncrementTick() != pdFALSE )
4067                                 {
4068                                     /* Other cores are interrupted from
4069                                      * within xTaskIncrementTick(). */
4070                                     xYieldPendings[ xCoreID ] = pdTRUE;
4071                                 }
4072                                 else
4073                                 {
4074                                     mtCOVERAGE_TEST_MARKER();
4075                                 }
4076
4077                                 --xPendedCounts;
4078                             } while( xPendedCounts > ( TickType_t ) 0U );
4079
4080                             xPendedTicks = 0;
4081                         }
4082                         else
4083                         {
4084                             mtCOVERAGE_TEST_MARKER();
4085                         }
4086                     }
4087
4088                     if( xYieldPendings[ xCoreID ] != pdFALSE )
4089                     {
4090                         #if ( configUSE_PREEMPTION != 0 )
4091                         {
4092                             xAlreadyYielded = pdTRUE;
4093                         }
4094                         #endif /* #if ( configUSE_PREEMPTION != 0 ) */
4095
4096                         #if ( configNUMBER_OF_CORES == 1 )
4097                         {
4098                             taskYIELD_TASK_CORE_IF_USING_PREEMPTION( pxCurrentTCB );
4099                         }
4100                         #endif /* #if ( configNUMBER_OF_CORES == 1 ) */
4101                     }
4102                     else
4103                     {
4104                         mtCOVERAGE_TEST_MARKER();
4105                     }
4106                 }
4107             }
4108             else
4109             {
4110                 mtCOVERAGE_TEST_MARKER();
4111             }
4112         }
4113         taskEXIT_CRITICAL();
4114     }
4115
4116     traceRETURN_xTaskResumeAll( xAlreadyYielded );
4117
4118     return xAlreadyYielded;
4119 }
4120 /*-----------------------------------------------------------*/
4121
4122 TickType_t xTaskGetTickCount( void )
4123 {
4124     TickType_t xTicks;
4125
4126     traceENTER_xTaskGetTickCount();
4127
4128     /* Critical section required if running on a 16 bit processor. */
4129     portTICK_TYPE_ENTER_CRITICAL();
4130     {
4131         xTicks = xTickCount;
4132     }
4133     portTICK_TYPE_EXIT_CRITICAL();
4134
4135     traceRETURN_xTaskGetTickCount( xTicks );
4136
4137     return xTicks;
4138 }
4139 /*-----------------------------------------------------------*/
4140
4141 TickType_t xTaskGetTickCountFromISR( void )
4142 {
4143     TickType_t xReturn;
4144     UBaseType_t uxSavedInterruptStatus;
4145
4146     traceENTER_xTaskGetTickCountFromISR();
4147
4148     /* RTOS ports that support interrupt nesting have the concept of a maximum
4149      * system call (or maximum API call) interrupt priority.  Interrupts that are
4150      * above the maximum system call priority are kept permanently enabled, even
4151      * when the RTOS kernel is in a critical section, but cannot make any calls to
4152      * FreeRTOS API functions.  If configASSERT() is defined in FreeRTOSConfig.h
4153      * then portASSERT_IF_INTERRUPT_PRIORITY_INVALID() will result in an assertion
4154      * failure if a FreeRTOS API function is called from an interrupt that has been
4155      * assigned a priority above the configured maximum system call priority.
4156      * Only FreeRTOS functions that end in FromISR can be called from interrupts
4157      * that have been assigned a priority at or (logically) below the maximum
4158      * system call  interrupt priority.  FreeRTOS maintains a separate interrupt
4159      * safe API to ensure interrupt entry is as fast and as simple as possible.
4160      * More information (albeit Cortex-M specific) is provided on the following
4161      * link: https://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html */
4162     portASSERT_IF_INTERRUPT_PRIORITY_INVALID();
4163
4164     uxSavedInterruptStatus = portTICK_TYPE_SET_INTERRUPT_MASK_FROM_ISR();
4165     {
4166         xReturn = xTickCount;
4167     }
4168     portTICK_TYPE_CLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus );
4169
4170     traceRETURN_xTaskGetTickCountFromISR( xReturn );
4171
4172     return xReturn;
4173 }
4174 /*-----------------------------------------------------------*/
4175
4176 UBaseType_t uxTaskGetNumberOfTasks( void )
4177 {
4178     traceENTER_uxTaskGetNumberOfTasks();
4179
4180     /* A critical section is not required because the variables are of type
4181      * BaseType_t. */
4182     traceRETURN_uxTaskGetNumberOfTasks( uxCurrentNumberOfTasks );
4183
4184     return uxCurrentNumberOfTasks;
4185 }
4186 /*-----------------------------------------------------------*/
4187
4188 char * pcTaskGetName( TaskHandle_t xTaskToQuery )
4189 {
4190     TCB_t * pxTCB;
4191
4192     traceENTER_pcTaskGetName( xTaskToQuery );
4193
4194     /* If null is passed in here then the name of the calling task is being
4195      * queried. */
4196     pxTCB = prvGetTCBFromHandle( xTaskToQuery );
4197     configASSERT( pxTCB );
4198
4199     traceRETURN_pcTaskGetName( &( pxTCB->pcTaskName[ 0 ] ) );
4200
4201     return &( pxTCB->pcTaskName[ 0 ] );
4202 }
4203 /*-----------------------------------------------------------*/
4204
4205 #if ( INCLUDE_xTaskGetHandle == 1 )
4206     static TCB_t * prvSearchForNameWithinSingleList( List_t * pxList,
4207                                                      const char pcNameToQuery[] )
4208     {
4209         TCB_t * pxReturn = NULL;
4210         TCB_t * pxTCB = NULL;
4211         UBaseType_t x;
4212         char cNextChar;
4213         BaseType_t xBreakLoop;
4214         const ListItem_t * pxEndMarker = listGET_END_MARKER( pxList );
4215         ListItem_t * pxIterator;
4216
4217         /* This function is called with the scheduler suspended. */
4218
4219         if( listCURRENT_LIST_LENGTH( pxList ) > ( UBaseType_t ) 0 )
4220         {
4221             for( pxIterator = listGET_HEAD_ENTRY( pxList ); pxIterator != pxEndMarker; pxIterator = listGET_NEXT( pxIterator ) )
4222             {
4223                 /* MISRA Ref 11.5.3 [Void pointer assignment] */
4224                 /* More details at: https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/MISRA.md#rule-115 */
4225                 /* coverity[misra_c_2012_rule_11_5_violation] */
4226                 pxTCB = listGET_LIST_ITEM_OWNER( pxIterator );
4227
4228                 /* Check each character in the name looking for a match or
4229                  * mismatch. */
4230                 xBreakLoop = pdFALSE;
4231
4232                 for( x = ( UBaseType_t ) 0; x < ( UBaseType_t ) configMAX_TASK_NAME_LEN; x++ )
4233                 {
4234                     cNextChar = pxTCB->pcTaskName[ x ];
4235
4236                     if( cNextChar != pcNameToQuery[ x ] )
4237                     {
4238                         /* Characters didn't match. */
4239                         xBreakLoop = pdTRUE;
4240                     }
4241                     else if( cNextChar == ( char ) 0x00 )
4242                     {
4243                         /* Both strings terminated, a match must have been
4244                          * found. */
4245                         pxReturn = pxTCB;
4246                         xBreakLoop = pdTRUE;
4247                     }
4248                     else
4249                     {
4250                         mtCOVERAGE_TEST_MARKER();
4251                     }
4252
4253                     if( xBreakLoop != pdFALSE )
4254                     {
4255                         break;
4256                     }
4257                 }
4258
4259                 if( pxReturn != NULL )
4260                 {
4261                     /* The handle has been found. */
4262                     break;
4263                 }
4264             }
4265         }
4266         else
4267         {
4268             mtCOVERAGE_TEST_MARKER();
4269         }
4270
4271         return pxReturn;
4272     }
4273
4274 #endif /* INCLUDE_xTaskGetHandle */
4275 /*-----------------------------------------------------------*/
4276
4277 #if ( INCLUDE_xTaskGetHandle == 1 )
4278
4279     TaskHandle_t xTaskGetHandle( const char * pcNameToQuery )
4280     {
4281         UBaseType_t uxQueue = configMAX_PRIORITIES;
4282         TCB_t * pxTCB;
4283
4284         traceENTER_xTaskGetHandle( pcNameToQuery );
4285
4286         /* Task names will be truncated to configMAX_TASK_NAME_LEN - 1 bytes. */
4287         configASSERT( strlen( pcNameToQuery ) < configMAX_TASK_NAME_LEN );
4288
4289         vTaskSuspendAll();
4290         {
4291             /* Search the ready lists. */
4292             do
4293             {
4294                 uxQueue--;
4295                 pxTCB = prvSearchForNameWithinSingleList( ( List_t * ) &( pxReadyTasksLists[ uxQueue ] ), pcNameToQuery );
4296
4297                 if( pxTCB != NULL )
4298                 {
4299                     /* Found the handle. */
4300                     break;
4301                 }
4302             } while( uxQueue > ( UBaseType_t ) tskIDLE_PRIORITY );
4303
4304             /* Search the delayed lists. */
4305             if( pxTCB == NULL )
4306             {
4307                 pxTCB = prvSearchForNameWithinSingleList( ( List_t * ) pxDelayedTaskList, pcNameToQuery );
4308             }
4309
4310             if( pxTCB == NULL )
4311             {
4312                 pxTCB = prvSearchForNameWithinSingleList( ( List_t * ) pxOverflowDelayedTaskList, pcNameToQuery );
4313             }
4314
4315             #if ( INCLUDE_vTaskSuspend == 1 )
4316             {
4317                 if( pxTCB == NULL )
4318                 {
4319                     /* Search the suspended list. */
4320                     pxTCB = prvSearchForNameWithinSingleList( &xSuspendedTaskList, pcNameToQuery );
4321                 }
4322             }
4323             #endif
4324
4325             #if ( INCLUDE_vTaskDelete == 1 )
4326             {
4327                 if( pxTCB == NULL )
4328                 {
4329                     /* Search the deleted list. */
4330                     pxTCB = prvSearchForNameWithinSingleList( &xTasksWaitingTermination, pcNameToQuery );
4331                 }
4332             }
4333             #endif
4334         }
4335         ( void ) xTaskResumeAll();
4336
4337         traceRETURN_xTaskGetHandle( pxTCB );
4338
4339         return pxTCB;
4340     }
4341
4342 #endif /* INCLUDE_xTaskGetHandle */
4343 /*-----------------------------------------------------------*/
4344
4345 #if ( configSUPPORT_STATIC_ALLOCATION == 1 )
4346
4347     BaseType_t xTaskGetStaticBuffers( TaskHandle_t xTask,
4348                                       StackType_t ** ppuxStackBuffer,
4349                                       StaticTask_t ** ppxTaskBuffer )
4350     {
4351         BaseType_t xReturn;
4352         TCB_t * pxTCB;
4353
4354         traceENTER_xTaskGetStaticBuffers( xTask, ppuxStackBuffer, ppxTaskBuffer );
4355
4356         configASSERT( ppuxStackBuffer != NULL );
4357         configASSERT( ppxTaskBuffer != NULL );
4358
4359         pxTCB = prvGetTCBFromHandle( xTask );
4360
4361         #if ( tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE == 1 )
4362         {
4363             if( pxTCB->ucStaticallyAllocated == tskSTATICALLY_ALLOCATED_STACK_AND_TCB )
4364             {
4365                 *ppuxStackBuffer = pxTCB->pxStack;
4366                 /* MISRA Ref 11.3.1 [Misaligned access] */
4367                 /* More details at: https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/MISRA.md#rule-113 */
4368                 /* coverity[misra_c_2012_rule_11_3_violation] */
4369                 *ppxTaskBuffer = ( StaticTask_t * ) pxTCB;
4370                 xReturn = pdTRUE;
4371             }
4372             else if( pxTCB->ucStaticallyAllocated == tskSTATICALLY_ALLOCATED_STACK_ONLY )
4373             {
4374                 *ppuxStackBuffer = pxTCB->pxStack;
4375                 *ppxTaskBuffer = NULL;
4376                 xReturn = pdTRUE;
4377             }
4378             else
4379             {
4380                 xReturn = pdFALSE;
4381             }
4382         }
4383         #else /* tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE == 1 */
4384         {
4385             *ppuxStackBuffer = pxTCB->pxStack;
4386             *ppxTaskBuffer = ( StaticTask_t * ) pxTCB;
4387             xReturn = pdTRUE;
4388         }
4389         #endif /* tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE == 1 */
4390
4391         traceRETURN_xTaskGetStaticBuffers( xReturn );
4392
4393         return xReturn;
4394     }
4395
4396 #endif /* configSUPPORT_STATIC_ALLOCATION */
4397 /*-----------------------------------------------------------*/
4398
4399 #if ( configUSE_TRACE_FACILITY == 1 )
4400
4401     UBaseType_t uxTaskGetSystemState( TaskStatus_t * const pxTaskStatusArray,
4402                                       const UBaseType_t uxArraySize,
4403                                       configRUN_TIME_COUNTER_TYPE * const pulTotalRunTime )
4404     {
4405         UBaseType_t uxTask = 0, uxQueue = configMAX_PRIORITIES;
4406
4407         traceENTER_uxTaskGetSystemState( pxTaskStatusArray, uxArraySize, pulTotalRunTime );
4408
4409         vTaskSuspendAll();
4410         {
4411             /* Is there a space in the array for each task in the system? */
4412             if( uxArraySize >= uxCurrentNumberOfTasks )
4413             {
4414                 /* Fill in an TaskStatus_t structure with information on each
4415                  * task in the Ready state. */
4416                 do
4417                 {
4418                     uxQueue--;
4419                     uxTask = ( UBaseType_t ) ( uxTask + prvListTasksWithinSingleList( &( pxTaskStatusArray[ uxTask ] ), &( pxReadyTasksLists[ uxQueue ] ), eReady ) );
4420                 } while( uxQueue > ( UBaseType_t ) tskIDLE_PRIORITY );
4421
4422                 /* Fill in an TaskStatus_t structure with information on each
4423                  * task in the Blocked state. */
4424                 uxTask = ( UBaseType_t ) ( uxTask + prvListTasksWithinSingleList( &( pxTaskStatusArray[ uxTask ] ), ( List_t * ) pxDelayedTaskList, eBlocked ) );
4425                 uxTask = ( UBaseType_t ) ( uxTask + prvListTasksWithinSingleList( &( pxTaskStatusArray[ uxTask ] ), ( List_t * ) pxOverflowDelayedTaskList, eBlocked ) );
4426
4427                 #if ( INCLUDE_vTaskDelete == 1 )
4428                 {
4429                     /* Fill in an TaskStatus_t structure with information on
4430                      * each task that has been deleted but not yet cleaned up. */
4431                     uxTask = ( UBaseType_t ) ( uxTask + prvListTasksWithinSingleList( &( pxTaskStatusArray[ uxTask ] ), &xTasksWaitingTermination, eDeleted ) );
4432                 }
4433                 #endif
4434
4435                 #if ( INCLUDE_vTaskSuspend == 1 )
4436                 {
4437                     /* Fill in an TaskStatus_t structure with information on
4438                      * each task in the Suspended state. */
4439                     uxTask = ( UBaseType_t ) ( uxTask + prvListTasksWithinSingleList( &( pxTaskStatusArray[ uxTask ] ), &xSuspendedTaskList, eSuspended ) );
4440                 }
4441                 #endif
4442
4443                 #if ( configGENERATE_RUN_TIME_STATS == 1 )
4444                 {
4445                     if( pulTotalRunTime != NULL )
4446                     {
4447                         #ifdef portALT_GET_RUN_TIME_COUNTER_VALUE
4448                             portALT_GET_RUN_TIME_COUNTER_VALUE( ( *pulTotalRunTime ) );
4449                         #else
4450                             *pulTotalRunTime = ( configRUN_TIME_COUNTER_TYPE ) portGET_RUN_TIME_COUNTER_VALUE();
4451                         #endif
4452                     }
4453                 }
4454                 #else /* if ( configGENERATE_RUN_TIME_STATS == 1 ) */
4455                 {
4456                     if( pulTotalRunTime != NULL )
4457                     {
4458                         *pulTotalRunTime = 0;
4459                     }
4460                 }
4461                 #endif /* if ( configGENERATE_RUN_TIME_STATS == 1 ) */
4462             }
4463             else
4464             {
4465                 mtCOVERAGE_TEST_MARKER();
4466             }
4467         }
4468         ( void ) xTaskResumeAll();
4469
4470         traceRETURN_uxTaskGetSystemState( uxTask );
4471
4472         return uxTask;
4473     }
4474
4475 #endif /* configUSE_TRACE_FACILITY */
4476 /*----------------------------------------------------------*/
4477
4478 #if ( INCLUDE_xTaskGetIdleTaskHandle == 1 )
4479
4480     #if ( configNUMBER_OF_CORES == 1 )
4481         TaskHandle_t xTaskGetIdleTaskHandle( void )
4482         {
4483             traceENTER_xTaskGetIdleTaskHandle();
4484
4485             /* If xTaskGetIdleTaskHandle() is called before the scheduler has been
4486              * started, then xIdleTaskHandles will be NULL. */
4487             configASSERT( ( xIdleTaskHandles[ 0 ] != NULL ) );
4488
4489             traceRETURN_xTaskGetIdleTaskHandle( xIdleTaskHandles[ 0 ] );
4490
4491             return xIdleTaskHandles[ 0 ];
4492         }
4493     #endif /* if ( configNUMBER_OF_CORES == 1 ) */
4494
4495     TaskHandle_t xTaskGetIdleTaskHandleForCore( BaseType_t xCoreID )
4496     {
4497         traceENTER_xTaskGetIdleTaskHandleForCore( xCoreID );
4498
4499         /* Ensure the core ID is valid. */
4500         configASSERT( taskVALID_CORE_ID( xCoreID ) == pdTRUE );
4501
4502         /* If xTaskGetIdleTaskHandle() is called before the scheduler has been
4503          * started, then xIdleTaskHandles will be NULL. */
4504         configASSERT( ( xIdleTaskHandles[ xCoreID ] != NULL ) );
4505
4506         traceRETURN_xTaskGetIdleTaskHandleForCore( xIdleTaskHandles[ xCoreID ] );
4507
4508         return xIdleTaskHandles[ xCoreID ];
4509     }
4510
4511 #endif /* INCLUDE_xTaskGetIdleTaskHandle */
4512 /*----------------------------------------------------------*/
4513
4514 /* This conditional compilation should use inequality to 0, not equality to 1.
4515  * This is to ensure vTaskStepTick() is available when user defined low power mode
4516  * implementations require configUSE_TICKLESS_IDLE to be set to a value other than
4517  * 1. */
4518 #if ( configUSE_TICKLESS_IDLE != 0 )
4519
4520     void vTaskStepTick( TickType_t xTicksToJump )
4521     {
4522         TickType_t xUpdatedTickCount;
4523
4524         traceENTER_vTaskStepTick( xTicksToJump );
4525
4526         /* Correct the tick count value after a period during which the tick
4527          * was suppressed.  Note this does *not* call the tick hook function for
4528          * each stepped tick. */
4529         xUpdatedTickCount = xTickCount + xTicksToJump;
4530         configASSERT( xUpdatedTickCount <= xNextTaskUnblockTime );
4531
4532         if( xUpdatedTickCount == xNextTaskUnblockTime )
4533         {
4534             /* Arrange for xTickCount to reach xNextTaskUnblockTime in
4535              * xTaskIncrementTick() when the scheduler resumes.  This ensures
4536              * that any delayed tasks are resumed at the correct time. */
4537             configASSERT( uxSchedulerSuspended != ( UBaseType_t ) 0U );
4538             configASSERT( xTicksToJump != ( TickType_t ) 0 );
4539
4540             /* Prevent the tick interrupt modifying xPendedTicks simultaneously. */
4541             taskENTER_CRITICAL();
4542             {
4543                 xPendedTicks++;
4544             }
4545             taskEXIT_CRITICAL();
4546             xTicksToJump--;
4547         }
4548         else
4549         {
4550             mtCOVERAGE_TEST_MARKER();
4551         }
4552
4553         xTickCount += xTicksToJump;
4554
4555         traceINCREASE_TICK_COUNT( xTicksToJump );
4556         traceRETURN_vTaskStepTick();
4557     }
4558
4559 #endif /* configUSE_TICKLESS_IDLE */
4560 /*----------------------------------------------------------*/
4561
4562 BaseType_t xTaskCatchUpTicks( TickType_t xTicksToCatchUp )
4563 {
4564     BaseType_t xYieldOccurred;
4565
4566     traceENTER_xTaskCatchUpTicks( xTicksToCatchUp );
4567
4568     /* Must not be called with the scheduler suspended as the implementation
4569      * relies on xPendedTicks being wound down to 0 in xTaskResumeAll(). */
4570     configASSERT( uxSchedulerSuspended == ( UBaseType_t ) 0U );
4571
4572     /* Use xPendedTicks to mimic xTicksToCatchUp number of ticks occurring when
4573      * the scheduler is suspended so the ticks are executed in xTaskResumeAll(). */
4574     vTaskSuspendAll();
4575
4576     /* Prevent the tick interrupt modifying xPendedTicks simultaneously. */
4577     taskENTER_CRITICAL();
4578     {
4579         xPendedTicks += xTicksToCatchUp;
4580     }
4581     taskEXIT_CRITICAL();
4582     xYieldOccurred = xTaskResumeAll();
4583
4584     traceRETURN_xTaskCatchUpTicks( xYieldOccurred );
4585
4586     return xYieldOccurred;
4587 }
4588 /*----------------------------------------------------------*/
4589
4590 #if ( INCLUDE_xTaskAbortDelay == 1 )
4591
4592     BaseType_t xTaskAbortDelay( TaskHandle_t xTask )
4593     {
4594         TCB_t * pxTCB = xTask;
4595         BaseType_t xReturn;
4596
4597         traceENTER_xTaskAbortDelay( xTask );
4598
4599         configASSERT( pxTCB );
4600
4601         vTaskSuspendAll();
4602         {
4603             /* A task can only be prematurely removed from the Blocked state if
4604              * it is actually in the Blocked state. */
4605             if( eTaskGetState( xTask ) == eBlocked )
4606             {
4607                 xReturn = pdPASS;
4608
4609                 /* Remove the reference to the task from the blocked list.  An
4610                  * interrupt won't touch the xStateListItem because the
4611                  * scheduler is suspended. */
4612                 ( void ) uxListRemove( &( pxTCB->xStateListItem ) );
4613
4614                 /* Is the task waiting on an event also?  If so remove it from
4615                  * the event list too.  Interrupts can touch the event list item,
4616                  * even though the scheduler is suspended, so a critical section
4617                  * is used. */
4618                 taskENTER_CRITICAL();
4619                 {
4620                     if( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) != NULL )
4621                     {
4622                         ( void ) uxListRemove( &( pxTCB->xEventListItem ) );
4623
4624                         /* This lets the task know it was forcibly removed from the
4625                          * blocked state so it should not re-evaluate its block time and
4626                          * then block again. */
4627                         pxTCB->ucDelayAborted = ( uint8_t ) pdTRUE;
4628                     }
4629                     else
4630                     {
4631                         mtCOVERAGE_TEST_MARKER();
4632                     }
4633                 }
4634                 taskEXIT_CRITICAL();
4635
4636                 /* Place the unblocked task into the appropriate ready list. */
4637                 prvAddTaskToReadyList( pxTCB );
4638
4639                 /* A task being unblocked cannot cause an immediate context
4640                  * switch if preemption is turned off. */
4641                 #if ( configUSE_PREEMPTION == 1 )
4642                 {
4643                     #if ( configNUMBER_OF_CORES == 1 )
4644                     {
4645                         /* Preemption is on, but a context switch should only be
4646                          * performed if the unblocked task has a priority that is
4647                          * higher than the currently executing task. */
4648                         if( pxTCB->uxPriority > pxCurrentTCB->uxPriority )
4649                         {
4650                             /* Pend the yield to be performed when the scheduler
4651                              * is unsuspended. */
4652                             xYieldPendings[ 0 ] = pdTRUE;
4653                         }
4654                         else
4655                         {
4656                             mtCOVERAGE_TEST_MARKER();
4657                         }
4658                     }
4659                     #else /* #if ( configNUMBER_OF_CORES == 1 ) */
4660                     {
4661                         taskENTER_CRITICAL();
4662                         {
4663                             prvYieldForTask( pxTCB );
4664                         }
4665                         taskEXIT_CRITICAL();
4666                     }
4667                     #endif /* #if ( configNUMBER_OF_CORES == 1 ) */
4668                 }
4669                 #endif /* #if ( configUSE_PREEMPTION == 1 ) */
4670             }
4671             else
4672             {
4673                 xReturn = pdFAIL;
4674             }
4675         }
4676         ( void ) xTaskResumeAll();
4677
4678         traceRETURN_xTaskAbortDelay( xReturn );
4679
4680         return xReturn;
4681     }
4682
4683 #endif /* INCLUDE_xTaskAbortDelay */
4684 /*----------------------------------------------------------*/
4685
4686 BaseType_t xTaskIncrementTick( void )
4687 {
4688     TCB_t * pxTCB;
4689     TickType_t xItemValue;
4690     BaseType_t xSwitchRequired = pdFALSE;
4691
4692     traceENTER_xTaskIncrementTick();
4693
4694     /* Called by the portable layer each time a tick interrupt occurs.
4695      * Increments the tick then checks to see if the new tick value will cause any
4696      * tasks to be unblocked. */
4697     traceTASK_INCREMENT_TICK( xTickCount );
4698
4699     /* Tick increment should occur on every kernel timer event. Core 0 has the
4700      * responsibility to increment the tick, or increment the pended ticks if the
4701      * scheduler is suspended.  If pended ticks is greater than zero, the core that
4702      * calls xTaskResumeAll has the responsibility to increment the tick. */
4703     if( uxSchedulerSuspended == ( UBaseType_t ) 0U )
4704     {
4705         /* Minor optimisation.  The tick count cannot change in this
4706          * block. */
4707         const TickType_t xConstTickCount = xTickCount + ( TickType_t ) 1;
4708
4709         /* Increment the RTOS tick, switching the delayed and overflowed
4710          * delayed lists if it wraps to 0. */
4711         xTickCount = xConstTickCount;
4712
4713         if( xConstTickCount == ( TickType_t ) 0U )
4714         {
4715             taskSWITCH_DELAYED_LISTS();
4716         }
4717         else
4718         {
4719             mtCOVERAGE_TEST_MARKER();
4720         }
4721
4722         /* See if this tick has made a timeout expire.  Tasks are stored in
4723          * the  queue in the order of their wake time - meaning once one task
4724          * has been found whose block time has not expired there is no need to
4725          * look any further down the list. */
4726         if( xConstTickCount >= xNextTaskUnblockTime )
4727         {
4728             for( ; ; )
4729             {
4730                 if( listLIST_IS_EMPTY( pxDelayedTaskList ) != pdFALSE )
4731                 {
4732                     /* The delayed list is empty.  Set xNextTaskUnblockTime
4733                      * to the maximum possible value so it is extremely
4734                      * unlikely that the
4735                      * if( xTickCount >= xNextTaskUnblockTime ) test will pass
4736                      * next time through. */
4737                     xNextTaskUnblockTime = portMAX_DELAY;
4738                     break;
4739                 }
4740                 else
4741                 {
4742                     /* The delayed list is not empty, get the value of the
4743                      * item at the head of the delayed list.  This is the time
4744                      * at which the task at the head of the delayed list must
4745                      * be removed from the Blocked state. */
4746                     /* MISRA Ref 11.5.3 [Void pointer assignment] */
4747                     /* More details at: https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/MISRA.md#rule-115 */
4748                     /* coverity[misra_c_2012_rule_11_5_violation] */
4749                     pxTCB = listGET_OWNER_OF_HEAD_ENTRY( pxDelayedTaskList );
4750                     xItemValue = listGET_LIST_ITEM_VALUE( &( pxTCB->xStateListItem ) );
4751
4752                     if( xConstTickCount < xItemValue )
4753                     {
4754                         /* It is not time to unblock this item yet, but the
4755                          * item value is the time at which the task at the head
4756                          * of the blocked list must be removed from the Blocked
4757                          * state -  so record the item value in
4758                          * xNextTaskUnblockTime. */
4759                         xNextTaskUnblockTime = xItemValue;
4760                         break;
4761                     }
4762                     else
4763                     {
4764                         mtCOVERAGE_TEST_MARKER();
4765                     }
4766
4767                     /* It is time to remove the item from the Blocked state. */
4768                     listREMOVE_ITEM( &( pxTCB->xStateListItem ) );
4769
4770                     /* Is the task waiting on an event also?  If so remove
4771                      * it from the event list. */
4772                     if( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) != NULL )
4773                     {
4774                         listREMOVE_ITEM( &( pxTCB->xEventListItem ) );
4775                     }
4776                     else
4777                     {
4778                         mtCOVERAGE_TEST_MARKER();
4779                     }
4780
4781                     /* Place the unblocked task into the appropriate ready
4782                      * list. */
4783                     prvAddTaskToReadyList( pxTCB );
4784
4785                     /* A task being unblocked cannot cause an immediate
4786                      * context switch if preemption is turned off. */
4787                     #if ( configUSE_PREEMPTION == 1 )
4788                     {
4789                         #if ( configNUMBER_OF_CORES == 1 )
4790                         {
4791                             /* Preemption is on, but a context switch should
4792                              * only be performed if the unblocked task's
4793                              * priority is higher than the currently executing
4794                              * task.
4795                              * The case of equal priority tasks sharing
4796                              * processing time (which happens when both
4797                              * preemption and time slicing are on) is
4798                              * handled below.*/
4799                             if( pxTCB->uxPriority > pxCurrentTCB->uxPriority )
4800                             {
4801                                 xSwitchRequired = pdTRUE;
4802                             }
4803                             else
4804                             {
4805                                 mtCOVERAGE_TEST_MARKER();
4806                             }
4807                         }
4808                         #else /* #if( configNUMBER_OF_CORES == 1 ) */
4809                         {
4810                             prvYieldForTask( pxTCB );
4811                         }
4812                         #endif /* #if( configNUMBER_OF_CORES == 1 ) */
4813                     }
4814                     #endif /* #if ( configUSE_PREEMPTION == 1 ) */
4815                 }
4816             }
4817         }
4818
4819         /* Tasks of equal priority to the currently running task will share
4820          * processing time (time slice) if preemption is on, and the application
4821          * writer has not explicitly turned time slicing off. */
4822         #if ( ( configUSE_PREEMPTION == 1 ) && ( configUSE_TIME_SLICING == 1 ) )
4823         {
4824             #if ( configNUMBER_OF_CORES == 1 )
4825             {
4826                 if( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ pxCurrentTCB->uxPriority ] ) ) > 1U )
4827                 {
4828                     xSwitchRequired = pdTRUE;
4829                 }
4830                 else
4831                 {
4832                     mtCOVERAGE_TEST_MARKER();
4833                 }
4834             }
4835             #else /* #if ( configNUMBER_OF_CORES == 1 ) */
4836             {
4837                 BaseType_t xCoreID;
4838
4839                 for( xCoreID = 0; xCoreID < ( ( BaseType_t ) configNUMBER_OF_CORES ); xCoreID++ )
4840                 {
4841                     if( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ pxCurrentTCBs[ xCoreID ]->uxPriority ] ) ) > 1U )
4842                     {
4843                         xYieldPendings[ xCoreID ] = pdTRUE;
4844                     }
4845                     else
4846                     {
4847                         mtCOVERAGE_TEST_MARKER();
4848                     }
4849                 }
4850             }
4851             #endif /* #if ( configNUMBER_OF_CORES == 1 ) */
4852         }
4853         #endif /* #if ( ( configUSE_PREEMPTION == 1 ) && ( configUSE_TIME_SLICING == 1 ) ) */
4854
4855         #if ( configUSE_TICK_HOOK == 1 )
4856         {
4857             /* Guard against the tick hook being called when the pended tick
4858              * count is being unwound (when the scheduler is being unlocked). */
4859             if( xPendedTicks == ( TickType_t ) 0 )
4860             {
4861                 vApplicationTickHook();
4862             }
4863             else
4864             {
4865                 mtCOVERAGE_TEST_MARKER();
4866             }
4867         }
4868         #endif /* configUSE_TICK_HOOK */
4869
4870         #if ( configUSE_PREEMPTION == 1 )
4871         {
4872             #if ( configNUMBER_OF_CORES == 1 )
4873             {
4874                 /* For single core the core ID is always 0. */
4875                 if( xYieldPendings[ 0 ] != pdFALSE )
4876                 {
4877                     xSwitchRequired = pdTRUE;
4878                 }
4879                 else
4880                 {
4881                     mtCOVERAGE_TEST_MARKER();
4882                 }
4883             }
4884             #else /* #if ( configNUMBER_OF_CORES == 1 ) */
4885             {
4886                 BaseType_t xCoreID, xCurrentCoreID;
4887                 xCurrentCoreID = ( BaseType_t ) portGET_CORE_ID();
4888
4889                 for( xCoreID = 0; xCoreID < ( BaseType_t ) configNUMBER_OF_CORES; xCoreID++ )
4890                 {
4891                     #if ( configUSE_TASK_PREEMPTION_DISABLE == 1 )
4892                         if( pxCurrentTCBs[ xCoreID ]->xPreemptionDisable == pdFALSE )
4893                     #endif
4894                     {
4895                         if( xYieldPendings[ xCoreID ] != pdFALSE )
4896                         {
4897                             if( xCoreID == xCurrentCoreID )
4898                             {
4899                                 xSwitchRequired = pdTRUE;
4900                             }
4901                             else
4902                             {
4903                                 prvYieldCore( xCoreID );
4904                             }
4905                         }
4906                         else
4907                         {
4908                             mtCOVERAGE_TEST_MARKER();
4909                         }
4910                     }
4911                 }
4912             }
4913             #endif /* #if ( configNUMBER_OF_CORES == 1 ) */
4914         }
4915         #endif /* #if ( configUSE_PREEMPTION == 1 ) */
4916     }
4917     else
4918     {
4919         xPendedTicks += 1U;
4920
4921         /* The tick hook gets called at regular intervals, even if the
4922          * scheduler is locked. */
4923         #if ( configUSE_TICK_HOOK == 1 )
4924         {
4925             vApplicationTickHook();
4926         }
4927         #endif
4928     }
4929
4930     traceRETURN_xTaskIncrementTick( xSwitchRequired );
4931
4932     return xSwitchRequired;
4933 }
4934 /*-----------------------------------------------------------*/
4935
4936 #if ( configUSE_APPLICATION_TASK_TAG == 1 )
4937
4938     void vTaskSetApplicationTaskTag( TaskHandle_t xTask,
4939                                      TaskHookFunction_t pxHookFunction )
4940     {
4941         TCB_t * xTCB;
4942
4943         traceENTER_vTaskSetApplicationTaskTag( xTask, pxHookFunction );
4944
4945         /* If xTask is NULL then it is the task hook of the calling task that is
4946          * getting set. */
4947         if( xTask == NULL )
4948         {
4949             xTCB = ( TCB_t * ) pxCurrentTCB;
4950         }
4951         else
4952         {
4953             xTCB = xTask;
4954         }
4955
4956         /* Save the hook function in the TCB.  A critical section is required as
4957          * the value can be accessed from an interrupt. */
4958         taskENTER_CRITICAL();
4959         {
4960             xTCB->pxTaskTag = pxHookFunction;
4961         }
4962         taskEXIT_CRITICAL();
4963
4964         traceRETURN_vTaskSetApplicationTaskTag();
4965     }
4966
4967 #endif /* configUSE_APPLICATION_TASK_TAG */
4968 /*-----------------------------------------------------------*/
4969
4970 #if ( configUSE_APPLICATION_TASK_TAG == 1 )
4971
4972     TaskHookFunction_t xTaskGetApplicationTaskTag( TaskHandle_t xTask )
4973     {
4974         TCB_t * pxTCB;
4975         TaskHookFunction_t xReturn;
4976
4977         traceENTER_xTaskGetApplicationTaskTag( xTask );
4978
4979         /* If xTask is NULL then set the calling task's hook. */
4980         pxTCB = prvGetTCBFromHandle( xTask );
4981
4982         /* Save the hook function in the TCB.  A critical section is required as
4983          * the value can be accessed from an interrupt. */
4984         taskENTER_CRITICAL();
4985         {
4986             xReturn = pxTCB->pxTaskTag;
4987         }
4988         taskEXIT_CRITICAL();
4989
4990         traceRETURN_xTaskGetApplicationTaskTag( xReturn );
4991
4992         return xReturn;
4993     }
4994
4995 #endif /* configUSE_APPLICATION_TASK_TAG */
4996 /*-----------------------------------------------------------*/
4997
4998 #if ( configUSE_APPLICATION_TASK_TAG == 1 )
4999
5000     TaskHookFunction_t xTaskGetApplicationTaskTagFromISR( TaskHandle_t xTask )
5001     {
5002         TCB_t * pxTCB;
5003         TaskHookFunction_t xReturn;
5004         UBaseType_t uxSavedInterruptStatus;
5005
5006         traceENTER_xTaskGetApplicationTaskTagFromISR( xTask );
5007
5008         /* If xTask is NULL then set the calling task's hook. */
5009         pxTCB = prvGetTCBFromHandle( xTask );
5010
5011         /* Save the hook function in the TCB.  A critical section is required as
5012          * the value can be accessed from an interrupt. */
5013         /* MISRA Ref 4.7.1 [Return value shall be checked] */
5014         /* More details at: https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/MISRA.md#dir-47 */
5015         /* coverity[misra_c_2012_directive_4_7_violation] */
5016         uxSavedInterruptStatus = taskENTER_CRITICAL_FROM_ISR();
5017         {
5018             xReturn = pxTCB->pxTaskTag;
5019         }
5020         taskEXIT_CRITICAL_FROM_ISR( uxSavedInterruptStatus );
5021
5022         traceRETURN_xTaskGetApplicationTaskTagFromISR( xReturn );
5023
5024         return xReturn;
5025     }
5026
5027 #endif /* configUSE_APPLICATION_TASK_TAG */
5028 /*-----------------------------------------------------------*/
5029
5030 #if ( configUSE_APPLICATION_TASK_TAG == 1 )
5031
5032     BaseType_t xTaskCallApplicationTaskHook( TaskHandle_t xTask,
5033                                              void * pvParameter )
5034     {
5035         TCB_t * xTCB;
5036         BaseType_t xReturn;
5037
5038         traceENTER_xTaskCallApplicationTaskHook( xTask, pvParameter );
5039
5040         /* If xTask is NULL then we are calling our own task hook. */
5041         if( xTask == NULL )
5042         {
5043             xTCB = pxCurrentTCB;
5044         }
5045         else
5046         {
5047             xTCB = xTask;
5048         }
5049
5050         if( xTCB->pxTaskTag != NULL )
5051         {
5052             xReturn = xTCB->pxTaskTag( pvParameter );
5053         }
5054         else
5055         {
5056             xReturn = pdFAIL;
5057         }
5058
5059         traceRETURN_xTaskCallApplicationTaskHook( xReturn );
5060
5061         return xReturn;
5062     }
5063
5064 #endif /* configUSE_APPLICATION_TASK_TAG */
5065 /*-----------------------------------------------------------*/
5066
5067 #if ( configNUMBER_OF_CORES == 1 )
5068     void vTaskSwitchContext( void )
5069     {
5070         traceENTER_vTaskSwitchContext();
5071
5072         if( uxSchedulerSuspended != ( UBaseType_t ) 0U )
5073         {
5074             /* The scheduler is currently suspended - do not allow a context
5075              * switch. */
5076             xYieldPendings[ 0 ] = pdTRUE;
5077         }
5078         else
5079         {
5080             xYieldPendings[ 0 ] = pdFALSE;
5081             traceTASK_SWITCHED_OUT();
5082
5083             #if ( configGENERATE_RUN_TIME_STATS == 1 )
5084             {
5085                 #ifdef portALT_GET_RUN_TIME_COUNTER_VALUE
5086                     portALT_GET_RUN_TIME_COUNTER_VALUE( ulTotalRunTime[ 0 ] );
5087                 #else
5088                     ulTotalRunTime[ 0 ] = portGET_RUN_TIME_COUNTER_VALUE();
5089                 #endif
5090
5091                 /* Add the amount of time the task has been running to the
5092                  * accumulated time so far.  The time the task started running was
5093                  * stored in ulTaskSwitchedInTime.  Note that there is no overflow
5094                  * protection here so count values are only valid until the timer
5095                  * overflows.  The guard against negative values is to protect
5096                  * against suspect run time stat counter implementations - which
5097                  * are provided by the application, not the kernel. */
5098                 if( ulTotalRunTime[ 0 ] > ulTaskSwitchedInTime[ 0 ] )
5099                 {
5100                     pxCurrentTCB->ulRunTimeCounter += ( ulTotalRunTime[ 0 ] - ulTaskSwitchedInTime[ 0 ] );
5101                 }
5102                 else
5103                 {
5104                     mtCOVERAGE_TEST_MARKER();
5105                 }
5106
5107                 ulTaskSwitchedInTime[ 0 ] = ulTotalRunTime[ 0 ];
5108             }
5109             #endif /* configGENERATE_RUN_TIME_STATS */
5110
5111             /* Check for stack overflow, if configured. */
5112             taskCHECK_FOR_STACK_OVERFLOW();
5113
5114             /* Before the currently running task is switched out, save its errno. */
5115             #if ( configUSE_POSIX_ERRNO == 1 )
5116             {
5117                 pxCurrentTCB->iTaskErrno = FreeRTOS_errno;
5118             }
5119             #endif
5120
5121             /* Select a new task to run using either the generic C or port
5122              * optimised asm code. */
5123             /* MISRA Ref 11.5.3 [Void pointer assignment] */
5124             /* More details at: https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/MISRA.md#rule-115 */
5125             /* coverity[misra_c_2012_rule_11_5_violation] */
5126             taskSELECT_HIGHEST_PRIORITY_TASK();
5127             traceTASK_SWITCHED_IN();
5128
5129             /* Macro to inject port specific behaviour immediately after
5130              * switching tasks, such as setting an end of stack watchpoint
5131              * or reconfiguring the MPU. */
5132             portTASK_SWITCH_HOOK( pxCurrentTCB );
5133
5134             /* After the new task is switched in, update the global errno. */
5135             #if ( configUSE_POSIX_ERRNO == 1 )
5136             {
5137                 FreeRTOS_errno = pxCurrentTCB->iTaskErrno;
5138             }
5139             #endif
5140
5141             #if ( configUSE_C_RUNTIME_TLS_SUPPORT == 1 )
5142             {
5143                 /* Switch C-Runtime's TLS Block to point to the TLS
5144                  * Block specific to this task. */
5145                 configSET_TLS_BLOCK( pxCurrentTCB->xTLSBlock );
5146             }
5147             #endif
5148         }
5149
5150         traceRETURN_vTaskSwitchContext();
5151     }
5152 #else /* if ( configNUMBER_OF_CORES == 1 ) */
5153     void vTaskSwitchContext( BaseType_t xCoreID )
5154     {
5155         traceENTER_vTaskSwitchContext();
5156
5157         /* Acquire both locks:
5158          * - The ISR lock protects the ready list from simultaneous access by
5159          *   both other ISRs and tasks.
5160          * - We also take the task lock to pause here in case another core has
5161          *   suspended the scheduler. We don't want to simply set xYieldPending
5162          *   and move on if another core suspended the scheduler. We should only
5163          *   do that if the current core has suspended the scheduler. */
5164
5165         portGET_TASK_LOCK(); /* Must always acquire the task lock first. */
5166         portGET_ISR_LOCK();
5167         {
5168             /* vTaskSwitchContext() must never be called from within a critical section.
5169              * This is not necessarily true for single core FreeRTOS, but it is for this
5170              * SMP port. */
5171             configASSERT( portGET_CRITICAL_NESTING_COUNT() == 0 );
5172
5173             if( uxSchedulerSuspended != ( UBaseType_t ) 0U )
5174             {
5175                 /* The scheduler is currently suspended - do not allow a context
5176                  * switch. */
5177                 xYieldPendings[ xCoreID ] = pdTRUE;
5178             }
5179             else
5180             {
5181                 xYieldPendings[ xCoreID ] = pdFALSE;
5182                 traceTASK_SWITCHED_OUT();
5183
5184                 #if ( configGENERATE_RUN_TIME_STATS == 1 )
5185                 {
5186                     #ifdef portALT_GET_RUN_TIME_COUNTER_VALUE
5187                         portALT_GET_RUN_TIME_COUNTER_VALUE( ulTotalRunTime[ xCoreID ] );
5188                     #else
5189                         ulTotalRunTime[ xCoreID ] = portGET_RUN_TIME_COUNTER_VALUE();
5190                     #endif
5191
5192                     /* Add the amount of time the task has been running to the
5193                      * accumulated time so far.  The time the task started running was
5194                      * stored in ulTaskSwitchedInTime.  Note that there is no overflow
5195                      * protection here so count values are only valid until the timer
5196                      * overflows.  The guard against negative values is to protect
5197                      * against suspect run time stat counter implementations - which
5198                      * are provided by the application, not the kernel. */
5199                     if( ulTotalRunTime[ xCoreID ] > ulTaskSwitchedInTime[ xCoreID ] )
5200                     {
5201                         pxCurrentTCBs[ xCoreID ]->ulRunTimeCounter += ( ulTotalRunTime[ xCoreID ] - ulTaskSwitchedInTime[ xCoreID ] );
5202                     }
5203                     else
5204                     {
5205                         mtCOVERAGE_TEST_MARKER();
5206                     }
5207
5208                     ulTaskSwitchedInTime[ xCoreID ] = ulTotalRunTime[ xCoreID ];
5209                 }
5210                 #endif /* configGENERATE_RUN_TIME_STATS */
5211
5212                 /* Check for stack overflow, if configured. */
5213                 taskCHECK_FOR_STACK_OVERFLOW();
5214
5215                 /* Before the currently running task is switched out, save its errno. */
5216                 #if ( configUSE_POSIX_ERRNO == 1 )
5217                 {
5218                     pxCurrentTCBs[ xCoreID ]->iTaskErrno = FreeRTOS_errno;
5219                 }
5220                 #endif
5221
5222                 /* Select a new task to run. */
5223                 taskSELECT_HIGHEST_PRIORITY_TASK( xCoreID );
5224                 traceTASK_SWITCHED_IN();
5225
5226                 /* Macro to inject port specific behaviour immediately after
5227                  * switching tasks, such as setting an end of stack watchpoint
5228                  * or reconfiguring the MPU. */
5229                 portTASK_SWITCH_HOOK( pxCurrentTCBs[ portGET_CORE_ID() ] );
5230
5231                 /* After the new task is switched in, update the global errno. */
5232                 #if ( configUSE_POSIX_ERRNO == 1 )
5233                 {
5234                     FreeRTOS_errno = pxCurrentTCBs[ xCoreID ]->iTaskErrno;
5235                 }
5236                 #endif
5237
5238                 #if ( configUSE_C_RUNTIME_TLS_SUPPORT == 1 )
5239                 {
5240                     /* Switch C-Runtime's TLS Block to point to the TLS
5241                      * Block specific to this task. */
5242                     configSET_TLS_BLOCK( pxCurrentTCBs[ xCoreID ]->xTLSBlock );
5243                 }
5244                 #endif
5245             }
5246         }
5247         portRELEASE_ISR_LOCK();
5248         portRELEASE_TASK_LOCK();
5249
5250         traceRETURN_vTaskSwitchContext();
5251     }
5252 #endif /* if ( configNUMBER_OF_CORES > 1 ) */
5253 /*-----------------------------------------------------------*/
5254
5255 void vTaskPlaceOnEventList( List_t * const pxEventList,
5256                             const TickType_t xTicksToWait )
5257 {
5258     traceENTER_vTaskPlaceOnEventList( pxEventList, xTicksToWait );
5259
5260     configASSERT( pxEventList );
5261
5262     /* THIS FUNCTION MUST BE CALLED WITH THE
5263      * SCHEDULER SUSPENDED AND THE QUEUE BEING ACCESSED LOCKED. */
5264
5265     /* Place the event list item of the TCB in the appropriate event list.
5266      * This is placed in the list in priority order so the highest priority task
5267      * is the first to be woken by the event.
5268      *
5269      * Note: Lists are sorted in ascending order by ListItem_t.xItemValue.
5270      * Normally, the xItemValue of a TCB's ListItem_t members is:
5271      *      xItemValue = ( configMAX_PRIORITIES - uxPriority )
5272      * Therefore, the event list is sorted in descending priority order.
5273      *
5274      * The queue that contains the event list is locked, preventing
5275      * simultaneous access from interrupts. */
5276     vListInsert( pxEventList, &( pxCurrentTCB->xEventListItem ) );
5277
5278     prvAddCurrentTaskToDelayedList( xTicksToWait, pdTRUE );
5279
5280     traceRETURN_vTaskPlaceOnEventList();
5281 }
5282 /*-----------------------------------------------------------*/
5283
5284 void vTaskPlaceOnUnorderedEventList( List_t * pxEventList,
5285                                      const TickType_t xItemValue,
5286                                      const TickType_t xTicksToWait )
5287 {
5288     traceENTER_vTaskPlaceOnUnorderedEventList( pxEventList, xItemValue, xTicksToWait );
5289
5290     configASSERT( pxEventList );
5291
5292     /* THIS FUNCTION MUST BE CALLED WITH THE SCHEDULER SUSPENDED.  It is used by
5293      * the event groups implementation. */
5294     configASSERT( uxSchedulerSuspended != ( UBaseType_t ) 0U );
5295
5296     /* Store the item value in the event list item.  It is safe to access the
5297      * event list item here as interrupts won't access the event list item of a
5298      * task that is not in the Blocked state. */
5299     listSET_LIST_ITEM_VALUE( &( pxCurrentTCB->xEventListItem ), xItemValue | taskEVENT_LIST_ITEM_VALUE_IN_USE );
5300
5301     /* Place the event list item of the TCB at the end of the appropriate event
5302      * list.  It is safe to access the event list here because it is part of an
5303      * event group implementation - and interrupts don't access event groups
5304      * directly (instead they access them indirectly by pending function calls to
5305      * the task level). */
5306     listINSERT_END( pxEventList, &( pxCurrentTCB->xEventListItem ) );
5307
5308     prvAddCurrentTaskToDelayedList( xTicksToWait, pdTRUE );
5309
5310     traceRETURN_vTaskPlaceOnUnorderedEventList();
5311 }
5312 /*-----------------------------------------------------------*/
5313
5314 #if ( configUSE_TIMERS == 1 )
5315
5316     void vTaskPlaceOnEventListRestricted( List_t * const pxEventList,
5317                                           TickType_t xTicksToWait,
5318                                           const BaseType_t xWaitIndefinitely )
5319     {
5320         traceENTER_vTaskPlaceOnEventListRestricted( pxEventList, xTicksToWait, xWaitIndefinitely );
5321
5322         configASSERT( pxEventList );
5323
5324         /* This function should not be called by application code hence the
5325          * 'Restricted' in its name.  It is not part of the public API.  It is
5326          * designed for use by kernel code, and has special calling requirements -
5327          * it should be called with the scheduler suspended. */
5328
5329
5330         /* Place the event list item of the TCB in the appropriate event list.
5331          * In this case it is assume that this is the only task that is going to
5332          * be waiting on this event list, so the faster vListInsertEnd() function
5333          * can be used in place of vListInsert. */
5334         listINSERT_END( pxEventList, &( pxCurrentTCB->xEventListItem ) );
5335
5336         /* If the task should block indefinitely then set the block time to a
5337          * value that will be recognised as an indefinite delay inside the
5338          * prvAddCurrentTaskToDelayedList() function. */
5339         if( xWaitIndefinitely != pdFALSE )
5340         {
5341             xTicksToWait = portMAX_DELAY;
5342         }
5343
5344         traceTASK_DELAY_UNTIL( ( xTickCount + xTicksToWait ) );
5345         prvAddCurrentTaskToDelayedList( xTicksToWait, xWaitIndefinitely );
5346
5347         traceRETURN_vTaskPlaceOnEventListRestricted();
5348     }
5349
5350 #endif /* configUSE_TIMERS */
5351 /*-----------------------------------------------------------*/
5352
5353 BaseType_t xTaskRemoveFromEventList( const List_t * const pxEventList )
5354 {
5355     TCB_t * pxUnblockedTCB;
5356     BaseType_t xReturn;
5357
5358     traceENTER_xTaskRemoveFromEventList( pxEventList );
5359
5360     /* THIS FUNCTION MUST BE CALLED FROM A CRITICAL SECTION.  It can also be
5361      * called from a critical section within an ISR. */
5362
5363     /* The event list is sorted in priority order, so the first in the list can
5364      * be removed as it is known to be the highest priority.  Remove the TCB from
5365      * the delayed list, and add it to the ready list.
5366      *
5367      * If an event is for a queue that is locked then this function will never
5368      * get called - the lock count on the queue will get modified instead.  This
5369      * means exclusive access to the event list is guaranteed here.
5370      *
5371      * This function assumes that a check has already been made to ensure that
5372      * pxEventList is not empty. */
5373     /* MISRA Ref 11.5.3 [Void pointer assignment] */
5374     /* More details at: https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/MISRA.md#rule-115 */
5375     /* coverity[misra_c_2012_rule_11_5_violation] */
5376     pxUnblockedTCB = listGET_OWNER_OF_HEAD_ENTRY( pxEventList );
5377     configASSERT( pxUnblockedTCB );
5378     listREMOVE_ITEM( &( pxUnblockedTCB->xEventListItem ) );
5379
5380     if( uxSchedulerSuspended == ( UBaseType_t ) 0U )
5381     {
5382         listREMOVE_ITEM( &( pxUnblockedTCB->xStateListItem ) );
5383         prvAddTaskToReadyList( pxUnblockedTCB );
5384
5385         #if ( configUSE_TICKLESS_IDLE != 0 )
5386         {
5387             /* If a task is blocked on a kernel object then xNextTaskUnblockTime
5388              * might be set to the blocked task's time out time.  If the task is
5389              * unblocked for a reason other than a timeout xNextTaskUnblockTime is
5390              * normally left unchanged, because it is automatically reset to a new
5391              * value when the tick count equals xNextTaskUnblockTime.  However if
5392              * tickless idling is used it might be more important to enter sleep mode
5393              * at the earliest possible time - so reset xNextTaskUnblockTime here to
5394              * ensure it is updated at the earliest possible time. */
5395             prvResetNextTaskUnblockTime();
5396         }
5397         #endif
5398     }
5399     else
5400     {
5401         /* The delayed and ready lists cannot be accessed, so hold this task
5402          * pending until the scheduler is resumed. */
5403         listINSERT_END( &( xPendingReadyList ), &( pxUnblockedTCB->xEventListItem ) );
5404     }
5405
5406     #if ( configNUMBER_OF_CORES == 1 )
5407     {
5408         if( pxUnblockedTCB->uxPriority > pxCurrentTCB->uxPriority )
5409         {
5410             /* Return true if the task removed from the event list has a higher
5411              * priority than the calling task.  This allows the calling task to know if
5412              * it should force a context switch now. */
5413             xReturn = pdTRUE;
5414
5415             /* Mark that a yield is pending in case the user is not using the
5416              * "xHigherPriorityTaskWoken" parameter to an ISR safe FreeRTOS function. */
5417             xYieldPendings[ 0 ] = pdTRUE;
5418         }
5419         else
5420         {
5421             xReturn = pdFALSE;
5422         }
5423     }
5424     #else /* #if ( configNUMBER_OF_CORES == 1 ) */
5425     {
5426         xReturn = pdFALSE;
5427
5428         #if ( configUSE_PREEMPTION == 1 )
5429         {
5430             prvYieldForTask( pxUnblockedTCB );
5431
5432             if( xYieldPendings[ portGET_CORE_ID() ] != pdFALSE )
5433             {
5434                 xReturn = pdTRUE;
5435             }
5436         }
5437         #endif /* #if ( configUSE_PREEMPTION == 1 ) */
5438     }
5439     #endif /* #if ( configNUMBER_OF_CORES == 1 ) */
5440
5441     traceRETURN_xTaskRemoveFromEventList( xReturn );
5442     return xReturn;
5443 }
5444 /*-----------------------------------------------------------*/
5445
5446 void vTaskRemoveFromUnorderedEventList( ListItem_t * pxEventListItem,
5447                                         const TickType_t xItemValue )
5448 {
5449     TCB_t * pxUnblockedTCB;
5450
5451     traceENTER_vTaskRemoveFromUnorderedEventList( pxEventListItem, xItemValue );
5452
5453     /* THIS FUNCTION MUST BE CALLED WITH THE SCHEDULER SUSPENDED.  It is used by
5454      * the event flags implementation. */
5455     configASSERT( uxSchedulerSuspended != ( UBaseType_t ) 0U );
5456
5457     /* Store the new item value in the event list. */
5458     listSET_LIST_ITEM_VALUE( pxEventListItem, xItemValue | taskEVENT_LIST_ITEM_VALUE_IN_USE );
5459
5460     /* Remove the event list form the event flag.  Interrupts do not access
5461      * event flags. */
5462     /* MISRA Ref 11.5.3 [Void pointer assignment] */
5463     /* More details at: https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/MISRA.md#rule-115 */
5464     /* coverity[misra_c_2012_rule_11_5_violation] */
5465     pxUnblockedTCB = listGET_LIST_ITEM_OWNER( pxEventListItem );
5466     configASSERT( pxUnblockedTCB );
5467     listREMOVE_ITEM( pxEventListItem );
5468
5469     #if ( configUSE_TICKLESS_IDLE != 0 )
5470     {
5471         /* If a task is blocked on a kernel object then xNextTaskUnblockTime
5472          * might be set to the blocked task's time out time.  If the task is
5473          * unblocked for a reason other than a timeout xNextTaskUnblockTime is
5474          * normally left unchanged, because it is automatically reset to a new
5475          * value when the tick count equals xNextTaskUnblockTime.  However if
5476          * tickless idling is used it might be more important to enter sleep mode
5477          * at the earliest possible time - so reset xNextTaskUnblockTime here to
5478          * ensure it is updated at the earliest possible time. */
5479         prvResetNextTaskUnblockTime();
5480     }
5481     #endif
5482
5483     /* Remove the task from the delayed list and add it to the ready list.  The
5484      * scheduler is suspended so interrupts will not be accessing the ready
5485      * lists. */
5486     listREMOVE_ITEM( &( pxUnblockedTCB->xStateListItem ) );
5487     prvAddTaskToReadyList( pxUnblockedTCB );
5488
5489     #if ( configNUMBER_OF_CORES == 1 )
5490     {
5491         if( pxUnblockedTCB->uxPriority > pxCurrentTCB->uxPriority )
5492         {
5493             /* The unblocked task has a priority above that of the calling task, so
5494              * a context switch is required.  This function is called with the
5495              * scheduler suspended so xYieldPending is set so the context switch
5496              * occurs immediately that the scheduler is resumed (unsuspended). */
5497             xYieldPendings[ 0 ] = pdTRUE;
5498         }
5499     }
5500     #else /* #if ( configNUMBER_OF_CORES == 1 ) */
5501     {
5502         #if ( configUSE_PREEMPTION == 1 )
5503         {
5504             taskENTER_CRITICAL();
5505             {
5506                 prvYieldForTask( pxUnblockedTCB );
5507             }
5508             taskEXIT_CRITICAL();
5509         }
5510         #endif
5511     }
5512     #endif /* #if ( configNUMBER_OF_CORES == 1 ) */
5513
5514     traceRETURN_vTaskRemoveFromUnorderedEventList();
5515 }
5516 /*-----------------------------------------------------------*/
5517
5518 void vTaskSetTimeOutState( TimeOut_t * const pxTimeOut )
5519 {
5520     traceENTER_vTaskSetTimeOutState( pxTimeOut );
5521
5522     configASSERT( pxTimeOut );
5523     taskENTER_CRITICAL();
5524     {
5525         pxTimeOut->xOverflowCount = xNumOfOverflows;
5526         pxTimeOut->xTimeOnEntering = xTickCount;
5527     }
5528     taskEXIT_CRITICAL();
5529
5530     traceRETURN_vTaskSetTimeOutState();
5531 }
5532 /*-----------------------------------------------------------*/
5533
5534 void vTaskInternalSetTimeOutState( TimeOut_t * const pxTimeOut )
5535 {
5536     traceENTER_vTaskInternalSetTimeOutState( pxTimeOut );
5537
5538     /* For internal use only as it does not use a critical section. */
5539     pxTimeOut->xOverflowCount = xNumOfOverflows;
5540     pxTimeOut->xTimeOnEntering = xTickCount;
5541
5542     traceRETURN_vTaskInternalSetTimeOutState();
5543 }
5544 /*-----------------------------------------------------------*/
5545
5546 BaseType_t xTaskCheckForTimeOut( TimeOut_t * const pxTimeOut,
5547                                  TickType_t * const pxTicksToWait )
5548 {
5549     BaseType_t xReturn;
5550
5551     traceENTER_xTaskCheckForTimeOut( pxTimeOut, pxTicksToWait );
5552
5553     configASSERT( pxTimeOut );
5554     configASSERT( pxTicksToWait );
5555
5556     taskENTER_CRITICAL();
5557     {
5558         /* Minor optimisation.  The tick count cannot change in this block. */
5559         const TickType_t xConstTickCount = xTickCount;
5560         const TickType_t xElapsedTime = xConstTickCount - pxTimeOut->xTimeOnEntering;
5561
5562         #if ( INCLUDE_xTaskAbortDelay == 1 )
5563             if( pxCurrentTCB->ucDelayAborted != ( uint8_t ) pdFALSE )
5564             {
5565                 /* The delay was aborted, which is not the same as a time out,
5566                  * but has the same result. */
5567                 pxCurrentTCB->ucDelayAborted = ( uint8_t ) pdFALSE;
5568                 xReturn = pdTRUE;
5569             }
5570             else
5571         #endif
5572
5573         #if ( INCLUDE_vTaskSuspend == 1 )
5574             if( *pxTicksToWait == portMAX_DELAY )
5575             {
5576                 /* If INCLUDE_vTaskSuspend is set to 1 and the block time
5577                  * specified is the maximum block time then the task should block
5578                  * indefinitely, and therefore never time out. */
5579                 xReturn = pdFALSE;
5580             }
5581             else
5582         #endif
5583
5584         if( ( xNumOfOverflows != pxTimeOut->xOverflowCount ) && ( xConstTickCount >= pxTimeOut->xTimeOnEntering ) )
5585         {
5586             /* The tick count is greater than the time at which
5587              * vTaskSetTimeout() was called, but has also overflowed since
5588              * vTaskSetTimeOut() was called.  It must have wrapped all the way
5589              * around and gone past again. This passed since vTaskSetTimeout()
5590              * was called. */
5591             xReturn = pdTRUE;
5592             *pxTicksToWait = ( TickType_t ) 0;
5593         }
5594         else if( xElapsedTime < *pxTicksToWait )
5595         {
5596             /* Not a genuine timeout. Adjust parameters for time remaining. */
5597             *pxTicksToWait -= xElapsedTime;
5598             vTaskInternalSetTimeOutState( pxTimeOut );
5599             xReturn = pdFALSE;
5600         }
5601         else
5602         {
5603             *pxTicksToWait = ( TickType_t ) 0;
5604             xReturn = pdTRUE;
5605         }
5606     }
5607     taskEXIT_CRITICAL();
5608
5609     traceRETURN_xTaskCheckForTimeOut( xReturn );
5610
5611     return xReturn;
5612 }
5613 /*-----------------------------------------------------------*/
5614
5615 void vTaskMissedYield( void )
5616 {
5617     traceENTER_vTaskMissedYield();
5618
5619     /* Must be called from within a critical section. */
5620     xYieldPendings[ portGET_CORE_ID() ] = pdTRUE;
5621
5622     traceRETURN_vTaskMissedYield();
5623 }
5624 /*-----------------------------------------------------------*/
5625
5626 #if ( configUSE_TRACE_FACILITY == 1 )
5627
5628     UBaseType_t uxTaskGetTaskNumber( TaskHandle_t xTask )
5629     {
5630         UBaseType_t uxReturn;
5631         TCB_t const * pxTCB;
5632
5633         traceENTER_uxTaskGetTaskNumber( xTask );
5634
5635         if( xTask != NULL )
5636         {
5637             pxTCB = xTask;
5638             uxReturn = pxTCB->uxTaskNumber;
5639         }
5640         else
5641         {
5642             uxReturn = 0U;
5643         }
5644
5645         traceRETURN_uxTaskGetTaskNumber( uxReturn );
5646
5647         return uxReturn;
5648     }
5649
5650 #endif /* configUSE_TRACE_FACILITY */
5651 /*-----------------------------------------------------------*/
5652
5653 #if ( configUSE_TRACE_FACILITY == 1 )
5654
5655     void vTaskSetTaskNumber( TaskHandle_t xTask,
5656                              const UBaseType_t uxHandle )
5657     {
5658         TCB_t * pxTCB;
5659
5660         traceENTER_vTaskSetTaskNumber( xTask, uxHandle );
5661
5662         if( xTask != NULL )
5663         {
5664             pxTCB = xTask;
5665             pxTCB->uxTaskNumber = uxHandle;
5666         }
5667
5668         traceRETURN_vTaskSetTaskNumber();
5669     }
5670
5671 #endif /* configUSE_TRACE_FACILITY */
5672 /*-----------------------------------------------------------*/
5673
5674 /*
5675  * -----------------------------------------------------------
5676  * The passive idle task.
5677  * ----------------------------------------------------------
5678  *
5679  * The passive idle task is used for all the additional cores in a SMP
5680  * system. There must be only 1 active idle task and the rest are passive
5681  * idle tasks.
5682  *
5683  * The portTASK_FUNCTION() macro is used to allow port/compiler specific
5684  * language extensions.  The equivalent prototype for this function is:
5685  *
5686  * void prvPassiveIdleTask( void *pvParameters );
5687  */
5688
5689 #if ( configNUMBER_OF_CORES > 1 )
5690     static portTASK_FUNCTION( prvPassiveIdleTask, pvParameters )
5691     {
5692         ( void ) pvParameters;
5693
5694         taskYIELD();
5695
5696         for( ; configCONTROL_INFINITE_LOOP(); )
5697         {
5698             #if ( configUSE_PREEMPTION == 0 )
5699             {
5700                 /* If we are not using preemption we keep forcing a task switch to
5701                  * see if any other task has become available.  If we are using
5702                  * preemption we don't need to do this as any task becoming available
5703                  * will automatically get the processor anyway. */
5704                 taskYIELD();
5705             }
5706             #endif /* configUSE_PREEMPTION */
5707
5708             #if ( ( configUSE_PREEMPTION == 1 ) && ( configIDLE_SHOULD_YIELD == 1 ) )
5709             {
5710                 /* When using preemption tasks of equal priority will be
5711                  * timesliced.  If a task that is sharing the idle priority is ready
5712                  * to run then the idle task should yield before the end of the
5713                  * timeslice.
5714                  *
5715                  * A critical region is not required here as we are just reading from
5716                  * the list, and an occasional incorrect value will not matter.  If
5717                  * the ready list at the idle priority contains one more task than the
5718                  * number of idle tasks, which is equal to the configured numbers of cores
5719                  * then a task other than the idle task is ready to execute. */
5720                 if( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ tskIDLE_PRIORITY ] ) ) > ( UBaseType_t ) configNUMBER_OF_CORES )
5721                 {
5722                     taskYIELD();
5723                 }
5724                 else
5725                 {
5726                     mtCOVERAGE_TEST_MARKER();
5727                 }
5728             }
5729             #endif /* ( ( configUSE_PREEMPTION == 1 ) && ( configIDLE_SHOULD_YIELD == 1 ) ) */
5730
5731             #if ( configUSE_PASSIVE_IDLE_HOOK == 1 )
5732             {
5733                 /* Call the user defined function from within the idle task.  This
5734                  * allows the application designer to add background functionality
5735                  * without the overhead of a separate task.
5736                  *
5737                  * This hook is intended to manage core activity such as disabling cores that go idle.
5738                  *
5739                  * NOTE: vApplicationPassiveIdleHook() MUST NOT, UNDER ANY CIRCUMSTANCES,
5740                  * CALL A FUNCTION THAT MIGHT BLOCK. */
5741                 vApplicationPassiveIdleHook();
5742             }
5743             #endif /* configUSE_PASSIVE_IDLE_HOOK */
5744         }
5745     }
5746 #endif /* #if ( configNUMBER_OF_CORES > 1 ) */
5747
5748 /*
5749  * -----------------------------------------------------------
5750  * The idle task.
5751  * ----------------------------------------------------------
5752  *
5753  * The portTASK_FUNCTION() macro is used to allow port/compiler specific
5754  * language extensions.  The equivalent prototype for this function is:
5755  *
5756  * void prvIdleTask( void *pvParameters );
5757  *
5758  */
5759
5760 static portTASK_FUNCTION( prvIdleTask, pvParameters )
5761 {
5762     /* Stop warnings. */
5763     ( void ) pvParameters;
5764
5765     /** THIS IS THE RTOS IDLE TASK - WHICH IS CREATED AUTOMATICALLY WHEN THE
5766      * SCHEDULER IS STARTED. **/
5767
5768     /* In case a task that has a secure context deletes itself, in which case
5769      * the idle task is responsible for deleting the task's secure context, if
5770      * any. */
5771     portALLOCATE_SECURE_CONTEXT( configMINIMAL_SECURE_STACK_SIZE );
5772
5773     #if ( configNUMBER_OF_CORES > 1 )
5774     {
5775         /* SMP all cores start up in the idle task. This initial yield gets the application
5776          * tasks started. */
5777         taskYIELD();
5778     }
5779     #endif /* #if ( configNUMBER_OF_CORES > 1 ) */
5780
5781     for( ; configCONTROL_INFINITE_LOOP(); )
5782     {
5783         /* See if any tasks have deleted themselves - if so then the idle task
5784          * is responsible for freeing the deleted task's TCB and stack. */
5785         prvCheckTasksWaitingTermination();
5786
5787         #if ( configUSE_PREEMPTION == 0 )
5788         {
5789             /* If we are not using preemption we keep forcing a task switch to
5790              * see if any other task has become available.  If we are using
5791              * preemption we don't need to do this as any task becoming available
5792              * will automatically get the processor anyway. */
5793             taskYIELD();
5794         }
5795         #endif /* configUSE_PREEMPTION */
5796
5797         #if ( ( configUSE_PREEMPTION == 1 ) && ( configIDLE_SHOULD_YIELD == 1 ) )
5798         {
5799             /* When using preemption tasks of equal priority will be
5800              * timesliced.  If a task that is sharing the idle priority is ready
5801              * to run then the idle task should yield before the end of the
5802              * timeslice.
5803              *
5804              * A critical region is not required here as we are just reading from
5805              * the list, and an occasional incorrect value will not matter.  If
5806              * the ready list at the idle priority contains one more task than the
5807              * number of idle tasks, which is equal to the configured numbers of cores
5808              * then a task other than the idle task is ready to execute. */
5809             if( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ tskIDLE_PRIORITY ] ) ) > ( UBaseType_t ) configNUMBER_OF_CORES )
5810             {
5811                 taskYIELD();
5812             }
5813             else
5814             {
5815                 mtCOVERAGE_TEST_MARKER();
5816             }
5817         }
5818         #endif /* ( ( configUSE_PREEMPTION == 1 ) && ( configIDLE_SHOULD_YIELD == 1 ) ) */
5819
5820         #if ( configUSE_IDLE_HOOK == 1 )
5821         {
5822             /* Call the user defined function from within the idle task. */
5823             vApplicationIdleHook();
5824         }
5825         #endif /* configUSE_IDLE_HOOK */
5826
5827         /* This conditional compilation should use inequality to 0, not equality
5828          * to 1.  This is to ensure portSUPPRESS_TICKS_AND_SLEEP() is called when
5829          * user defined low power mode  implementations require
5830          * configUSE_TICKLESS_IDLE to be set to a value other than 1. */
5831         #if ( configUSE_TICKLESS_IDLE != 0 )
5832         {
5833             TickType_t xExpectedIdleTime;
5834
5835             /* It is not desirable to suspend then resume the scheduler on
5836              * each iteration of the idle task.  Therefore, a preliminary
5837              * test of the expected idle time is performed without the
5838              * scheduler suspended.  The result here is not necessarily
5839              * valid. */
5840             xExpectedIdleTime = prvGetExpectedIdleTime();
5841
5842             if( xExpectedIdleTime >= ( TickType_t ) configEXPECTED_IDLE_TIME_BEFORE_SLEEP )
5843             {
5844                 vTaskSuspendAll();
5845                 {
5846                     /* Now the scheduler is suspended, the expected idle
5847                      * time can be sampled again, and this time its value can
5848                      * be used. */
5849                     configASSERT( xNextTaskUnblockTime >= xTickCount );
5850                     xExpectedIdleTime = prvGetExpectedIdleTime();
5851
5852                     /* Define the following macro to set xExpectedIdleTime to 0
5853                      * if the application does not want
5854                      * portSUPPRESS_TICKS_AND_SLEEP() to be called. */
5855                     configPRE_SUPPRESS_TICKS_AND_SLEEP_PROCESSING( xExpectedIdleTime );
5856
5857                     if( xExpectedIdleTime >= ( TickType_t ) configEXPECTED_IDLE_TIME_BEFORE_SLEEP )
5858                     {
5859                         traceLOW_POWER_IDLE_BEGIN();
5860                         portSUPPRESS_TICKS_AND_SLEEP( xExpectedIdleTime );
5861                         traceLOW_POWER_IDLE_END();
5862                     }
5863                     else
5864                     {
5865                         mtCOVERAGE_TEST_MARKER();
5866                     }
5867                 }
5868                 ( void ) xTaskResumeAll();
5869             }
5870             else
5871             {
5872                 mtCOVERAGE_TEST_MARKER();
5873             }
5874         }
5875         #endif /* configUSE_TICKLESS_IDLE */
5876
5877         #if ( ( configNUMBER_OF_CORES > 1 ) && ( configUSE_PASSIVE_IDLE_HOOK == 1 ) )
5878         {
5879             /* Call the user defined function from within the idle task.  This
5880              * allows the application designer to add background functionality
5881              * without the overhead of a separate task.
5882              *
5883              * This hook is intended to manage core activity such as disabling cores that go idle.
5884              *
5885              * NOTE: vApplicationPassiveIdleHook() MUST NOT, UNDER ANY CIRCUMSTANCES,
5886              * CALL A FUNCTION THAT MIGHT BLOCK. */
5887             vApplicationPassiveIdleHook();
5888         }
5889         #endif /* #if ( ( configNUMBER_OF_CORES > 1 ) && ( configUSE_PASSIVE_IDLE_HOOK == 1 ) ) */
5890     }
5891 }
5892 /*-----------------------------------------------------------*/
5893
5894 #if ( configUSE_TICKLESS_IDLE != 0 )
5895
5896     eSleepModeStatus eTaskConfirmSleepModeStatus( void )
5897     {
5898         #if ( INCLUDE_vTaskSuspend == 1 )
5899             /* The idle task exists in addition to the application tasks. */
5900             const UBaseType_t uxNonApplicationTasks = configNUMBER_OF_CORES;
5901         #endif /* INCLUDE_vTaskSuspend */
5902
5903         eSleepModeStatus eReturn = eStandardSleep;
5904
5905         traceENTER_eTaskConfirmSleepModeStatus();
5906
5907         /* This function must be called from a critical section. */
5908
5909         if( listCURRENT_LIST_LENGTH( &xPendingReadyList ) != 0U )
5910         {
5911             /* A task was made ready while the scheduler was suspended. */
5912             eReturn = eAbortSleep;
5913         }
5914         else if( xYieldPendings[ portGET_CORE_ID() ] != pdFALSE )
5915         {
5916             /* A yield was pended while the scheduler was suspended. */
5917             eReturn = eAbortSleep;
5918         }
5919         else if( xPendedTicks != 0U )
5920         {
5921             /* A tick interrupt has already occurred but was held pending
5922              * because the scheduler is suspended. */
5923             eReturn = eAbortSleep;
5924         }
5925
5926         #if ( INCLUDE_vTaskSuspend == 1 )
5927             else if( listCURRENT_LIST_LENGTH( &xSuspendedTaskList ) == ( uxCurrentNumberOfTasks - uxNonApplicationTasks ) )
5928             {
5929                 /* If all the tasks are in the suspended list (which might mean they
5930                  * have an infinite block time rather than actually being suspended)
5931                  * then it is safe to turn all clocks off and just wait for external
5932                  * interrupts. */
5933                 eReturn = eNoTasksWaitingTimeout;
5934             }
5935         #endif /* INCLUDE_vTaskSuspend */
5936         else
5937         {
5938             mtCOVERAGE_TEST_MARKER();
5939         }
5940
5941         traceRETURN_eTaskConfirmSleepModeStatus( eReturn );
5942
5943         return eReturn;
5944     }
5945
5946 #endif /* configUSE_TICKLESS_IDLE */
5947 /*-----------------------------------------------------------*/
5948
5949 #if ( configNUM_THREAD_LOCAL_STORAGE_POINTERS != 0 )
5950
5951     void vTaskSetThreadLocalStoragePointer( TaskHandle_t xTaskToSet,
5952                                             BaseType_t xIndex,
5953                                             void * pvValue )
5954     {
5955         TCB_t * pxTCB;
5956
5957         traceENTER_vTaskSetThreadLocalStoragePointer( xTaskToSet, xIndex, pvValue );
5958
5959         if( ( xIndex >= 0 ) &&
5960             ( xIndex < ( BaseType_t ) configNUM_THREAD_LOCAL_STORAGE_POINTERS ) )
5961         {
5962             pxTCB = prvGetTCBFromHandle( xTaskToSet );
5963             configASSERT( pxTCB != NULL );
5964             pxTCB->pvThreadLocalStoragePointers[ xIndex ] = pvValue;
5965         }
5966
5967         traceRETURN_vTaskSetThreadLocalStoragePointer();
5968     }
5969
5970 #endif /* configNUM_THREAD_LOCAL_STORAGE_POINTERS */
5971 /*-----------------------------------------------------------*/
5972
5973 #if ( configNUM_THREAD_LOCAL_STORAGE_POINTERS != 0 )
5974
5975     void * pvTaskGetThreadLocalStoragePointer( TaskHandle_t xTaskToQuery,
5976                                                BaseType_t xIndex )
5977     {
5978         void * pvReturn = NULL;
5979         TCB_t * pxTCB;
5980
5981         traceENTER_pvTaskGetThreadLocalStoragePointer( xTaskToQuery, xIndex );
5982
5983         if( ( xIndex >= 0 ) &&
5984             ( xIndex < ( BaseType_t ) configNUM_THREAD_LOCAL_STORAGE_POINTERS ) )
5985         {
5986             pxTCB = prvGetTCBFromHandle( xTaskToQuery );
5987             pvReturn = pxTCB->pvThreadLocalStoragePointers[ xIndex ];
5988         }
5989         else
5990         {
5991             pvReturn = NULL;
5992         }
5993
5994         traceRETURN_pvTaskGetThreadLocalStoragePointer( pvReturn );
5995
5996         return pvReturn;
5997     }
5998
5999 #endif /* configNUM_THREAD_LOCAL_STORAGE_POINTERS */
6000 /*-----------------------------------------------------------*/
6001
6002 #if ( portUSING_MPU_WRAPPERS == 1 )
6003
6004     void vTaskAllocateMPURegions( TaskHandle_t xTaskToModify,
6005                                   const MemoryRegion_t * const pxRegions )
6006     {
6007         TCB_t * pxTCB;
6008
6009         traceENTER_vTaskAllocateMPURegions( xTaskToModify, pxRegions );
6010
6011         /* If null is passed in here then we are modifying the MPU settings of
6012          * the calling task. */
6013         pxTCB = prvGetTCBFromHandle( xTaskToModify );
6014
6015         vPortStoreTaskMPUSettings( &( pxTCB->xMPUSettings ), pxRegions, NULL, 0 );
6016
6017         traceRETURN_vTaskAllocateMPURegions();
6018     }
6019
6020 #endif /* portUSING_MPU_WRAPPERS */
6021 /*-----------------------------------------------------------*/
6022
6023 static void prvInitialiseTaskLists( void )
6024 {
6025     UBaseType_t uxPriority;
6026
6027     for( uxPriority = ( UBaseType_t ) 0U; uxPriority < ( UBaseType_t ) configMAX_PRIORITIES; uxPriority++ )
6028     {
6029         vListInitialise( &( pxReadyTasksLists[ uxPriority ] ) );
6030     }
6031
6032     vListInitialise( &xDelayedTaskList1 );
6033     vListInitialise( &xDelayedTaskList2 );
6034     vListInitialise( &xPendingReadyList );
6035
6036     #if ( INCLUDE_vTaskDelete == 1 )
6037     {
6038         vListInitialise( &xTasksWaitingTermination );
6039     }
6040     #endif /* INCLUDE_vTaskDelete */
6041
6042     #if ( INCLUDE_vTaskSuspend == 1 )
6043     {
6044         vListInitialise( &xSuspendedTaskList );
6045     }
6046     #endif /* INCLUDE_vTaskSuspend */
6047
6048     /* Start with pxDelayedTaskList using list1 and the pxOverflowDelayedTaskList
6049      * using list2. */
6050     pxDelayedTaskList = &xDelayedTaskList1;
6051     pxOverflowDelayedTaskList = &xDelayedTaskList2;
6052 }
6053 /*-----------------------------------------------------------*/
6054
6055 static void prvCheckTasksWaitingTermination( void )
6056 {
6057     /** THIS FUNCTION IS CALLED FROM THE RTOS IDLE TASK **/
6058
6059     #if ( INCLUDE_vTaskDelete == 1 )
6060     {
6061         TCB_t * pxTCB;
6062
6063         /* uxDeletedTasksWaitingCleanUp is used to prevent taskENTER_CRITICAL()
6064          * being called too often in the idle task. */
6065         while( uxDeletedTasksWaitingCleanUp > ( UBaseType_t ) 0U )
6066         {
6067             #if ( configNUMBER_OF_CORES == 1 )
6068             {
6069                 taskENTER_CRITICAL();
6070                 {
6071                     {
6072                         /* MISRA Ref 11.5.3 [Void pointer assignment] */
6073                         /* More details at: https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/MISRA.md#rule-115 */
6074                         /* coverity[misra_c_2012_rule_11_5_violation] */
6075                         pxTCB = listGET_OWNER_OF_HEAD_ENTRY( ( &xTasksWaitingTermination ) );
6076                         ( void ) uxListRemove( &( pxTCB->xStateListItem ) );
6077                         --uxCurrentNumberOfTasks;
6078                         --uxDeletedTasksWaitingCleanUp;
6079                     }
6080                 }
6081                 taskEXIT_CRITICAL();
6082
6083                 prvDeleteTCB( pxTCB );
6084             }
6085             #else /* #if( configNUMBER_OF_CORES == 1 ) */
6086             {
6087                 pxTCB = NULL;
6088
6089                 taskENTER_CRITICAL();
6090                 {
6091                     /* For SMP, multiple idles can be running simultaneously
6092                      * and we need to check that other idles did not cleanup while we were
6093                      * waiting to enter the critical section. */
6094                     if( uxDeletedTasksWaitingCleanUp > ( UBaseType_t ) 0U )
6095                     {
6096                         /* MISRA Ref 11.5.3 [Void pointer assignment] */
6097                         /* More details at: https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/MISRA.md#rule-115 */
6098                         /* coverity[misra_c_2012_rule_11_5_violation] */
6099                         pxTCB = listGET_OWNER_OF_HEAD_ENTRY( ( &xTasksWaitingTermination ) );
6100
6101                         if( pxTCB->xTaskRunState == taskTASK_NOT_RUNNING )
6102                         {
6103                             ( void ) uxListRemove( &( pxTCB->xStateListItem ) );
6104                             --uxCurrentNumberOfTasks;
6105                             --uxDeletedTasksWaitingCleanUp;
6106                         }
6107                         else
6108                         {
6109                             /* The TCB to be deleted still has not yet been switched out
6110                              * by the scheduler, so we will just exit this loop early and
6111                              * try again next time. */
6112                             taskEXIT_CRITICAL();
6113                             break;
6114                         }
6115                     }
6116                 }
6117                 taskEXIT_CRITICAL();
6118
6119                 if( pxTCB != NULL )
6120                 {
6121                     prvDeleteTCB( pxTCB );
6122                 }
6123             }
6124             #endif /* #if( configNUMBER_OF_CORES == 1 ) */
6125         }
6126     }
6127     #endif /* INCLUDE_vTaskDelete */
6128 }
6129 /*-----------------------------------------------------------*/
6130
6131 #if ( configUSE_TRACE_FACILITY == 1 )
6132
6133     void vTaskGetInfo( TaskHandle_t xTask,
6134                        TaskStatus_t * pxTaskStatus,
6135                        BaseType_t xGetFreeStackSpace,
6136                        eTaskState eState )
6137     {
6138         TCB_t * pxTCB;
6139
6140         traceENTER_vTaskGetInfo( xTask, pxTaskStatus, xGetFreeStackSpace, eState );
6141
6142         /* xTask is NULL then get the state of the calling task. */
6143         pxTCB = prvGetTCBFromHandle( xTask );
6144
6145         pxTaskStatus->xHandle = pxTCB;
6146         pxTaskStatus->pcTaskName = ( const char * ) &( pxTCB->pcTaskName[ 0 ] );
6147         pxTaskStatus->uxCurrentPriority = pxTCB->uxPriority;
6148         pxTaskStatus->pxStackBase = pxTCB->pxStack;
6149         #if ( ( portSTACK_GROWTH > 0 ) || ( configRECORD_STACK_HIGH_ADDRESS == 1 ) )
6150             pxTaskStatus->pxTopOfStack = ( StackType_t * ) pxTCB->pxTopOfStack;
6151             pxTaskStatus->pxEndOfStack = pxTCB->pxEndOfStack;
6152         #endif
6153         pxTaskStatus->xTaskNumber = pxTCB->uxTCBNumber;
6154
6155         #if ( ( configUSE_CORE_AFFINITY == 1 ) && ( configNUMBER_OF_CORES > 1 ) )
6156         {
6157             pxTaskStatus->uxCoreAffinityMask = pxTCB->uxCoreAffinityMask;
6158         }
6159         #endif
6160
6161         #if ( configUSE_MUTEXES == 1 )
6162         {
6163             pxTaskStatus->uxBasePriority = pxTCB->uxBasePriority;
6164         }
6165         #else
6166         {
6167             pxTaskStatus->uxBasePriority = 0;
6168         }
6169         #endif
6170
6171         #if ( configGENERATE_RUN_TIME_STATS == 1 )
6172         {
6173             pxTaskStatus->ulRunTimeCounter = pxTCB->ulRunTimeCounter;
6174         }
6175         #else
6176         {
6177             pxTaskStatus->ulRunTimeCounter = ( configRUN_TIME_COUNTER_TYPE ) 0;
6178         }
6179         #endif
6180
6181         /* Obtaining the task state is a little fiddly, so is only done if the
6182          * value of eState passed into this function is eInvalid - otherwise the
6183          * state is just set to whatever is passed in. */
6184         if( eState != eInvalid )
6185         {
6186             if( taskTASK_IS_RUNNING( pxTCB ) == pdTRUE )
6187             {
6188                 pxTaskStatus->eCurrentState = eRunning;
6189             }
6190             else
6191             {
6192                 pxTaskStatus->eCurrentState = eState;
6193
6194                 #if ( INCLUDE_vTaskSuspend == 1 )
6195                 {
6196                     /* If the task is in the suspended list then there is a
6197                      *  chance it is actually just blocked indefinitely - so really
6198                      *  it should be reported as being in the Blocked state. */
6199                     if( eState == eSuspended )
6200                     {
6201                         vTaskSuspendAll();
6202                         {
6203                             if( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) != NULL )
6204                             {
6205                                 pxTaskStatus->eCurrentState = eBlocked;
6206                             }
6207                             else
6208                             {
6209                                 #if ( configUSE_TASK_NOTIFICATIONS == 1 )
6210                                 {
6211                                     BaseType_t x;
6212
6213                                     /* The task does not appear on the event list item of
6214                                      * and of the RTOS objects, but could still be in the
6215                                      * blocked state if it is waiting on its notification
6216                                      * rather than waiting on an object.  If not, is
6217                                      * suspended. */
6218                                     for( x = ( BaseType_t ) 0; x < ( BaseType_t ) configTASK_NOTIFICATION_ARRAY_ENTRIES; x++ )
6219                                     {
6220                                         if( pxTCB->ucNotifyState[ x ] == taskWAITING_NOTIFICATION )
6221                                         {
6222                                             pxTaskStatus->eCurrentState = eBlocked;
6223                                             break;
6224                                         }
6225                                     }
6226                                 }
6227                                 #endif /* if ( configUSE_TASK_NOTIFICATIONS == 1 ) */
6228                             }
6229                         }
6230                         ( void ) xTaskResumeAll();
6231                     }
6232                 }
6233                 #endif /* INCLUDE_vTaskSuspend */
6234
6235                 /* Tasks can be in pending ready list and other state list at the
6236                  * same time. These tasks are in ready state no matter what state
6237                  * list the task is in. */
6238                 taskENTER_CRITICAL();
6239                 {
6240                     if( listIS_CONTAINED_WITHIN( &xPendingReadyList, &( pxTCB->xEventListItem ) ) != pdFALSE )
6241                     {
6242                         pxTaskStatus->eCurrentState = eReady;
6243                     }
6244                 }
6245                 taskEXIT_CRITICAL();
6246             }
6247         }
6248         else
6249         {
6250             pxTaskStatus->eCurrentState = eTaskGetState( pxTCB );
6251         }
6252
6253         /* Obtaining the stack space takes some time, so the xGetFreeStackSpace
6254          * parameter is provided to allow it to be skipped. */
6255         if( xGetFreeStackSpace != pdFALSE )
6256         {
6257             #if ( portSTACK_GROWTH > 0 )
6258             {
6259                 pxTaskStatus->usStackHighWaterMark = prvTaskCheckFreeStackSpace( ( uint8_t * ) pxTCB->pxEndOfStack );
6260             }
6261             #else
6262             {
6263                 pxTaskStatus->usStackHighWaterMark = prvTaskCheckFreeStackSpace( ( uint8_t * ) pxTCB->pxStack );
6264             }
6265             #endif
6266         }
6267         else
6268         {
6269             pxTaskStatus->usStackHighWaterMark = 0;
6270         }
6271
6272         traceRETURN_vTaskGetInfo();
6273     }
6274
6275 #endif /* configUSE_TRACE_FACILITY */
6276 /*-----------------------------------------------------------*/
6277
6278 #if ( configUSE_TRACE_FACILITY == 1 )
6279
6280     static UBaseType_t prvListTasksWithinSingleList( TaskStatus_t * pxTaskStatusArray,
6281                                                      List_t * pxList,
6282                                                      eTaskState eState )
6283     {
6284         UBaseType_t uxTask = 0;
6285         const ListItem_t * pxEndMarker = listGET_END_MARKER( pxList );
6286         ListItem_t * pxIterator;
6287         TCB_t * pxTCB = NULL;
6288
6289         if( listCURRENT_LIST_LENGTH( pxList ) > ( UBaseType_t ) 0 )
6290         {
6291             /* Populate an TaskStatus_t structure within the
6292              * pxTaskStatusArray array for each task that is referenced from
6293              * pxList.  See the definition of TaskStatus_t in task.h for the
6294              * meaning of each TaskStatus_t structure member. */
6295             for( pxIterator = listGET_HEAD_ENTRY( pxList ); pxIterator != pxEndMarker; pxIterator = listGET_NEXT( pxIterator ) )
6296             {
6297                 /* MISRA Ref 11.5.3 [Void pointer assignment] */
6298                 /* More details at: https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/MISRA.md#rule-115 */
6299                 /* coverity[misra_c_2012_rule_11_5_violation] */
6300                 pxTCB = listGET_LIST_ITEM_OWNER( pxIterator );
6301
6302                 vTaskGetInfo( ( TaskHandle_t ) pxTCB, &( pxTaskStatusArray[ uxTask ] ), pdTRUE, eState );
6303                 uxTask++;
6304             }
6305         }
6306         else
6307         {
6308             mtCOVERAGE_TEST_MARKER();
6309         }
6310
6311         return uxTask;
6312     }
6313
6314 #endif /* configUSE_TRACE_FACILITY */
6315 /*-----------------------------------------------------------*/
6316
6317 #if ( ( configUSE_TRACE_FACILITY == 1 ) || ( INCLUDE_uxTaskGetStackHighWaterMark == 1 ) || ( INCLUDE_uxTaskGetStackHighWaterMark2 == 1 ) )
6318
6319     static configSTACK_DEPTH_TYPE prvTaskCheckFreeStackSpace( const uint8_t * pucStackByte )
6320     {
6321         configSTACK_DEPTH_TYPE uxCount = 0U;
6322
6323         while( *pucStackByte == ( uint8_t ) tskSTACK_FILL_BYTE )
6324         {
6325             pucStackByte -= portSTACK_GROWTH;
6326             uxCount++;
6327         }
6328
6329         uxCount /= ( configSTACK_DEPTH_TYPE ) sizeof( StackType_t );
6330
6331         return uxCount;
6332     }
6333
6334 #endif /* ( ( configUSE_TRACE_FACILITY == 1 ) || ( INCLUDE_uxTaskGetStackHighWaterMark == 1 ) || ( INCLUDE_uxTaskGetStackHighWaterMark2 == 1 ) ) */
6335 /*-----------------------------------------------------------*/
6336
6337 #if ( INCLUDE_uxTaskGetStackHighWaterMark2 == 1 )
6338
6339 /* uxTaskGetStackHighWaterMark() and uxTaskGetStackHighWaterMark2() are the
6340  * same except for their return type.  Using configSTACK_DEPTH_TYPE allows the
6341  * user to determine the return type.  It gets around the problem of the value
6342  * overflowing on 8-bit types without breaking backward compatibility for
6343  * applications that expect an 8-bit return type. */
6344     configSTACK_DEPTH_TYPE uxTaskGetStackHighWaterMark2( TaskHandle_t xTask )
6345     {
6346         TCB_t * pxTCB;
6347         uint8_t * pucEndOfStack;
6348         configSTACK_DEPTH_TYPE uxReturn;
6349
6350         traceENTER_uxTaskGetStackHighWaterMark2( xTask );
6351
6352         /* uxTaskGetStackHighWaterMark() and uxTaskGetStackHighWaterMark2() are
6353          * the same except for their return type.  Using configSTACK_DEPTH_TYPE
6354          * allows the user to determine the return type.  It gets around the
6355          * problem of the value overflowing on 8-bit types without breaking
6356          * backward compatibility for applications that expect an 8-bit return
6357          * type. */
6358
6359         pxTCB = prvGetTCBFromHandle( xTask );
6360
6361         #if portSTACK_GROWTH < 0
6362         {
6363             pucEndOfStack = ( uint8_t * ) pxTCB->pxStack;
6364         }
6365         #else
6366         {
6367             pucEndOfStack = ( uint8_t * ) pxTCB->pxEndOfStack;
6368         }
6369         #endif
6370
6371         uxReturn = prvTaskCheckFreeStackSpace( pucEndOfStack );
6372
6373         traceRETURN_uxTaskGetStackHighWaterMark2( uxReturn );
6374
6375         return uxReturn;
6376     }
6377
6378 #endif /* INCLUDE_uxTaskGetStackHighWaterMark2 */
6379 /*-----------------------------------------------------------*/
6380
6381 #if ( INCLUDE_uxTaskGetStackHighWaterMark == 1 )
6382
6383     UBaseType_t uxTaskGetStackHighWaterMark( TaskHandle_t xTask )
6384     {
6385         TCB_t * pxTCB;
6386         uint8_t * pucEndOfStack;
6387         UBaseType_t uxReturn;
6388
6389         traceENTER_uxTaskGetStackHighWaterMark( xTask );
6390
6391         pxTCB = prvGetTCBFromHandle( xTask );
6392
6393         #if portSTACK_GROWTH < 0
6394         {
6395             pucEndOfStack = ( uint8_t * ) pxTCB->pxStack;
6396         }
6397         #else
6398         {
6399             pucEndOfStack = ( uint8_t * ) pxTCB->pxEndOfStack;
6400         }
6401         #endif
6402
6403         uxReturn = ( UBaseType_t ) prvTaskCheckFreeStackSpace( pucEndOfStack );
6404
6405         traceRETURN_uxTaskGetStackHighWaterMark( uxReturn );
6406
6407         return uxReturn;
6408     }
6409
6410 #endif /* INCLUDE_uxTaskGetStackHighWaterMark */
6411 /*-----------------------------------------------------------*/
6412
6413 #if ( INCLUDE_vTaskDelete == 1 )
6414
6415     static void prvDeleteTCB( TCB_t * pxTCB )
6416     {
6417         /* This call is required specifically for the TriCore port.  It must be
6418          * above the vPortFree() calls.  The call is also used by ports/demos that
6419          * want to allocate and clean RAM statically. */
6420         portCLEAN_UP_TCB( pxTCB );
6421
6422         #if ( configUSE_C_RUNTIME_TLS_SUPPORT == 1 )
6423         {
6424             /* Free up the memory allocated for the task's TLS Block. */
6425             configDEINIT_TLS_BLOCK( pxTCB->xTLSBlock );
6426         }
6427         #endif
6428
6429         #if ( ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 0 ) && ( portUSING_MPU_WRAPPERS == 0 ) )
6430         {
6431             /* The task can only have been allocated dynamically - free both
6432              * the stack and TCB. */
6433             vPortFreeStack( pxTCB->pxStack );
6434             vPortFree( pxTCB );
6435         }
6436         #elif ( tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE != 0 )
6437         {
6438             /* The task could have been allocated statically or dynamically, so
6439              * check what was statically allocated before trying to free the
6440              * memory. */
6441             if( pxTCB->ucStaticallyAllocated == tskDYNAMICALLY_ALLOCATED_STACK_AND_TCB )
6442             {
6443                 /* Both the stack and TCB were allocated dynamically, so both
6444                  * must be freed. */
6445                 vPortFreeStack( pxTCB->pxStack );
6446                 vPortFree( pxTCB );
6447             }
6448             else if( pxTCB->ucStaticallyAllocated == tskSTATICALLY_ALLOCATED_STACK_ONLY )
6449             {
6450                 /* Only the stack was statically allocated, so the TCB is the
6451                  * only memory that must be freed. */
6452                 vPortFree( pxTCB );
6453             }
6454             else
6455             {
6456                 /* Neither the stack nor the TCB were allocated dynamically, so
6457                  * nothing needs to be freed. */
6458                 configASSERT( pxTCB->ucStaticallyAllocated == tskSTATICALLY_ALLOCATED_STACK_AND_TCB );
6459                 mtCOVERAGE_TEST_MARKER();
6460             }
6461         }
6462         #endif /* configSUPPORT_DYNAMIC_ALLOCATION */
6463     }
6464
6465 #endif /* INCLUDE_vTaskDelete */
6466 /*-----------------------------------------------------------*/
6467
6468 static void prvResetNextTaskUnblockTime( void )
6469 {
6470     if( listLIST_IS_EMPTY( pxDelayedTaskList ) != pdFALSE )
6471     {
6472         /* The new current delayed list is empty.  Set xNextTaskUnblockTime to
6473          * the maximum possible value so it is  extremely unlikely that the
6474          * if( xTickCount >= xNextTaskUnblockTime ) test will pass until
6475          * there is an item in the delayed list. */
6476         xNextTaskUnblockTime = portMAX_DELAY;
6477     }
6478     else
6479     {
6480         /* The new current delayed list is not empty, get the value of
6481          * the item at the head of the delayed list.  This is the time at
6482          * which the task at the head of the delayed list should be removed
6483          * from the Blocked state. */
6484         xNextTaskUnblockTime = listGET_ITEM_VALUE_OF_HEAD_ENTRY( pxDelayedTaskList );
6485     }
6486 }
6487 /*-----------------------------------------------------------*/
6488
6489 #if ( ( INCLUDE_xTaskGetCurrentTaskHandle == 1 ) || ( configUSE_RECURSIVE_MUTEXES == 1 ) ) || ( configNUMBER_OF_CORES > 1 )
6490
6491     #if ( configNUMBER_OF_CORES == 1 )
6492         TaskHandle_t xTaskGetCurrentTaskHandle( void )
6493         {
6494             TaskHandle_t xReturn;
6495
6496             traceENTER_xTaskGetCurrentTaskHandle();
6497
6498             /* A critical section is not required as this is not called from
6499              * an interrupt and the current TCB will always be the same for any
6500              * individual execution thread. */
6501             xReturn = pxCurrentTCB;
6502
6503             traceRETURN_xTaskGetCurrentTaskHandle( xReturn );
6504
6505             return xReturn;
6506         }
6507     #else /* #if ( configNUMBER_OF_CORES == 1 ) */
6508         TaskHandle_t xTaskGetCurrentTaskHandle( void )
6509         {
6510             TaskHandle_t xReturn;
6511             UBaseType_t uxSavedInterruptStatus;
6512
6513             traceENTER_xTaskGetCurrentTaskHandle();
6514
6515             uxSavedInterruptStatus = portSET_INTERRUPT_MASK();
6516             {
6517                 xReturn = pxCurrentTCBs[ portGET_CORE_ID() ];
6518             }
6519             portCLEAR_INTERRUPT_MASK( uxSavedInterruptStatus );
6520
6521             traceRETURN_xTaskGetCurrentTaskHandle( xReturn );
6522
6523             return xReturn;
6524         }
6525     #endif /* #if ( configNUMBER_OF_CORES == 1 ) */
6526
6527     TaskHandle_t xTaskGetCurrentTaskHandleForCore( BaseType_t xCoreID )
6528     {
6529         TaskHandle_t xReturn = NULL;
6530
6531         traceENTER_xTaskGetCurrentTaskHandleForCore( xCoreID );
6532
6533         if( taskVALID_CORE_ID( xCoreID ) != pdFALSE )
6534         {
6535             #if ( configNUMBER_OF_CORES == 1 )
6536                 xReturn = pxCurrentTCB;
6537             #else /* #if ( configNUMBER_OF_CORES == 1 ) */
6538                 xReturn = pxCurrentTCBs[ xCoreID ];
6539             #endif /* #if ( configNUMBER_OF_CORES == 1 ) */
6540         }
6541
6542         traceRETURN_xTaskGetCurrentTaskHandleForCore( xReturn );
6543
6544         return xReturn;
6545     }
6546
6547 #endif /* ( ( INCLUDE_xTaskGetCurrentTaskHandle == 1 ) || ( configUSE_RECURSIVE_MUTEXES == 1 ) ) */
6548 /*-----------------------------------------------------------*/
6549
6550 #if ( ( INCLUDE_xTaskGetSchedulerState == 1 ) || ( configUSE_TIMERS == 1 ) )
6551
6552     BaseType_t xTaskGetSchedulerState( void )
6553     {
6554         BaseType_t xReturn;
6555
6556         traceENTER_xTaskGetSchedulerState();
6557
6558         if( xSchedulerRunning == pdFALSE )
6559         {
6560             xReturn = taskSCHEDULER_NOT_STARTED;
6561         }
6562         else
6563         {
6564             #if ( configNUMBER_OF_CORES > 1 )
6565                 taskENTER_CRITICAL();
6566             #endif
6567             {
6568                 if( uxSchedulerSuspended == ( UBaseType_t ) 0U )
6569                 {
6570                     xReturn = taskSCHEDULER_RUNNING;
6571                 }
6572                 else
6573                 {
6574                     xReturn = taskSCHEDULER_SUSPENDED;
6575                 }
6576             }
6577             #if ( configNUMBER_OF_CORES > 1 )
6578                 taskEXIT_CRITICAL();
6579             #endif
6580         }
6581
6582         traceRETURN_xTaskGetSchedulerState( xReturn );
6583
6584         return xReturn;
6585     }
6586
6587 #endif /* ( ( INCLUDE_xTaskGetSchedulerState == 1 ) || ( configUSE_TIMERS == 1 ) ) */
6588 /*-----------------------------------------------------------*/
6589
6590 #if ( configUSE_MUTEXES == 1 )
6591
6592     BaseType_t xTaskPriorityInherit( TaskHandle_t const pxMutexHolder )
6593     {
6594         TCB_t * const pxMutexHolderTCB = pxMutexHolder;
6595         BaseType_t xReturn = pdFALSE;
6596
6597         traceENTER_xTaskPriorityInherit( pxMutexHolder );
6598
6599         /* If the mutex is taken by an interrupt, the mutex holder is NULL. Priority
6600          * inheritance is not applied in this scenario. */
6601         if( pxMutexHolder != NULL )
6602         {
6603             /* If the holder of the mutex has a priority below the priority of
6604              * the task attempting to obtain the mutex then it will temporarily
6605              * inherit the priority of the task attempting to obtain the mutex. */
6606             if( pxMutexHolderTCB->uxPriority < pxCurrentTCB->uxPriority )
6607             {
6608                 /* Adjust the mutex holder state to account for its new
6609                  * priority.  Only reset the event list item value if the value is
6610                  * not being used for anything else. */
6611                 if( ( listGET_LIST_ITEM_VALUE( &( pxMutexHolderTCB->xEventListItem ) ) & taskEVENT_LIST_ITEM_VALUE_IN_USE ) == ( ( TickType_t ) 0U ) )
6612                 {
6613                     listSET_LIST_ITEM_VALUE( &( pxMutexHolderTCB->xEventListItem ), ( TickType_t ) configMAX_PRIORITIES - ( TickType_t ) pxCurrentTCB->uxPriority );
6614                 }
6615                 else
6616                 {
6617                     mtCOVERAGE_TEST_MARKER();
6618                 }
6619
6620                 /* If the task being modified is in the ready state it will need
6621                  * to be moved into a new list. */
6622                 if( listIS_CONTAINED_WITHIN( &( pxReadyTasksLists[ pxMutexHolderTCB->uxPriority ] ), &( pxMutexHolderTCB->xStateListItem ) ) != pdFALSE )
6623                 {
6624                     if( uxListRemove( &( pxMutexHolderTCB->xStateListItem ) ) == ( UBaseType_t ) 0 )
6625                     {
6626                         /* It is known that the task is in its ready list so
6627                          * there is no need to check again and the port level
6628                          * reset macro can be called directly. */
6629                         portRESET_READY_PRIORITY( pxMutexHolderTCB->uxPriority, uxTopReadyPriority );
6630                     }
6631                     else
6632                     {
6633                         mtCOVERAGE_TEST_MARKER();
6634                     }
6635
6636                     /* Inherit the priority before being moved into the new list. */
6637                     pxMutexHolderTCB->uxPriority = pxCurrentTCB->uxPriority;
6638                     prvAddTaskToReadyList( pxMutexHolderTCB );
6639                     #if ( configNUMBER_OF_CORES > 1 )
6640                     {
6641                         /* The priority of the task is raised. Yield for this task
6642                          * if it is not running. */
6643                         if( taskTASK_IS_RUNNING( pxMutexHolderTCB ) != pdTRUE )
6644                         {
6645                             prvYieldForTask( pxMutexHolderTCB );
6646                         }
6647                     }
6648                     #endif /* if ( configNUMBER_OF_CORES > 1 ) */
6649                 }
6650                 else
6651                 {
6652                     /* Just inherit the priority. */
6653                     pxMutexHolderTCB->uxPriority = pxCurrentTCB->uxPriority;
6654                 }
6655
6656                 traceTASK_PRIORITY_INHERIT( pxMutexHolderTCB, pxCurrentTCB->uxPriority );
6657
6658                 /* Inheritance occurred. */
6659                 xReturn = pdTRUE;
6660             }
6661             else
6662             {
6663                 if( pxMutexHolderTCB->uxBasePriority < pxCurrentTCB->uxPriority )
6664                 {
6665                     /* The base priority of the mutex holder is lower than the
6666                      * priority of the task attempting to take the mutex, but the
6667                      * current priority of the mutex holder is not lower than the
6668                      * priority of the task attempting to take the mutex.
6669                      * Therefore the mutex holder must have already inherited a
6670                      * priority, but inheritance would have occurred if that had
6671                      * not been the case. */
6672                     xReturn = pdTRUE;
6673                 }
6674                 else
6675                 {
6676                     mtCOVERAGE_TEST_MARKER();
6677                 }
6678             }
6679         }
6680         else
6681         {
6682             mtCOVERAGE_TEST_MARKER();
6683         }
6684
6685         traceRETURN_xTaskPriorityInherit( xReturn );
6686
6687         return xReturn;
6688     }
6689
6690 #endif /* configUSE_MUTEXES */
6691 /*-----------------------------------------------------------*/
6692
6693 #if ( configUSE_MUTEXES == 1 )
6694
6695     BaseType_t xTaskPriorityDisinherit( TaskHandle_t const pxMutexHolder )
6696     {
6697         TCB_t * const pxTCB = pxMutexHolder;
6698         BaseType_t xReturn = pdFALSE;
6699
6700         traceENTER_xTaskPriorityDisinherit( pxMutexHolder );
6701
6702         if( pxMutexHolder != NULL )
6703         {
6704             /* A task can only have an inherited priority if it holds the mutex.
6705              * If the mutex is held by a task then it cannot be given from an
6706              * interrupt, and if a mutex is given by the holding task then it must
6707              * be the running state task. */
6708             configASSERT( pxTCB == pxCurrentTCB );
6709             configASSERT( pxTCB->uxMutexesHeld );
6710             ( pxTCB->uxMutexesHeld )--;
6711
6712             /* Has the holder of the mutex inherited the priority of another
6713              * task? */
6714             if( pxTCB->uxPriority != pxTCB->uxBasePriority )
6715             {
6716                 /* Only disinherit if no other mutexes are held. */
6717                 if( pxTCB->uxMutexesHeld == ( UBaseType_t ) 0 )
6718                 {
6719                     /* A task can only have an inherited priority if it holds
6720                      * the mutex.  If the mutex is held by a task then it cannot be
6721                      * given from an interrupt, and if a mutex is given by the
6722                      * holding task then it must be the running state task.  Remove
6723                      * the holding task from the ready list. */
6724                     if( uxListRemove( &( pxTCB->xStateListItem ) ) == ( UBaseType_t ) 0 )
6725                     {
6726                         portRESET_READY_PRIORITY( pxTCB->uxPriority, uxTopReadyPriority );
6727                     }
6728                     else
6729                     {
6730                         mtCOVERAGE_TEST_MARKER();
6731                     }
6732
6733                     /* Disinherit the priority before adding the task into the
6734                      * new  ready list. */
6735                     traceTASK_PRIORITY_DISINHERIT( pxTCB, pxTCB->uxBasePriority );
6736                     pxTCB->uxPriority = pxTCB->uxBasePriority;
6737
6738                     /* Reset the event list item value.  It cannot be in use for
6739                      * any other purpose if this task is running, and it must be
6740                      * running to give back the mutex. */
6741                     listSET_LIST_ITEM_VALUE( &( pxTCB->xEventListItem ), ( TickType_t ) configMAX_PRIORITIES - ( TickType_t ) pxTCB->uxPriority );
6742                     prvAddTaskToReadyList( pxTCB );
6743                     #if ( configNUMBER_OF_CORES > 1 )
6744                     {
6745                         /* The priority of the task is dropped. Yield the core on
6746                          * which the task is running. */
6747                         if( taskTASK_IS_RUNNING( pxTCB ) == pdTRUE )
6748                         {
6749                             prvYieldCore( pxTCB->xTaskRunState );
6750                         }
6751                     }
6752                     #endif /* if ( configNUMBER_OF_CORES > 1 ) */
6753
6754                     /* Return true to indicate that a context switch is required.
6755                      * This is only actually required in the corner case whereby
6756                      * multiple mutexes were held and the mutexes were given back
6757                      * in an order different to that in which they were taken.
6758                      * If a context switch did not occur when the first mutex was
6759                      * returned, even if a task was waiting on it, then a context
6760                      * switch should occur when the last mutex is returned whether
6761                      * a task is waiting on it or not. */
6762                     xReturn = pdTRUE;
6763                 }
6764                 else
6765                 {
6766                     mtCOVERAGE_TEST_MARKER();
6767                 }
6768             }
6769             else
6770             {
6771                 mtCOVERAGE_TEST_MARKER();
6772             }
6773         }
6774         else
6775         {
6776             mtCOVERAGE_TEST_MARKER();
6777         }
6778
6779         traceRETURN_xTaskPriorityDisinherit( xReturn );
6780
6781         return xReturn;
6782     }
6783
6784 #endif /* configUSE_MUTEXES */
6785 /*-----------------------------------------------------------*/
6786
6787 #if ( configUSE_MUTEXES == 1 )
6788
6789     void vTaskPriorityDisinheritAfterTimeout( TaskHandle_t const pxMutexHolder,
6790                                               UBaseType_t uxHighestPriorityWaitingTask )
6791     {
6792         TCB_t * const pxTCB = pxMutexHolder;
6793         UBaseType_t uxPriorityUsedOnEntry, uxPriorityToUse;
6794         const UBaseType_t uxOnlyOneMutexHeld = ( UBaseType_t ) 1;
6795
6796         traceENTER_vTaskPriorityDisinheritAfterTimeout( pxMutexHolder, uxHighestPriorityWaitingTask );
6797
6798         if( pxMutexHolder != NULL )
6799         {
6800             /* If pxMutexHolder is not NULL then the holder must hold at least
6801              * one mutex. */
6802             configASSERT( pxTCB->uxMutexesHeld );
6803
6804             /* Determine the priority to which the priority of the task that
6805              * holds the mutex should be set.  This will be the greater of the
6806              * holding task's base priority and the priority of the highest
6807              * priority task that is waiting to obtain the mutex. */
6808             if( pxTCB->uxBasePriority < uxHighestPriorityWaitingTask )
6809             {
6810                 uxPriorityToUse = uxHighestPriorityWaitingTask;
6811             }
6812             else
6813             {
6814                 uxPriorityToUse = pxTCB->uxBasePriority;
6815             }
6816
6817             /* Does the priority need to change? */
6818             if( pxTCB->uxPriority != uxPriorityToUse )
6819             {
6820                 /* Only disinherit if no other mutexes are held.  This is a
6821                  * simplification in the priority inheritance implementation.  If
6822                  * the task that holds the mutex is also holding other mutexes then
6823                  * the other mutexes may have caused the priority inheritance. */
6824                 if( pxTCB->uxMutexesHeld == uxOnlyOneMutexHeld )
6825                 {
6826                     /* If a task has timed out because it already holds the
6827                      * mutex it was trying to obtain then it cannot of inherited
6828                      * its own priority. */
6829                     configASSERT( pxTCB != pxCurrentTCB );
6830
6831                     /* Disinherit the priority, remembering the previous
6832                      * priority to facilitate determining the subject task's
6833                      * state. */
6834                     traceTASK_PRIORITY_DISINHERIT( pxTCB, uxPriorityToUse );
6835                     uxPriorityUsedOnEntry = pxTCB->uxPriority;
6836                     pxTCB->uxPriority = uxPriorityToUse;
6837
6838                     /* Only reset the event list item value if the value is not
6839                      * being used for anything else. */
6840                     if( ( listGET_LIST_ITEM_VALUE( &( pxTCB->xEventListItem ) ) & taskEVENT_LIST_ITEM_VALUE_IN_USE ) == ( ( TickType_t ) 0U ) )
6841                     {
6842                         listSET_LIST_ITEM_VALUE( &( pxTCB->xEventListItem ), ( TickType_t ) configMAX_PRIORITIES - ( TickType_t ) uxPriorityToUse );
6843                     }
6844                     else
6845                     {
6846                         mtCOVERAGE_TEST_MARKER();
6847                     }
6848
6849                     /* If the running task is not the task that holds the mutex
6850                      * then the task that holds the mutex could be in either the
6851                      * Ready, Blocked or Suspended states.  Only remove the task
6852                      * from its current state list if it is in the Ready state as
6853                      * the task's priority is going to change and there is one
6854                      * Ready list per priority. */
6855                     if( listIS_CONTAINED_WITHIN( &( pxReadyTasksLists[ uxPriorityUsedOnEntry ] ), &( pxTCB->xStateListItem ) ) != pdFALSE )
6856                     {
6857                         if( uxListRemove( &( pxTCB->xStateListItem ) ) == ( UBaseType_t ) 0 )
6858                         {
6859                             /* It is known that the task is in its ready list so
6860                              * there is no need to check again and the port level
6861                              * reset macro can be called directly. */
6862                             portRESET_READY_PRIORITY( pxTCB->uxPriority, uxTopReadyPriority );
6863                         }
6864                         else
6865                         {
6866                             mtCOVERAGE_TEST_MARKER();
6867                         }
6868
6869                         prvAddTaskToReadyList( pxTCB );
6870                         #if ( configNUMBER_OF_CORES > 1 )
6871                         {
6872                             /* The priority of the task is dropped. Yield the core on
6873                              * which the task is running. */
6874                             if( taskTASK_IS_RUNNING( pxTCB ) == pdTRUE )
6875                             {
6876                                 prvYieldCore( pxTCB->xTaskRunState );
6877                             }
6878                         }
6879                         #endif /* if ( configNUMBER_OF_CORES > 1 ) */
6880                     }
6881                     else
6882                     {
6883                         mtCOVERAGE_TEST_MARKER();
6884                     }
6885                 }
6886                 else
6887                 {
6888                     mtCOVERAGE_TEST_MARKER();
6889                 }
6890             }
6891             else
6892             {
6893                 mtCOVERAGE_TEST_MARKER();
6894             }
6895         }
6896         else
6897         {
6898             mtCOVERAGE_TEST_MARKER();
6899         }
6900
6901         traceRETURN_vTaskPriorityDisinheritAfterTimeout();
6902     }
6903
6904 #endif /* configUSE_MUTEXES */
6905 /*-----------------------------------------------------------*/
6906
6907 #if ( configNUMBER_OF_CORES > 1 )
6908
6909 /* If not in a critical section then yield immediately.
6910  * Otherwise set xYieldPendings to true to wait to
6911  * yield until exiting the critical section.
6912  */
6913     void vTaskYieldWithinAPI( void )
6914     {
6915         traceENTER_vTaskYieldWithinAPI();
6916
6917         if( portGET_CRITICAL_NESTING_COUNT() == 0U )
6918         {
6919             portYIELD();
6920         }
6921         else
6922         {
6923             xYieldPendings[ portGET_CORE_ID() ] = pdTRUE;
6924         }
6925
6926         traceRETURN_vTaskYieldWithinAPI();
6927     }
6928 #endif /* #if ( configNUMBER_OF_CORES > 1 ) */
6929
6930 /*-----------------------------------------------------------*/
6931
6932 #if ( ( portCRITICAL_NESTING_IN_TCB == 1 ) && ( configNUMBER_OF_CORES == 1 ) )
6933
6934     void vTaskEnterCritical( void )
6935     {
6936         traceENTER_vTaskEnterCritical();
6937
6938         portDISABLE_INTERRUPTS();
6939
6940         if( xSchedulerRunning != pdFALSE )
6941         {
6942             ( pxCurrentTCB->uxCriticalNesting )++;
6943
6944             /* This is not the interrupt safe version of the enter critical
6945              * function so  assert() if it is being called from an interrupt
6946              * context.  Only API functions that end in "FromISR" can be used in an
6947              * interrupt.  Only assert if the critical nesting count is 1 to
6948              * protect against recursive calls if the assert function also uses a
6949              * critical section. */
6950             if( pxCurrentTCB->uxCriticalNesting == 1U )
6951             {
6952                 portASSERT_IF_IN_ISR();
6953             }
6954         }
6955         else
6956         {
6957             mtCOVERAGE_TEST_MARKER();
6958         }
6959
6960         traceRETURN_vTaskEnterCritical();
6961     }
6962
6963 #endif /* #if ( ( portCRITICAL_NESTING_IN_TCB == 1 ) && ( configNUMBER_OF_CORES == 1 ) ) */
6964 /*-----------------------------------------------------------*/
6965
6966 #if ( configNUMBER_OF_CORES > 1 )
6967
6968     void vTaskEnterCritical( void )
6969     {
6970         traceENTER_vTaskEnterCritical();
6971
6972         portDISABLE_INTERRUPTS();
6973
6974         if( xSchedulerRunning != pdFALSE )
6975         {
6976             if( portGET_CRITICAL_NESTING_COUNT() == 0U )
6977             {
6978                 portGET_TASK_LOCK();
6979                 portGET_ISR_LOCK();
6980             }
6981
6982             portINCREMENT_CRITICAL_NESTING_COUNT();
6983
6984             /* This is not the interrupt safe version of the enter critical
6985              * function so  assert() if it is being called from an interrupt
6986              * context.  Only API functions that end in "FromISR" can be used in an
6987              * interrupt.  Only assert if the critical nesting count is 1 to
6988              * protect against recursive calls if the assert function also uses a
6989              * critical section. */
6990             if( portGET_CRITICAL_NESTING_COUNT() == 1U )
6991             {
6992                 portASSERT_IF_IN_ISR();
6993
6994                 if( uxSchedulerSuspended == 0U )
6995                 {
6996                     /* The only time there would be a problem is if this is called
6997                      * before a context switch and vTaskExitCritical() is called
6998                      * after pxCurrentTCB changes. Therefore this should not be
6999                      * used within vTaskSwitchContext(). */
7000                     prvCheckForRunStateChange();
7001                 }
7002             }
7003         }
7004         else
7005         {
7006             mtCOVERAGE_TEST_MARKER();
7007         }
7008
7009         traceRETURN_vTaskEnterCritical();
7010     }
7011
7012 #endif /* #if ( configNUMBER_OF_CORES > 1 ) */
7013
7014 /*-----------------------------------------------------------*/
7015
7016 #if ( configNUMBER_OF_CORES > 1 )
7017
7018     UBaseType_t vTaskEnterCriticalFromISR( void )
7019     {
7020         UBaseType_t uxSavedInterruptStatus = 0;
7021
7022         traceENTER_vTaskEnterCriticalFromISR();
7023
7024         if( xSchedulerRunning != pdFALSE )
7025         {
7026             uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR();
7027
7028             if( portGET_CRITICAL_NESTING_COUNT() == 0U )
7029             {
7030                 portGET_ISR_LOCK();
7031             }
7032
7033             portINCREMENT_CRITICAL_NESTING_COUNT();
7034         }
7035         else
7036         {
7037             mtCOVERAGE_TEST_MARKER();
7038         }
7039
7040         traceRETURN_vTaskEnterCriticalFromISR( uxSavedInterruptStatus );
7041
7042         return uxSavedInterruptStatus;
7043     }
7044
7045 #endif /* #if ( configNUMBER_OF_CORES > 1 ) */
7046 /*-----------------------------------------------------------*/
7047
7048 #if ( ( portCRITICAL_NESTING_IN_TCB == 1 ) && ( configNUMBER_OF_CORES == 1 ) )
7049
7050     void vTaskExitCritical( void )
7051     {
7052         traceENTER_vTaskExitCritical();
7053
7054         if( xSchedulerRunning != pdFALSE )
7055         {
7056             /* If pxCurrentTCB->uxCriticalNesting is zero then this function
7057              * does not match a previous call to vTaskEnterCritical(). */
7058             configASSERT( pxCurrentTCB->uxCriticalNesting > 0U );
7059
7060             /* This function should not be called in ISR. Use vTaskExitCriticalFromISR
7061              * to exit critical section from ISR. */
7062             portASSERT_IF_IN_ISR();
7063
7064             if( pxCurrentTCB->uxCriticalNesting > 0U )
7065             {
7066                 ( pxCurrentTCB->uxCriticalNesting )--;
7067
7068                 if( pxCurrentTCB->uxCriticalNesting == 0U )
7069                 {
7070                     portENABLE_INTERRUPTS();
7071                 }
7072                 else
7073                 {
7074                     mtCOVERAGE_TEST_MARKER();
7075                 }
7076             }
7077             else
7078             {
7079                 mtCOVERAGE_TEST_MARKER();
7080             }
7081         }
7082         else
7083         {
7084             mtCOVERAGE_TEST_MARKER();
7085         }
7086
7087         traceRETURN_vTaskExitCritical();
7088     }
7089
7090 #endif /* #if ( ( portCRITICAL_NESTING_IN_TCB == 1 ) && ( configNUMBER_OF_CORES == 1 ) ) */
7091 /*-----------------------------------------------------------*/
7092
7093 #if ( configNUMBER_OF_CORES > 1 )
7094
7095     void vTaskExitCritical( void )
7096     {
7097         traceENTER_vTaskExitCritical();
7098
7099         if( xSchedulerRunning != pdFALSE )
7100         {
7101             /* If critical nesting count is zero then this function
7102              * does not match a previous call to vTaskEnterCritical(). */
7103             configASSERT( portGET_CRITICAL_NESTING_COUNT() > 0U );
7104
7105             /* This function should not be called in ISR. Use vTaskExitCriticalFromISR
7106              * to exit critical section from ISR. */
7107             portASSERT_IF_IN_ISR();
7108
7109             if( portGET_CRITICAL_NESTING_COUNT() > 0U )
7110             {
7111                 portDECREMENT_CRITICAL_NESTING_COUNT();
7112
7113                 if( portGET_CRITICAL_NESTING_COUNT() == 0U )
7114                 {
7115                     BaseType_t xYieldCurrentTask;
7116
7117                     /* Get the xYieldPending stats inside the critical section. */
7118                     xYieldCurrentTask = xYieldPendings[ portGET_CORE_ID() ];
7119
7120                     portRELEASE_ISR_LOCK();
7121                     portRELEASE_TASK_LOCK();
7122                     portENABLE_INTERRUPTS();
7123
7124                     /* When a task yields in a critical section it just sets
7125                      * xYieldPending to true. So now that we have exited the
7126                      * critical section check if xYieldPending is true, and
7127                      * if so yield. */
7128                     if( xYieldCurrentTask != pdFALSE )
7129                     {
7130                         portYIELD();
7131                     }
7132                 }
7133                 else
7134                 {
7135                     mtCOVERAGE_TEST_MARKER();
7136                 }
7137             }
7138             else
7139             {
7140                 mtCOVERAGE_TEST_MARKER();
7141             }
7142         }
7143         else
7144         {
7145             mtCOVERAGE_TEST_MARKER();
7146         }
7147
7148         traceRETURN_vTaskExitCritical();
7149     }
7150
7151 #endif /* #if ( configNUMBER_OF_CORES > 1 ) */
7152 /*-----------------------------------------------------------*/
7153
7154 #if ( configNUMBER_OF_CORES > 1 )
7155
7156     void vTaskExitCriticalFromISR( UBaseType_t uxSavedInterruptStatus )
7157     {
7158         traceENTER_vTaskExitCriticalFromISR( uxSavedInterruptStatus );
7159
7160         if( xSchedulerRunning != pdFALSE )
7161         {
7162             /* If critical nesting count is zero then this function
7163              * does not match a previous call to vTaskEnterCritical(). */
7164             configASSERT( portGET_CRITICAL_NESTING_COUNT() > 0U );
7165
7166             if( portGET_CRITICAL_NESTING_COUNT() > 0U )
7167             {
7168                 portDECREMENT_CRITICAL_NESTING_COUNT();
7169
7170                 if( portGET_CRITICAL_NESTING_COUNT() == 0U )
7171                 {
7172                     portRELEASE_ISR_LOCK();
7173                     portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus );
7174                 }
7175                 else
7176                 {
7177                     mtCOVERAGE_TEST_MARKER();
7178                 }
7179             }
7180             else
7181             {
7182                 mtCOVERAGE_TEST_MARKER();
7183             }
7184         }
7185         else
7186         {
7187             mtCOVERAGE_TEST_MARKER();
7188         }
7189
7190         traceRETURN_vTaskExitCriticalFromISR();
7191     }
7192
7193 #endif /* #if ( configNUMBER_OF_CORES > 1 ) */
7194 /*-----------------------------------------------------------*/
7195
7196 #if ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 )
7197
7198     static char * prvWriteNameToBuffer( char * pcBuffer,
7199                                         const char * pcTaskName )
7200     {
7201         size_t x;
7202
7203         /* Start by copying the entire string. */
7204         ( void ) strcpy( pcBuffer, pcTaskName );
7205
7206         /* Pad the end of the string with spaces to ensure columns line up when
7207          * printed out. */
7208         for( x = strlen( pcBuffer ); x < ( size_t ) ( ( size_t ) configMAX_TASK_NAME_LEN - 1U ); x++ )
7209         {
7210             pcBuffer[ x ] = ' ';
7211         }
7212
7213         /* Terminate. */
7214         pcBuffer[ x ] = ( char ) 0x00;
7215
7216         /* Return the new end of string. */
7217         return &( pcBuffer[ x ] );
7218     }
7219
7220 #endif /* ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 ) */
7221 /*-----------------------------------------------------------*/
7222
7223 #if ( ( configUSE_TRACE_FACILITY == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 ) )
7224
7225     void vTaskListTasks( char * pcWriteBuffer,
7226                          size_t uxBufferLength )
7227     {
7228         TaskStatus_t * pxTaskStatusArray;
7229         size_t uxConsumedBufferLength = 0;
7230         size_t uxCharsWrittenBySnprintf;
7231         int iSnprintfReturnValue;
7232         BaseType_t xOutputBufferFull = pdFALSE;
7233         UBaseType_t uxArraySize, x;
7234         char cStatus;
7235
7236         traceENTER_vTaskListTasks( pcWriteBuffer, uxBufferLength );
7237
7238         /*
7239          * PLEASE NOTE:
7240          *
7241          * This function is provided for convenience only, and is used by many
7242          * of the demo applications.  Do not consider it to be part of the
7243          * scheduler.
7244          *
7245          * vTaskListTasks() calls uxTaskGetSystemState(), then formats part of the
7246          * uxTaskGetSystemState() output into a human readable table that
7247          * displays task: names, states, priority, stack usage and task number.
7248          * Stack usage specified as the number of unused StackType_t words stack can hold
7249          * on top of stack - not the number of bytes.
7250          *
7251          * vTaskListTasks() has a dependency on the snprintf() C library function that
7252          * might bloat the code size, use a lot of stack, and provide different
7253          * results on different platforms.  An alternative, tiny, third party,
7254          * and limited functionality implementation of snprintf() is provided in
7255          * many of the FreeRTOS/Demo sub-directories in a file called
7256          * printf-stdarg.c (note printf-stdarg.c does not provide a full
7257          * snprintf() implementation!).
7258          *
7259          * It is recommended that production systems call uxTaskGetSystemState()
7260          * directly to get access to raw stats data, rather than indirectly
7261          * through a call to vTaskListTasks().
7262          */
7263
7264
7265         /* Make sure the write buffer does not contain a string. */
7266         *pcWriteBuffer = ( char ) 0x00;
7267
7268         /* Take a snapshot of the number of tasks in case it changes while this
7269          * function is executing. */
7270         uxArraySize = uxCurrentNumberOfTasks;
7271
7272         /* Allocate an array index for each task.  NOTE!  if
7273          * configSUPPORT_DYNAMIC_ALLOCATION is set to 0 then pvPortMalloc() will
7274          * equate to NULL. */
7275         /* MISRA Ref 11.5.1 [Malloc memory assignment] */
7276         /* More details at: https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/MISRA.md#rule-115 */
7277         /* coverity[misra_c_2012_rule_11_5_violation] */
7278         pxTaskStatusArray = pvPortMalloc( uxCurrentNumberOfTasks * sizeof( TaskStatus_t ) );
7279
7280         if( pxTaskStatusArray != NULL )
7281         {
7282             /* Generate the (binary) data. */
7283             uxArraySize = uxTaskGetSystemState( pxTaskStatusArray, uxArraySize, NULL );
7284
7285             /* Create a human readable table from the binary data. */
7286             for( x = 0; x < uxArraySize; x++ )
7287             {
7288                 switch( pxTaskStatusArray[ x ].eCurrentState )
7289                 {
7290                     case eRunning:
7291                         cStatus = tskRUNNING_CHAR;
7292                         break;
7293
7294                     case eReady:
7295                         cStatus = tskREADY_CHAR;
7296                         break;
7297
7298                     case eBlocked:
7299                         cStatus = tskBLOCKED_CHAR;
7300                         break;
7301
7302                     case eSuspended:
7303                         cStatus = tskSUSPENDED_CHAR;
7304                         break;
7305
7306                     case eDeleted:
7307                         cStatus = tskDELETED_CHAR;
7308                         break;
7309
7310                     case eInvalid: /* Fall through. */
7311                     default:       /* Should not get here, but it is included
7312                                     * to prevent static checking errors. */
7313                         cStatus = ( char ) 0x00;
7314                         break;
7315                 }
7316
7317                 /* Is there enough space in the buffer to hold task name? */
7318                 if( ( uxConsumedBufferLength + configMAX_TASK_NAME_LEN ) <= uxBufferLength )
7319                 {
7320                     /* Write the task name to the string, padding with spaces so it
7321                      * can be printed in tabular form more easily. */
7322                     pcWriteBuffer = prvWriteNameToBuffer( pcWriteBuffer, pxTaskStatusArray[ x ].pcTaskName );
7323                     /* Do not count the terminating null character. */
7324                     uxConsumedBufferLength = uxConsumedBufferLength + ( configMAX_TASK_NAME_LEN - 1U );
7325
7326                     /* Is there space left in the buffer? -1 is done because snprintf
7327                      * writes a terminating null character. So we are essentially
7328                      * checking if the buffer has space to write at least one non-null
7329                      * character. */
7330                     if( uxConsumedBufferLength < ( uxBufferLength - 1U ) )
7331                     {
7332                         /* Write the rest of the string. */
7333                         #if ( ( configUSE_CORE_AFFINITY == 1 ) && ( configNUMBER_OF_CORES > 1 ) )
7334                             /* MISRA Ref 21.6.1 [snprintf for utility] */
7335                             /* More details at: https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/MISRA.md#rule-216 */
7336                             /* coverity[misra_c_2012_rule_21_6_violation] */
7337                             iSnprintfReturnValue = snprintf( pcWriteBuffer,
7338                                                              uxBufferLength - uxConsumedBufferLength,
7339                                                              "\t%c\t%u\t%u\t%u\t0x%x\r\n",
7340                                                              cStatus,
7341                                                              ( unsigned int ) pxTaskStatusArray[ x ].uxCurrentPriority,
7342                                                              ( unsigned int ) pxTaskStatusArray[ x ].usStackHighWaterMark,
7343                                                              ( unsigned int ) pxTaskStatusArray[ x ].xTaskNumber,
7344                                                              ( unsigned int ) pxTaskStatusArray[ x ].uxCoreAffinityMask );
7345                         #else /* ( ( configUSE_CORE_AFFINITY == 1 ) && ( configNUMBER_OF_CORES > 1 ) ) */
7346                             /* MISRA Ref 21.6.1 [snprintf for utility] */
7347                             /* More details at: https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/MISRA.md#rule-216 */
7348                             /* coverity[misra_c_2012_rule_21_6_violation] */
7349                             iSnprintfReturnValue = snprintf( pcWriteBuffer,
7350                                                              uxBufferLength - uxConsumedBufferLength,
7351                                                              "\t%c\t%u\t%u\t%u\r\n",
7352                                                              cStatus,
7353                                                              ( unsigned int ) pxTaskStatusArray[ x ].uxCurrentPriority,
7354                                                              ( unsigned int ) pxTaskStatusArray[ x ].usStackHighWaterMark,
7355                                                              ( unsigned int ) pxTaskStatusArray[ x ].xTaskNumber );
7356                         #endif /* ( ( configUSE_CORE_AFFINITY == 1 ) && ( configNUMBER_OF_CORES > 1 ) ) */
7357                         uxCharsWrittenBySnprintf = prvSnprintfReturnValueToCharsWritten( iSnprintfReturnValue, uxBufferLength - uxConsumedBufferLength );
7358
7359                         uxConsumedBufferLength += uxCharsWrittenBySnprintf;
7360                         pcWriteBuffer += uxCharsWrittenBySnprintf;
7361                     }
7362                     else
7363                     {
7364                         xOutputBufferFull = pdTRUE;
7365                     }
7366                 }
7367                 else
7368                 {
7369                     xOutputBufferFull = pdTRUE;
7370                 }
7371
7372                 if( xOutputBufferFull == pdTRUE )
7373                 {
7374                     break;
7375                 }
7376             }
7377
7378             /* Free the array again.  NOTE!  If configSUPPORT_DYNAMIC_ALLOCATION
7379              * is 0 then vPortFree() will be #defined to nothing. */
7380             vPortFree( pxTaskStatusArray );
7381         }
7382         else
7383         {
7384             mtCOVERAGE_TEST_MARKER();
7385         }
7386
7387         traceRETURN_vTaskListTasks();
7388     }
7389
7390 #endif /* ( ( configUSE_TRACE_FACILITY == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 ) ) */
7391 /*----------------------------------------------------------*/
7392
7393 #if ( ( configGENERATE_RUN_TIME_STATS == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 ) && ( configUSE_TRACE_FACILITY == 1 ) )
7394
7395     void vTaskGetRunTimeStatistics( char * pcWriteBuffer,
7396                                     size_t uxBufferLength )
7397     {
7398         TaskStatus_t * pxTaskStatusArray;
7399         size_t uxConsumedBufferLength = 0;
7400         size_t uxCharsWrittenBySnprintf;
7401         int iSnprintfReturnValue;
7402         BaseType_t xOutputBufferFull = pdFALSE;
7403         UBaseType_t uxArraySize, x;
7404         configRUN_TIME_COUNTER_TYPE ulTotalTime = 0;
7405         configRUN_TIME_COUNTER_TYPE ulStatsAsPercentage;
7406
7407         traceENTER_vTaskGetRunTimeStatistics( pcWriteBuffer, uxBufferLength );
7408
7409         /*
7410          * PLEASE NOTE:
7411          *
7412          * This function is provided for convenience only, and is used by many
7413          * of the demo applications.  Do not consider it to be part of the
7414          * scheduler.
7415          *
7416          * vTaskGetRunTimeStatistics() calls uxTaskGetSystemState(), then formats part
7417          * of the uxTaskGetSystemState() output into a human readable table that
7418          * displays the amount of time each task has spent in the Running state
7419          * in both absolute and percentage terms.
7420          *
7421          * vTaskGetRunTimeStatistics() has a dependency on the snprintf() C library
7422          * function that might bloat the code size, use a lot of stack, and
7423          * provide different results on different platforms.  An alternative,
7424          * tiny, third party, and limited functionality implementation of
7425          * snprintf() is provided in many of the FreeRTOS/Demo sub-directories in
7426          * a file called printf-stdarg.c (note printf-stdarg.c does not provide
7427          * a full snprintf() implementation!).
7428          *
7429          * It is recommended that production systems call uxTaskGetSystemState()
7430          * directly to get access to raw stats data, rather than indirectly
7431          * through a call to vTaskGetRunTimeStatistics().
7432          */
7433
7434         /* Make sure the write buffer does not contain a string. */
7435         *pcWriteBuffer = ( char ) 0x00;
7436
7437         /* Take a snapshot of the number of tasks in case it changes while this
7438          * function is executing. */
7439         uxArraySize = uxCurrentNumberOfTasks;
7440
7441         /* Allocate an array index for each task.  NOTE!  If
7442          * configSUPPORT_DYNAMIC_ALLOCATION is set to 0 then pvPortMalloc() will
7443          * equate to NULL. */
7444         /* MISRA Ref 11.5.1 [Malloc memory assignment] */
7445         /* More details at: https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/MISRA.md#rule-115 */
7446         /* coverity[misra_c_2012_rule_11_5_violation] */
7447         pxTaskStatusArray = pvPortMalloc( uxCurrentNumberOfTasks * sizeof( TaskStatus_t ) );
7448
7449         if( pxTaskStatusArray != NULL )
7450         {
7451             /* Generate the (binary) data. */
7452             uxArraySize = uxTaskGetSystemState( pxTaskStatusArray, uxArraySize, &ulTotalTime );
7453
7454             /* For percentage calculations. */
7455             ulTotalTime /= ( ( configRUN_TIME_COUNTER_TYPE ) 100U );
7456
7457             /* Avoid divide by zero errors. */
7458             if( ulTotalTime > 0U )
7459             {
7460                 /* Create a human readable table from the binary data. */
7461                 for( x = 0; x < uxArraySize; x++ )
7462                 {
7463                     /* What percentage of the total run time has the task used?
7464                      * This will always be rounded down to the nearest integer.
7465                      * ulTotalRunTime has already been divided by 100. */
7466                     ulStatsAsPercentage = pxTaskStatusArray[ x ].ulRunTimeCounter / ulTotalTime;
7467
7468                     /* Is there enough space in the buffer to hold task name? */
7469                     if( ( uxConsumedBufferLength + configMAX_TASK_NAME_LEN ) <= uxBufferLength )
7470                     {
7471                         /* Write the task name to the string, padding with
7472                          * spaces so it can be printed in tabular form more
7473                          * easily. */
7474                         pcWriteBuffer = prvWriteNameToBuffer( pcWriteBuffer, pxTaskStatusArray[ x ].pcTaskName );
7475                         /* Do not count the terminating null character. */
7476                         uxConsumedBufferLength = uxConsumedBufferLength + ( configMAX_TASK_NAME_LEN - 1U );
7477
7478                         /* Is there space left in the buffer? -1 is done because snprintf
7479                          * writes a terminating null character. So we are essentially
7480                          * checking if the buffer has space to write at least one non-null
7481                          * character. */
7482                         if( uxConsumedBufferLength < ( uxBufferLength - 1U ) )
7483                         {
7484                             if( ulStatsAsPercentage > 0U )
7485                             {
7486                                 #ifdef portLU_PRINTF_SPECIFIER_REQUIRED
7487                                 {
7488                                     /* MISRA Ref 21.6.1 [snprintf for utility] */
7489                                     /* More details at: https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/MISRA.md#rule-216 */
7490                                     /* coverity[misra_c_2012_rule_21_6_violation] */
7491                                     iSnprintfReturnValue = snprintf( pcWriteBuffer,
7492                                                                      uxBufferLength - uxConsumedBufferLength,
7493                                                                      "\t%lu\t\t%lu%%\r\n",
7494                                                                      pxTaskStatusArray[ x ].ulRunTimeCounter,
7495                                                                      ulStatsAsPercentage );
7496                                 }
7497                                 #else /* ifdef portLU_PRINTF_SPECIFIER_REQUIRED */
7498                                 {
7499                                     /* sizeof( int ) == sizeof( long ) so a smaller
7500                                      * printf() library can be used. */
7501                                     /* MISRA Ref 21.6.1 [snprintf for utility] */
7502                                     /* More details at: https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/MISRA.md#rule-216 */
7503                                     /* coverity[misra_c_2012_rule_21_6_violation] */
7504                                     iSnprintfReturnValue = snprintf( pcWriteBuffer,
7505                                                                      uxBufferLength - uxConsumedBufferLength,
7506                                                                      "\t%u\t\t%u%%\r\n",
7507                                                                      ( unsigned int ) pxTaskStatusArray[ x ].ulRunTimeCounter,
7508                                                                      ( unsigned int ) ulStatsAsPercentage );
7509                                 }
7510                                 #endif /* ifdef portLU_PRINTF_SPECIFIER_REQUIRED */
7511                             }
7512                             else
7513                             {
7514                                 /* If the percentage is zero here then the task has
7515                                  * consumed less than 1% of the total run time. */
7516                                 #ifdef portLU_PRINTF_SPECIFIER_REQUIRED
7517                                 {
7518                                     /* MISRA Ref 21.6.1 [snprintf for utility] */
7519                                     /* More details at: https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/MISRA.md#rule-216 */
7520                                     /* coverity[misra_c_2012_rule_21_6_violation] */
7521                                     iSnprintfReturnValue = snprintf( pcWriteBuffer,
7522                                                                      uxBufferLength - uxConsumedBufferLength,
7523                                                                      "\t%lu\t\t<1%%\r\n",
7524                                                                      pxTaskStatusArray[ x ].ulRunTimeCounter );
7525                                 }
7526                                 #else
7527                                 {
7528                                     /* sizeof( int ) == sizeof( long ) so a smaller
7529                                      * printf() library can be used. */
7530                                     /* MISRA Ref 21.6.1 [snprintf for utility] */
7531                                     /* More details at: https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/MISRA.md#rule-216 */
7532                                     /* coverity[misra_c_2012_rule_21_6_violation] */
7533                                     iSnprintfReturnValue = snprintf( pcWriteBuffer,
7534                                                                      uxBufferLength - uxConsumedBufferLength,
7535                                                                      "\t%u\t\t<1%%\r\n",
7536                                                                      ( unsigned int ) pxTaskStatusArray[ x ].ulRunTimeCounter );
7537                                 }
7538                                 #endif /* ifdef portLU_PRINTF_SPECIFIER_REQUIRED */
7539                             }
7540
7541                             uxCharsWrittenBySnprintf = prvSnprintfReturnValueToCharsWritten( iSnprintfReturnValue, uxBufferLength - uxConsumedBufferLength );
7542                             uxConsumedBufferLength += uxCharsWrittenBySnprintf;
7543                             pcWriteBuffer += uxCharsWrittenBySnprintf;
7544                         }
7545                         else
7546                         {
7547                             xOutputBufferFull = pdTRUE;
7548                         }
7549                     }
7550                     else
7551                     {
7552                         xOutputBufferFull = pdTRUE;
7553                     }
7554
7555                     if( xOutputBufferFull == pdTRUE )
7556                     {
7557                         break;
7558                     }
7559                 }
7560             }
7561             else
7562             {
7563                 mtCOVERAGE_TEST_MARKER();
7564             }
7565
7566             /* Free the array again.  NOTE!  If configSUPPORT_DYNAMIC_ALLOCATION
7567              * is 0 then vPortFree() will be #defined to nothing. */
7568             vPortFree( pxTaskStatusArray );
7569         }
7570         else
7571         {
7572             mtCOVERAGE_TEST_MARKER();
7573         }
7574
7575         traceRETURN_vTaskGetRunTimeStatistics();
7576     }
7577
7578 #endif /* ( ( configGENERATE_RUN_TIME_STATS == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 ) ) */
7579 /*-----------------------------------------------------------*/
7580
7581 TickType_t uxTaskResetEventItemValue( void )
7582 {
7583     TickType_t uxReturn;
7584
7585     traceENTER_uxTaskResetEventItemValue();
7586
7587     uxReturn = listGET_LIST_ITEM_VALUE( &( pxCurrentTCB->xEventListItem ) );
7588
7589     /* Reset the event list item to its normal value - so it can be used with
7590      * queues and semaphores. */
7591     listSET_LIST_ITEM_VALUE( &( pxCurrentTCB->xEventListItem ), ( ( TickType_t ) configMAX_PRIORITIES - ( TickType_t ) pxCurrentTCB->uxPriority ) );
7592
7593     traceRETURN_uxTaskResetEventItemValue( uxReturn );
7594
7595     return uxReturn;
7596 }
7597 /*-----------------------------------------------------------*/
7598
7599 #if ( configUSE_MUTEXES == 1 )
7600
7601     TaskHandle_t pvTaskIncrementMutexHeldCount( void )
7602     {
7603         TCB_t * pxTCB;
7604
7605         traceENTER_pvTaskIncrementMutexHeldCount();
7606
7607         pxTCB = pxCurrentTCB;
7608
7609         /* If xSemaphoreCreateMutex() is called before any tasks have been created
7610          * then pxCurrentTCB will be NULL. */
7611         if( pxTCB != NULL )
7612         {
7613             ( pxTCB->uxMutexesHeld )++;
7614         }
7615
7616         traceRETURN_pvTaskIncrementMutexHeldCount( pxTCB );
7617
7618         return pxTCB;
7619     }
7620
7621 #endif /* configUSE_MUTEXES */
7622 /*-----------------------------------------------------------*/
7623
7624 #if ( configUSE_TASK_NOTIFICATIONS == 1 )
7625
7626     uint32_t ulTaskGenericNotifyTake( UBaseType_t uxIndexToWaitOn,
7627                                       BaseType_t xClearCountOnExit,
7628                                       TickType_t xTicksToWait )
7629     {
7630         uint32_t ulReturn;
7631         BaseType_t xAlreadyYielded, xShouldBlock = pdFALSE;
7632
7633         traceENTER_ulTaskGenericNotifyTake( uxIndexToWaitOn, xClearCountOnExit, xTicksToWait );
7634
7635         configASSERT( uxIndexToWaitOn < configTASK_NOTIFICATION_ARRAY_ENTRIES );
7636
7637         /* We suspend the scheduler here as prvAddCurrentTaskToDelayedList is a
7638          * non-deterministic operation. */
7639         vTaskSuspendAll();
7640         {
7641             /* We MUST enter a critical section to atomically check if a notification
7642              * has occurred and set the flag to indicate that we are waiting for
7643              * a notification. If we do not do so, a notification sent from an ISR
7644              * will get lost. */
7645             taskENTER_CRITICAL();
7646             {
7647                 /* Only block if the notification count is not already non-zero. */
7648                 if( pxCurrentTCB->ulNotifiedValue[ uxIndexToWaitOn ] == 0U )
7649                 {
7650                     /* Mark this task as waiting for a notification. */
7651                     pxCurrentTCB->ucNotifyState[ uxIndexToWaitOn ] = taskWAITING_NOTIFICATION;
7652
7653                     if( xTicksToWait > ( TickType_t ) 0 )
7654                     {
7655                         xShouldBlock = pdTRUE;
7656                     }
7657                     else
7658                     {
7659                         mtCOVERAGE_TEST_MARKER();
7660                     }
7661                 }
7662                 else
7663                 {
7664                     mtCOVERAGE_TEST_MARKER();
7665                 }
7666             }
7667             taskEXIT_CRITICAL();
7668
7669             /* We are now out of the critical section but the scheduler is still
7670              * suspended, so we are safe to do non-deterministic operations such
7671              * as prvAddCurrentTaskToDelayedList. */
7672             if( xShouldBlock == pdTRUE )
7673             {
7674                 traceTASK_NOTIFY_TAKE_BLOCK( uxIndexToWaitOn );
7675                 prvAddCurrentTaskToDelayedList( xTicksToWait, pdTRUE );
7676             }
7677             else
7678             {
7679                 mtCOVERAGE_TEST_MARKER();
7680             }
7681         }
7682         xAlreadyYielded = xTaskResumeAll();
7683
7684         /* Force a reschedule if xTaskResumeAll has not already done so. */
7685         if( ( xShouldBlock == pdTRUE ) && ( xAlreadyYielded == pdFALSE ) )
7686         {
7687             taskYIELD_WITHIN_API();
7688         }
7689         else
7690         {
7691             mtCOVERAGE_TEST_MARKER();
7692         }
7693
7694         taskENTER_CRITICAL();
7695         {
7696             traceTASK_NOTIFY_TAKE( uxIndexToWaitOn );
7697             ulReturn = pxCurrentTCB->ulNotifiedValue[ uxIndexToWaitOn ];
7698
7699             if( ulReturn != 0U )
7700             {
7701                 if( xClearCountOnExit != pdFALSE )
7702                 {
7703                     pxCurrentTCB->ulNotifiedValue[ uxIndexToWaitOn ] = ( uint32_t ) 0U;
7704                 }
7705                 else
7706                 {
7707                     pxCurrentTCB->ulNotifiedValue[ uxIndexToWaitOn ] = ulReturn - ( uint32_t ) 1;
7708                 }
7709             }
7710             else
7711             {
7712                 mtCOVERAGE_TEST_MARKER();
7713             }
7714
7715             pxCurrentTCB->ucNotifyState[ uxIndexToWaitOn ] = taskNOT_WAITING_NOTIFICATION;
7716         }
7717         taskEXIT_CRITICAL();
7718
7719         traceRETURN_ulTaskGenericNotifyTake( ulReturn );
7720
7721         return ulReturn;
7722     }
7723
7724 #endif /* configUSE_TASK_NOTIFICATIONS */
7725 /*-----------------------------------------------------------*/
7726
7727 #if ( configUSE_TASK_NOTIFICATIONS == 1 )
7728
7729     BaseType_t xTaskGenericNotifyWait( UBaseType_t uxIndexToWaitOn,
7730                                        uint32_t ulBitsToClearOnEntry,
7731                                        uint32_t ulBitsToClearOnExit,
7732                                        uint32_t * pulNotificationValue,
7733                                        TickType_t xTicksToWait )
7734     {
7735         BaseType_t xReturn, xAlreadyYielded, xShouldBlock = pdFALSE;
7736
7737         traceENTER_xTaskGenericNotifyWait( uxIndexToWaitOn, ulBitsToClearOnEntry, ulBitsToClearOnExit, pulNotificationValue, xTicksToWait );
7738
7739         configASSERT( uxIndexToWaitOn < configTASK_NOTIFICATION_ARRAY_ENTRIES );
7740
7741         /* We suspend the scheduler here as prvAddCurrentTaskToDelayedList is a
7742          * non-deterministic operation. */
7743         vTaskSuspendAll();
7744         {
7745             /* We MUST enter a critical section to atomically check and update the
7746              * task notification value. If we do not do so, a notification from
7747              * an ISR will get lost. */
7748             taskENTER_CRITICAL();
7749             {
7750                 /* Only block if a notification is not already pending. */
7751                 if( pxCurrentTCB->ucNotifyState[ uxIndexToWaitOn ] != taskNOTIFICATION_RECEIVED )
7752                 {
7753                     /* Clear bits in the task's notification value as bits may get
7754                      * set by the notifying task or interrupt. This can be used
7755                      * to clear the value to zero. */
7756                     pxCurrentTCB->ulNotifiedValue[ uxIndexToWaitOn ] &= ~ulBitsToClearOnEntry;
7757
7758                     /* Mark this task as waiting for a notification. */
7759                     pxCurrentTCB->ucNotifyState[ uxIndexToWaitOn ] = taskWAITING_NOTIFICATION;
7760
7761                     if( xTicksToWait > ( TickType_t ) 0 )
7762                     {
7763                         xShouldBlock = pdTRUE;
7764                     }
7765                     else
7766                     {
7767                         mtCOVERAGE_TEST_MARKER();
7768                     }
7769                 }
7770                 else
7771                 {
7772                     mtCOVERAGE_TEST_MARKER();
7773                 }
7774             }
7775             taskEXIT_CRITICAL();
7776
7777             /* We are now out of the critical section but the scheduler is still
7778              * suspended, so we are safe to do non-deterministic operations such
7779              * as prvAddCurrentTaskToDelayedList. */
7780             if( xShouldBlock == pdTRUE )
7781             {
7782                 traceTASK_NOTIFY_WAIT_BLOCK( uxIndexToWaitOn );
7783                 prvAddCurrentTaskToDelayedList( xTicksToWait, pdTRUE );
7784             }
7785             else
7786             {
7787                 mtCOVERAGE_TEST_MARKER();
7788             }
7789         }
7790         xAlreadyYielded = xTaskResumeAll();
7791
7792         /* Force a reschedule if xTaskResumeAll has not already done so. */
7793         if( ( xShouldBlock == pdTRUE ) && ( xAlreadyYielded == pdFALSE ) )
7794         {
7795             taskYIELD_WITHIN_API();
7796         }
7797         else
7798         {
7799             mtCOVERAGE_TEST_MARKER();
7800         }
7801
7802         taskENTER_CRITICAL();
7803         {
7804             traceTASK_NOTIFY_WAIT( uxIndexToWaitOn );
7805
7806             if( pulNotificationValue != NULL )
7807             {
7808                 /* Output the current notification value, which may or may not
7809                  * have changed. */
7810                 *pulNotificationValue = pxCurrentTCB->ulNotifiedValue[ uxIndexToWaitOn ];
7811             }
7812
7813             /* If ucNotifyValue is set then either the task never entered the
7814              * blocked state (because a notification was already pending) or the
7815              * task unblocked because of a notification.  Otherwise the task
7816              * unblocked because of a timeout. */
7817             if( pxCurrentTCB->ucNotifyState[ uxIndexToWaitOn ] != taskNOTIFICATION_RECEIVED )
7818             {
7819                 /* A notification was not received. */
7820                 xReturn = pdFALSE;
7821             }
7822             else
7823             {
7824                 /* A notification was already pending or a notification was
7825                  * received while the task was waiting. */
7826                 pxCurrentTCB->ulNotifiedValue[ uxIndexToWaitOn ] &= ~ulBitsToClearOnExit;
7827                 xReturn = pdTRUE;
7828             }
7829
7830             pxCurrentTCB->ucNotifyState[ uxIndexToWaitOn ] = taskNOT_WAITING_NOTIFICATION;
7831         }
7832         taskEXIT_CRITICAL();
7833
7834         traceRETURN_xTaskGenericNotifyWait( xReturn );
7835
7836         return xReturn;
7837     }
7838
7839 #endif /* configUSE_TASK_NOTIFICATIONS */
7840 /*-----------------------------------------------------------*/
7841
7842 #if ( configUSE_TASK_NOTIFICATIONS == 1 )
7843
7844     BaseType_t xTaskGenericNotify( TaskHandle_t xTaskToNotify,
7845                                    UBaseType_t uxIndexToNotify,
7846                                    uint32_t ulValue,
7847                                    eNotifyAction eAction,
7848                                    uint32_t * pulPreviousNotificationValue )
7849     {
7850         TCB_t * pxTCB;
7851         BaseType_t xReturn = pdPASS;
7852         uint8_t ucOriginalNotifyState;
7853
7854         traceENTER_xTaskGenericNotify( xTaskToNotify, uxIndexToNotify, ulValue, eAction, pulPreviousNotificationValue );
7855
7856         configASSERT( uxIndexToNotify < configTASK_NOTIFICATION_ARRAY_ENTRIES );
7857         configASSERT( xTaskToNotify );
7858         pxTCB = xTaskToNotify;
7859
7860         taskENTER_CRITICAL();
7861         {
7862             if( pulPreviousNotificationValue != NULL )
7863             {
7864                 *pulPreviousNotificationValue = pxTCB->ulNotifiedValue[ uxIndexToNotify ];
7865             }
7866
7867             ucOriginalNotifyState = pxTCB->ucNotifyState[ uxIndexToNotify ];
7868
7869             pxTCB->ucNotifyState[ uxIndexToNotify ] = taskNOTIFICATION_RECEIVED;
7870
7871             switch( eAction )
7872             {
7873                 case eSetBits:
7874                     pxTCB->ulNotifiedValue[ uxIndexToNotify ] |= ulValue;
7875                     break;
7876
7877                 case eIncrement:
7878                     ( pxTCB->ulNotifiedValue[ uxIndexToNotify ] )++;
7879                     break;
7880
7881                 case eSetValueWithOverwrite:
7882                     pxTCB->ulNotifiedValue[ uxIndexToNotify ] = ulValue;
7883                     break;
7884
7885                 case eSetValueWithoutOverwrite:
7886
7887                     if( ucOriginalNotifyState != taskNOTIFICATION_RECEIVED )
7888                     {
7889                         pxTCB->ulNotifiedValue[ uxIndexToNotify ] = ulValue;
7890                     }
7891                     else
7892                     {
7893                         /* The value could not be written to the task. */
7894                         xReturn = pdFAIL;
7895                     }
7896
7897                     break;
7898
7899                 case eNoAction:
7900
7901                     /* The task is being notified without its notify value being
7902                      * updated. */
7903                     break;
7904
7905                 default:
7906
7907                     /* Should not get here if all enums are handled.
7908                      * Artificially force an assert by testing a value the
7909                      * compiler can't assume is const. */
7910                     configASSERT( xTickCount == ( TickType_t ) 0 );
7911
7912                     break;
7913             }
7914
7915             traceTASK_NOTIFY( uxIndexToNotify );
7916
7917             /* If the task is in the blocked state specifically to wait for a
7918              * notification then unblock it now. */
7919             if( ucOriginalNotifyState == taskWAITING_NOTIFICATION )
7920             {
7921                 listREMOVE_ITEM( &( pxTCB->xStateListItem ) );
7922                 prvAddTaskToReadyList( pxTCB );
7923
7924                 /* The task should not have been on an event list. */
7925                 configASSERT( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) == NULL );
7926
7927                 #if ( configUSE_TICKLESS_IDLE != 0 )
7928                 {
7929                     /* If a task is blocked waiting for a notification then
7930                      * xNextTaskUnblockTime might be set to the blocked task's time
7931                      * out time.  If the task is unblocked for a reason other than
7932                      * a timeout xNextTaskUnblockTime is normally left unchanged,
7933                      * because it will automatically get reset to a new value when
7934                      * the tick count equals xNextTaskUnblockTime.  However if
7935                      * tickless idling is used it might be more important to enter
7936                      * sleep mode at the earliest possible time - so reset
7937                      * xNextTaskUnblockTime here to ensure it is updated at the
7938                      * earliest possible time. */
7939                     prvResetNextTaskUnblockTime();
7940                 }
7941                 #endif
7942
7943                 /* Check if the notified task has a priority above the currently
7944                  * executing task. */
7945                 taskYIELD_ANY_CORE_IF_USING_PREEMPTION( pxTCB );
7946             }
7947             else
7948             {
7949                 mtCOVERAGE_TEST_MARKER();
7950             }
7951         }
7952         taskEXIT_CRITICAL();
7953
7954         traceRETURN_xTaskGenericNotify( xReturn );
7955
7956         return xReturn;
7957     }
7958
7959 #endif /* configUSE_TASK_NOTIFICATIONS */
7960 /*-----------------------------------------------------------*/
7961
7962 #if ( configUSE_TASK_NOTIFICATIONS == 1 )
7963
7964     BaseType_t xTaskGenericNotifyFromISR( TaskHandle_t xTaskToNotify,
7965                                           UBaseType_t uxIndexToNotify,
7966                                           uint32_t ulValue,
7967                                           eNotifyAction eAction,
7968                                           uint32_t * pulPreviousNotificationValue,
7969                                           BaseType_t * pxHigherPriorityTaskWoken )
7970     {
7971         TCB_t * pxTCB;
7972         uint8_t ucOriginalNotifyState;
7973         BaseType_t xReturn = pdPASS;
7974         UBaseType_t uxSavedInterruptStatus;
7975
7976         traceENTER_xTaskGenericNotifyFromISR( xTaskToNotify, uxIndexToNotify, ulValue, eAction, pulPreviousNotificationValue, pxHigherPriorityTaskWoken );
7977
7978         configASSERT( xTaskToNotify );
7979         configASSERT( uxIndexToNotify < configTASK_NOTIFICATION_ARRAY_ENTRIES );
7980
7981         /* RTOS ports that support interrupt nesting have the concept of a
7982          * maximum  system call (or maximum API call) interrupt priority.
7983          * Interrupts that are  above the maximum system call priority are keep
7984          * permanently enabled, even when the RTOS kernel is in a critical section,
7985          * but cannot make any calls to FreeRTOS API functions.  If configASSERT()
7986          * is defined in FreeRTOSConfig.h then
7987          * portASSERT_IF_INTERRUPT_PRIORITY_INVALID() will result in an assertion
7988          * failure if a FreeRTOS API function is called from an interrupt that has
7989          * been assigned a priority above the configured maximum system call
7990          * priority.  Only FreeRTOS functions that end in FromISR can be called
7991          * from interrupts  that have been assigned a priority at or (logically)
7992          * below the maximum system call interrupt priority.  FreeRTOS maintains a
7993          * separate interrupt safe API to ensure interrupt entry is as fast and as
7994          * simple as possible.  More information (albeit Cortex-M specific) is
7995          * provided on the following link:
7996          * https://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html */
7997         portASSERT_IF_INTERRUPT_PRIORITY_INVALID();
7998
7999         pxTCB = xTaskToNotify;
8000
8001         /* MISRA Ref 4.7.1 [Return value shall be checked] */
8002         /* More details at: https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/MISRA.md#dir-47 */
8003         /* coverity[misra_c_2012_directive_4_7_violation] */
8004         uxSavedInterruptStatus = ( UBaseType_t ) taskENTER_CRITICAL_FROM_ISR();
8005         {
8006             if( pulPreviousNotificationValue != NULL )
8007             {
8008                 *pulPreviousNotificationValue = pxTCB->ulNotifiedValue[ uxIndexToNotify ];
8009             }
8010
8011             ucOriginalNotifyState = pxTCB->ucNotifyState[ uxIndexToNotify ];
8012             pxTCB->ucNotifyState[ uxIndexToNotify ] = taskNOTIFICATION_RECEIVED;
8013
8014             switch( eAction )
8015             {
8016                 case eSetBits:
8017                     pxTCB->ulNotifiedValue[ uxIndexToNotify ] |= ulValue;
8018                     break;
8019
8020                 case eIncrement:
8021                     ( pxTCB->ulNotifiedValue[ uxIndexToNotify ] )++;
8022                     break;
8023
8024                 case eSetValueWithOverwrite:
8025                     pxTCB->ulNotifiedValue[ uxIndexToNotify ] = ulValue;
8026                     break;
8027
8028                 case eSetValueWithoutOverwrite:
8029
8030                     if( ucOriginalNotifyState != taskNOTIFICATION_RECEIVED )
8031                     {
8032                         pxTCB->ulNotifiedValue[ uxIndexToNotify ] = ulValue;
8033                     }
8034                     else
8035                     {
8036                         /* The value could not be written to the task. */
8037                         xReturn = pdFAIL;
8038                     }
8039
8040                     break;
8041
8042                 case eNoAction:
8043
8044                     /* The task is being notified without its notify value being
8045                      * updated. */
8046                     break;
8047
8048                 default:
8049
8050                     /* Should not get here if all enums are handled.
8051                      * Artificially force an assert by testing a value the
8052                      * compiler can't assume is const. */
8053                     configASSERT( xTickCount == ( TickType_t ) 0 );
8054                     break;
8055             }
8056
8057             traceTASK_NOTIFY_FROM_ISR( uxIndexToNotify );
8058
8059             /* If the task is in the blocked state specifically to wait for a
8060              * notification then unblock it now. */
8061             if( ucOriginalNotifyState == taskWAITING_NOTIFICATION )
8062             {
8063                 /* The task should not have been on an event list. */
8064                 configASSERT( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) == NULL );
8065
8066                 if( uxSchedulerSuspended == ( UBaseType_t ) 0U )
8067                 {
8068                     listREMOVE_ITEM( &( pxTCB->xStateListItem ) );
8069                     prvAddTaskToReadyList( pxTCB );
8070
8071                     #if ( configUSE_TICKLESS_IDLE != 0 )
8072                     {
8073                         /* If a task is blocked waiting for a notification then
8074                          * xNextTaskUnblockTime might be set to the blocked task's time
8075                          * out time.  If the task is unblocked for a reason other than
8076                          * a timeout xNextTaskUnblockTime is normally left unchanged,
8077                          * because it will automatically get reset to a new value when
8078                          * the tick count equals xNextTaskUnblockTime.  However if
8079                          * tickless idling is used it might be more important to enter
8080                          * sleep mode at the earliest possible time - so reset
8081                          * xNextTaskUnblockTime here to ensure it is updated at the
8082                          * earliest possible time. */
8083                         prvResetNextTaskUnblockTime();
8084                     }
8085                     #endif
8086                 }
8087                 else
8088                 {
8089                     /* The delayed and ready lists cannot be accessed, so hold
8090                      * this task pending until the scheduler is resumed. */
8091                     listINSERT_END( &( xPendingReadyList ), &( pxTCB->xEventListItem ) );
8092                 }
8093
8094                 #if ( configNUMBER_OF_CORES == 1 )
8095                 {
8096                     if( pxTCB->uxPriority > pxCurrentTCB->uxPriority )
8097                     {
8098                         /* The notified task has a priority above the currently
8099                          * executing task so a yield is required. */
8100                         if( pxHigherPriorityTaskWoken != NULL )
8101                         {
8102                             *pxHigherPriorityTaskWoken = pdTRUE;
8103                         }
8104
8105                         /* Mark that a yield is pending in case the user is not
8106                          * using the "xHigherPriorityTaskWoken" parameter to an ISR
8107                          * safe FreeRTOS function. */
8108                         xYieldPendings[ 0 ] = pdTRUE;
8109                     }
8110                     else
8111                     {
8112                         mtCOVERAGE_TEST_MARKER();
8113                     }
8114                 }
8115                 #else /* #if ( configNUMBER_OF_CORES == 1 ) */
8116                 {
8117                     #if ( configUSE_PREEMPTION == 1 )
8118                     {
8119                         prvYieldForTask( pxTCB );
8120
8121                         if( xYieldPendings[ portGET_CORE_ID() ] == pdTRUE )
8122                         {
8123                             if( pxHigherPriorityTaskWoken != NULL )
8124                             {
8125                                 *pxHigherPriorityTaskWoken = pdTRUE;
8126                             }
8127                         }
8128                     }
8129                     #endif /* if ( configUSE_PREEMPTION == 1 ) */
8130                 }
8131                 #endif /* #if ( configNUMBER_OF_CORES == 1 ) */
8132             }
8133         }
8134         taskEXIT_CRITICAL_FROM_ISR( uxSavedInterruptStatus );
8135
8136         traceRETURN_xTaskGenericNotifyFromISR( xReturn );
8137
8138         return xReturn;
8139     }
8140
8141 #endif /* configUSE_TASK_NOTIFICATIONS */
8142 /*-----------------------------------------------------------*/
8143
8144 #if ( configUSE_TASK_NOTIFICATIONS == 1 )
8145
8146     void vTaskGenericNotifyGiveFromISR( TaskHandle_t xTaskToNotify,
8147                                         UBaseType_t uxIndexToNotify,
8148                                         BaseType_t * pxHigherPriorityTaskWoken )
8149     {
8150         TCB_t * pxTCB;
8151         uint8_t ucOriginalNotifyState;
8152         UBaseType_t uxSavedInterruptStatus;
8153
8154         traceENTER_vTaskGenericNotifyGiveFromISR( xTaskToNotify, uxIndexToNotify, pxHigherPriorityTaskWoken );
8155
8156         configASSERT( xTaskToNotify );
8157         configASSERT( uxIndexToNotify < configTASK_NOTIFICATION_ARRAY_ENTRIES );
8158
8159         /* RTOS ports that support interrupt nesting have the concept of a
8160          * maximum  system call (or maximum API call) interrupt priority.
8161          * Interrupts that are  above the maximum system call priority are keep
8162          * permanently enabled, even when the RTOS kernel is in a critical section,
8163          * but cannot make any calls to FreeRTOS API functions.  If configASSERT()
8164          * is defined in FreeRTOSConfig.h then
8165          * portASSERT_IF_INTERRUPT_PRIORITY_INVALID() will result in an assertion
8166          * failure if a FreeRTOS API function is called from an interrupt that has
8167          * been assigned a priority above the configured maximum system call
8168          * priority.  Only FreeRTOS functions that end in FromISR can be called
8169          * from interrupts  that have been assigned a priority at or (logically)
8170          * below the maximum system call interrupt priority.  FreeRTOS maintains a
8171          * separate interrupt safe API to ensure interrupt entry is as fast and as
8172          * simple as possible.  More information (albeit Cortex-M specific) is
8173          * provided on the following link:
8174          * https://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html */
8175         portASSERT_IF_INTERRUPT_PRIORITY_INVALID();
8176
8177         pxTCB = xTaskToNotify;
8178
8179         /* MISRA Ref 4.7.1 [Return value shall be checked] */
8180         /* More details at: https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/MISRA.md#dir-47 */
8181         /* coverity[misra_c_2012_directive_4_7_violation] */
8182         uxSavedInterruptStatus = ( UBaseType_t ) taskENTER_CRITICAL_FROM_ISR();
8183         {
8184             ucOriginalNotifyState = pxTCB->ucNotifyState[ uxIndexToNotify ];
8185             pxTCB->ucNotifyState[ uxIndexToNotify ] = taskNOTIFICATION_RECEIVED;
8186
8187             /* 'Giving' is equivalent to incrementing a count in a counting
8188              * semaphore. */
8189             ( pxTCB->ulNotifiedValue[ uxIndexToNotify ] )++;
8190
8191             traceTASK_NOTIFY_GIVE_FROM_ISR( uxIndexToNotify );
8192
8193             /* If the task is in the blocked state specifically to wait for a
8194              * notification then unblock it now. */
8195             if( ucOriginalNotifyState == taskWAITING_NOTIFICATION )
8196             {
8197                 /* The task should not have been on an event list. */
8198                 configASSERT( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) == NULL );
8199
8200                 if( uxSchedulerSuspended == ( UBaseType_t ) 0U )
8201                 {
8202                     listREMOVE_ITEM( &( pxTCB->xStateListItem ) );
8203                     prvAddTaskToReadyList( pxTCB );
8204
8205                     #if ( configUSE_TICKLESS_IDLE != 0 )
8206                     {
8207                         /* If a task is blocked waiting for a notification then
8208                          * xNextTaskUnblockTime might be set to the blocked task's time
8209                          * out time.  If the task is unblocked for a reason other than
8210                          * a timeout xNextTaskUnblockTime is normally left unchanged,
8211                          * because it will automatically get reset to a new value when
8212                          * the tick count equals xNextTaskUnblockTime.  However if
8213                          * tickless idling is used it might be more important to enter
8214                          * sleep mode at the earliest possible time - so reset
8215                          * xNextTaskUnblockTime here to ensure it is updated at the
8216                          * earliest possible time. */
8217                         prvResetNextTaskUnblockTime();
8218                     }
8219                     #endif
8220                 }
8221                 else
8222                 {
8223                     /* The delayed and ready lists cannot be accessed, so hold
8224                      * this task pending until the scheduler is resumed. */
8225                     listINSERT_END( &( xPendingReadyList ), &( pxTCB->xEventListItem ) );
8226                 }
8227
8228                 #if ( configNUMBER_OF_CORES == 1 )
8229                 {
8230                     if( pxTCB->uxPriority > pxCurrentTCB->uxPriority )
8231                     {
8232                         /* The notified task has a priority above the currently
8233                          * executing task so a yield is required. */
8234                         if( pxHigherPriorityTaskWoken != NULL )
8235                         {
8236                             *pxHigherPriorityTaskWoken = pdTRUE;
8237                         }
8238
8239                         /* Mark that a yield is pending in case the user is not
8240                          * using the "xHigherPriorityTaskWoken" parameter in an ISR
8241                          * safe FreeRTOS function. */
8242                         xYieldPendings[ 0 ] = pdTRUE;
8243                     }
8244                     else
8245                     {
8246                         mtCOVERAGE_TEST_MARKER();
8247                     }
8248                 }
8249                 #else /* #if ( configNUMBER_OF_CORES == 1 ) */
8250                 {
8251                     #if ( configUSE_PREEMPTION == 1 )
8252                     {
8253                         prvYieldForTask( pxTCB );
8254
8255                         if( xYieldPendings[ portGET_CORE_ID() ] == pdTRUE )
8256                         {
8257                             if( pxHigherPriorityTaskWoken != NULL )
8258                             {
8259                                 *pxHigherPriorityTaskWoken = pdTRUE;
8260                             }
8261                         }
8262                     }
8263                     #endif /* #if ( configUSE_PREEMPTION == 1 ) */
8264                 }
8265                 #endif /* #if ( configNUMBER_OF_CORES == 1 ) */
8266             }
8267         }
8268         taskEXIT_CRITICAL_FROM_ISR( uxSavedInterruptStatus );
8269
8270         traceRETURN_vTaskGenericNotifyGiveFromISR();
8271     }
8272
8273 #endif /* configUSE_TASK_NOTIFICATIONS */
8274 /*-----------------------------------------------------------*/
8275
8276 #if ( configUSE_TASK_NOTIFICATIONS == 1 )
8277
8278     BaseType_t xTaskGenericNotifyStateClear( TaskHandle_t xTask,
8279                                              UBaseType_t uxIndexToClear )
8280     {
8281         TCB_t * pxTCB;
8282         BaseType_t xReturn;
8283
8284         traceENTER_xTaskGenericNotifyStateClear( xTask, uxIndexToClear );
8285
8286         configASSERT( uxIndexToClear < configTASK_NOTIFICATION_ARRAY_ENTRIES );
8287
8288         /* If null is passed in here then it is the calling task that is having
8289          * its notification state cleared. */
8290         pxTCB = prvGetTCBFromHandle( xTask );
8291
8292         taskENTER_CRITICAL();
8293         {
8294             if( pxTCB->ucNotifyState[ uxIndexToClear ] == taskNOTIFICATION_RECEIVED )
8295             {
8296                 pxTCB->ucNotifyState[ uxIndexToClear ] = taskNOT_WAITING_NOTIFICATION;
8297                 xReturn = pdPASS;
8298             }
8299             else
8300             {
8301                 xReturn = pdFAIL;
8302             }
8303         }
8304         taskEXIT_CRITICAL();
8305
8306         traceRETURN_xTaskGenericNotifyStateClear( xReturn );
8307
8308         return xReturn;
8309     }
8310
8311 #endif /* configUSE_TASK_NOTIFICATIONS */
8312 /*-----------------------------------------------------------*/
8313
8314 #if ( configUSE_TASK_NOTIFICATIONS == 1 )
8315
8316     uint32_t ulTaskGenericNotifyValueClear( TaskHandle_t xTask,
8317                                             UBaseType_t uxIndexToClear,
8318                                             uint32_t ulBitsToClear )
8319     {
8320         TCB_t * pxTCB;
8321         uint32_t ulReturn;
8322
8323         traceENTER_ulTaskGenericNotifyValueClear( xTask, uxIndexToClear, ulBitsToClear );
8324
8325         configASSERT( uxIndexToClear < configTASK_NOTIFICATION_ARRAY_ENTRIES );
8326
8327         /* If null is passed in here then it is the calling task that is having
8328          * its notification state cleared. */
8329         pxTCB = prvGetTCBFromHandle( xTask );
8330
8331         taskENTER_CRITICAL();
8332         {
8333             /* Return the notification as it was before the bits were cleared,
8334              * then clear the bit mask. */
8335             ulReturn = pxTCB->ulNotifiedValue[ uxIndexToClear ];
8336             pxTCB->ulNotifiedValue[ uxIndexToClear ] &= ~ulBitsToClear;
8337         }
8338         taskEXIT_CRITICAL();
8339
8340         traceRETURN_ulTaskGenericNotifyValueClear( ulReturn );
8341
8342         return ulReturn;
8343     }
8344
8345 #endif /* configUSE_TASK_NOTIFICATIONS */
8346 /*-----------------------------------------------------------*/
8347
8348 #if ( configGENERATE_RUN_TIME_STATS == 1 )
8349
8350     configRUN_TIME_COUNTER_TYPE ulTaskGetRunTimeCounter( const TaskHandle_t xTask )
8351     {
8352         TCB_t * pxTCB;
8353
8354         traceENTER_ulTaskGetRunTimeCounter( xTask );
8355
8356         pxTCB = prvGetTCBFromHandle( xTask );
8357
8358         traceRETURN_ulTaskGetRunTimeCounter( pxTCB->ulRunTimeCounter );
8359
8360         return pxTCB->ulRunTimeCounter;
8361     }
8362
8363 #endif /* if ( configGENERATE_RUN_TIME_STATS == 1 ) */
8364 /*-----------------------------------------------------------*/
8365
8366 #if ( configGENERATE_RUN_TIME_STATS == 1 )
8367
8368     configRUN_TIME_COUNTER_TYPE ulTaskGetRunTimePercent( const TaskHandle_t xTask )
8369     {
8370         TCB_t * pxTCB;
8371         configRUN_TIME_COUNTER_TYPE ulTotalTime, ulReturn;
8372
8373         traceENTER_ulTaskGetRunTimePercent( xTask );
8374
8375         ulTotalTime = ( configRUN_TIME_COUNTER_TYPE ) portGET_RUN_TIME_COUNTER_VALUE();
8376
8377         /* For percentage calculations. */
8378         ulTotalTime /= ( configRUN_TIME_COUNTER_TYPE ) 100;
8379
8380         /* Avoid divide by zero errors. */
8381         if( ulTotalTime > ( configRUN_TIME_COUNTER_TYPE ) 0 )
8382         {
8383             pxTCB = prvGetTCBFromHandle( xTask );
8384             ulReturn = pxTCB->ulRunTimeCounter / ulTotalTime;
8385         }
8386         else
8387         {
8388             ulReturn = 0;
8389         }
8390
8391         traceRETURN_ulTaskGetRunTimePercent( ulReturn );
8392
8393         return ulReturn;
8394     }
8395
8396 #endif /* if ( configGENERATE_RUN_TIME_STATS == 1 ) */
8397 /*-----------------------------------------------------------*/
8398
8399 #if ( ( configGENERATE_RUN_TIME_STATS == 1 ) && ( INCLUDE_xTaskGetIdleTaskHandle == 1 ) )
8400
8401     configRUN_TIME_COUNTER_TYPE ulTaskGetIdleRunTimeCounter( void )
8402     {
8403         configRUN_TIME_COUNTER_TYPE ulReturn = 0;
8404         BaseType_t i;
8405
8406         traceENTER_ulTaskGetIdleRunTimeCounter();
8407
8408         for( i = 0; i < ( BaseType_t ) configNUMBER_OF_CORES; i++ )
8409         {
8410             ulReturn += xIdleTaskHandles[ i ]->ulRunTimeCounter;
8411         }
8412
8413         traceRETURN_ulTaskGetIdleRunTimeCounter( ulReturn );
8414
8415         return ulReturn;
8416     }
8417
8418 #endif /* if ( ( configGENERATE_RUN_TIME_STATS == 1 ) && ( INCLUDE_xTaskGetIdleTaskHandle == 1 ) ) */
8419 /*-----------------------------------------------------------*/
8420
8421 #if ( ( configGENERATE_RUN_TIME_STATS == 1 ) && ( INCLUDE_xTaskGetIdleTaskHandle == 1 ) )
8422
8423     configRUN_TIME_COUNTER_TYPE ulTaskGetIdleRunTimePercent( void )
8424     {
8425         configRUN_TIME_COUNTER_TYPE ulTotalTime, ulReturn;
8426         configRUN_TIME_COUNTER_TYPE ulRunTimeCounter = 0;
8427         BaseType_t i;
8428
8429         traceENTER_ulTaskGetIdleRunTimePercent();
8430
8431         ulTotalTime = portGET_RUN_TIME_COUNTER_VALUE() * configNUMBER_OF_CORES;
8432
8433         /* For percentage calculations. */
8434         ulTotalTime /= ( configRUN_TIME_COUNTER_TYPE ) 100;
8435
8436         /* Avoid divide by zero errors. */
8437         if( ulTotalTime > ( configRUN_TIME_COUNTER_TYPE ) 0 )
8438         {
8439             for( i = 0; i < ( BaseType_t ) configNUMBER_OF_CORES; i++ )
8440             {
8441                 ulRunTimeCounter += xIdleTaskHandles[ i ]->ulRunTimeCounter;
8442             }
8443
8444             ulReturn = ulRunTimeCounter / ulTotalTime;
8445         }
8446         else
8447         {
8448             ulReturn = 0;
8449         }
8450
8451         traceRETURN_ulTaskGetIdleRunTimePercent( ulReturn );
8452
8453         return ulReturn;
8454     }
8455
8456 #endif /* if ( ( configGENERATE_RUN_TIME_STATS == 1 ) && ( INCLUDE_xTaskGetIdleTaskHandle == 1 ) ) */
8457 /*-----------------------------------------------------------*/
8458
8459 static void prvAddCurrentTaskToDelayedList( TickType_t xTicksToWait,
8460                                             const BaseType_t xCanBlockIndefinitely )
8461 {
8462     TickType_t xTimeToWake;
8463     const TickType_t xConstTickCount = xTickCount;
8464     List_t * const pxDelayedList = pxDelayedTaskList;
8465     List_t * const pxOverflowDelayedList = pxOverflowDelayedTaskList;
8466
8467     #if ( INCLUDE_xTaskAbortDelay == 1 )
8468     {
8469         /* About to enter a delayed list, so ensure the ucDelayAborted flag is
8470          * reset to pdFALSE so it can be detected as having been set to pdTRUE
8471          * when the task leaves the Blocked state. */
8472         pxCurrentTCB->ucDelayAborted = ( uint8_t ) pdFALSE;
8473     }
8474     #endif
8475
8476     /* Remove the task from the ready list before adding it to the blocked list
8477      * as the same list item is used for both lists. */
8478     if( uxListRemove( &( pxCurrentTCB->xStateListItem ) ) == ( UBaseType_t ) 0 )
8479     {
8480         /* The current task must be in a ready list, so there is no need to
8481          * check, and the port reset macro can be called directly. */
8482         portRESET_READY_PRIORITY( pxCurrentTCB->uxPriority, uxTopReadyPriority );
8483     }
8484     else
8485     {
8486         mtCOVERAGE_TEST_MARKER();
8487     }
8488
8489     #if ( INCLUDE_vTaskSuspend == 1 )
8490     {
8491         if( ( xTicksToWait == portMAX_DELAY ) && ( xCanBlockIndefinitely != pdFALSE ) )
8492         {
8493             /* Add the task to the suspended task list instead of a delayed task
8494              * list to ensure it is not woken by a timing event.  It will block
8495              * indefinitely. */
8496             listINSERT_END( &xSuspendedTaskList, &( pxCurrentTCB->xStateListItem ) );
8497         }
8498         else
8499         {
8500             /* Calculate the time at which the task should be woken if the event
8501              * does not occur.  This may overflow but this doesn't matter, the
8502              * kernel will manage it correctly. */
8503             xTimeToWake = xConstTickCount + xTicksToWait;
8504
8505             /* The list item will be inserted in wake time order. */
8506             listSET_LIST_ITEM_VALUE( &( pxCurrentTCB->xStateListItem ), xTimeToWake );
8507
8508             if( xTimeToWake < xConstTickCount )
8509             {
8510                 /* Wake time has overflowed.  Place this item in the overflow
8511                  * list. */
8512                 traceMOVED_TASK_TO_OVERFLOW_DELAYED_LIST();
8513                 vListInsert( pxOverflowDelayedList, &( pxCurrentTCB->xStateListItem ) );
8514             }
8515             else
8516             {
8517                 /* The wake time has not overflowed, so the current block list
8518                  * is used. */
8519                 traceMOVED_TASK_TO_DELAYED_LIST();
8520                 vListInsert( pxDelayedList, &( pxCurrentTCB->xStateListItem ) );
8521
8522                 /* If the task entering the blocked state was placed at the
8523                  * head of the list of blocked tasks then xNextTaskUnblockTime
8524                  * needs to be updated too. */
8525                 if( xTimeToWake < xNextTaskUnblockTime )
8526                 {
8527                     xNextTaskUnblockTime = xTimeToWake;
8528                 }
8529                 else
8530                 {
8531                     mtCOVERAGE_TEST_MARKER();
8532                 }
8533             }
8534         }
8535     }
8536     #else /* INCLUDE_vTaskSuspend */
8537     {
8538         /* Calculate the time at which the task should be woken if the event
8539          * does not occur.  This may overflow but this doesn't matter, the kernel
8540          * will manage it correctly. */
8541         xTimeToWake = xConstTickCount + xTicksToWait;
8542
8543         /* The list item will be inserted in wake time order. */
8544         listSET_LIST_ITEM_VALUE( &( pxCurrentTCB->xStateListItem ), xTimeToWake );
8545
8546         if( xTimeToWake < xConstTickCount )
8547         {
8548             traceMOVED_TASK_TO_OVERFLOW_DELAYED_LIST();
8549             /* Wake time has overflowed.  Place this item in the overflow list. */
8550             vListInsert( pxOverflowDelayedList, &( pxCurrentTCB->xStateListItem ) );
8551         }
8552         else
8553         {
8554             traceMOVED_TASK_TO_DELAYED_LIST();
8555             /* The wake time has not overflowed, so the current block list is used. */
8556             vListInsert( pxDelayedList, &( pxCurrentTCB->xStateListItem ) );
8557
8558             /* If the task entering the blocked state was placed at the head of the
8559              * list of blocked tasks then xNextTaskUnblockTime needs to be updated
8560              * too. */
8561             if( xTimeToWake < xNextTaskUnblockTime )
8562             {
8563                 xNextTaskUnblockTime = xTimeToWake;
8564             }
8565             else
8566             {
8567                 mtCOVERAGE_TEST_MARKER();
8568             }
8569         }
8570
8571         /* Avoid compiler warning when INCLUDE_vTaskSuspend is not 1. */
8572         ( void ) xCanBlockIndefinitely;
8573     }
8574     #endif /* INCLUDE_vTaskSuspend */
8575 }
8576 /*-----------------------------------------------------------*/
8577
8578 #if ( portUSING_MPU_WRAPPERS == 1 )
8579
8580     xMPU_SETTINGS * xTaskGetMPUSettings( TaskHandle_t xTask )
8581     {
8582         TCB_t * pxTCB;
8583
8584         traceENTER_xTaskGetMPUSettings( xTask );
8585
8586         pxTCB = prvGetTCBFromHandle( xTask );
8587
8588         traceRETURN_xTaskGetMPUSettings( &( pxTCB->xMPUSettings ) );
8589
8590         return &( pxTCB->xMPUSettings );
8591     }
8592
8593 #endif /* portUSING_MPU_WRAPPERS */
8594 /*-----------------------------------------------------------*/
8595
8596 /* Code below here allows additional code to be inserted into this source file,
8597  * especially where access to file scope functions and data is needed (for example
8598  * when performing module tests). */
8599
8600 #ifdef FREERTOS_MODULE_TEST
8601     #include "tasks_test_access_functions.h"
8602 #endif
8603
8604
8605 #if ( configINCLUDE_FREERTOS_TASK_C_ADDITIONS_H == 1 )
8606
8607     #include "freertos_tasks_c_additions.h"
8608
8609     #ifdef FREERTOS_TASKS_C_ADDITIONS_INIT
8610         static void freertos_tasks_c_additions_init( void )
8611         {
8612             FREERTOS_TASKS_C_ADDITIONS_INIT();
8613         }
8614     #endif
8615
8616 #endif /* if ( configINCLUDE_FREERTOS_TASK_C_ADDITIONS_H == 1 ) */
8617 /*-----------------------------------------------------------*/
8618
8619 #if ( ( configSUPPORT_STATIC_ALLOCATION == 1 ) && ( configKERNEL_PROVIDED_STATIC_MEMORY == 1 ) && ( portUSING_MPU_WRAPPERS == 0 ) )
8620
8621 /*
8622  * This is the kernel provided implementation of vApplicationGetIdleTaskMemory()
8623  * to provide the memory that is used by the Idle task. It is used when
8624  * configKERNEL_PROVIDED_STATIC_MEMORY is set to 1. The application can provide
8625  * it's own implementation of vApplicationGetIdleTaskMemory by setting
8626  * configKERNEL_PROVIDED_STATIC_MEMORY to 0 or leaving it undefined.
8627  */
8628     void vApplicationGetIdleTaskMemory( StaticTask_t ** ppxIdleTaskTCBBuffer,
8629                                         StackType_t ** ppxIdleTaskStackBuffer,
8630                                         configSTACK_DEPTH_TYPE * puxIdleTaskStackSize )
8631     {
8632         static StaticTask_t xIdleTaskTCB;
8633         static StackType_t uxIdleTaskStack[ configMINIMAL_STACK_SIZE ];
8634
8635         *ppxIdleTaskTCBBuffer = &( xIdleTaskTCB );
8636         *ppxIdleTaskStackBuffer = &( uxIdleTaskStack[ 0 ] );
8637         *puxIdleTaskStackSize = configMINIMAL_STACK_SIZE;
8638     }
8639
8640     #if ( configNUMBER_OF_CORES > 1 )
8641
8642         void vApplicationGetPassiveIdleTaskMemory( StaticTask_t ** ppxIdleTaskTCBBuffer,
8643                                                    StackType_t ** ppxIdleTaskStackBuffer,
8644                                                    configSTACK_DEPTH_TYPE * puxIdleTaskStackSize,
8645                                                    BaseType_t xPassiveIdleTaskIndex )
8646         {
8647             static StaticTask_t xIdleTaskTCBs[ configNUMBER_OF_CORES - 1 ];
8648             static StackType_t uxIdleTaskStacks[ configNUMBER_OF_CORES - 1 ][ configMINIMAL_STACK_SIZE ];
8649
8650             *ppxIdleTaskTCBBuffer = &( xIdleTaskTCBs[ xPassiveIdleTaskIndex ] );
8651             *ppxIdleTaskStackBuffer = &( uxIdleTaskStacks[ xPassiveIdleTaskIndex ][ 0 ] );
8652             *puxIdleTaskStackSize = configMINIMAL_STACK_SIZE;
8653         }
8654
8655     #endif /* #if ( configNUMBER_OF_CORES > 1 ) */
8656
8657 #endif /* #if ( ( configSUPPORT_STATIC_ALLOCATION == 1 ) && ( configKERNEL_PROVIDED_STATIC_MEMORY == 1 ) && ( portUSING_MPU_WRAPPERS == 0 ) ) */
8658 /*-----------------------------------------------------------*/
8659
8660 #if ( ( configSUPPORT_STATIC_ALLOCATION == 1 ) && ( configKERNEL_PROVIDED_STATIC_MEMORY == 1 ) && ( portUSING_MPU_WRAPPERS == 0 ) && ( configUSE_TIMERS == 1 ) )
8661
8662 /*
8663  * This is the kernel provided implementation of vApplicationGetTimerTaskMemory()
8664  * to provide the memory that is used by the Timer service task. It is used when
8665  * configKERNEL_PROVIDED_STATIC_MEMORY is set to 1. The application can provide
8666  * it's own implementation of vApplicationGetTimerTaskMemory by setting
8667  * configKERNEL_PROVIDED_STATIC_MEMORY to 0 or leaving it undefined.
8668  */
8669     void vApplicationGetTimerTaskMemory( StaticTask_t ** ppxTimerTaskTCBBuffer,
8670                                          StackType_t ** ppxTimerTaskStackBuffer,
8671                                          configSTACK_DEPTH_TYPE * puxTimerTaskStackSize )
8672     {
8673         static StaticTask_t xTimerTaskTCB;
8674         static StackType_t uxTimerTaskStack[ configTIMER_TASK_STACK_DEPTH ];
8675
8676         *ppxTimerTaskTCBBuffer = &( xTimerTaskTCB );
8677         *ppxTimerTaskStackBuffer = &( uxTimerTaskStack[ 0 ] );
8678         *puxTimerTaskStackSize = configTIMER_TASK_STACK_DEPTH;
8679     }
8680
8681 #endif /* #if ( ( configSUPPORT_STATIC_ALLOCATION == 1 ) && ( configKERNEL_PROVIDED_STATIC_MEMORY == 1 ) && ( portUSING_MPU_WRAPPERS == 0 ) && ( configUSE_TIMERS == 1 ) ) */
8682 /*-----------------------------------------------------------*/
8683
8684 /*
8685  * Reset the state in this file. This state is normally initialized at start up.
8686  * This function must be called by the application before restarting the
8687  * scheduler.
8688  */
8689 void vTaskResetState( void )
8690 {
8691     BaseType_t xCoreID;
8692
8693     /* Task control block. */
8694     #if ( configNUMBER_OF_CORES == 1 )
8695     {
8696         pxCurrentTCB = NULL;
8697     }
8698     #endif /* #if ( configNUMBER_OF_CORES == 1 ) */
8699
8700     #if ( INCLUDE_vTaskDelete == 1 )
8701     {
8702         uxDeletedTasksWaitingCleanUp = ( UBaseType_t ) 0U;
8703     }
8704     #endif /* #if ( INCLUDE_vTaskDelete == 1 ) */
8705
8706     #if ( configUSE_POSIX_ERRNO == 1 )
8707     {
8708         FreeRTOS_errno = 0;
8709     }
8710     #endif /* #if ( configUSE_POSIX_ERRNO == 1 ) */
8711
8712     /* Other file private variables. */
8713     uxCurrentNumberOfTasks = ( UBaseType_t ) 0U;
8714     xTickCount = ( TickType_t ) configINITIAL_TICK_COUNT;
8715     uxTopReadyPriority = tskIDLE_PRIORITY;
8716     xSchedulerRunning = pdFALSE;
8717     xPendedTicks = ( TickType_t ) 0U;
8718
8719     for( xCoreID = 0; xCoreID < configNUMBER_OF_CORES; xCoreID++ )
8720     {
8721         xYieldPendings[ xCoreID ] = pdFALSE;
8722     }
8723
8724     xNumOfOverflows = ( BaseType_t ) 0;
8725     uxTaskNumber = ( UBaseType_t ) 0U;
8726     xNextTaskUnblockTime = ( TickType_t ) 0U;
8727
8728     uxSchedulerSuspended = ( UBaseType_t ) 0U;
8729
8730     #if ( configGENERATE_RUN_TIME_STATS == 1 )
8731     {
8732         for( xCoreID = 0; xCoreID < configNUMBER_OF_CORES; xCoreID++ )
8733         {
8734             ulTaskSwitchedInTime[ xCoreID ] = 0U;
8735             ulTotalRunTime[ xCoreID ] = 0U;
8736         }
8737     }
8738     #endif /* #if ( configGENERATE_RUN_TIME_STATS == 1 ) */
8739 }
8740 /*-----------------------------------------------------------*/