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