]> begriffs open source - freertos/blob - tasks.c
Fix MISRA_C_2012 rule 20.7 violation (#843)
[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         xPortStartScheduler();
3731
3732         /* In most cases, xPortStartScheduler() will not return. If it
3733          * returns pdTRUE then there was not enough heap memory available
3734          * to create either the Idle or the Timer task. If it returned
3735          * pdFALSE, then the application called xTaskEndScheduler().
3736          * Most ports don't implement xTaskEndScheduler() as there is
3737          * nothing to return to. */
3738     }
3739     else
3740     {
3741         /* This line will only be reached if the kernel could not be started,
3742          * because there was not enough FreeRTOS heap to create the idle task
3743          * or the timer task. */
3744         configASSERT( xReturn != errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY );
3745     }
3746
3747     /* Prevent compiler warnings if INCLUDE_xTaskGetIdleTaskHandle is set to 0,
3748      * meaning xIdleTaskHandles are not used anywhere else. */
3749     ( void ) xIdleTaskHandles;
3750
3751     /* OpenOCD makes use of uxTopUsedPriority for thread debugging. Prevent uxTopUsedPriority
3752      * from getting optimized out as it is no longer used by the kernel. */
3753     ( void ) uxTopUsedPriority;
3754
3755     traceRETURN_vTaskStartScheduler();
3756 }
3757 /*-----------------------------------------------------------*/
3758
3759 void vTaskEndScheduler( void )
3760 {
3761     traceENTER_vTaskEndScheduler();
3762
3763     /* Stop the scheduler interrupts and call the portable scheduler end
3764      * routine so the original ISRs can be restored if necessary.  The port
3765      * layer must ensure interrupts enable  bit is left in the correct state. */
3766     portDISABLE_INTERRUPTS();
3767     xSchedulerRunning = pdFALSE;
3768     vPortEndScheduler();
3769
3770     traceRETURN_vTaskEndScheduler();
3771 }
3772 /*----------------------------------------------------------*/
3773
3774 void vTaskSuspendAll( void )
3775 {
3776     traceENTER_vTaskSuspendAll();
3777
3778     #if ( configNUMBER_OF_CORES == 1 )
3779     {
3780         /* A critical section is not required as the variable is of type
3781          * BaseType_t.  Please read Richard Barry's reply in the following link to a
3782          * post in the FreeRTOS support forum before reporting this as a bug! -
3783          * https://goo.gl/wu4acr */
3784
3785         /* portSOFTWARE_BARRIER() is only implemented for emulated/simulated ports that
3786          * do not otherwise exhibit real time behaviour. */
3787         portSOFTWARE_BARRIER();
3788
3789         /* The scheduler is suspended if uxSchedulerSuspended is non-zero.  An increment
3790          * is used to allow calls to vTaskSuspendAll() to nest. */
3791         ++uxSchedulerSuspended;
3792
3793         /* Enforces ordering for ports and optimised compilers that may otherwise place
3794          * the above increment elsewhere. */
3795         portMEMORY_BARRIER();
3796     }
3797     #else /* #if ( configNUMBER_OF_CORES == 1 ) */
3798     {
3799         UBaseType_t ulState;
3800
3801         /* This must only be called from within a task. */
3802         portASSERT_IF_IN_ISR();
3803
3804         if( xSchedulerRunning != pdFALSE )
3805         {
3806             /* Writes to uxSchedulerSuspended must be protected by both the task AND ISR locks.
3807              * We must disable interrupts before we grab the locks in the event that this task is
3808              * interrupted and switches context before incrementing uxSchedulerSuspended.
3809              * It is safe to re-enable interrupts after releasing the ISR lock and incrementing
3810              * uxSchedulerSuspended since that will prevent context switches. */
3811             ulState = portSET_INTERRUPT_MASK();
3812
3813             /* portSOFRWARE_BARRIER() is only implemented for emulated/simulated ports that
3814              * do not otherwise exhibit real time behaviour. */
3815             portSOFTWARE_BARRIER();
3816
3817             portGET_TASK_LOCK();
3818
3819             /* uxSchedulerSuspended is increased after prvCheckForRunStateChange. The
3820              * purpose is to prevent altering the variable when fromISR APIs are readying
3821              * it. */
3822             if( uxSchedulerSuspended == 0U )
3823             {
3824                 if( portGET_CRITICAL_NESTING_COUNT() == 0U )
3825                 {
3826                     prvCheckForRunStateChange();
3827                 }
3828                 else
3829                 {
3830                     mtCOVERAGE_TEST_MARKER();
3831                 }
3832             }
3833             else
3834             {
3835                 mtCOVERAGE_TEST_MARKER();
3836             }
3837
3838             portGET_ISR_LOCK();
3839
3840             /* The scheduler is suspended if uxSchedulerSuspended is non-zero. An increment
3841              * is used to allow calls to vTaskSuspendAll() to nest. */
3842             ++uxSchedulerSuspended;
3843             portRELEASE_ISR_LOCK();
3844
3845             portCLEAR_INTERRUPT_MASK( ulState );
3846         }
3847         else
3848         {
3849             mtCOVERAGE_TEST_MARKER();
3850         }
3851     }
3852     #endif /* #if ( configNUMBER_OF_CORES == 1 ) */
3853
3854     traceRETURN_vTaskSuspendAll();
3855 }
3856
3857 /*----------------------------------------------------------*/
3858
3859 #if ( configUSE_TICKLESS_IDLE != 0 )
3860
3861     static TickType_t prvGetExpectedIdleTime( void )
3862     {
3863         TickType_t xReturn;
3864         UBaseType_t uxHigherPriorityReadyTasks = pdFALSE;
3865
3866         /* uxHigherPriorityReadyTasks takes care of the case where
3867          * configUSE_PREEMPTION is 0, so there may be tasks above the idle priority
3868          * task that are in the Ready state, even though the idle task is
3869          * running. */
3870         #if ( configUSE_PORT_OPTIMISED_TASK_SELECTION == 0 )
3871         {
3872             if( uxTopReadyPriority > tskIDLE_PRIORITY )
3873             {
3874                 uxHigherPriorityReadyTasks = pdTRUE;
3875             }
3876         }
3877         #else
3878         {
3879             const UBaseType_t uxLeastSignificantBit = ( UBaseType_t ) 0x01;
3880
3881             /* When port optimised task selection is used the uxTopReadyPriority
3882              * variable is used as a bit map.  If bits other than the least
3883              * significant bit are set then there are tasks that have a priority
3884              * above the idle priority that are in the Ready state.  This takes
3885              * care of the case where the co-operative scheduler is in use. */
3886             if( uxTopReadyPriority > uxLeastSignificantBit )
3887             {
3888                 uxHigherPriorityReadyTasks = pdTRUE;
3889             }
3890         }
3891         #endif /* if ( configUSE_PORT_OPTIMISED_TASK_SELECTION == 0 ) */
3892
3893         if( pxCurrentTCB->uxPriority > tskIDLE_PRIORITY )
3894         {
3895             xReturn = 0;
3896         }
3897         else if( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ tskIDLE_PRIORITY ] ) ) > 1U )
3898         {
3899             /* There are other idle priority tasks in the ready state.  If
3900              * time slicing is used then the very next tick interrupt must be
3901              * processed. */
3902             xReturn = 0;
3903         }
3904         else if( uxHigherPriorityReadyTasks != pdFALSE )
3905         {
3906             /* There are tasks in the Ready state that have a priority above the
3907              * idle priority.  This path can only be reached if
3908              * configUSE_PREEMPTION is 0. */
3909             xReturn = 0;
3910         }
3911         else
3912         {
3913             xReturn = xNextTaskUnblockTime - xTickCount;
3914         }
3915
3916         return xReturn;
3917     }
3918
3919 #endif /* configUSE_TICKLESS_IDLE */
3920 /*----------------------------------------------------------*/
3921
3922 BaseType_t xTaskResumeAll( void )
3923 {
3924     TCB_t * pxTCB = NULL;
3925     BaseType_t xAlreadyYielded = pdFALSE;
3926
3927     traceENTER_xTaskResumeAll();
3928
3929     #if ( configNUMBER_OF_CORES > 1 )
3930         if( xSchedulerRunning != pdFALSE )
3931     #endif
3932     {
3933         /* It is possible that an ISR caused a task to be removed from an event
3934          * list while the scheduler was suspended.  If this was the case then the
3935          * removed task will have been added to the xPendingReadyList.  Once the
3936          * scheduler has been resumed it is safe to move all the pending ready
3937          * tasks from this list into their appropriate ready list. */
3938         taskENTER_CRITICAL();
3939         {
3940             BaseType_t xCoreID;
3941             xCoreID = ( BaseType_t ) portGET_CORE_ID();
3942
3943             /* If uxSchedulerSuspended is zero then this function does not match a
3944              * previous call to vTaskSuspendAll(). */
3945             configASSERT( uxSchedulerSuspended != 0U );
3946
3947             --uxSchedulerSuspended;
3948             portRELEASE_TASK_LOCK();
3949
3950             if( uxSchedulerSuspended == ( UBaseType_t ) 0U )
3951             {
3952                 if( uxCurrentNumberOfTasks > ( UBaseType_t ) 0U )
3953                 {
3954                     /* Move any readied tasks from the pending list into the
3955                      * appropriate ready list. */
3956                     while( listLIST_IS_EMPTY( &xPendingReadyList ) == pdFALSE )
3957                     {
3958                         /* MISRA Ref 11.5.3 [Void pointer assignment] */
3959                         /* More details at: https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/MISRA.md#rule-115 */
3960                         /* coverity[misra_c_2012_rule_11_5_violation] */
3961                         pxTCB = listGET_OWNER_OF_HEAD_ENTRY( ( &xPendingReadyList ) );
3962                         listREMOVE_ITEM( &( pxTCB->xEventListItem ) );
3963                         portMEMORY_BARRIER();
3964                         listREMOVE_ITEM( &( pxTCB->xStateListItem ) );
3965                         prvAddTaskToReadyList( pxTCB );
3966
3967                         #if ( configNUMBER_OF_CORES == 1 )
3968                         {
3969                             /* If the moved task has a priority higher than the current
3970                              * task then a yield must be performed. */
3971                             if( pxTCB->uxPriority > pxCurrentTCB->uxPriority )
3972                             {
3973                                 xYieldPendings[ xCoreID ] = pdTRUE;
3974                             }
3975                             else
3976                             {
3977                                 mtCOVERAGE_TEST_MARKER();
3978                             }
3979                         }
3980                         #else /* #if ( configNUMBER_OF_CORES == 1 ) */
3981                         {
3982                             /* All appropriate tasks yield at the moment a task is added to xPendingReadyList.
3983                              * If the current core yielded then vTaskSwitchContext() has already been called
3984                              * which sets xYieldPendings for the current core to pdTRUE. */
3985                         }
3986                         #endif /* #if ( configNUMBER_OF_CORES == 1 ) */
3987                     }
3988
3989                     if( pxTCB != NULL )
3990                     {
3991                         /* A task was unblocked while the scheduler was suspended,
3992                          * which may have prevented the next unblock time from being
3993                          * re-calculated, in which case re-calculate it now.  Mainly
3994                          * important for low power tickless implementations, where
3995                          * this can prevent an unnecessary exit from low power
3996                          * state. */
3997                         prvResetNextTaskUnblockTime();
3998                     }
3999
4000                     /* If any ticks occurred while the scheduler was suspended then
4001                      * they should be processed now.  This ensures the tick count does
4002                      * not  slip, and that any delayed tasks are resumed at the correct
4003                      * time.
4004                      *
4005                      * It should be safe to call xTaskIncrementTick here from any core
4006                      * since we are in a critical section and xTaskIncrementTick itself
4007                      * protects itself within a critical section. Suspending the scheduler
4008                      * from any core causes xTaskIncrementTick to increment uxPendedCounts. */
4009                     {
4010                         TickType_t xPendedCounts = xPendedTicks; /* Non-volatile copy. */
4011
4012                         if( xPendedCounts > ( TickType_t ) 0U )
4013                         {
4014                             do
4015                             {
4016                                 if( xTaskIncrementTick() != pdFALSE )
4017                                 {
4018                                     /* Other cores are interrupted from
4019                                      * within xTaskIncrementTick(). */
4020                                     xYieldPendings[ xCoreID ] = pdTRUE;
4021                                 }
4022                                 else
4023                                 {
4024                                     mtCOVERAGE_TEST_MARKER();
4025                                 }
4026
4027                                 --xPendedCounts;
4028                             } while( xPendedCounts > ( TickType_t ) 0U );
4029
4030                             xPendedTicks = 0;
4031                         }
4032                         else
4033                         {
4034                             mtCOVERAGE_TEST_MARKER();
4035                         }
4036                     }
4037
4038                     if( xYieldPendings[ xCoreID ] != pdFALSE )
4039                     {
4040                         #if ( configUSE_PREEMPTION != 0 )
4041                         {
4042                             xAlreadyYielded = pdTRUE;
4043                         }
4044                         #endif /* #if ( configUSE_PREEMPTION != 0 ) */
4045
4046                         #if ( configNUMBER_OF_CORES == 1 )
4047                         {
4048                             taskYIELD_TASK_CORE_IF_USING_PREEMPTION( pxCurrentTCB );
4049                         }
4050                         #endif /* #if ( configNUMBER_OF_CORES == 1 ) */
4051                     }
4052                     else
4053                     {
4054                         mtCOVERAGE_TEST_MARKER();
4055                     }
4056                 }
4057             }
4058             else
4059             {
4060                 mtCOVERAGE_TEST_MARKER();
4061             }
4062         }
4063         taskEXIT_CRITICAL();
4064     }
4065
4066     traceRETURN_xTaskResumeAll( xAlreadyYielded );
4067
4068     return xAlreadyYielded;
4069 }
4070 /*-----------------------------------------------------------*/
4071
4072 TickType_t xTaskGetTickCount( void )
4073 {
4074     TickType_t xTicks;
4075
4076     traceENTER_xTaskGetTickCount();
4077
4078     /* Critical section required if running on a 16 bit processor. */
4079     portTICK_TYPE_ENTER_CRITICAL();
4080     {
4081         xTicks = xTickCount;
4082     }
4083     portTICK_TYPE_EXIT_CRITICAL();
4084
4085     traceRETURN_xTaskGetTickCount( xTicks );
4086
4087     return xTicks;
4088 }
4089 /*-----------------------------------------------------------*/
4090
4091 TickType_t xTaskGetTickCountFromISR( void )
4092 {
4093     TickType_t xReturn;
4094     UBaseType_t uxSavedInterruptStatus;
4095
4096     traceENTER_xTaskGetTickCountFromISR();
4097
4098     /* RTOS ports that support interrupt nesting have the concept of a maximum
4099      * system call (or maximum API call) interrupt priority.  Interrupts that are
4100      * above the maximum system call priority are kept permanently enabled, even
4101      * when the RTOS kernel is in a critical section, but cannot make any calls to
4102      * FreeRTOS API functions.  If configASSERT() is defined in FreeRTOSConfig.h
4103      * then portASSERT_IF_INTERRUPT_PRIORITY_INVALID() will result in an assertion
4104      * failure if a FreeRTOS API function is called from an interrupt that has been
4105      * assigned a priority above the configured maximum system call priority.
4106      * Only FreeRTOS functions that end in FromISR can be called from interrupts
4107      * that have been assigned a priority at or (logically) below the maximum
4108      * system call  interrupt priority.  FreeRTOS maintains a separate interrupt
4109      * safe API to ensure interrupt entry is as fast and as simple as possible.
4110      * More information (albeit Cortex-M specific) is provided on the following
4111      * link: https://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html */
4112     portASSERT_IF_INTERRUPT_PRIORITY_INVALID();
4113
4114     uxSavedInterruptStatus = portTICK_TYPE_SET_INTERRUPT_MASK_FROM_ISR();
4115     {
4116         xReturn = xTickCount;
4117     }
4118     portTICK_TYPE_CLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus );
4119
4120     traceRETURN_xTaskGetTickCountFromISR( xReturn );
4121
4122     return xReturn;
4123 }
4124 /*-----------------------------------------------------------*/
4125
4126 UBaseType_t uxTaskGetNumberOfTasks( void )
4127 {
4128     traceENTER_uxTaskGetNumberOfTasks();
4129
4130     /* A critical section is not required because the variables are of type
4131      * BaseType_t. */
4132     traceRETURN_uxTaskGetNumberOfTasks( uxCurrentNumberOfTasks );
4133
4134     return uxCurrentNumberOfTasks;
4135 }
4136 /*-----------------------------------------------------------*/
4137
4138 char * pcTaskGetName( TaskHandle_t xTaskToQuery ) /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
4139 {
4140     TCB_t * pxTCB;
4141
4142     traceENTER_pcTaskGetName( xTaskToQuery );
4143
4144     /* If null is passed in here then the name of the calling task is being
4145      * queried. */
4146     pxTCB = prvGetTCBFromHandle( xTaskToQuery );
4147     configASSERT( pxTCB );
4148
4149     traceRETURN_pcTaskGetName( &( pxTCB->pcTaskName[ 0 ] ) );
4150
4151     return &( pxTCB->pcTaskName[ 0 ] );
4152 }
4153 /*-----------------------------------------------------------*/
4154
4155 #if ( INCLUDE_xTaskGetHandle == 1 )
4156
4157     #if ( configNUMBER_OF_CORES == 1 )
4158         static TCB_t * prvSearchForNameWithinSingleList( List_t * pxList,
4159                                                          const char pcNameToQuery[] )
4160         {
4161             TCB_t * pxNextTCB;
4162             TCB_t * pxFirstTCB;
4163             TCB_t * pxReturn = NULL;
4164             UBaseType_t x;
4165             char cNextChar;
4166             BaseType_t xBreakLoop;
4167
4168             /* This function is called with the scheduler suspended. */
4169
4170             if( listCURRENT_LIST_LENGTH( pxList ) > ( UBaseType_t ) 0 )
4171             {
4172                 /* MISRA Ref 11.5.3 [Void pointer assignment] */
4173                 /* More details at: https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/MISRA.md#rule-115 */
4174                 /* coverity[misra_c_2012_rule_11_5_violation] */
4175                 listGET_OWNER_OF_NEXT_ENTRY( pxFirstTCB, pxList );
4176
4177                 do
4178                 {
4179                     /* MISRA Ref 11.5.3 [Void pointer assignment] */
4180                     /* More details at: https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/MISRA.md#rule-115 */
4181                     /* coverity[misra_c_2012_rule_11_5_violation] */
4182                     listGET_OWNER_OF_NEXT_ENTRY( pxNextTCB, pxList );
4183
4184                     /* Check each character in the name looking for a match or
4185                      * mismatch. */
4186                     xBreakLoop = pdFALSE;
4187
4188                     for( x = ( UBaseType_t ) 0; x < ( UBaseType_t ) configMAX_TASK_NAME_LEN; x++ )
4189                     {
4190                         cNextChar = pxNextTCB->pcTaskName[ x ];
4191
4192                         if( cNextChar != pcNameToQuery[ x ] )
4193                         {
4194                             /* Characters didn't match. */
4195                             xBreakLoop = pdTRUE;
4196                         }
4197                         else if( cNextChar == ( char ) 0x00 )
4198                         {
4199                             /* Both strings terminated, a match must have been
4200                              * found. */
4201                             pxReturn = pxNextTCB;
4202                             xBreakLoop = pdTRUE;
4203                         }
4204                         else
4205                         {
4206                             mtCOVERAGE_TEST_MARKER();
4207                         }
4208
4209                         if( xBreakLoop != pdFALSE )
4210                         {
4211                             break;
4212                         }
4213                     }
4214
4215                     if( pxReturn != NULL )
4216                     {
4217                         /* The handle has been found. */
4218                         break;
4219                     }
4220                 } while( pxNextTCB != pxFirstTCB );
4221             }
4222             else
4223             {
4224                 mtCOVERAGE_TEST_MARKER();
4225             }
4226
4227             return pxReturn;
4228         }
4229     #else /* if ( configNUMBER_OF_CORES == 1 ) */
4230         static TCB_t * prvSearchForNameWithinSingleList( List_t * pxList,
4231                                                          const char pcNameToQuery[] )
4232         {
4233             TCB_t * pxReturn = NULL;
4234             UBaseType_t x;
4235             char cNextChar;
4236             BaseType_t xBreakLoop;
4237             const ListItem_t * pxEndMarker = listGET_END_MARKER( pxList );
4238             ListItem_t * pxIterator;
4239
4240             /* This function is called with the scheduler suspended. */
4241
4242             if( listCURRENT_LIST_LENGTH( pxList ) > ( UBaseType_t ) 0 )
4243             {
4244                 for( pxIterator = listGET_HEAD_ENTRY( pxList ); pxIterator != pxEndMarker; pxIterator = listGET_NEXT( pxIterator ) )
4245                 {
4246                     /* MISRA Ref 11.5.3 [Void pointer assignment] */
4247                     /* More details at: https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/MISRA.md#rule-115 */
4248                     /* coverity[misra_c_2012_rule_11_5_violation] */
4249                     TCB_t * pxTCB = listGET_LIST_ITEM_OWNER( pxIterator );
4250
4251                     /* Check each character in the name looking for a match or
4252                      * mismatch. */
4253                     xBreakLoop = pdFALSE;
4254
4255                     for( x = ( UBaseType_t ) 0; x < ( UBaseType_t ) configMAX_TASK_NAME_LEN; x++ )
4256                     {
4257                         cNextChar = pxTCB->pcTaskName[ x ];
4258
4259                         if( cNextChar != pcNameToQuery[ x ] )
4260                         {
4261                             /* Characters didn't match. */
4262                             xBreakLoop = pdTRUE;
4263                         }
4264                         else if( cNextChar == ( char ) 0x00 )
4265                         {
4266                             /* Both strings terminated, a match must have been
4267                              * found. */
4268                             pxReturn = pxTCB;
4269                             xBreakLoop = pdTRUE;
4270                         }
4271                         else
4272                         {
4273                             mtCOVERAGE_TEST_MARKER();
4274                         }
4275
4276                         if( xBreakLoop != pdFALSE )
4277                         {
4278                             break;
4279                         }
4280                     }
4281
4282                     if( pxReturn != NULL )
4283                     {
4284                         /* The handle has been found. */
4285                         break;
4286                     }
4287                 }
4288             }
4289             else
4290             {
4291                 mtCOVERAGE_TEST_MARKER();
4292             }
4293
4294             return pxReturn;
4295         }
4296     #endif /* #if ( configNUMBER_OF_CORES == 1 ) */
4297
4298 #endif /* INCLUDE_xTaskGetHandle */
4299 /*-----------------------------------------------------------*/
4300
4301 #if ( INCLUDE_xTaskGetHandle == 1 )
4302
4303     TaskHandle_t xTaskGetHandle( const char * pcNameToQuery ) /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
4304     {
4305         UBaseType_t uxQueue = configMAX_PRIORITIES;
4306         TCB_t * pxTCB;
4307
4308         traceENTER_xTaskGetHandle( pcNameToQuery );
4309
4310         /* Task names will be truncated to configMAX_TASK_NAME_LEN - 1 bytes. */
4311         configASSERT( strlen( pcNameToQuery ) < configMAX_TASK_NAME_LEN );
4312
4313         vTaskSuspendAll();
4314         {
4315             /* Search the ready lists. */
4316             do
4317             {
4318                 uxQueue--;
4319                 pxTCB = prvSearchForNameWithinSingleList( ( List_t * ) &( pxReadyTasksLists[ uxQueue ] ), pcNameToQuery );
4320
4321                 if( pxTCB != NULL )
4322                 {
4323                     /* Found the handle. */
4324                     break;
4325                 }
4326             } while( uxQueue > ( UBaseType_t ) tskIDLE_PRIORITY ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */
4327
4328             /* Search the delayed lists. */
4329             if( pxTCB == NULL )
4330             {
4331                 pxTCB = prvSearchForNameWithinSingleList( ( List_t * ) pxDelayedTaskList, pcNameToQuery );
4332             }
4333
4334             if( pxTCB == NULL )
4335             {
4336                 pxTCB = prvSearchForNameWithinSingleList( ( List_t * ) pxOverflowDelayedTaskList, pcNameToQuery );
4337             }
4338
4339             #if ( INCLUDE_vTaskSuspend == 1 )
4340             {
4341                 if( pxTCB == NULL )
4342                 {
4343                     /* Search the suspended list. */
4344                     pxTCB = prvSearchForNameWithinSingleList( &xSuspendedTaskList, pcNameToQuery );
4345                 }
4346             }
4347             #endif
4348
4349             #if ( INCLUDE_vTaskDelete == 1 )
4350             {
4351                 if( pxTCB == NULL )
4352                 {
4353                     /* Search the deleted list. */
4354                     pxTCB = prvSearchForNameWithinSingleList( &xTasksWaitingTermination, pcNameToQuery );
4355                 }
4356             }
4357             #endif
4358         }
4359         ( void ) xTaskResumeAll();
4360
4361         traceRETURN_xTaskGetHandle( pxTCB );
4362
4363         return pxTCB;
4364     }
4365
4366 #endif /* INCLUDE_xTaskGetHandle */
4367 /*-----------------------------------------------------------*/
4368
4369 #if ( configSUPPORT_STATIC_ALLOCATION == 1 )
4370
4371     BaseType_t xTaskGetStaticBuffers( TaskHandle_t xTask,
4372                                       StackType_t ** ppuxStackBuffer,
4373                                       StaticTask_t ** ppxTaskBuffer )
4374     {
4375         BaseType_t xReturn;
4376         TCB_t * pxTCB;
4377
4378         traceENTER_xTaskGetStaticBuffers( xTask, ppuxStackBuffer, ppxTaskBuffer );
4379
4380         configASSERT( ppuxStackBuffer != NULL );
4381         configASSERT( ppxTaskBuffer != NULL );
4382
4383         pxTCB = prvGetTCBFromHandle( xTask );
4384
4385         #if ( tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE == 1 )
4386         {
4387             if( pxTCB->ucStaticallyAllocated == tskSTATICALLY_ALLOCATED_STACK_AND_TCB )
4388             {
4389                 *ppuxStackBuffer = pxTCB->pxStack;
4390                 /* MISRA Ref 11.3.1 [Misaligned access] */
4391                 /* More details at: https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/MISRA.md#rule-113 */
4392                 /* coverity[misra_c_2012_rule_11_3_violation] */
4393                 *ppxTaskBuffer = ( StaticTask_t * ) pxTCB;
4394                 xReturn = pdTRUE;
4395             }
4396             else if( pxTCB->ucStaticallyAllocated == tskSTATICALLY_ALLOCATED_STACK_ONLY )
4397             {
4398                 *ppuxStackBuffer = pxTCB->pxStack;
4399                 *ppxTaskBuffer = NULL;
4400                 xReturn = pdTRUE;
4401             }
4402             else
4403             {
4404                 xReturn = pdFALSE;
4405             }
4406         }
4407         #else /* tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE == 1 */
4408         {
4409             *ppuxStackBuffer = pxTCB->pxStack;
4410             *ppxTaskBuffer = ( StaticTask_t * ) pxTCB;
4411             xReturn = pdTRUE;
4412         }
4413         #endif /* tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE == 1 */
4414
4415         traceRETURN_xTaskGetStaticBuffers( xReturn );
4416
4417         return xReturn;
4418     }
4419
4420 #endif /* configSUPPORT_STATIC_ALLOCATION */
4421 /*-----------------------------------------------------------*/
4422
4423 #if ( configUSE_TRACE_FACILITY == 1 )
4424
4425     UBaseType_t uxTaskGetSystemState( TaskStatus_t * const pxTaskStatusArray,
4426                                       const UBaseType_t uxArraySize,
4427                                       configRUN_TIME_COUNTER_TYPE * const pulTotalRunTime )
4428     {
4429         UBaseType_t uxTask = 0, uxQueue = configMAX_PRIORITIES;
4430
4431         traceENTER_uxTaskGetSystemState( pxTaskStatusArray, uxArraySize, pulTotalRunTime );
4432
4433         vTaskSuspendAll();
4434         {
4435             /* Is there a space in the array for each task in the system? */
4436             if( uxArraySize >= uxCurrentNumberOfTasks )
4437             {
4438                 /* Fill in an TaskStatus_t structure with information on each
4439                  * task in the Ready state. */
4440                 do
4441                 {
4442                     uxQueue--;
4443                     uxTask = ( UBaseType_t ) ( uxTask + prvListTasksWithinSingleList( &( pxTaskStatusArray[ uxTask ] ), &( pxReadyTasksLists[ uxQueue ] ), eReady ) );
4444                 } while( uxQueue > ( UBaseType_t ) tskIDLE_PRIORITY ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */
4445
4446                 /* Fill in an TaskStatus_t structure with information on each
4447                  * task in the Blocked state. */
4448                 uxTask = ( UBaseType_t ) ( uxTask + prvListTasksWithinSingleList( &( pxTaskStatusArray[ uxTask ] ), ( List_t * ) pxDelayedTaskList, eBlocked ) );
4449                 uxTask = ( UBaseType_t ) ( uxTask + prvListTasksWithinSingleList( &( pxTaskStatusArray[ uxTask ] ), ( List_t * ) pxOverflowDelayedTaskList, eBlocked ) );
4450
4451                 #if ( INCLUDE_vTaskDelete == 1 )
4452                 {
4453                     /* Fill in an TaskStatus_t structure with information on
4454                      * each task that has been deleted but not yet cleaned up. */
4455                     uxTask = ( UBaseType_t ) ( uxTask + prvListTasksWithinSingleList( &( pxTaskStatusArray[ uxTask ] ), &xTasksWaitingTermination, eDeleted ) );
4456                 }
4457                 #endif
4458
4459                 #if ( INCLUDE_vTaskSuspend == 1 )
4460                 {
4461                     /* Fill in an TaskStatus_t structure with information on
4462                      * each task in the Suspended state. */
4463                     uxTask = ( UBaseType_t ) ( uxTask + prvListTasksWithinSingleList( &( pxTaskStatusArray[ uxTask ] ), &xSuspendedTaskList, eSuspended ) );
4464                 }
4465                 #endif
4466
4467                 #if ( configGENERATE_RUN_TIME_STATS == 1 )
4468                 {
4469                     if( pulTotalRunTime != NULL )
4470                     {
4471                         #ifdef portALT_GET_RUN_TIME_COUNTER_VALUE
4472                             portALT_GET_RUN_TIME_COUNTER_VALUE( ( *pulTotalRunTime ) );
4473                         #else
4474                             *pulTotalRunTime = ( configRUN_TIME_COUNTER_TYPE ) portGET_RUN_TIME_COUNTER_VALUE();
4475                         #endif
4476                     }
4477                 }
4478                 #else /* if ( configGENERATE_RUN_TIME_STATS == 1 ) */
4479                 {
4480                     if( pulTotalRunTime != NULL )
4481                     {
4482                         *pulTotalRunTime = 0;
4483                     }
4484                 }
4485                 #endif /* if ( configGENERATE_RUN_TIME_STATS == 1 ) */
4486             }
4487             else
4488             {
4489                 mtCOVERAGE_TEST_MARKER();
4490             }
4491         }
4492         ( void ) xTaskResumeAll();
4493
4494         traceRETURN_uxTaskGetSystemState( uxTask );
4495
4496         return uxTask;
4497     }
4498
4499 #endif /* configUSE_TRACE_FACILITY */
4500 /*----------------------------------------------------------*/
4501
4502 #if ( INCLUDE_xTaskGetIdleTaskHandle == 1 )
4503
4504     #if ( configNUMBER_OF_CORES == 1 )
4505         TaskHandle_t xTaskGetIdleTaskHandle( void )
4506         {
4507             traceENTER_xTaskGetIdleTaskHandle();
4508
4509             /* If xTaskGetIdleTaskHandle() is called before the scheduler has been
4510              * started, then xIdleTaskHandles will be NULL. */
4511             configASSERT( ( xIdleTaskHandles[ 0 ] != NULL ) );
4512
4513             traceRETURN_xTaskGetIdleTaskHandle( xIdleTaskHandles[ 0 ] );
4514
4515             return xIdleTaskHandles[ 0 ];
4516         }
4517     #endif /* if ( configNUMBER_OF_CORES == 1 ) */
4518
4519     TaskHandle_t xTaskGetIdleTaskHandleForCore( BaseType_t xCoreID )
4520     {
4521         traceENTER_xTaskGetIdleTaskHandleForCore( xCoreID );
4522
4523         /* Ensure the core ID is valid. */
4524         configASSERT( taskVALID_CORE_ID( xCoreID ) == pdTRUE );
4525
4526         /* If xTaskGetIdleTaskHandle() is called before the scheduler has been
4527          * started, then xIdleTaskHandles will be NULL. */
4528         configASSERT( ( xIdleTaskHandles[ xCoreID ] != NULL ) );
4529
4530         traceRETURN_xTaskGetIdleTaskHandleForCore( xIdleTaskHandles[ xCoreID ] );
4531
4532         return xIdleTaskHandles[ xCoreID ];
4533     }
4534
4535 #endif /* INCLUDE_xTaskGetIdleTaskHandle */
4536 /*----------------------------------------------------------*/
4537
4538 /* This conditional compilation should use inequality to 0, not equality to 1.
4539  * This is to ensure vTaskStepTick() is available when user defined low power mode
4540  * implementations require configUSE_TICKLESS_IDLE to be set to a value other than
4541  * 1. */
4542 #if ( configUSE_TICKLESS_IDLE != 0 )
4543
4544     void vTaskStepTick( TickType_t xTicksToJump )
4545     {
4546         traceENTER_vTaskStepTick( xTicksToJump );
4547
4548         /* Correct the tick count value after a period during which the tick
4549          * was suppressed.  Note this does *not* call the tick hook function for
4550          * each stepped tick. */
4551         configASSERT( ( xTickCount + xTicksToJump ) <= xNextTaskUnblockTime );
4552
4553         if( ( xTickCount + xTicksToJump ) == xNextTaskUnblockTime )
4554         {
4555             /* Arrange for xTickCount to reach xNextTaskUnblockTime in
4556              * xTaskIncrementTick() when the scheduler resumes.  This ensures
4557              * that any delayed tasks are resumed at the correct time. */
4558             configASSERT( uxSchedulerSuspended != ( UBaseType_t ) 0U );
4559             configASSERT( xTicksToJump != ( TickType_t ) 0 );
4560
4561             /* Prevent the tick interrupt modifying xPendedTicks simultaneously. */
4562             taskENTER_CRITICAL();
4563             {
4564                 xPendedTicks++;
4565             }
4566             taskEXIT_CRITICAL();
4567             xTicksToJump--;
4568         }
4569         else
4570         {
4571             mtCOVERAGE_TEST_MARKER();
4572         }
4573
4574         xTickCount += xTicksToJump;
4575
4576         traceINCREASE_TICK_COUNT( xTicksToJump );
4577         traceRETURN_vTaskStepTick();
4578     }
4579
4580 #endif /* configUSE_TICKLESS_IDLE */
4581 /*----------------------------------------------------------*/
4582
4583 BaseType_t xTaskCatchUpTicks( TickType_t xTicksToCatchUp )
4584 {
4585     BaseType_t xYieldOccurred;
4586
4587     traceENTER_xTaskCatchUpTicks( xTicksToCatchUp );
4588
4589     /* Must not be called with the scheduler suspended as the implementation
4590      * relies on xPendedTicks being wound down to 0 in xTaskResumeAll(). */
4591     configASSERT( uxSchedulerSuspended == ( UBaseType_t ) 0U );
4592
4593     /* Use xPendedTicks to mimic xTicksToCatchUp number of ticks occurring when
4594      * the scheduler is suspended so the ticks are executed in xTaskResumeAll(). */
4595     vTaskSuspendAll();
4596
4597     /* Prevent the tick interrupt modifying xPendedTicks simultaneously. */
4598     taskENTER_CRITICAL();
4599     {
4600         xPendedTicks += xTicksToCatchUp;
4601     }
4602     taskEXIT_CRITICAL();
4603     xYieldOccurred = xTaskResumeAll();
4604
4605     traceRETURN_xTaskCatchUpTicks( xYieldOccurred );
4606
4607     return xYieldOccurred;
4608 }
4609 /*----------------------------------------------------------*/
4610
4611 #if ( INCLUDE_xTaskAbortDelay == 1 )
4612
4613     BaseType_t xTaskAbortDelay( TaskHandle_t xTask )
4614     {
4615         TCB_t * pxTCB = xTask;
4616         BaseType_t xReturn;
4617
4618         traceENTER_xTaskAbortDelay( xTask );
4619
4620         configASSERT( pxTCB );
4621
4622         vTaskSuspendAll();
4623         {
4624             /* A task can only be prematurely removed from the Blocked state if
4625              * it is actually in the Blocked state. */
4626             if( eTaskGetState( xTask ) == eBlocked )
4627             {
4628                 xReturn = pdPASS;
4629
4630                 /* Remove the reference to the task from the blocked list.  An
4631                  * interrupt won't touch the xStateListItem because the
4632                  * scheduler is suspended. */
4633                 ( void ) uxListRemove( &( pxTCB->xStateListItem ) );
4634
4635                 /* Is the task waiting on an event also?  If so remove it from
4636                  * the event list too.  Interrupts can touch the event list item,
4637                  * even though the scheduler is suspended, so a critical section
4638                  * is used. */
4639                 taskENTER_CRITICAL();
4640                 {
4641                     if( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) != NULL )
4642                     {
4643                         ( void ) uxListRemove( &( pxTCB->xEventListItem ) );
4644
4645                         /* This lets the task know it was forcibly removed from the
4646                          * blocked state so it should not re-evaluate its block time and
4647                          * then block again. */
4648                         pxTCB->ucDelayAborted = pdTRUE;
4649                     }
4650                     else
4651                     {
4652                         mtCOVERAGE_TEST_MARKER();
4653                     }
4654                 }
4655                 taskEXIT_CRITICAL();
4656
4657                 /* Place the unblocked task into the appropriate ready list. */
4658                 prvAddTaskToReadyList( pxTCB );
4659
4660                 /* A task being unblocked cannot cause an immediate context
4661                  * switch if preemption is turned off. */
4662                 #if ( configUSE_PREEMPTION == 1 )
4663                 {
4664                     #if ( configNUMBER_OF_CORES == 1 )
4665                     {
4666                         /* Preemption is on, but a context switch should only be
4667                          * performed if the unblocked task has a priority that is
4668                          * higher than the currently executing task. */
4669                         if( pxTCB->uxPriority > pxCurrentTCB->uxPriority )
4670                         {
4671                             /* Pend the yield to be performed when the scheduler
4672                              * is unsuspended. */
4673                             xYieldPendings[ 0 ] = pdTRUE;
4674                         }
4675                         else
4676                         {
4677                             mtCOVERAGE_TEST_MARKER();
4678                         }
4679                     }
4680                     #else /* #if ( configNUMBER_OF_CORES == 1 ) */
4681                     {
4682                         taskENTER_CRITICAL();
4683                         {
4684                             prvYieldForTask( pxTCB );
4685                         }
4686                         taskEXIT_CRITICAL();
4687                     }
4688                     #endif /* #if ( configNUMBER_OF_CORES == 1 ) */
4689                 }
4690                 #endif /* #if ( configUSE_PREEMPTION == 1 ) */
4691             }
4692             else
4693             {
4694                 xReturn = pdFAIL;
4695             }
4696         }
4697         ( void ) xTaskResumeAll();
4698
4699         traceRETURN_xTaskAbortDelay( xReturn );
4700
4701         return xReturn;
4702     }
4703
4704 #endif /* INCLUDE_xTaskAbortDelay */
4705 /*----------------------------------------------------------*/
4706
4707 BaseType_t xTaskIncrementTick( void )
4708 {
4709     TCB_t * pxTCB;
4710     TickType_t xItemValue;
4711     BaseType_t xSwitchRequired = pdFALSE;
4712
4713     #if ( configUSE_PREEMPTION == 1 ) && ( configNUMBER_OF_CORES > 1 )
4714     BaseType_t xYieldRequiredForCore[ configNUMBER_OF_CORES ] = { pdFALSE };
4715     #endif /* #if ( configUSE_PREEMPTION == 1 ) && ( configNUMBER_OF_CORES > 1 ) */
4716
4717     traceENTER_xTaskIncrementTick();
4718
4719     /* Called by the portable layer each time a tick interrupt occurs.
4720      * Increments the tick then checks to see if the new tick value will cause any
4721      * tasks to be unblocked. */
4722     traceTASK_INCREMENT_TICK( xTickCount );
4723
4724     /* Tick increment should occur on every kernel timer event. Core 0 has the
4725      * responsibility to increment the tick, or increment the pended ticks if the
4726      * scheduler is suspended.  If pended ticks is greater than zero, the core that
4727      * calls xTaskResumeAll has the responsibility to increment the tick. */
4728     if( uxSchedulerSuspended == ( UBaseType_t ) 0U )
4729     {
4730         /* Minor optimisation.  The tick count cannot change in this
4731          * block. */
4732         const TickType_t xConstTickCount = xTickCount + ( TickType_t ) 1;
4733
4734         /* Increment the RTOS tick, switching the delayed and overflowed
4735          * delayed lists if it wraps to 0. */
4736         xTickCount = xConstTickCount;
4737
4738         if( xConstTickCount == ( TickType_t ) 0U ) /*lint !e774 'if' does not always evaluate to false as it is looking for an overflow. */
4739         {
4740             taskSWITCH_DELAYED_LISTS();
4741         }
4742         else
4743         {
4744             mtCOVERAGE_TEST_MARKER();
4745         }
4746
4747         /* See if this tick has made a timeout expire.  Tasks are stored in
4748          * the  queue in the order of their wake time - meaning once one task
4749          * has been found whose block time has not expired there is no need to
4750          * look any further down the list. */
4751         if( xConstTickCount >= xNextTaskUnblockTime )
4752         {
4753             for( ; ; )
4754             {
4755                 if( listLIST_IS_EMPTY( pxDelayedTaskList ) != pdFALSE )
4756                 {
4757                     /* The delayed list is empty.  Set xNextTaskUnblockTime
4758                      * to the maximum possible value so it is extremely
4759                      * unlikely that the
4760                      * if( xTickCount >= xNextTaskUnblockTime ) test will pass
4761                      * next time through. */
4762                     xNextTaskUnblockTime = portMAX_DELAY; /*lint !e961 MISRA exception as the casts are only redundant for some ports. */
4763                     break;
4764                 }
4765                 else
4766                 {
4767                     /* The delayed list is not empty, get the value of the
4768                      * item at the head of the delayed list.  This is the time
4769                      * at which the task at the head of the delayed list must
4770                      * be removed from the Blocked state. */
4771                     /* MISRA Ref 11.5.3 [Void pointer assignment] */
4772                     /* More details at: https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/MISRA.md#rule-115 */
4773                     /* coverity[misra_c_2012_rule_11_5_violation] */
4774                     pxTCB = listGET_OWNER_OF_HEAD_ENTRY( pxDelayedTaskList );
4775                     xItemValue = listGET_LIST_ITEM_VALUE( &( pxTCB->xStateListItem ) );
4776
4777                     if( xConstTickCount < xItemValue )
4778                     {
4779                         /* It is not time to unblock this item yet, but the
4780                          * item value is the time at which the task at the head
4781                          * of the blocked list must be removed from the Blocked
4782                          * state -  so record the item value in
4783                          * xNextTaskUnblockTime. */
4784                         xNextTaskUnblockTime = xItemValue;
4785                         break; /*lint !e9011 Code structure here is deemed easier to understand with multiple breaks. */
4786                     }
4787                     else
4788                     {
4789                         mtCOVERAGE_TEST_MARKER();
4790                     }
4791
4792                     /* It is time to remove the item from the Blocked state. */
4793                     listREMOVE_ITEM( &( pxTCB->xStateListItem ) );
4794
4795                     /* Is the task waiting on an event also?  If so remove
4796                      * it from the event list. */
4797                     if( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) != NULL )
4798                     {
4799                         listREMOVE_ITEM( &( pxTCB->xEventListItem ) );
4800                     }
4801                     else
4802                     {
4803                         mtCOVERAGE_TEST_MARKER();
4804                     }
4805
4806                     /* Place the unblocked task into the appropriate ready
4807                      * list. */
4808                     prvAddTaskToReadyList( pxTCB );
4809
4810                     /* A task being unblocked cannot cause an immediate
4811                      * context switch if preemption is turned off. */
4812                     #if ( configUSE_PREEMPTION == 1 )
4813                     {
4814                         #if ( configNUMBER_OF_CORES == 1 )
4815                         {
4816                             /* Preemption is on, but a context switch should
4817                              * only be performed if the unblocked task's
4818                              * priority is higher than the currently executing
4819                              * task.
4820                              * The case of equal priority tasks sharing
4821                              * processing time (which happens when both
4822                              * preemption and time slicing are on) is
4823                              * handled below.*/
4824                             if( pxTCB->uxPriority > pxCurrentTCB->uxPriority )
4825                             {
4826                                 xSwitchRequired = pdTRUE;
4827                             }
4828                             else
4829                             {
4830                                 mtCOVERAGE_TEST_MARKER();
4831                             }
4832                         }
4833                         #else /* #if( configNUMBER_OF_CORES == 1 ) */
4834                         {
4835                             prvYieldForTask( pxTCB );
4836                         }
4837                         #endif /* #if( configNUMBER_OF_CORES == 1 ) */
4838                     }
4839                     #endif /* #if ( configUSE_PREEMPTION == 1 ) */
4840                 }
4841             }
4842         }
4843
4844         /* Tasks of equal priority to the currently running task will share
4845          * processing time (time slice) if preemption is on, and the application
4846          * writer has not explicitly turned time slicing off. */
4847         #if ( ( configUSE_PREEMPTION == 1 ) && ( configUSE_TIME_SLICING == 1 ) )
4848         {
4849             #if ( configNUMBER_OF_CORES == 1 )
4850             {
4851                 if( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ pxCurrentTCB->uxPriority ] ) ) > 1U )
4852                 {
4853                     xSwitchRequired = pdTRUE;
4854                 }
4855                 else
4856                 {
4857                     mtCOVERAGE_TEST_MARKER();
4858                 }
4859             }
4860             #else /* #if ( configNUMBER_OF_CORES == 1 ) */
4861             {
4862                 BaseType_t xCoreID;
4863
4864                 for( xCoreID = 0; xCoreID < ( ( BaseType_t ) configNUMBER_OF_CORES ); xCoreID++ )
4865                 {
4866                     if( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ pxCurrentTCBs[ xCoreID ]->uxPriority ] ) ) > 1U )
4867                     {
4868                         xYieldRequiredForCore[ xCoreID ] = pdTRUE;
4869                     }
4870                     else
4871                     {
4872                         mtCOVERAGE_TEST_MARKER();
4873                     }
4874                 }
4875             }
4876             #endif /* #if ( configNUMBER_OF_CORES == 1 ) */
4877         }
4878         #endif /* #if ( ( configUSE_PREEMPTION == 1 ) && ( configUSE_TIME_SLICING == 1 ) ) */
4879
4880         #if ( configUSE_TICK_HOOK == 1 )
4881         {
4882             /* Guard against the tick hook being called when the pended tick
4883              * count is being unwound (when the scheduler is being unlocked). */
4884             if( xPendedTicks == ( TickType_t ) 0 )
4885             {
4886                 vApplicationTickHook();
4887             }
4888             else
4889             {
4890                 mtCOVERAGE_TEST_MARKER();
4891             }
4892         }
4893         #endif /* configUSE_TICK_HOOK */
4894
4895         #if ( configUSE_PREEMPTION == 1 )
4896         {
4897             #if ( configNUMBER_OF_CORES == 1 )
4898             {
4899                 /* For single core the core ID is always 0. */
4900                 if( xYieldPendings[ 0 ] != pdFALSE )
4901                 {
4902                     xSwitchRequired = pdTRUE;
4903                 }
4904                 else
4905                 {
4906                     mtCOVERAGE_TEST_MARKER();
4907                 }
4908             }
4909             #else /* #if ( configNUMBER_OF_CORES == 1 ) */
4910             {
4911                 BaseType_t xCoreID, xCurrentCoreID;
4912                 xCurrentCoreID = ( BaseType_t ) portGET_CORE_ID();
4913
4914                 for( xCoreID = 0; xCoreID < ( BaseType_t ) configNUMBER_OF_CORES; xCoreID++ )
4915                 {
4916                     #if ( configUSE_TASK_PREEMPTION_DISABLE == 1 )
4917                         if( pxCurrentTCBs[ xCoreID ]->xPreemptionDisable == pdFALSE )
4918                     #endif
4919                     {
4920                         if( ( xYieldRequiredForCore[ xCoreID ] != pdFALSE ) || ( xYieldPendings[ xCoreID ] != pdFALSE ) )
4921                         {
4922                             if( xCoreID == xCurrentCoreID )
4923                             {
4924                                 xSwitchRequired = pdTRUE;
4925                             }
4926                             else
4927                             {
4928                                 prvYieldCore( xCoreID );
4929                             }
4930                         }
4931                         else
4932                         {
4933                             mtCOVERAGE_TEST_MARKER();
4934                         }
4935                     }
4936                 }
4937             }
4938             #endif /* #if ( configNUMBER_OF_CORES == 1 ) */
4939         }
4940         #endif /* #if ( configUSE_PREEMPTION == 1 ) */
4941     }
4942     else
4943     {
4944         ++xPendedTicks;
4945
4946         /* The tick hook gets called at regular intervals, even if the
4947          * scheduler is locked. */
4948         #if ( configUSE_TICK_HOOK == 1 )
4949         {
4950             vApplicationTickHook();
4951         }
4952         #endif
4953     }
4954
4955     traceRETURN_xTaskIncrementTick( xSwitchRequired );
4956
4957     return xSwitchRequired;
4958 }
4959 /*-----------------------------------------------------------*/
4960
4961 #if ( configUSE_APPLICATION_TASK_TAG == 1 )
4962
4963     void vTaskSetApplicationTaskTag( TaskHandle_t xTask,
4964                                      TaskHookFunction_t pxHookFunction )
4965     {
4966         TCB_t * xTCB;
4967
4968         traceENTER_vTaskSetApplicationTaskTag( xTask, pxHookFunction );
4969
4970         /* If xTask is NULL then it is the task hook of the calling task that is
4971          * getting set. */
4972         if( xTask == NULL )
4973         {
4974             xTCB = ( TCB_t * ) pxCurrentTCB;
4975         }
4976         else
4977         {
4978             xTCB = xTask;
4979         }
4980
4981         /* Save the hook function in the TCB.  A critical section is required as
4982          * the value can be accessed from an interrupt. */
4983         taskENTER_CRITICAL();
4984         {
4985             xTCB->pxTaskTag = pxHookFunction;
4986         }
4987         taskEXIT_CRITICAL();
4988
4989         traceRETURN_vTaskSetApplicationTaskTag();
4990     }
4991
4992 #endif /* configUSE_APPLICATION_TASK_TAG */
4993 /*-----------------------------------------------------------*/
4994
4995 #if ( configUSE_APPLICATION_TASK_TAG == 1 )
4996
4997     TaskHookFunction_t xTaskGetApplicationTaskTag( TaskHandle_t xTask )
4998     {
4999         TCB_t * pxTCB;
5000         TaskHookFunction_t xReturn;
5001
5002         traceENTER_xTaskGetApplicationTaskTag( xTask );
5003
5004         /* If xTask is NULL then set the calling task's hook. */
5005         pxTCB = prvGetTCBFromHandle( xTask );
5006
5007         /* Save the hook function in the TCB.  A critical section is required as
5008          * the value can be accessed from an interrupt. */
5009         taskENTER_CRITICAL();
5010         {
5011             xReturn = pxTCB->pxTaskTag;
5012         }
5013         taskEXIT_CRITICAL();
5014
5015         traceRETURN_xTaskGetApplicationTaskTag( xReturn );
5016
5017         return xReturn;
5018     }
5019
5020 #endif /* configUSE_APPLICATION_TASK_TAG */
5021 /*-----------------------------------------------------------*/
5022
5023 #if ( configUSE_APPLICATION_TASK_TAG == 1 )
5024
5025     TaskHookFunction_t xTaskGetApplicationTaskTagFromISR( TaskHandle_t xTask )
5026     {
5027         TCB_t * pxTCB;
5028         TaskHookFunction_t xReturn;
5029         UBaseType_t uxSavedInterruptStatus;
5030
5031         traceENTER_xTaskGetApplicationTaskTagFromISR( xTask );
5032
5033         /* If xTask is NULL then set the calling task's hook. */
5034         pxTCB = prvGetTCBFromHandle( xTask );
5035
5036         /* Save the hook function in the TCB.  A critical section is required as
5037          * the value can be accessed from an interrupt. */
5038         uxSavedInterruptStatus = taskENTER_CRITICAL_FROM_ISR();
5039         {
5040             xReturn = pxTCB->pxTaskTag;
5041         }
5042         taskEXIT_CRITICAL_FROM_ISR( uxSavedInterruptStatus );
5043
5044         traceRETURN_xTaskGetApplicationTaskTagFromISR( xReturn );
5045
5046         return xReturn;
5047     }
5048
5049 #endif /* configUSE_APPLICATION_TASK_TAG */
5050 /*-----------------------------------------------------------*/
5051
5052 #if ( configUSE_APPLICATION_TASK_TAG == 1 )
5053
5054     BaseType_t xTaskCallApplicationTaskHook( TaskHandle_t xTask,
5055                                              void * pvParameter )
5056     {
5057         TCB_t * xTCB;
5058         BaseType_t xReturn;
5059
5060         traceENTER_xTaskCallApplicationTaskHook( xTask, pvParameter );
5061
5062         /* If xTask is NULL then we are calling our own task hook. */
5063         if( xTask == NULL )
5064         {
5065             xTCB = pxCurrentTCB;
5066         }
5067         else
5068         {
5069             xTCB = xTask;
5070         }
5071
5072         if( xTCB->pxTaskTag != NULL )
5073         {
5074             xReturn = xTCB->pxTaskTag( pvParameter );
5075         }
5076         else
5077         {
5078             xReturn = pdFAIL;
5079         }
5080
5081         traceRETURN_xTaskCallApplicationTaskHook( xReturn );
5082
5083         return xReturn;
5084     }
5085
5086 #endif /* configUSE_APPLICATION_TASK_TAG */
5087 /*-----------------------------------------------------------*/
5088
5089 #if ( configNUMBER_OF_CORES == 1 )
5090     void vTaskSwitchContext( void )
5091     {
5092         traceENTER_vTaskSwitchContext();
5093
5094         if( uxSchedulerSuspended != ( UBaseType_t ) 0U )
5095         {
5096             /* The scheduler is currently suspended - do not allow a context
5097              * switch. */
5098             xYieldPendings[ 0 ] = pdTRUE;
5099         }
5100         else
5101         {
5102             xYieldPendings[ 0 ] = pdFALSE;
5103             traceTASK_SWITCHED_OUT();
5104
5105             #if ( configGENERATE_RUN_TIME_STATS == 1 )
5106             {
5107                 #ifdef portALT_GET_RUN_TIME_COUNTER_VALUE
5108                     portALT_GET_RUN_TIME_COUNTER_VALUE( ulTotalRunTime[ 0 ] );
5109                 #else
5110                     ulTotalRunTime[ 0 ] = portGET_RUN_TIME_COUNTER_VALUE();
5111                 #endif
5112
5113                 /* Add the amount of time the task has been running to the
5114                  * accumulated time so far.  The time the task started running was
5115                  * stored in ulTaskSwitchedInTime.  Note that there is no overflow
5116                  * protection here so count values are only valid until the timer
5117                  * overflows.  The guard against negative values is to protect
5118                  * against suspect run time stat counter implementations - which
5119                  * are provided by the application, not the kernel. */
5120                 if( ulTotalRunTime[ 0 ] > ulTaskSwitchedInTime[ 0 ] )
5121                 {
5122                     pxCurrentTCB->ulRunTimeCounter += ( ulTotalRunTime[ 0 ] - ulTaskSwitchedInTime[ 0 ] );
5123                 }
5124                 else
5125                 {
5126                     mtCOVERAGE_TEST_MARKER();
5127                 }
5128
5129                 ulTaskSwitchedInTime[ 0 ] = ulTotalRunTime[ 0 ];
5130             }
5131             #endif /* configGENERATE_RUN_TIME_STATS */
5132
5133             /* Check for stack overflow, if configured. */
5134             taskCHECK_FOR_STACK_OVERFLOW();
5135
5136             /* Before the currently running task is switched out, save its errno. */
5137             #if ( configUSE_POSIX_ERRNO == 1 )
5138             {
5139                 pxCurrentTCB->iTaskErrno = FreeRTOS_errno;
5140             }
5141             #endif
5142
5143             /* Select a new task to run using either the generic C or port
5144              * optimised asm code. */
5145             /* MISRA Ref 11.5.3 [Void pointer assignment] */
5146             /* More details at: https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/MISRA.md#rule-115 */
5147             /* coverity[misra_c_2012_rule_11_5_violation] */
5148             taskSELECT_HIGHEST_PRIORITY_TASK();
5149             traceTASK_SWITCHED_IN();
5150
5151             /* After the new task is switched in, update the global errno. */
5152             #if ( configUSE_POSIX_ERRNO == 1 )
5153             {
5154                 FreeRTOS_errno = pxCurrentTCB->iTaskErrno;
5155             }
5156             #endif
5157
5158             #if ( configUSE_C_RUNTIME_TLS_SUPPORT == 1 )
5159             {
5160                 /* Switch C-Runtime's TLS Block to point to the TLS
5161                  * Block specific to this task. */
5162                 configSET_TLS_BLOCK( pxCurrentTCB->xTLSBlock );
5163             }
5164             #endif
5165         }
5166
5167         traceRETURN_vTaskSwitchContext();
5168     }
5169 #else /* if ( configNUMBER_OF_CORES == 1 ) */
5170     void vTaskSwitchContext( BaseType_t xCoreID )
5171     {
5172         traceENTER_vTaskSwitchContext();
5173
5174         /* Acquire both locks:
5175          * - The ISR lock protects the ready list from simultaneous access by
5176          *   both other ISRs and tasks.
5177          * - We also take the task lock to pause here in case another core has
5178          *   suspended the scheduler. We don't want to simply set xYieldPending
5179          *   and move on if another core suspended the scheduler. We should only
5180          *   do that if the current core has suspended the scheduler. */
5181
5182         portGET_TASK_LOCK(); /* Must always acquire the task lock first. */
5183         portGET_ISR_LOCK();
5184         {
5185             /* vTaskSwitchContext() must never be called from within a critical section.
5186              * This is not necessarily true for single core FreeRTOS, but it is for this
5187              * SMP port. */
5188             configASSERT( portGET_CRITICAL_NESTING_COUNT() == 0 );
5189
5190             if( uxSchedulerSuspended != ( UBaseType_t ) 0U )
5191             {
5192                 /* The scheduler is currently suspended - do not allow a context
5193                  * switch. */
5194                 xYieldPendings[ xCoreID ] = pdTRUE;
5195             }
5196             else
5197             {
5198                 xYieldPendings[ xCoreID ] = pdFALSE;
5199                 traceTASK_SWITCHED_OUT();
5200
5201                 #if ( configGENERATE_RUN_TIME_STATS == 1 )
5202                 {
5203                     #ifdef portALT_GET_RUN_TIME_COUNTER_VALUE
5204                         portALT_GET_RUN_TIME_COUNTER_VALUE( ulTotalRunTime[ xCoreID ] );
5205                     #else
5206                         ulTotalRunTime[ xCoreID ] = portGET_RUN_TIME_COUNTER_VALUE();
5207                     #endif
5208
5209                     /* Add the amount of time the task has been running to the
5210                      * accumulated time so far.  The time the task started running was
5211                      * stored in ulTaskSwitchedInTime.  Note that there is no overflow
5212                      * protection here so count values are only valid until the timer
5213                      * overflows.  The guard against negative values is to protect
5214                      * against suspect run time stat counter implementations - which
5215                      * are provided by the application, not the kernel. */
5216                     if( ulTotalRunTime[ xCoreID ] > ulTaskSwitchedInTime[ xCoreID ] )
5217                     {
5218                         pxCurrentTCBs[ xCoreID ]->ulRunTimeCounter += ( ulTotalRunTime[ xCoreID ] - ulTaskSwitchedInTime[ xCoreID ] );
5219                     }
5220                     else
5221                     {
5222                         mtCOVERAGE_TEST_MARKER();
5223                     }
5224
5225                     ulTaskSwitchedInTime[ xCoreID ] = ulTotalRunTime[ xCoreID ];
5226                 }
5227                 #endif /* configGENERATE_RUN_TIME_STATS */
5228
5229                 /* Check for stack overflow, if configured. */
5230                 taskCHECK_FOR_STACK_OVERFLOW();
5231
5232                 /* Before the currently running task is switched out, save its errno. */
5233                 #if ( configUSE_POSIX_ERRNO == 1 )
5234                 {
5235                     pxCurrentTCBs[ xCoreID ]->iTaskErrno = FreeRTOS_errno;
5236                 }
5237                 #endif
5238
5239                 /* Select a new task to run. */
5240                 taskSELECT_HIGHEST_PRIORITY_TASK( xCoreID );
5241                 traceTASK_SWITCHED_IN();
5242
5243                 /* After the new task is switched in, update the global errno. */
5244                 #if ( configUSE_POSIX_ERRNO == 1 )
5245                 {
5246                     FreeRTOS_errno = pxCurrentTCBs[ xCoreID ]->iTaskErrno;
5247                 }
5248                 #endif
5249
5250                 #if ( configUSE_C_RUNTIME_TLS_SUPPORT == 1 )
5251                 {
5252                     /* Switch C-Runtime's TLS Block to point to the TLS
5253                      * Block specific to this task. */
5254                     configSET_TLS_BLOCK( pxCurrentTCBs[ xCoreID ]->xTLSBlock );
5255                 }
5256                 #endif
5257             }
5258         }
5259         portRELEASE_ISR_LOCK();
5260         portRELEASE_TASK_LOCK();
5261
5262         traceRETURN_vTaskSwitchContext();
5263     }
5264 #endif /* if ( configNUMBER_OF_CORES > 1 ) */
5265 /*-----------------------------------------------------------*/
5266
5267 void vTaskPlaceOnEventList( List_t * const pxEventList,
5268                             const TickType_t xTicksToWait )
5269 {
5270     traceENTER_vTaskPlaceOnEventList( pxEventList, xTicksToWait );
5271
5272     configASSERT( pxEventList );
5273
5274     /* THIS FUNCTION MUST BE CALLED WITH THE
5275      * SCHEDULER SUSPENDED AND THE QUEUE BEING ACCESSED LOCKED. */
5276
5277     /* Place the event list item of the TCB in the appropriate event list.
5278      * This is placed in the list in priority order so the highest priority task
5279      * is the first to be woken by the event.
5280      *
5281      * Note: Lists are sorted in ascending order by ListItem_t.xItemValue.
5282      * Normally, the xItemValue of a TCB's ListItem_t members is:
5283      *      xItemValue = ( configMAX_PRIORITIES - uxPriority )
5284      * Therefore, the event list is sorted in descending priority order.
5285      *
5286      * The queue that contains the event list is locked, preventing
5287      * simultaneous access from interrupts. */
5288     vListInsert( pxEventList, &( pxCurrentTCB->xEventListItem ) );
5289
5290     prvAddCurrentTaskToDelayedList( xTicksToWait, pdTRUE );
5291
5292     traceRETURN_vTaskPlaceOnEventList();
5293 }
5294 /*-----------------------------------------------------------*/
5295
5296 void vTaskPlaceOnUnorderedEventList( List_t * pxEventList,
5297                                      const TickType_t xItemValue,
5298                                      const TickType_t xTicksToWait )
5299 {
5300     traceENTER_vTaskPlaceOnUnorderedEventList( pxEventList, xItemValue, xTicksToWait );
5301
5302     configASSERT( pxEventList );
5303
5304     /* THIS FUNCTION MUST BE CALLED WITH THE SCHEDULER SUSPENDED.  It is used by
5305      * the event groups implementation. */
5306     configASSERT( uxSchedulerSuspended != ( UBaseType_t ) 0U );
5307
5308     /* Store the item value in the event list item.  It is safe to access the
5309      * event list item here as interrupts won't access the event list item of a
5310      * task that is not in the Blocked state. */
5311     listSET_LIST_ITEM_VALUE( &( pxCurrentTCB->xEventListItem ), xItemValue | taskEVENT_LIST_ITEM_VALUE_IN_USE );
5312
5313     /* Place the event list item of the TCB at the end of the appropriate event
5314      * list.  It is safe to access the event list here because it is part of an
5315      * event group implementation - and interrupts don't access event groups
5316      * directly (instead they access them indirectly by pending function calls to
5317      * the task level). */
5318     listINSERT_END( pxEventList, &( pxCurrentTCB->xEventListItem ) );
5319
5320     prvAddCurrentTaskToDelayedList( xTicksToWait, pdTRUE );
5321
5322     traceRETURN_vTaskPlaceOnUnorderedEventList();
5323 }
5324 /*-----------------------------------------------------------*/
5325
5326 #if ( configUSE_TIMERS == 1 )
5327
5328     void vTaskPlaceOnEventListRestricted( List_t * const pxEventList,
5329                                           TickType_t xTicksToWait,
5330                                           const BaseType_t xWaitIndefinitely )
5331     {
5332         traceENTER_vTaskPlaceOnEventListRestricted( pxEventList, xTicksToWait, xWaitIndefinitely );
5333
5334         configASSERT( pxEventList );
5335
5336         /* This function should not be called by application code hence the
5337          * 'Restricted' in its name.  It is not part of the public API.  It is
5338          * designed for use by kernel code, and has special calling requirements -
5339          * it should be called with the scheduler suspended. */
5340
5341
5342         /* Place the event list item of the TCB in the appropriate event list.
5343          * In this case it is assume that this is the only task that is going to
5344          * be waiting on this event list, so the faster vListInsertEnd() function
5345          * can be used in place of vListInsert. */
5346         listINSERT_END( pxEventList, &( pxCurrentTCB->xEventListItem ) );
5347
5348         /* If the task should block indefinitely then set the block time to a
5349          * value that will be recognised as an indefinite delay inside the
5350          * prvAddCurrentTaskToDelayedList() function. */
5351         if( xWaitIndefinitely != pdFALSE )
5352         {
5353             xTicksToWait = portMAX_DELAY;
5354         }
5355
5356         traceTASK_DELAY_UNTIL( ( xTickCount + xTicksToWait ) );
5357         prvAddCurrentTaskToDelayedList( xTicksToWait, xWaitIndefinitely );
5358
5359         traceRETURN_vTaskPlaceOnEventListRestricted();
5360     }
5361
5362 #endif /* configUSE_TIMERS */
5363 /*-----------------------------------------------------------*/
5364
5365 BaseType_t xTaskRemoveFromEventList( const List_t * const pxEventList )
5366 {
5367     TCB_t * pxUnblockedTCB;
5368     BaseType_t xReturn;
5369
5370     traceENTER_xTaskRemoveFromEventList( pxEventList );
5371
5372     /* THIS FUNCTION MUST BE CALLED FROM A CRITICAL SECTION.  It can also be
5373      * called from a critical section within an ISR. */
5374
5375     /* The event list is sorted in priority order, so the first in the list can
5376      * be removed as it is known to be the highest priority.  Remove the TCB from
5377      * the delayed list, and add it to the ready list.
5378      *
5379      * If an event is for a queue that is locked then this function will never
5380      * get called - the lock count on the queue will get modified instead.  This
5381      * means exclusive access to the event list is guaranteed here.
5382      *
5383      * This function assumes that a check has already been made to ensure that
5384      * pxEventList is not empty. */
5385     /* MISRA Ref 11.5.3 [Void pointer assignment] */
5386     /* More details at: https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/MISRA.md#rule-115 */
5387     /* coverity[misra_c_2012_rule_11_5_violation] */
5388     pxUnblockedTCB = listGET_OWNER_OF_HEAD_ENTRY( pxEventList );
5389     configASSERT( pxUnblockedTCB );
5390     listREMOVE_ITEM( &( pxUnblockedTCB->xEventListItem ) );
5391
5392     if( uxSchedulerSuspended == ( UBaseType_t ) 0U )
5393     {
5394         listREMOVE_ITEM( &( pxUnblockedTCB->xStateListItem ) );
5395         prvAddTaskToReadyList( pxUnblockedTCB );
5396
5397         #if ( configUSE_TICKLESS_IDLE != 0 )
5398         {
5399             /* If a task is blocked on a kernel object then xNextTaskUnblockTime
5400              * might be set to the blocked task's time out time.  If the task is
5401              * unblocked for a reason other than a timeout xNextTaskUnblockTime is
5402              * normally left unchanged, because it is automatically reset to a new
5403              * value when the tick count equals xNextTaskUnblockTime.  However if
5404              * tickless idling is used it might be more important to enter sleep mode
5405              * at the earliest possible time - so reset xNextTaskUnblockTime here to
5406              * ensure it is updated at the earliest possible time. */
5407             prvResetNextTaskUnblockTime();
5408         }
5409         #endif
5410     }
5411     else
5412     {
5413         /* The delayed and ready lists cannot be accessed, so hold this task
5414          * pending until the scheduler is resumed. */
5415         listINSERT_END( &( xPendingReadyList ), &( pxUnblockedTCB->xEventListItem ) );
5416     }
5417
5418     #if ( configNUMBER_OF_CORES == 1 )
5419     {
5420         if( pxUnblockedTCB->uxPriority > pxCurrentTCB->uxPriority )
5421         {
5422             /* Return true if the task removed from the event list has a higher
5423              * priority than the calling task.  This allows the calling task to know if
5424              * it should force a context switch now. */
5425             xReturn = pdTRUE;
5426
5427             /* Mark that a yield is pending in case the user is not using the
5428              * "xHigherPriorityTaskWoken" parameter to an ISR safe FreeRTOS function. */
5429             xYieldPendings[ 0 ] = pdTRUE;
5430         }
5431         else
5432         {
5433             xReturn = pdFALSE;
5434         }
5435     }
5436     #else /* #if ( configNUMBER_OF_CORES == 1 ) */
5437     {
5438         xReturn = pdFALSE;
5439
5440         #if ( configUSE_PREEMPTION == 1 )
5441         {
5442             prvYieldForTask( pxUnblockedTCB );
5443
5444             if( xYieldPendings[ portGET_CORE_ID() ] != pdFALSE )
5445             {
5446                 xReturn = pdTRUE;
5447             }
5448         }
5449         #endif /* #if ( configUSE_PREEMPTION == 1 ) */
5450     }
5451     #endif /* #if ( configNUMBER_OF_CORES == 1 ) */
5452
5453     traceRETURN_xTaskRemoveFromEventList( xReturn );
5454     return xReturn;
5455 }
5456 /*-----------------------------------------------------------*/
5457
5458 void vTaskRemoveFromUnorderedEventList( ListItem_t * pxEventListItem,
5459                                         const TickType_t xItemValue )
5460 {
5461     TCB_t * pxUnblockedTCB;
5462
5463     traceENTER_vTaskRemoveFromUnorderedEventList( pxEventListItem, xItemValue );
5464
5465     /* THIS FUNCTION MUST BE CALLED WITH THE SCHEDULER SUSPENDED.  It is used by
5466      * the event flags implementation. */
5467     configASSERT( uxSchedulerSuspended != ( UBaseType_t ) 0U );
5468
5469     /* Store the new item value in the event list. */
5470     listSET_LIST_ITEM_VALUE( pxEventListItem, xItemValue | taskEVENT_LIST_ITEM_VALUE_IN_USE );
5471
5472     /* Remove the event list form the event flag.  Interrupts do not access
5473      * event flags. */
5474     /* MISRA Ref 11.5.3 [Void pointer assignment] */
5475     /* More details at: https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/MISRA.md#rule-115 */
5476     /* coverity[misra_c_2012_rule_11_5_violation] */
5477     pxUnblockedTCB = listGET_LIST_ITEM_OWNER( pxEventListItem );
5478     configASSERT( pxUnblockedTCB );
5479     listREMOVE_ITEM( pxEventListItem );
5480
5481     #if ( configUSE_TICKLESS_IDLE != 0 )
5482     {
5483         /* If a task is blocked on a kernel object then xNextTaskUnblockTime
5484          * might be set to the blocked task's time out time.  If the task is
5485          * unblocked for a reason other than a timeout xNextTaskUnblockTime is
5486          * normally left unchanged, because it is automatically reset to a new
5487          * value when the tick count equals xNextTaskUnblockTime.  However if
5488          * tickless idling is used it might be more important to enter sleep mode
5489          * at the earliest possible time - so reset xNextTaskUnblockTime here to
5490          * ensure it is updated at the earliest possible time. */
5491         prvResetNextTaskUnblockTime();
5492     }
5493     #endif
5494
5495     /* Remove the task from the delayed list and add it to the ready list.  The
5496      * scheduler is suspended so interrupts will not be accessing the ready
5497      * lists. */
5498     listREMOVE_ITEM( &( pxUnblockedTCB->xStateListItem ) );
5499     prvAddTaskToReadyList( pxUnblockedTCB );
5500
5501     #if ( configNUMBER_OF_CORES == 1 )
5502     {
5503         if( pxUnblockedTCB->uxPriority > pxCurrentTCB->uxPriority )
5504         {
5505             /* The unblocked task has a priority above that of the calling task, so
5506              * a context switch is required.  This function is called with the
5507              * scheduler suspended so xYieldPending is set so the context switch
5508              * occurs immediately that the scheduler is resumed (unsuspended). */
5509             xYieldPendings[ 0 ] = pdTRUE;
5510         }
5511     }
5512     #else /* #if ( configNUMBER_OF_CORES == 1 ) */
5513     {
5514         #if ( configUSE_PREEMPTION == 1 )
5515         {
5516             taskENTER_CRITICAL();
5517             {
5518                 prvYieldForTask( pxUnblockedTCB );
5519             }
5520             taskEXIT_CRITICAL();
5521         }
5522         #endif
5523     }
5524     #endif /* #if ( configNUMBER_OF_CORES == 1 ) */
5525
5526     traceRETURN_vTaskRemoveFromUnorderedEventList();
5527 }
5528 /*-----------------------------------------------------------*/
5529
5530 void vTaskSetTimeOutState( TimeOut_t * const pxTimeOut )
5531 {
5532     traceENTER_vTaskSetTimeOutState( pxTimeOut );
5533
5534     configASSERT( pxTimeOut );
5535     taskENTER_CRITICAL();
5536     {
5537         pxTimeOut->xOverflowCount = xNumOfOverflows;
5538         pxTimeOut->xTimeOnEntering = xTickCount;
5539     }
5540     taskEXIT_CRITICAL();
5541
5542     traceRETURN_vTaskSetTimeOutState();
5543 }
5544 /*-----------------------------------------------------------*/
5545
5546 void vTaskInternalSetTimeOutState( TimeOut_t * const pxTimeOut )
5547 {
5548     traceENTER_vTaskInternalSetTimeOutState( pxTimeOut );
5549
5550     /* For internal use only as it does not use a critical section. */
5551     pxTimeOut->xOverflowCount = xNumOfOverflows;
5552     pxTimeOut->xTimeOnEntering = xTickCount;
5553
5554     traceRETURN_vTaskInternalSetTimeOutState();
5555 }
5556 /*-----------------------------------------------------------*/
5557
5558 BaseType_t xTaskCheckForTimeOut( TimeOut_t * const pxTimeOut,
5559                                  TickType_t * const pxTicksToWait )
5560 {
5561     BaseType_t xReturn;
5562
5563     traceENTER_xTaskCheckForTimeOut( pxTimeOut, pxTicksToWait );
5564
5565     configASSERT( pxTimeOut );
5566     configASSERT( pxTicksToWait );
5567
5568     taskENTER_CRITICAL();
5569     {
5570         /* Minor optimisation.  The tick count cannot change in this block. */
5571         const TickType_t xConstTickCount = xTickCount;
5572         const TickType_t xElapsedTime = xConstTickCount - pxTimeOut->xTimeOnEntering;
5573
5574         #if ( INCLUDE_xTaskAbortDelay == 1 )
5575             if( pxCurrentTCB->ucDelayAborted != ( uint8_t ) pdFALSE )
5576             {
5577                 /* The delay was aborted, which is not the same as a time out,
5578                  * but has the same result. */
5579                 pxCurrentTCB->ucDelayAborted = pdFALSE;
5580                 xReturn = pdTRUE;
5581             }
5582             else
5583         #endif
5584
5585         #if ( INCLUDE_vTaskSuspend == 1 )
5586             if( *pxTicksToWait == portMAX_DELAY )
5587             {
5588                 /* If INCLUDE_vTaskSuspend is set to 1 and the block time
5589                  * specified is the maximum block time then the task should block
5590                  * indefinitely, and therefore never time out. */
5591                 xReturn = pdFALSE;
5592             }
5593             else
5594         #endif
5595
5596         if( ( xNumOfOverflows != pxTimeOut->xOverflowCount ) && ( xConstTickCount >= pxTimeOut->xTimeOnEntering ) ) /*lint !e525 Indentation preferred as is to make code within pre-processor directives clearer. */
5597         {
5598             /* The tick count is greater than the time at which
5599              * vTaskSetTimeout() was called, but has also overflowed since
5600              * vTaskSetTimeOut() was called.  It must have wrapped all the way
5601              * around and gone past again. This passed since vTaskSetTimeout()
5602              * was called. */
5603             xReturn = pdTRUE;
5604             *pxTicksToWait = ( TickType_t ) 0;
5605         }
5606         else if( xElapsedTime < *pxTicksToWait ) /*lint !e961 Explicit casting is only redundant with some compilers, whereas others require it to prevent integer conversion errors. */
5607         {
5608             /* Not a genuine timeout. Adjust parameters for time remaining. */
5609             *pxTicksToWait -= xElapsedTime;
5610             vTaskInternalSetTimeOutState( pxTimeOut );
5611             xReturn = pdFALSE;
5612         }
5613         else
5614         {
5615             *pxTicksToWait = ( TickType_t ) 0;
5616             xReturn = pdTRUE;
5617         }
5618     }
5619     taskEXIT_CRITICAL();
5620
5621     traceRETURN_xTaskCheckForTimeOut( xReturn );
5622
5623     return xReturn;
5624 }
5625 /*-----------------------------------------------------------*/
5626
5627 void vTaskMissedYield( void )
5628 {
5629     traceENTER_vTaskMissedYield();
5630
5631     /* Must be called from within a critical section. */
5632     xYieldPendings[ portGET_CORE_ID() ] = pdTRUE;
5633
5634     traceRETURN_vTaskMissedYield();
5635 }
5636 /*-----------------------------------------------------------*/
5637
5638 #if ( configUSE_TRACE_FACILITY == 1 )
5639
5640     UBaseType_t uxTaskGetTaskNumber( TaskHandle_t xTask )
5641     {
5642         UBaseType_t uxReturn;
5643         TCB_t const * pxTCB;
5644
5645         traceENTER_uxTaskGetTaskNumber( xTask );
5646
5647         if( xTask != NULL )
5648         {
5649             pxTCB = xTask;
5650             uxReturn = pxTCB->uxTaskNumber;
5651         }
5652         else
5653         {
5654             uxReturn = 0U;
5655         }
5656
5657         traceRETURN_uxTaskGetTaskNumber( uxReturn );
5658
5659         return uxReturn;
5660     }
5661
5662 #endif /* configUSE_TRACE_FACILITY */
5663 /*-----------------------------------------------------------*/
5664
5665 #if ( configUSE_TRACE_FACILITY == 1 )
5666
5667     void vTaskSetTaskNumber( TaskHandle_t xTask,
5668                              const UBaseType_t uxHandle )
5669     {
5670         TCB_t * pxTCB;
5671
5672         traceENTER_vTaskSetTaskNumber( xTask, uxHandle );
5673
5674         if( xTask != NULL )
5675         {
5676             pxTCB = xTask;
5677             pxTCB->uxTaskNumber = uxHandle;
5678         }
5679
5680         traceRETURN_vTaskSetTaskNumber();
5681     }
5682
5683 #endif /* configUSE_TRACE_FACILITY */
5684 /*-----------------------------------------------------------*/
5685
5686 /*
5687  * -----------------------------------------------------------
5688  * The passive idle task.
5689  * ----------------------------------------------------------
5690  *
5691  * The passive idle task is used for all the additional cores in a SMP
5692  * system. There must be only 1 active idle task and the rest are passive
5693  * idle tasks.
5694  *
5695  * The portTASK_FUNCTION() macro is used to allow port/compiler specific
5696  * language extensions.  The equivalent prototype for this function is:
5697  *
5698  * void prvPassiveIdleTask( void *pvParameters );
5699  */
5700
5701 #if ( configNUMBER_OF_CORES > 1 )
5702     static portTASK_FUNCTION( prvPassiveIdleTask, pvParameters )
5703     {
5704         ( void ) pvParameters;
5705
5706         taskYIELD();
5707
5708         for( ; configCONTROL_INFINITE_LOOP(); )
5709         {
5710             #if ( configUSE_PREEMPTION == 0 )
5711             {
5712                 /* If we are not using preemption we keep forcing a task switch to
5713                  * see if any other task has become available.  If we are using
5714                  * preemption we don't need to do this as any task becoming available
5715                  * will automatically get the processor anyway. */
5716                 taskYIELD();
5717             }
5718             #endif /* configUSE_PREEMPTION */
5719
5720             #if ( ( configUSE_PREEMPTION == 1 ) && ( configIDLE_SHOULD_YIELD == 1 ) )
5721             {
5722                 /* When using preemption tasks of equal priority will be
5723                  * timesliced.  If a task that is sharing the idle priority is ready
5724                  * to run then the idle task should yield before the end of the
5725                  * timeslice.
5726                  *
5727                  * A critical region is not required here as we are just reading from
5728                  * the list, and an occasional incorrect value will not matter.  If
5729                  * the ready list at the idle priority contains one more task than the
5730                  * number of idle tasks, which is equal to the configured numbers of cores
5731                  * then a task other than the idle task is ready to execute. */
5732                 if( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ tskIDLE_PRIORITY ] ) ) > ( UBaseType_t ) configNUMBER_OF_CORES )
5733                 {
5734                     taskYIELD();
5735                 }
5736                 else
5737                 {
5738                     mtCOVERAGE_TEST_MARKER();
5739                 }
5740             }
5741             #endif /* ( ( configUSE_PREEMPTION == 1 ) && ( configIDLE_SHOULD_YIELD == 1 ) ) */
5742
5743             #if ( configUSE_PASSIVE_IDLE_HOOK == 1 )
5744             {
5745                 /* Call the user defined function from within the idle task.  This
5746                  * allows the application designer to add background functionality
5747                  * without the overhead of a separate task.
5748                  *
5749                  * This hook is intended to manage core activity such as disabling cores that go idle.
5750                  *
5751                  * NOTE: vApplicationPassiveIdleHook() MUST NOT, UNDER ANY CIRCUMSTANCES,
5752                  * CALL A FUNCTION THAT MIGHT BLOCK. */
5753                 vApplicationPassiveIdleHook();
5754             }
5755             #endif /* configUSE_PASSIVE_IDLE_HOOK */
5756         }
5757     }
5758 #endif /* #if ( configNUMBER_OF_CORES > 1 ) */
5759
5760 /*
5761  * -----------------------------------------------------------
5762  * The idle task.
5763  * ----------------------------------------------------------
5764  *
5765  * The portTASK_FUNCTION() macro is used to allow port/compiler specific
5766  * language extensions.  The equivalent prototype for this function is:
5767  *
5768  * void prvIdleTask( void *pvParameters );
5769  *
5770  */
5771
5772 static portTASK_FUNCTION( prvIdleTask, pvParameters )
5773 {
5774     /* Stop warnings. */
5775     ( void ) pvParameters;
5776
5777     /** THIS IS THE RTOS IDLE TASK - WHICH IS CREATED AUTOMATICALLY WHEN THE
5778      * SCHEDULER IS STARTED. **/
5779
5780     /* In case a task that has a secure context deletes itself, in which case
5781      * the idle task is responsible for deleting the task's secure context, if
5782      * any. */
5783     portALLOCATE_SECURE_CONTEXT( configMINIMAL_SECURE_STACK_SIZE );
5784
5785     #if ( configNUMBER_OF_CORES > 1 )
5786     {
5787         /* SMP all cores start up in the idle task. This initial yield gets the application
5788          * tasks started. */
5789         taskYIELD();
5790     }
5791     #endif /* #if ( configNUMBER_OF_CORES > 1 ) */
5792
5793     for( ; configCONTROL_INFINITE_LOOP(); )
5794     {
5795         /* See if any tasks have deleted themselves - if so then the idle task
5796          * is responsible for freeing the deleted task's TCB and stack. */
5797         prvCheckTasksWaitingTermination();
5798
5799         #if ( configUSE_PREEMPTION == 0 )
5800         {
5801             /* If we are not using preemption we keep forcing a task switch to
5802              * see if any other task has become available.  If we are using
5803              * preemption we don't need to do this as any task becoming available
5804              * will automatically get the processor anyway. */
5805             taskYIELD();
5806         }
5807         #endif /* configUSE_PREEMPTION */
5808
5809         #if ( ( configUSE_PREEMPTION == 1 ) && ( configIDLE_SHOULD_YIELD == 1 ) )
5810         {
5811             /* When using preemption tasks of equal priority will be
5812              * timesliced.  If a task that is sharing the idle priority is ready
5813              * to run then the idle task should yield before the end of the
5814              * timeslice.
5815              *
5816              * A critical region is not required here as we are just reading from
5817              * the list, and an occasional incorrect value will not matter.  If
5818              * the ready list at the idle priority contains one more task than the
5819              * number of idle tasks, which is equal to the configured numbers of cores
5820              * then a task other than the idle task is ready to execute. */
5821             if( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ tskIDLE_PRIORITY ] ) ) > ( UBaseType_t ) configNUMBER_OF_CORES )
5822             {
5823                 taskYIELD();
5824             }
5825             else
5826             {
5827                 mtCOVERAGE_TEST_MARKER();
5828             }
5829         }
5830         #endif /* ( ( configUSE_PREEMPTION == 1 ) && ( configIDLE_SHOULD_YIELD == 1 ) ) */
5831
5832         #if ( configUSE_IDLE_HOOK == 1 )
5833         {
5834             /* Call the user defined function from within the idle task. */
5835             vApplicationIdleHook();
5836         }
5837         #endif /* configUSE_IDLE_HOOK */
5838
5839         /* This conditional compilation should use inequality to 0, not equality
5840          * to 1.  This is to ensure portSUPPRESS_TICKS_AND_SLEEP() is called when
5841          * user defined low power mode  implementations require
5842          * configUSE_TICKLESS_IDLE to be set to a value other than 1. */
5843         #if ( configUSE_TICKLESS_IDLE != 0 )
5844         {
5845             TickType_t xExpectedIdleTime;
5846
5847             /* It is not desirable to suspend then resume the scheduler on
5848              * each iteration of the idle task.  Therefore, a preliminary
5849              * test of the expected idle time is performed without the
5850              * scheduler suspended.  The result here is not necessarily
5851              * valid. */
5852             xExpectedIdleTime = prvGetExpectedIdleTime();
5853
5854             if( xExpectedIdleTime >= ( TickType_t ) configEXPECTED_IDLE_TIME_BEFORE_SLEEP )
5855             {
5856                 vTaskSuspendAll();
5857                 {
5858                     /* Now the scheduler is suspended, the expected idle
5859                      * time can be sampled again, and this time its value can
5860                      * be used. */
5861                     configASSERT( xNextTaskUnblockTime >= xTickCount );
5862                     xExpectedIdleTime = prvGetExpectedIdleTime();
5863
5864                     /* Define the following macro to set xExpectedIdleTime to 0
5865                      * if the application does not want
5866                      * portSUPPRESS_TICKS_AND_SLEEP() to be called. */
5867                     configPRE_SUPPRESS_TICKS_AND_SLEEP_PROCESSING( xExpectedIdleTime );
5868
5869                     if( xExpectedIdleTime >= ( TickType_t ) configEXPECTED_IDLE_TIME_BEFORE_SLEEP )
5870                     {
5871                         traceLOW_POWER_IDLE_BEGIN();
5872                         portSUPPRESS_TICKS_AND_SLEEP( xExpectedIdleTime );
5873                         traceLOW_POWER_IDLE_END();
5874                     }
5875                     else
5876                     {
5877                         mtCOVERAGE_TEST_MARKER();
5878                     }
5879                 }
5880                 ( void ) xTaskResumeAll();
5881             }
5882             else
5883             {
5884                 mtCOVERAGE_TEST_MARKER();
5885             }
5886         }
5887         #endif /* configUSE_TICKLESS_IDLE */
5888
5889         #if ( ( configNUMBER_OF_CORES > 1 ) && ( configUSE_PASSIVE_IDLE_HOOK == 1 ) )
5890         {
5891             /* Call the user defined function from within the idle task.  This
5892              * allows the application designer to add background functionality
5893              * without the overhead of a separate task.
5894              *
5895              * This hook is intended to manage core activity such as disabling cores that go idle.
5896              *
5897              * NOTE: vApplicationPassiveIdleHook() MUST NOT, UNDER ANY CIRCUMSTANCES,
5898              * CALL A FUNCTION THAT MIGHT BLOCK. */
5899             vApplicationPassiveIdleHook();
5900         }
5901         #endif /* #if ( ( configNUMBER_OF_CORES > 1 ) && ( configUSE_PASSIVE_IDLE_HOOK == 1 ) ) */
5902     }
5903 }
5904 /*-----------------------------------------------------------*/
5905
5906 #if ( configUSE_TICKLESS_IDLE != 0 )
5907
5908     eSleepModeStatus eTaskConfirmSleepModeStatus( void )
5909     {
5910         #if ( INCLUDE_vTaskSuspend == 1 )
5911             /* The idle task exists in addition to the application tasks. */
5912             const UBaseType_t uxNonApplicationTasks = configNUMBER_OF_CORES;
5913         #endif /* INCLUDE_vTaskSuspend */
5914
5915         eSleepModeStatus eReturn = eStandardSleep;
5916
5917         traceENTER_eTaskConfirmSleepModeStatus();
5918
5919         /* This function must be called from a critical section. */
5920
5921         if( listCURRENT_LIST_LENGTH( &xPendingReadyList ) != 0U )
5922         {
5923             /* A task was made ready while the scheduler was suspended. */
5924             eReturn = eAbortSleep;
5925         }
5926         else if( xYieldPendings[ portGET_CORE_ID() ] != pdFALSE )
5927         {
5928             /* A yield was pended while the scheduler was suspended. */
5929             eReturn = eAbortSleep;
5930         }
5931         else if( xPendedTicks != 0U )
5932         {
5933             /* A tick interrupt has already occurred but was held pending
5934              * because the scheduler is suspended. */
5935             eReturn = eAbortSleep;
5936         }
5937
5938         #if ( INCLUDE_vTaskSuspend == 1 )
5939             else if( listCURRENT_LIST_LENGTH( &xSuspendedTaskList ) == ( uxCurrentNumberOfTasks - uxNonApplicationTasks ) )
5940             {
5941                 /* If all the tasks are in the suspended list (which might mean they
5942                  * have an infinite block time rather than actually being suspended)
5943                  * then it is safe to turn all clocks off and just wait for external
5944                  * interrupts. */
5945                 eReturn = eNoTasksWaitingTimeout;
5946             }
5947         #endif /* INCLUDE_vTaskSuspend */
5948         else
5949         {
5950             mtCOVERAGE_TEST_MARKER();
5951         }
5952
5953         traceRETURN_eTaskConfirmSleepModeStatus( eReturn );
5954
5955         return eReturn;
5956     }
5957
5958 #endif /* configUSE_TICKLESS_IDLE */
5959 /*-----------------------------------------------------------*/
5960
5961 #if ( configNUM_THREAD_LOCAL_STORAGE_POINTERS != 0 )
5962
5963     void vTaskSetThreadLocalStoragePointer( TaskHandle_t xTaskToSet,
5964                                             BaseType_t xIndex,
5965                                             void * pvValue )
5966     {
5967         TCB_t * pxTCB;
5968
5969         traceENTER_vTaskSetThreadLocalStoragePointer( xTaskToSet, xIndex, pvValue );
5970
5971         if( ( xIndex >= 0 ) &&
5972             ( xIndex < ( BaseType_t ) configNUM_THREAD_LOCAL_STORAGE_POINTERS ) )
5973         {
5974             pxTCB = prvGetTCBFromHandle( xTaskToSet );
5975             configASSERT( pxTCB != NULL );
5976             pxTCB->pvThreadLocalStoragePointers[ xIndex ] = pvValue;
5977         }
5978
5979         traceRETURN_vTaskSetThreadLocalStoragePointer();
5980     }
5981
5982 #endif /* configNUM_THREAD_LOCAL_STORAGE_POINTERS */
5983 /*-----------------------------------------------------------*/
5984
5985 #if ( configNUM_THREAD_LOCAL_STORAGE_POINTERS != 0 )
5986
5987     void * pvTaskGetThreadLocalStoragePointer( TaskHandle_t xTaskToQuery,
5988                                                BaseType_t xIndex )
5989     {
5990         void * pvReturn = NULL;
5991         TCB_t * pxTCB;
5992
5993         traceENTER_pvTaskGetThreadLocalStoragePointer( xTaskToQuery, xIndex );
5994
5995         if( ( xIndex >= 0 ) &&
5996             ( xIndex < ( BaseType_t ) configNUM_THREAD_LOCAL_STORAGE_POINTERS ) )
5997         {
5998             pxTCB = prvGetTCBFromHandle( xTaskToQuery );
5999             pvReturn = pxTCB->pvThreadLocalStoragePointers[ xIndex ];
6000         }
6001         else
6002         {
6003             pvReturn = NULL;
6004         }
6005
6006         traceRETURN_pvTaskGetThreadLocalStoragePointer( pvReturn );
6007
6008         return pvReturn;
6009     }
6010
6011 #endif /* configNUM_THREAD_LOCAL_STORAGE_POINTERS */
6012 /*-----------------------------------------------------------*/
6013
6014 #if ( portUSING_MPU_WRAPPERS == 1 )
6015
6016     void vTaskAllocateMPURegions( TaskHandle_t xTaskToModify,
6017                                   const MemoryRegion_t * const pxRegions )
6018     {
6019         TCB_t * pxTCB;
6020
6021         traceENTER_vTaskAllocateMPURegions( xTaskToModify, pxRegions );
6022
6023         /* If null is passed in here then we are modifying the MPU settings of
6024          * the calling task. */
6025         pxTCB = prvGetTCBFromHandle( xTaskToModify );
6026
6027         vPortStoreTaskMPUSettings( &( pxTCB->xMPUSettings ), pxRegions, NULL, 0 );
6028
6029         traceRETURN_vTaskAllocateMPURegions();
6030     }
6031
6032 #endif /* portUSING_MPU_WRAPPERS */
6033 /*-----------------------------------------------------------*/
6034
6035 static void prvInitialiseTaskLists( void )
6036 {
6037     UBaseType_t uxPriority;
6038
6039     for( uxPriority = ( UBaseType_t ) 0U; uxPriority < ( UBaseType_t ) configMAX_PRIORITIES; uxPriority++ )
6040     {
6041         vListInitialise( &( pxReadyTasksLists[ uxPriority ] ) );
6042     }
6043
6044     vListInitialise( &xDelayedTaskList1 );
6045     vListInitialise( &xDelayedTaskList2 );
6046     vListInitialise( &xPendingReadyList );
6047
6048     #if ( INCLUDE_vTaskDelete == 1 )
6049     {
6050         vListInitialise( &xTasksWaitingTermination );
6051     }
6052     #endif /* INCLUDE_vTaskDelete */
6053
6054     #if ( INCLUDE_vTaskSuspend == 1 )
6055     {
6056         vListInitialise( &xSuspendedTaskList );
6057     }
6058     #endif /* INCLUDE_vTaskSuspend */
6059
6060     /* Start with pxDelayedTaskList using list1 and the pxOverflowDelayedTaskList
6061      * using list2. */
6062     pxDelayedTaskList = &xDelayedTaskList1;
6063     pxOverflowDelayedTaskList = &xDelayedTaskList2;
6064 }
6065 /*-----------------------------------------------------------*/
6066
6067 static void prvCheckTasksWaitingTermination( void )
6068 {
6069     /** THIS FUNCTION IS CALLED FROM THE RTOS IDLE TASK **/
6070
6071     #if ( INCLUDE_vTaskDelete == 1 )
6072     {
6073         TCB_t * pxTCB;
6074
6075         /* uxDeletedTasksWaitingCleanUp is used to prevent taskENTER_CRITICAL()
6076          * being called too often in the idle task. */
6077         while( uxDeletedTasksWaitingCleanUp > ( UBaseType_t ) 0U )
6078         {
6079             #if ( configNUMBER_OF_CORES == 1 )
6080             {
6081                 taskENTER_CRITICAL();
6082                 {
6083                     {
6084                         /* MISRA Ref 11.5.3 [Void pointer assignment] */
6085                         /* More details at: https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/MISRA.md#rule-115 */
6086                         /* coverity[misra_c_2012_rule_11_5_violation] */
6087                         pxTCB = listGET_OWNER_OF_HEAD_ENTRY( ( &xTasksWaitingTermination ) );
6088                         ( void ) uxListRemove( &( pxTCB->xStateListItem ) );
6089                         --uxCurrentNumberOfTasks;
6090                         --uxDeletedTasksWaitingCleanUp;
6091                     }
6092                 }
6093                 taskEXIT_CRITICAL();
6094
6095                 prvDeleteTCB( pxTCB );
6096             }
6097             #else /* #if( configNUMBER_OF_CORES == 1 ) */
6098             {
6099                 pxTCB = NULL;
6100
6101                 taskENTER_CRITICAL();
6102                 {
6103                     /* For SMP, multiple idles can be running simultaneously
6104                      * and we need to check that other idles did not cleanup while we were
6105                      * waiting to enter the critical section. */
6106                     if( uxDeletedTasksWaitingCleanUp > ( UBaseType_t ) 0U )
6107                     {
6108                         /* MISRA Ref 11.5.3 [Void pointer assignment] */
6109                         /* More details at: https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/MISRA.md#rule-115 */
6110                         /* coverity[misra_c_2012_rule_11_5_violation] */
6111                         pxTCB = listGET_OWNER_OF_HEAD_ENTRY( ( &xTasksWaitingTermination ) );
6112
6113                         if( pxTCB->xTaskRunState == taskTASK_NOT_RUNNING )
6114                         {
6115                             ( void ) uxListRemove( &( pxTCB->xStateListItem ) );
6116                             --uxCurrentNumberOfTasks;
6117                             --uxDeletedTasksWaitingCleanUp;
6118                         }
6119                         else
6120                         {
6121                             /* The TCB to be deleted still has not yet been switched out
6122                              * by the scheduler, so we will just exit this loop early and
6123                              * try again next time. */
6124                             taskEXIT_CRITICAL();
6125                             break;
6126                         }
6127                     }
6128                 }
6129                 taskEXIT_CRITICAL();
6130
6131                 if( pxTCB != NULL )
6132                 {
6133                     prvDeleteTCB( pxTCB );
6134                 }
6135             }
6136             #endif /* #if( configNUMBER_OF_CORES == 1 ) */
6137         }
6138     }
6139     #endif /* INCLUDE_vTaskDelete */
6140 }
6141 /*-----------------------------------------------------------*/
6142
6143 #if ( configUSE_TRACE_FACILITY == 1 )
6144
6145     void vTaskGetInfo( TaskHandle_t xTask,
6146                        TaskStatus_t * pxTaskStatus,
6147                        BaseType_t xGetFreeStackSpace,
6148                        eTaskState eState )
6149     {
6150         TCB_t * pxTCB;
6151
6152         traceENTER_vTaskGetInfo( xTask, pxTaskStatus, xGetFreeStackSpace, eState );
6153
6154         /* xTask is NULL then get the state of the calling task. */
6155         pxTCB = prvGetTCBFromHandle( xTask );
6156
6157         pxTaskStatus->xHandle = pxTCB;
6158         pxTaskStatus->pcTaskName = ( const char * ) &( pxTCB->pcTaskName[ 0 ] );
6159         pxTaskStatus->uxCurrentPriority = pxTCB->uxPriority;
6160         pxTaskStatus->pxStackBase = pxTCB->pxStack;
6161         #if ( ( portSTACK_GROWTH > 0 ) || ( configRECORD_STACK_HIGH_ADDRESS == 1 ) )
6162             pxTaskStatus->pxTopOfStack = ( StackType_t * ) pxTCB->pxTopOfStack;
6163             pxTaskStatus->pxEndOfStack = pxTCB->pxEndOfStack;
6164         #endif
6165         pxTaskStatus->xTaskNumber = pxTCB->uxTCBNumber;
6166
6167         #if ( ( configUSE_CORE_AFFINITY == 1 ) && ( configNUMBER_OF_CORES > 1 ) )
6168         {
6169             pxTaskStatus->uxCoreAffinityMask = pxTCB->uxCoreAffinityMask;
6170         }
6171         #endif
6172
6173         #if ( configUSE_MUTEXES == 1 )
6174         {
6175             pxTaskStatus->uxBasePriority = pxTCB->uxBasePriority;
6176         }
6177         #else
6178         {
6179             pxTaskStatus->uxBasePriority = 0;
6180         }
6181         #endif
6182
6183         #if ( configGENERATE_RUN_TIME_STATS == 1 )
6184         {
6185             pxTaskStatus->ulRunTimeCounter = pxTCB->ulRunTimeCounter;
6186         }
6187         #else
6188         {
6189             pxTaskStatus->ulRunTimeCounter = ( configRUN_TIME_COUNTER_TYPE ) 0;
6190         }
6191         #endif
6192
6193         /* Obtaining the task state is a little fiddly, so is only done if the
6194          * value of eState passed into this function is eInvalid - otherwise the
6195          * state is just set to whatever is passed in. */
6196         if( eState != eInvalid )
6197         {
6198             if( taskTASK_IS_RUNNING( pxTCB ) == pdTRUE )
6199             {
6200                 pxTaskStatus->eCurrentState = eRunning;
6201             }
6202             else
6203             {
6204                 pxTaskStatus->eCurrentState = eState;
6205
6206                 #if ( INCLUDE_vTaskSuspend == 1 )
6207                 {
6208                     /* If the task is in the suspended list then there is a
6209                      *  chance it is actually just blocked indefinitely - so really
6210                      *  it should be reported as being in the Blocked state. */
6211                     if( eState == eSuspended )
6212                     {
6213                         vTaskSuspendAll();
6214                         {
6215                             if( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) != NULL )
6216                             {
6217                                 pxTaskStatus->eCurrentState = eBlocked;
6218                             }
6219                             else
6220                             {
6221                                 BaseType_t x;
6222
6223                                 /* The task does not appear on the event list item of
6224                                  * and of the RTOS objects, but could still be in the
6225                                  * blocked state if it is waiting on its notification
6226                                  * rather than waiting on an object.  If not, is
6227                                  * suspended. */
6228                                 for( x = ( BaseType_t ) 0; x < ( BaseType_t ) configTASK_NOTIFICATION_ARRAY_ENTRIES; x++ )
6229                                 {
6230                                     if( pxTCB->ucNotifyState[ x ] == taskWAITING_NOTIFICATION )
6231                                     {
6232                                         pxTaskStatus->eCurrentState = eBlocked;
6233                                         break;
6234                                     }
6235                                 }
6236                             }
6237                         }
6238                         ( void ) xTaskResumeAll();
6239                     }
6240                 }
6241                 #endif /* INCLUDE_vTaskSuspend */
6242
6243                 /* Tasks can be in pending ready list and other state list at the
6244                  * same time. These tasks are in ready state no matter what state
6245                  * list the task is in. */
6246                 taskENTER_CRITICAL();
6247                 {
6248                     if( listIS_CONTAINED_WITHIN( &xPendingReadyList, &( pxTCB->xEventListItem ) ) != pdFALSE )
6249                     {
6250                         pxTaskStatus->eCurrentState = eReady;
6251                     }
6252                 }
6253                 taskEXIT_CRITICAL();
6254             }
6255         }
6256         else
6257         {
6258             pxTaskStatus->eCurrentState = eTaskGetState( pxTCB );
6259         }
6260
6261         /* Obtaining the stack space takes some time, so the xGetFreeStackSpace
6262          * parameter is provided to allow it to be skipped. */
6263         if( xGetFreeStackSpace != pdFALSE )
6264         {
6265             #if ( portSTACK_GROWTH > 0 )
6266             {
6267                 pxTaskStatus->usStackHighWaterMark = prvTaskCheckFreeStackSpace( ( uint8_t * ) pxTCB->pxEndOfStack );
6268             }
6269             #else
6270             {
6271                 pxTaskStatus->usStackHighWaterMark = prvTaskCheckFreeStackSpace( ( uint8_t * ) pxTCB->pxStack );
6272             }
6273             #endif
6274         }
6275         else
6276         {
6277             pxTaskStatus->usStackHighWaterMark = 0;
6278         }
6279
6280         traceRETURN_vTaskGetInfo();
6281     }
6282
6283 #endif /* configUSE_TRACE_FACILITY */
6284 /*-----------------------------------------------------------*/
6285
6286 #if ( configUSE_TRACE_FACILITY == 1 )
6287
6288     static UBaseType_t prvListTasksWithinSingleList( TaskStatus_t * pxTaskStatusArray,
6289                                                      List_t * pxList,
6290                                                      eTaskState eState )
6291     {
6292         configLIST_VOLATILE TCB_t * pxNextTCB;
6293         configLIST_VOLATILE TCB_t * pxFirstTCB;
6294         UBaseType_t uxTask = 0;
6295
6296         if( listCURRENT_LIST_LENGTH( pxList ) > ( UBaseType_t ) 0 )
6297         {
6298             /* MISRA Ref 11.5.3 [Void pointer assignment] */
6299             /* More details at: https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/MISRA.md#rule-115 */
6300             /* coverity[misra_c_2012_rule_11_5_violation] */
6301             listGET_OWNER_OF_NEXT_ENTRY( pxFirstTCB, pxList );
6302
6303             /* Populate an TaskStatus_t structure within the
6304              * pxTaskStatusArray array for each task that is referenced from
6305              * pxList.  See the definition of TaskStatus_t in task.h for the
6306              * meaning of each TaskStatus_t structure member. */
6307             do
6308             {
6309                 /* MISRA Ref 11.5.3 [Void pointer assignment] */
6310                 /* More details at: https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/MISRA.md#rule-115 */
6311                 /* coverity[misra_c_2012_rule_11_5_violation] */
6312                 listGET_OWNER_OF_NEXT_ENTRY( pxNextTCB, pxList );
6313                 vTaskGetInfo( ( TaskHandle_t ) pxNextTCB, &( pxTaskStatusArray[ uxTask ] ), pdTRUE, eState );
6314                 uxTask++;
6315             } while( pxNextTCB != pxFirstTCB );
6316         }
6317         else
6318         {
6319             mtCOVERAGE_TEST_MARKER();
6320         }
6321
6322         return uxTask;
6323     }
6324
6325 #endif /* configUSE_TRACE_FACILITY */
6326 /*-----------------------------------------------------------*/
6327
6328 #if ( ( configUSE_TRACE_FACILITY == 1 ) || ( INCLUDE_uxTaskGetStackHighWaterMark == 1 ) || ( INCLUDE_uxTaskGetStackHighWaterMark2 == 1 ) )
6329
6330     static configSTACK_DEPTH_TYPE prvTaskCheckFreeStackSpace( const uint8_t * pucStackByte )
6331     {
6332         uint32_t ulCount = 0U;
6333
6334         while( *pucStackByte == ( uint8_t ) tskSTACK_FILL_BYTE )
6335         {
6336             pucStackByte -= portSTACK_GROWTH;
6337             ulCount++;
6338         }
6339
6340         ulCount /= ( uint32_t ) sizeof( StackType_t ); /*lint !e961 Casting is not redundant on smaller architectures. */
6341
6342         return ( configSTACK_DEPTH_TYPE ) ulCount;
6343     }
6344
6345 #endif /* ( ( configUSE_TRACE_FACILITY == 1 ) || ( INCLUDE_uxTaskGetStackHighWaterMark == 1 ) || ( INCLUDE_uxTaskGetStackHighWaterMark2 == 1 ) ) */
6346 /*-----------------------------------------------------------*/
6347
6348 #if ( INCLUDE_uxTaskGetStackHighWaterMark2 == 1 )
6349
6350 /* uxTaskGetStackHighWaterMark() and uxTaskGetStackHighWaterMark2() are the
6351  * same except for their return type.  Using configSTACK_DEPTH_TYPE allows the
6352  * user to determine the return type.  It gets around the problem of the value
6353  * overflowing on 8-bit types without breaking backward compatibility for
6354  * applications that expect an 8-bit return type. */
6355     configSTACK_DEPTH_TYPE uxTaskGetStackHighWaterMark2( TaskHandle_t xTask )
6356     {
6357         TCB_t * pxTCB;
6358         uint8_t * pucEndOfStack;
6359         configSTACK_DEPTH_TYPE uxReturn;
6360
6361         traceENTER_uxTaskGetStackHighWaterMark2( xTask );
6362
6363         /* uxTaskGetStackHighWaterMark() and uxTaskGetStackHighWaterMark2() are
6364          * the same except for their return type.  Using configSTACK_DEPTH_TYPE
6365          * allows the user to determine the return type.  It gets around the
6366          * problem of the value overflowing on 8-bit types without breaking
6367          * backward compatibility for applications that expect an 8-bit return
6368          * type. */
6369
6370         pxTCB = prvGetTCBFromHandle( xTask );
6371
6372         #if portSTACK_GROWTH < 0
6373         {
6374             pucEndOfStack = ( uint8_t * ) pxTCB->pxStack;
6375         }
6376         #else
6377         {
6378             pucEndOfStack = ( uint8_t * ) pxTCB->pxEndOfStack;
6379         }
6380         #endif
6381
6382         uxReturn = prvTaskCheckFreeStackSpace( pucEndOfStack );
6383
6384         traceRETURN_uxTaskGetStackHighWaterMark2( uxReturn );
6385
6386         return uxReturn;
6387     }
6388
6389 #endif /* INCLUDE_uxTaskGetStackHighWaterMark2 */
6390 /*-----------------------------------------------------------*/
6391
6392 #if ( INCLUDE_uxTaskGetStackHighWaterMark == 1 )
6393
6394     UBaseType_t uxTaskGetStackHighWaterMark( TaskHandle_t xTask )
6395     {
6396         TCB_t * pxTCB;
6397         uint8_t * pucEndOfStack;
6398         UBaseType_t uxReturn;
6399
6400         traceENTER_uxTaskGetStackHighWaterMark( xTask );
6401
6402         pxTCB = prvGetTCBFromHandle( xTask );
6403
6404         #if portSTACK_GROWTH < 0
6405         {
6406             pucEndOfStack = ( uint8_t * ) pxTCB->pxStack;
6407         }
6408         #else
6409         {
6410             pucEndOfStack = ( uint8_t * ) pxTCB->pxEndOfStack;
6411         }
6412         #endif
6413
6414         uxReturn = ( UBaseType_t ) prvTaskCheckFreeStackSpace( pucEndOfStack );
6415
6416         traceRETURN_uxTaskGetStackHighWaterMark( uxReturn );
6417
6418         return uxReturn;
6419     }
6420
6421 #endif /* INCLUDE_uxTaskGetStackHighWaterMark */
6422 /*-----------------------------------------------------------*/
6423
6424 #if ( INCLUDE_vTaskDelete == 1 )
6425
6426     static void prvDeleteTCB( TCB_t * pxTCB )
6427     {
6428         /* This call is required specifically for the TriCore port.  It must be
6429          * above the vPortFree() calls.  The call is also used by ports/demos that
6430          * want to allocate and clean RAM statically. */
6431         portCLEAN_UP_TCB( pxTCB );
6432
6433         #if ( configUSE_C_RUNTIME_TLS_SUPPORT == 1 )
6434         {
6435             /* Free up the memory allocated for the task's TLS Block. */
6436             configDEINIT_TLS_BLOCK( pxTCB->xTLSBlock );
6437         }
6438         #endif
6439
6440         #if ( ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 0 ) && ( portUSING_MPU_WRAPPERS == 0 ) )
6441         {
6442             /* The task can only have been allocated dynamically - free both
6443              * the stack and TCB. */
6444             vPortFreeStack( pxTCB->pxStack );
6445             vPortFree( pxTCB );
6446         }
6447         #elif ( tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE != 0 ) /*lint !e731 !e9029 Macro has been consolidated for readability reasons. */
6448         {
6449             /* The task could have been allocated statically or dynamically, so
6450              * check what was statically allocated before trying to free the
6451              * memory. */
6452             if( pxTCB->ucStaticallyAllocated == tskDYNAMICALLY_ALLOCATED_STACK_AND_TCB )
6453             {
6454                 /* Both the stack and TCB were allocated dynamically, so both
6455                  * must be freed. */
6456                 vPortFreeStack( pxTCB->pxStack );
6457                 vPortFree( pxTCB );
6458             }
6459             else if( pxTCB->ucStaticallyAllocated == tskSTATICALLY_ALLOCATED_STACK_ONLY )
6460             {
6461                 /* Only the stack was statically allocated, so the TCB is the
6462                  * only memory that must be freed. */
6463                 vPortFree( pxTCB );
6464             }
6465             else
6466             {
6467                 /* Neither the stack nor the TCB were allocated dynamically, so
6468                  * nothing needs to be freed. */
6469                 configASSERT( pxTCB->ucStaticallyAllocated == tskSTATICALLY_ALLOCATED_STACK_AND_TCB );
6470                 mtCOVERAGE_TEST_MARKER();
6471             }
6472         }
6473         #endif /* configSUPPORT_DYNAMIC_ALLOCATION */
6474     }
6475
6476 #endif /* INCLUDE_vTaskDelete */
6477 /*-----------------------------------------------------------*/
6478
6479 static void prvResetNextTaskUnblockTime( void )
6480 {
6481     if( listLIST_IS_EMPTY( pxDelayedTaskList ) != pdFALSE )
6482     {
6483         /* The new current delayed list is empty.  Set xNextTaskUnblockTime to
6484          * the maximum possible value so it is  extremely unlikely that the
6485          * if( xTickCount >= xNextTaskUnblockTime ) test will pass until
6486          * there is an item in the delayed list. */
6487         xNextTaskUnblockTime = portMAX_DELAY;
6488     }
6489     else
6490     {
6491         /* The new current delayed list is not empty, get the value of
6492          * the item at the head of the delayed list.  This is the time at
6493          * which the task at the head of the delayed list should be removed
6494          * from the Blocked state. */
6495         xNextTaskUnblockTime = listGET_ITEM_VALUE_OF_HEAD_ENTRY( pxDelayedTaskList );
6496     }
6497 }
6498 /*-----------------------------------------------------------*/
6499
6500 #if ( ( INCLUDE_xTaskGetCurrentTaskHandle == 1 ) || ( configUSE_MUTEXES == 1 ) ) || ( configNUMBER_OF_CORES > 1 )
6501
6502     #if ( configNUMBER_OF_CORES == 1 )
6503         TaskHandle_t xTaskGetCurrentTaskHandle( void )
6504         {
6505             TaskHandle_t xReturn;
6506
6507             traceENTER_xTaskGetCurrentTaskHandle();
6508
6509             /* A critical section is not required as this is not called from
6510              * an interrupt and the current TCB will always be the same for any
6511              * individual execution thread. */
6512             xReturn = pxCurrentTCB;
6513
6514             traceRETURN_xTaskGetCurrentTaskHandle( xReturn );
6515
6516             return xReturn;
6517         }
6518     #else /* #if ( configNUMBER_OF_CORES == 1 ) */
6519         TaskHandle_t xTaskGetCurrentTaskHandle( void )
6520         {
6521             TaskHandle_t xReturn;
6522             UBaseType_t uxSavedInterruptStatus;
6523
6524             traceENTER_xTaskGetCurrentTaskHandle();
6525
6526             uxSavedInterruptStatus = portSET_INTERRUPT_MASK();
6527             {
6528                 xReturn = pxCurrentTCBs[ portGET_CORE_ID() ];
6529             }
6530             portCLEAR_INTERRUPT_MASK( uxSavedInterruptStatus );
6531
6532             traceRETURN_xTaskGetCurrentTaskHandle( xReturn );
6533
6534             return xReturn;
6535         }
6536
6537         TaskHandle_t xTaskGetCurrentTaskHandleForCore( BaseType_t xCoreID )
6538         {
6539             TaskHandle_t xReturn = NULL;
6540
6541             traceENTER_xTaskGetCurrentTaskHandleForCore( xCoreID );
6542
6543             if( taskVALID_CORE_ID( xCoreID ) != pdFALSE )
6544             {
6545                 xReturn = pxCurrentTCBs[ xCoreID ];
6546             }
6547
6548             traceRETURN_xTaskGetCurrentTaskHandleForCore( xReturn );
6549
6550             return xReturn;
6551         }
6552     #endif /* #if ( configNUMBER_OF_CORES == 1 ) */
6553
6554 #endif /* ( ( INCLUDE_xTaskGetCurrentTaskHandle == 1 ) || ( configUSE_MUTEXES == 1 ) ) */
6555 /*-----------------------------------------------------------*/
6556
6557 #if ( ( INCLUDE_xTaskGetSchedulerState == 1 ) || ( configUSE_TIMERS == 1 ) )
6558
6559     BaseType_t xTaskGetSchedulerState( void )
6560     {
6561         BaseType_t xReturn;
6562
6563         traceENTER_xTaskGetSchedulerState();
6564
6565         if( xSchedulerRunning == pdFALSE )
6566         {
6567             xReturn = taskSCHEDULER_NOT_STARTED;
6568         }
6569         else
6570         {
6571             #if ( configNUMBER_OF_CORES > 1 )
6572                 taskENTER_CRITICAL();
6573             #endif
6574             {
6575                 if( uxSchedulerSuspended == ( UBaseType_t ) 0U )
6576                 {
6577                     xReturn = taskSCHEDULER_RUNNING;
6578                 }
6579                 else
6580                 {
6581                     xReturn = taskSCHEDULER_SUSPENDED;
6582                 }
6583             }
6584             #if ( configNUMBER_OF_CORES > 1 )
6585                 taskEXIT_CRITICAL();
6586             #endif
6587         }
6588
6589         traceRETURN_xTaskGetSchedulerState( xReturn );
6590
6591         return xReturn;
6592     }
6593
6594 #endif /* ( ( INCLUDE_xTaskGetSchedulerState == 1 ) || ( configUSE_TIMERS == 1 ) ) */
6595 /*-----------------------------------------------------------*/
6596
6597 #if ( configUSE_MUTEXES == 1 )
6598
6599     BaseType_t xTaskPriorityInherit( TaskHandle_t const pxMutexHolder )
6600     {
6601         TCB_t * const pxMutexHolderTCB = pxMutexHolder;
6602         BaseType_t xReturn = pdFALSE;
6603
6604         traceENTER_xTaskPriorityInherit( pxMutexHolder );
6605
6606         /* If the mutex is taken by an interrupt, the mutex holder is NULL. Priority
6607          * inheritance is not applied in this scenario. */
6608         if( pxMutexHolder != NULL )
6609         {
6610             /* If the holder of the mutex has a priority below the priority of
6611              * the task attempting to obtain the mutex then it will temporarily
6612              * inherit the priority of the task attempting to obtain the mutex. */
6613             if( pxMutexHolderTCB->uxPriority < pxCurrentTCB->uxPriority )
6614             {
6615                 /* Adjust the mutex holder state to account for its new
6616                  * priority.  Only reset the event list item value if the value is
6617                  * not being used for anything else. */
6618                 if( ( listGET_LIST_ITEM_VALUE( &( pxMutexHolderTCB->xEventListItem ) ) & taskEVENT_LIST_ITEM_VALUE_IN_USE ) == ( ( TickType_t ) 0UL ) )
6619                 {
6620                     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. */
6621                 }
6622                 else
6623                 {
6624                     mtCOVERAGE_TEST_MARKER();
6625                 }
6626
6627                 /* If the task being modified is in the ready state it will need
6628                  * to be moved into a new list. */
6629                 if( listIS_CONTAINED_WITHIN( &( pxReadyTasksLists[ pxMutexHolderTCB->uxPriority ] ), &( pxMutexHolderTCB->xStateListItem ) ) != pdFALSE )
6630                 {
6631                     if( uxListRemove( &( pxMutexHolderTCB->xStateListItem ) ) == ( UBaseType_t ) 0 )
6632                     {
6633                         /* It is known that the task is in its ready list so
6634                          * there is no need to check again and the port level
6635                          * reset macro can be called directly. */
6636                         portRESET_READY_PRIORITY( pxMutexHolderTCB->uxPriority, uxTopReadyPriority );
6637                     }
6638                     else
6639                     {
6640                         mtCOVERAGE_TEST_MARKER();
6641                     }
6642
6643                     /* Inherit the priority before being moved into the new list. */
6644                     pxMutexHolderTCB->uxPriority = pxCurrentTCB->uxPriority;
6645                     prvAddTaskToReadyList( pxMutexHolderTCB );
6646                     #if ( configNUMBER_OF_CORES > 1 )
6647                     {
6648                         /* The priority of the task is raised. Yield for this task
6649                          * if it is not running. */
6650                         if( taskTASK_IS_RUNNING( pxMutexHolderTCB ) != pdTRUE )
6651                         {
6652                             prvYieldForTask( pxMutexHolderTCB );
6653                         }
6654                     }
6655                     #endif /* if ( configNUMBER_OF_CORES > 1 ) */
6656                 }
6657                 else
6658                 {
6659                     /* Just inherit the priority. */
6660                     pxMutexHolderTCB->uxPriority = pxCurrentTCB->uxPriority;
6661                 }
6662
6663                 traceTASK_PRIORITY_INHERIT( pxMutexHolderTCB, pxCurrentTCB->uxPriority );
6664
6665                 /* Inheritance occurred. */
6666                 xReturn = pdTRUE;
6667             }
6668             else
6669             {
6670                 if( pxMutexHolderTCB->uxBasePriority < pxCurrentTCB->uxPriority )
6671                 {
6672                     /* The base priority of the mutex holder is lower than the
6673                      * priority of the task attempting to take the mutex, but the
6674                      * current priority of the mutex holder is not lower than the
6675                      * priority of the task attempting to take the mutex.
6676                      * Therefore the mutex holder must have already inherited a
6677                      * priority, but inheritance would have occurred if that had
6678                      * not been the case. */
6679                     xReturn = pdTRUE;
6680                 }
6681                 else
6682                 {
6683                     mtCOVERAGE_TEST_MARKER();
6684                 }
6685             }
6686         }
6687         else
6688         {
6689             mtCOVERAGE_TEST_MARKER();
6690         }
6691
6692         traceRETURN_xTaskPriorityInherit( xReturn );
6693
6694         return xReturn;
6695     }
6696
6697 #endif /* configUSE_MUTEXES */
6698 /*-----------------------------------------------------------*/
6699
6700 #if ( configUSE_MUTEXES == 1 )
6701
6702     BaseType_t xTaskPriorityDisinherit( TaskHandle_t const pxMutexHolder )
6703     {
6704         TCB_t * const pxTCB = pxMutexHolder;
6705         BaseType_t xReturn = pdFALSE;
6706
6707         traceENTER_xTaskPriorityDisinherit( pxMutexHolder );
6708
6709         if( pxMutexHolder != NULL )
6710         {
6711             /* A task can only have an inherited priority if it holds the mutex.
6712              * If the mutex is held by a task then it cannot be given from an
6713              * interrupt, and if a mutex is given by the holding task then it must
6714              * be the running state task. */
6715             configASSERT( pxTCB == pxCurrentTCB );
6716             configASSERT( pxTCB->uxMutexesHeld );
6717             ( pxTCB->uxMutexesHeld )--;
6718
6719             /* Has the holder of the mutex inherited the priority of another
6720              * task? */
6721             if( pxTCB->uxPriority != pxTCB->uxBasePriority )
6722             {
6723                 /* Only disinherit if no other mutexes are held. */
6724                 if( pxTCB->uxMutexesHeld == ( UBaseType_t ) 0 )
6725                 {
6726                     /* A task can only have an inherited priority if it holds
6727                      * the mutex.  If the mutex is held by a task then it cannot be
6728                      * given from an interrupt, and if a mutex is given by the
6729                      * holding task then it must be the running state task.  Remove
6730                      * the holding task from the ready list. */
6731                     if( uxListRemove( &( pxTCB->xStateListItem ) ) == ( UBaseType_t ) 0 )
6732                     {
6733                         portRESET_READY_PRIORITY( pxTCB->uxPriority, uxTopReadyPriority );
6734                     }
6735                     else
6736                     {
6737                         mtCOVERAGE_TEST_MARKER();
6738                     }
6739
6740                     /* Disinherit the priority before adding the task into the
6741                      * new  ready list. */
6742                     traceTASK_PRIORITY_DISINHERIT( pxTCB, pxTCB->uxBasePriority );
6743                     pxTCB->uxPriority = pxTCB->uxBasePriority;
6744
6745                     /* Reset the event list item value.  It cannot be in use for
6746                      * any other purpose if this task is running, and it must be
6747                      * running to give back the mutex. */
6748                     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. */
6749                     prvAddTaskToReadyList( pxTCB );
6750                     #if ( configNUMBER_OF_CORES > 1 )
6751                     {
6752                         /* The priority of the task is dropped. Yield the core on
6753                          * which the task is running. */
6754                         if( taskTASK_IS_RUNNING( pxTCB ) == pdTRUE )
6755                         {
6756                             prvYieldCore( pxTCB->xTaskRunState );
6757                         }
6758                     }
6759                     #endif /* if ( configNUMBER_OF_CORES > 1 ) */
6760
6761                     /* Return true to indicate that a context switch is required.
6762                      * This is only actually required in the corner case whereby
6763                      * multiple mutexes were held and the mutexes were given back
6764                      * in an order different to that in which they were taken.
6765                      * If a context switch did not occur when the first mutex was
6766                      * returned, even if a task was waiting on it, then a context
6767                      * switch should occur when the last mutex is returned whether
6768                      * a task is waiting on it or not. */
6769                     xReturn = pdTRUE;
6770                 }
6771                 else
6772                 {
6773                     mtCOVERAGE_TEST_MARKER();
6774                 }
6775             }
6776             else
6777             {
6778                 mtCOVERAGE_TEST_MARKER();
6779             }
6780         }
6781         else
6782         {
6783             mtCOVERAGE_TEST_MARKER();
6784         }
6785
6786         traceRETURN_xTaskPriorityDisinherit( xReturn );
6787
6788         return xReturn;
6789     }
6790
6791 #endif /* configUSE_MUTEXES */
6792 /*-----------------------------------------------------------*/
6793
6794 #if ( configUSE_MUTEXES == 1 )
6795
6796     void vTaskPriorityDisinheritAfterTimeout( TaskHandle_t const pxMutexHolder,
6797                                               UBaseType_t uxHighestPriorityWaitingTask )
6798     {
6799         TCB_t * const pxTCB = pxMutexHolder;
6800         UBaseType_t uxPriorityUsedOnEntry, uxPriorityToUse;
6801         const UBaseType_t uxOnlyOneMutexHeld = ( UBaseType_t ) 1;
6802
6803         traceENTER_vTaskPriorityDisinheritAfterTimeout( pxMutexHolder, uxHighestPriorityWaitingTask );
6804
6805         if( pxMutexHolder != NULL )
6806         {
6807             /* If pxMutexHolder is not NULL then the holder must hold at least
6808              * one mutex. */
6809             configASSERT( pxTCB->uxMutexesHeld );
6810
6811             /* Determine the priority to which the priority of the task that
6812              * holds the mutex should be set.  This will be the greater of the
6813              * holding task's base priority and the priority of the highest
6814              * priority task that is waiting to obtain the mutex. */
6815             if( pxTCB->uxBasePriority < uxHighestPriorityWaitingTask )
6816             {
6817                 uxPriorityToUse = uxHighestPriorityWaitingTask;
6818             }
6819             else
6820             {
6821                 uxPriorityToUse = pxTCB->uxBasePriority;
6822             }
6823
6824             /* Does the priority need to change? */
6825             if( pxTCB->uxPriority != uxPriorityToUse )
6826             {
6827                 /* Only disinherit if no other mutexes are held.  This is a
6828                  * simplification in the priority inheritance implementation.  If
6829                  * the task that holds the mutex is also holding other mutexes then
6830                  * the other mutexes may have caused the priority inheritance. */
6831                 if( pxTCB->uxMutexesHeld == uxOnlyOneMutexHeld )
6832                 {
6833                     /* If a task has timed out because it already holds the
6834                      * mutex it was trying to obtain then it cannot of inherited
6835                      * its own priority. */
6836                     configASSERT( pxTCB != pxCurrentTCB );
6837
6838                     /* Disinherit the priority, remembering the previous
6839                      * priority to facilitate determining the subject task's
6840                      * state. */
6841                     traceTASK_PRIORITY_DISINHERIT( pxTCB, uxPriorityToUse );
6842                     uxPriorityUsedOnEntry = pxTCB->uxPriority;
6843                     pxTCB->uxPriority = uxPriorityToUse;
6844
6845                     /* Only reset the event list item value if the value is not
6846                      * being used for anything else. */
6847                     if( ( listGET_LIST_ITEM_VALUE( &( pxTCB->xEventListItem ) ) & taskEVENT_LIST_ITEM_VALUE_IN_USE ) == ( ( TickType_t ) 0UL ) )
6848                     {
6849                         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. */
6850                     }
6851                     else
6852                     {
6853                         mtCOVERAGE_TEST_MARKER();
6854                     }
6855
6856                     /* If the running task is not the task that holds the mutex
6857                      * then the task that holds the mutex could be in either the
6858                      * Ready, Blocked or Suspended states.  Only remove the task
6859                      * from its current state list if it is in the Ready state as
6860                      * the task's priority is going to change and there is one
6861                      * Ready list per priority. */
6862                     if( listIS_CONTAINED_WITHIN( &( pxReadyTasksLists[ uxPriorityUsedOnEntry ] ), &( pxTCB->xStateListItem ) ) != pdFALSE )
6863                     {
6864                         if( uxListRemove( &( pxTCB->xStateListItem ) ) == ( UBaseType_t ) 0 )
6865                         {
6866                             /* It is known that the task is in its ready list so
6867                              * there is no need to check again and the port level
6868                              * reset macro can be called directly. */
6869                             portRESET_READY_PRIORITY( pxTCB->uxPriority, uxTopReadyPriority );
6870                         }
6871                         else
6872                         {
6873                             mtCOVERAGE_TEST_MARKER();
6874                         }
6875
6876                         prvAddTaskToReadyList( pxTCB );
6877                         #if ( configNUMBER_OF_CORES > 1 )
6878                         {
6879                             /* The priority of the task is dropped. Yield the core on
6880                              * which the task is running. */
6881                             if( taskTASK_IS_RUNNING( pxTCB ) == pdTRUE )
6882                             {
6883                                 prvYieldCore( pxTCB->xTaskRunState );
6884                             }
6885                         }
6886                         #endif /* if ( configNUMBER_OF_CORES > 1 ) */
6887                     }
6888                     else
6889                     {
6890                         mtCOVERAGE_TEST_MARKER();
6891                     }
6892                 }
6893                 else
6894                 {
6895                     mtCOVERAGE_TEST_MARKER();
6896                 }
6897             }
6898             else
6899             {
6900                 mtCOVERAGE_TEST_MARKER();
6901             }
6902         }
6903         else
6904         {
6905             mtCOVERAGE_TEST_MARKER();
6906         }
6907
6908         traceRETURN_vTaskPriorityDisinheritAfterTimeout();
6909     }
6910
6911 #endif /* configUSE_MUTEXES */
6912 /*-----------------------------------------------------------*/
6913
6914 #if ( configNUMBER_OF_CORES > 1 )
6915
6916 /* If not in a critical section then yield immediately.
6917  * Otherwise set xYieldPendings to true to wait to
6918  * yield until exiting the critical section.
6919  */
6920     void vTaskYieldWithinAPI( void )
6921     {
6922         traceENTER_vTaskYieldWithinAPI();
6923
6924         if( portGET_CRITICAL_NESTING_COUNT() == 0U )
6925         {
6926             portYIELD();
6927         }
6928         else
6929         {
6930             xYieldPendings[ portGET_CORE_ID() ] = pdTRUE;
6931         }
6932
6933         traceRETURN_vTaskYieldWithinAPI();
6934     }
6935 #endif /* #if ( configNUMBER_OF_CORES > 1 ) */
6936
6937 /*-----------------------------------------------------------*/
6938
6939 #if ( ( portCRITICAL_NESTING_IN_TCB == 1 ) && ( configNUMBER_OF_CORES == 1 ) )
6940
6941     void vTaskEnterCritical( void )
6942     {
6943         traceENTER_vTaskEnterCritical();
6944
6945         portDISABLE_INTERRUPTS();
6946
6947         if( xSchedulerRunning != pdFALSE )
6948         {
6949             ( pxCurrentTCB->uxCriticalNesting )++;
6950
6951             /* This is not the interrupt safe version of the enter critical
6952              * function so  assert() if it is being called from an interrupt
6953              * context.  Only API functions that end in "FromISR" can be used in an
6954              * interrupt.  Only assert if the critical nesting count is 1 to
6955              * protect against recursive calls if the assert function also uses a
6956              * critical section. */
6957             if( pxCurrentTCB->uxCriticalNesting == 1U )
6958             {
6959                 portASSERT_IF_IN_ISR();
6960             }
6961         }
6962         else
6963         {
6964             mtCOVERAGE_TEST_MARKER();
6965         }
6966
6967         traceRETURN_vTaskEnterCritical();
6968     }
6969
6970 #endif /* #if ( ( portCRITICAL_NESTING_IN_TCB == 1 ) && ( configNUMBER_OF_CORES == 1 ) ) */
6971 /*-----------------------------------------------------------*/
6972
6973 #if ( configNUMBER_OF_CORES > 1 )
6974
6975     void vTaskEnterCritical( void )
6976     {
6977         traceENTER_vTaskEnterCritical();
6978
6979         portDISABLE_INTERRUPTS();
6980
6981         if( xSchedulerRunning != pdFALSE )
6982         {
6983             if( portGET_CRITICAL_NESTING_COUNT() == 0U )
6984             {
6985                 portGET_TASK_LOCK();
6986                 portGET_ISR_LOCK();
6987             }
6988
6989             portINCREMENT_CRITICAL_NESTING_COUNT();
6990
6991             /* This is not the interrupt safe version of the enter critical
6992              * function so  assert() if it is being called from an interrupt
6993              * context.  Only API functions that end in "FromISR" can be used in an
6994              * interrupt.  Only assert if the critical nesting count is 1 to
6995              * protect against recursive calls if the assert function also uses a
6996              * critical section. */
6997             if( portGET_CRITICAL_NESTING_COUNT() == 1U )
6998             {
6999                 portASSERT_IF_IN_ISR();
7000
7001                 if( uxSchedulerSuspended == 0U )
7002                 {
7003                     /* The only time there would be a problem is if this is called
7004                      * before a context switch and vTaskExitCritical() is called
7005                      * after pxCurrentTCB changes. Therefore this should not be
7006                      * used within vTaskSwitchContext(). */
7007                     prvCheckForRunStateChange();
7008                 }
7009             }
7010         }
7011         else
7012         {
7013             mtCOVERAGE_TEST_MARKER();
7014         }
7015
7016         traceRETURN_vTaskEnterCritical();
7017     }
7018
7019 #endif /* #if ( configNUMBER_OF_CORES > 1 ) */
7020
7021 /*-----------------------------------------------------------*/
7022
7023 #if ( configNUMBER_OF_CORES > 1 )
7024
7025     UBaseType_t vTaskEnterCriticalFromISR( void )
7026     {
7027         UBaseType_t uxSavedInterruptStatus = 0;
7028
7029         traceENTER_vTaskEnterCriticalFromISR();
7030
7031         if( xSchedulerRunning != pdFALSE )
7032         {
7033             uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR();
7034
7035             if( portGET_CRITICAL_NESTING_COUNT() == 0U )
7036             {
7037                 portGET_ISR_LOCK();
7038             }
7039
7040             portINCREMENT_CRITICAL_NESTING_COUNT();
7041         }
7042         else
7043         {
7044             mtCOVERAGE_TEST_MARKER();
7045         }
7046
7047         traceRETURN_vTaskEnterCriticalFromISR( uxSavedInterruptStatus );
7048
7049         return uxSavedInterruptStatus;
7050     }
7051
7052 #endif /* #if ( configNUMBER_OF_CORES > 1 ) */
7053 /*-----------------------------------------------------------*/
7054
7055 #if ( ( portCRITICAL_NESTING_IN_TCB == 1 ) && ( configNUMBER_OF_CORES == 1 ) )
7056
7057     void vTaskExitCritical( void )
7058     {
7059         traceENTER_vTaskExitCritical();
7060
7061         if( xSchedulerRunning != pdFALSE )
7062         {
7063             /* If pxCurrentTCB->uxCriticalNesting is zero then this function
7064              * does not match a previous call to vTaskEnterCritical(). */
7065             configASSERT( pxCurrentTCB->uxCriticalNesting > 0U );
7066
7067             /* This function should not be called in ISR. Use vTaskExitCriticalFromISR
7068              * to exit critical section from ISR. */
7069             portASSERT_IF_IN_ISR();
7070
7071             if( pxCurrentTCB->uxCriticalNesting > 0U )
7072             {
7073                 ( pxCurrentTCB->uxCriticalNesting )--;
7074
7075                 if( pxCurrentTCB->uxCriticalNesting == 0U )
7076                 {
7077                     portENABLE_INTERRUPTS();
7078                 }
7079                 else
7080                 {
7081                     mtCOVERAGE_TEST_MARKER();
7082                 }
7083             }
7084             else
7085             {
7086                 mtCOVERAGE_TEST_MARKER();
7087             }
7088         }
7089         else
7090         {
7091             mtCOVERAGE_TEST_MARKER();
7092         }
7093
7094         traceRETURN_vTaskExitCritical();
7095     }
7096
7097 #endif /* #if ( ( portCRITICAL_NESTING_IN_TCB == 1 ) && ( configNUMBER_OF_CORES == 1 ) ) */
7098 /*-----------------------------------------------------------*/
7099
7100 #if ( configNUMBER_OF_CORES > 1 )
7101
7102     void vTaskExitCritical( void )
7103     {
7104         traceENTER_vTaskExitCritical();
7105
7106         if( xSchedulerRunning != pdFALSE )
7107         {
7108             /* If critical nesting count is zero then this function
7109              * does not match a previous call to vTaskEnterCritical(). */
7110             configASSERT( portGET_CRITICAL_NESTING_COUNT() > 0U );
7111
7112             /* This function should not be called in ISR. Use vTaskExitCriticalFromISR
7113              * to exit critical section from ISR. */
7114             portASSERT_IF_IN_ISR();
7115
7116             if( portGET_CRITICAL_NESTING_COUNT() > 0U )
7117             {
7118                 portDECREMENT_CRITICAL_NESTING_COUNT();
7119
7120                 if( portGET_CRITICAL_NESTING_COUNT() == 0U )
7121                 {
7122                     BaseType_t xYieldCurrentTask;
7123
7124                     /* Get the xYieldPending stats inside the critical section. */
7125                     xYieldCurrentTask = xYieldPendings[ portGET_CORE_ID() ];
7126
7127                     portRELEASE_ISR_LOCK();
7128                     portRELEASE_TASK_LOCK();
7129                     portENABLE_INTERRUPTS();
7130
7131                     /* When a task yields in a critical section it just sets
7132                      * xYieldPending to true. So now that we have exited the
7133                      * critical section check if xYieldPending is true, and
7134                      * if so yield. */
7135                     if( xYieldCurrentTask != pdFALSE )
7136                     {
7137                         portYIELD();
7138                     }
7139                 }
7140                 else
7141                 {
7142                     mtCOVERAGE_TEST_MARKER();
7143                 }
7144             }
7145             else
7146             {
7147                 mtCOVERAGE_TEST_MARKER();
7148             }
7149         }
7150         else
7151         {
7152             mtCOVERAGE_TEST_MARKER();
7153         }
7154
7155         traceRETURN_vTaskExitCritical();
7156     }
7157
7158 #endif /* #if ( configNUMBER_OF_CORES > 1 ) */
7159 /*-----------------------------------------------------------*/
7160
7161 #if ( configNUMBER_OF_CORES > 1 )
7162
7163     void vTaskExitCriticalFromISR( UBaseType_t uxSavedInterruptStatus )
7164     {
7165         traceENTER_vTaskExitCriticalFromISR( uxSavedInterruptStatus );
7166
7167         if( xSchedulerRunning != pdFALSE )
7168         {
7169             /* If critical nesting count is zero then this function
7170              * does not match a previous call to vTaskEnterCritical(). */
7171             configASSERT( portGET_CRITICAL_NESTING_COUNT() > 0U );
7172
7173             if( portGET_CRITICAL_NESTING_COUNT() > 0U )
7174             {
7175                 portDECREMENT_CRITICAL_NESTING_COUNT();
7176
7177                 if( portGET_CRITICAL_NESTING_COUNT() == 0U )
7178                 {
7179                     portRELEASE_ISR_LOCK();
7180                     portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus );
7181                 }
7182                 else
7183                 {
7184                     mtCOVERAGE_TEST_MARKER();
7185                 }
7186             }
7187             else
7188             {
7189                 mtCOVERAGE_TEST_MARKER();
7190             }
7191         }
7192         else
7193         {
7194             mtCOVERAGE_TEST_MARKER();
7195         }
7196
7197         traceRETURN_vTaskExitCriticalFromISR();
7198     }
7199
7200 #endif /* #if ( configNUMBER_OF_CORES > 1 ) */
7201 /*-----------------------------------------------------------*/
7202
7203 #if ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 )
7204
7205     static char * prvWriteNameToBuffer( char * pcBuffer,
7206                                         const char * pcTaskName )
7207     {
7208         size_t x;
7209
7210         /* Start by copying the entire string. */
7211         ( void ) strcpy( pcBuffer, pcTaskName );
7212
7213         /* Pad the end of the string with spaces to ensure columns line up when
7214          * printed out. */
7215         for( x = strlen( pcBuffer ); x < ( size_t ) ( ( size_t ) configMAX_TASK_NAME_LEN - 1U ); x++ )
7216         {
7217             pcBuffer[ x ] = ' ';
7218         }
7219
7220         /* Terminate. */
7221         pcBuffer[ x ] = ( char ) 0x00;
7222
7223         /* Return the new end of string. */
7224         return &( pcBuffer[ x ] );
7225     }
7226
7227 #endif /* ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 ) */
7228 /*-----------------------------------------------------------*/
7229
7230 #if ( ( configUSE_TRACE_FACILITY == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 ) )
7231
7232     void vTaskListTasks( char * pcWriteBuffer,
7233                          size_t uxBufferLength )
7234     {
7235         TaskStatus_t * pxTaskStatusArray;
7236         size_t uxConsumedBufferLength = 0;
7237         size_t uxCharsWrittenBySnprintf;
7238         int iSnprintfReturnValue;
7239         BaseType_t xOutputBufferFull = pdFALSE;
7240         UBaseType_t uxArraySize, x;
7241         char cStatus;
7242
7243         traceENTER_vTaskListTasks( pcWriteBuffer, uxBufferLength );
7244
7245         /*
7246          * PLEASE NOTE:
7247          *
7248          * This function is provided for convenience only, and is used by many
7249          * of the demo applications.  Do not consider it to be part of the
7250          * scheduler.
7251          *
7252          * vTaskListTasks() calls uxTaskGetSystemState(), then formats part of the
7253          * uxTaskGetSystemState() output into a human readable table that
7254          * displays task: names, states, priority, stack usage and task number.
7255          * Stack usage specified as the number of unused StackType_t words stack can hold
7256          * on top of stack - not the number of bytes.
7257          *
7258          * vTaskListTasks() has a dependency on the snprintf() C library function that
7259          * might bloat the code size, use a lot of stack, and provide different
7260          * results on different platforms.  An alternative, tiny, third party,
7261          * and limited functionality implementation of snprintf() is provided in
7262          * many of the FreeRTOS/Demo sub-directories in a file called
7263          * printf-stdarg.c (note printf-stdarg.c does not provide a full
7264          * snprintf() implementation!).
7265          *
7266          * It is recommended that production systems call uxTaskGetSystemState()
7267          * directly to get access to raw stats data, rather than indirectly
7268          * through a call to vTaskListTasks().
7269          */
7270
7271
7272         /* Make sure the write buffer does not contain a string. */
7273         *pcWriteBuffer = ( char ) 0x00;
7274
7275         /* Take a snapshot of the number of tasks in case it changes while this
7276          * function is executing. */
7277         uxArraySize = uxCurrentNumberOfTasks;
7278
7279         /* Allocate an array index for each task.  NOTE!  if
7280          * configSUPPORT_DYNAMIC_ALLOCATION is set to 0 then pvPortMalloc() will
7281          * equate to NULL. */
7282         /* MISRA Ref 11.5.1 [Malloc memory assignment] */
7283         /* More details at: https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/MISRA.md#rule-115 */
7284         /* coverity[misra_c_2012_rule_11_5_violation] */
7285         pxTaskStatusArray = pvPortMalloc( uxCurrentNumberOfTasks * sizeof( TaskStatus_t ) );
7286
7287         if( pxTaskStatusArray != NULL )
7288         {
7289             /* Generate the (binary) data. */
7290             uxArraySize = uxTaskGetSystemState( pxTaskStatusArray, uxArraySize, NULL );
7291
7292             /* Create a human readable table from the binary data. */
7293             for( x = 0; x < uxArraySize; x++ )
7294             {
7295                 switch( pxTaskStatusArray[ x ].eCurrentState )
7296                 {
7297                     case eRunning:
7298                         cStatus = tskRUNNING_CHAR;
7299                         break;
7300
7301                     case eReady:
7302                         cStatus = tskREADY_CHAR;
7303                         break;
7304
7305                     case eBlocked:
7306                         cStatus = tskBLOCKED_CHAR;
7307                         break;
7308
7309                     case eSuspended:
7310                         cStatus = tskSUSPENDED_CHAR;
7311                         break;
7312
7313                     case eDeleted:
7314                         cStatus = tskDELETED_CHAR;
7315                         break;
7316
7317                     case eInvalid: /* Fall through. */
7318                     default:       /* Should not get here, but it is included
7319                                     * to prevent static checking errors. */
7320                         cStatus = ( char ) 0x00;
7321                         break;
7322                 }
7323
7324                 /* Is there enough space in the buffer to hold task name? */
7325                 if( ( uxConsumedBufferLength + configMAX_TASK_NAME_LEN ) <= uxBufferLength )
7326                 {
7327                     /* Write the task name to the string, padding with spaces so it
7328                      * can be printed in tabular form more easily. */
7329                     pcWriteBuffer = prvWriteNameToBuffer( pcWriteBuffer, pxTaskStatusArray[ x ].pcTaskName );
7330                     /* Do not count the terminating null character. */
7331                     uxConsumedBufferLength = uxConsumedBufferLength + ( configMAX_TASK_NAME_LEN - 1U );
7332
7333                     /* Is there space left in the buffer? -1 is done because snprintf
7334                      * writes a terminating null character. So we are essentially
7335                      * checking if the buffer has space to write at least one non-null
7336                      * character. */
7337                     if( uxConsumedBufferLength < ( uxBufferLength - 1U ) )
7338                     {
7339                         /* Write the rest of the string. */
7340                         #if ( ( configUSE_CORE_AFFINITY == 1 ) && ( configNUMBER_OF_CORES > 1 ) )
7341                             iSnprintfReturnValue = snprintf( pcWriteBuffer,
7342                                                              uxBufferLength - uxConsumedBufferLength,
7343                                                              "\t%c\t%u\t%u\t%u\t0x%x\r\n",
7344                                                              cStatus,
7345                                                              ( unsigned int ) pxTaskStatusArray[ x ].uxCurrentPriority,
7346                                                              ( unsigned int ) pxTaskStatusArray[ x ].usStackHighWaterMark,
7347                                                              ( unsigned int ) pxTaskStatusArray[ x ].xTaskNumber,
7348                                                              ( 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. */
7349                         #else /* ( ( configUSE_CORE_AFFINITY == 1 ) && ( configNUMBER_OF_CORES > 1 ) ) */
7350                             iSnprintfReturnValue = snprintf( pcWriteBuffer,
7351                                                              uxBufferLength - uxConsumedBufferLength,
7352                                                              "\t%c\t%u\t%u\t%u\r\n",
7353                                                              cStatus,
7354                                                              ( unsigned int ) pxTaskStatusArray[ x ].uxCurrentPriority,
7355                                                              ( unsigned int ) pxTaskStatusArray[ x ].usStackHighWaterMark,
7356                                                              ( 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. */
7357                         #endif /* ( ( configUSE_CORE_AFFINITY == 1 ) && ( configNUMBER_OF_CORES > 1 ) ) */
7358                         uxCharsWrittenBySnprintf = prvSnprintfReturnValueToCharsWritten( iSnprintfReturnValue, uxBufferLength - uxConsumedBufferLength );
7359
7360                         uxConsumedBufferLength += uxCharsWrittenBySnprintf;
7361                         pcWriteBuffer += uxCharsWrittenBySnprintf; /*lint !e9016 Pointer arithmetic ok on char pointers especially as in this case where it best denotes the intent of the code. */
7362                     }
7363                     else
7364                     {
7365                         xOutputBufferFull = pdTRUE;
7366                     }
7367                 }
7368                 else
7369                 {
7370                     xOutputBufferFull = pdTRUE;
7371                 }
7372
7373                 if( xOutputBufferFull == pdTRUE )
7374                 {
7375                     break;
7376                 }
7377             }
7378
7379             /* Free the array again.  NOTE!  If configSUPPORT_DYNAMIC_ALLOCATION
7380              * is 0 then vPortFree() will be #defined to nothing. */
7381             vPortFree( pxTaskStatusArray );
7382         }
7383         else
7384         {
7385             mtCOVERAGE_TEST_MARKER();
7386         }
7387
7388         traceRETURN_vTaskListTasks();
7389     }
7390
7391 #endif /* ( ( configUSE_TRACE_FACILITY == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 ) ) */
7392 /*----------------------------------------------------------*/
7393
7394 #if ( ( configGENERATE_RUN_TIME_STATS == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 ) && ( configUSE_TRACE_FACILITY == 1 ) )
7395
7396     void vTaskGetRunTimeStatistics( char * pcWriteBuffer,
7397                                     size_t uxBufferLength )
7398     {
7399         TaskStatus_t * pxTaskStatusArray;
7400         size_t uxConsumedBufferLength = 0;
7401         size_t uxCharsWrittenBySnprintf;
7402         int iSnprintfReturnValue;
7403         BaseType_t xOutputBufferFull = pdFALSE;
7404         UBaseType_t uxArraySize, x;
7405         configRUN_TIME_COUNTER_TYPE ulTotalTime, ulStatsAsPercentage;
7406
7407         traceENTER_vTaskGetRunTimeStatistics( pcWriteBuffer, uxBufferLength );
7408
7409         /*
7410          * PLEASE NOTE:
7411          *
7412          * This function is provided for convenience only, and is used by many
7413          * of the demo applications.  Do not consider it to be part of the
7414          * scheduler.
7415          *
7416          * vTaskGetRunTimeStatistics() calls uxTaskGetSystemState(), then formats part
7417          * of the uxTaskGetSystemState() output into a human readable table that
7418          * displays the amount of time each task has spent in the Running state
7419          * in both absolute and percentage terms.
7420          *
7421          * vTaskGetRunTimeStatistics() has a dependency on the snprintf() C library
7422          * function that might bloat the code size, use a lot of stack, and
7423          * provide different results on different platforms.  An alternative,
7424          * tiny, third party, and limited functionality implementation of
7425          * snprintf() is provided in many of the FreeRTOS/Demo sub-directories in
7426          * a file called printf-stdarg.c (note printf-stdarg.c does not provide
7427          * a full snprintf() implementation!).
7428          *
7429          * It is recommended that production systems call uxTaskGetSystemState()
7430          * directly to get access to raw stats data, rather than indirectly
7431          * through a call to vTaskGetRunTimeStatistics().
7432          */
7433
7434         /* Make sure the write buffer does not contain a string. */
7435         *pcWriteBuffer = ( char ) 0x00;
7436
7437         /* Take a snapshot of the number of tasks in case it changes while this
7438          * function is executing. */
7439         uxArraySize = uxCurrentNumberOfTasks;
7440
7441         /* Allocate an array index for each task.  NOTE!  If
7442          * configSUPPORT_DYNAMIC_ALLOCATION is set to 0 then pvPortMalloc() will
7443          * equate to NULL. */
7444         /* MISRA Ref 11.5.1 [Malloc memory assignment] */
7445         /* More details at: https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/MISRA.md#rule-115 */
7446         /* coverity[misra_c_2012_rule_11_5_violation] */
7447         pxTaskStatusArray = pvPortMalloc( uxCurrentNumberOfTasks * sizeof( TaskStatus_t ) );
7448
7449         if( pxTaskStatusArray != NULL )
7450         {
7451             /* Generate the (binary) data. */
7452             uxArraySize = uxTaskGetSystemState( pxTaskStatusArray, uxArraySize, &ulTotalTime );
7453
7454             /* For percentage calculations. */
7455             ulTotalTime /= ( ( configRUN_TIME_COUNTER_TYPE ) 100UL );
7456
7457             /* Avoid divide by zero errors. */
7458             if( ulTotalTime > 0UL )
7459             {
7460                 /* Create a human readable table from the binary data. */
7461                 for( x = 0; x < uxArraySize; x++ )
7462                 {
7463                     /* What percentage of the total run time has the task used?
7464                      * This will always be rounded down to the nearest integer.
7465                      * ulTotalRunTime has already been divided by 100. */
7466                     ulStatsAsPercentage = pxTaskStatusArray[ x ].ulRunTimeCounter / ulTotalTime;
7467
7468                     /* Is there enough space in the buffer to hold task name? */
7469                     if( ( uxConsumedBufferLength + configMAX_TASK_NAME_LEN ) <= uxBufferLength )
7470                     {
7471                         /* Write the task name to the string, padding with
7472                          * spaces so it can be printed in tabular form more
7473                          * easily. */
7474                         pcWriteBuffer = prvWriteNameToBuffer( pcWriteBuffer, pxTaskStatusArray[ x ].pcTaskName );
7475                         /* Do not count the terminating null character. */
7476                         uxConsumedBufferLength = uxConsumedBufferLength + ( configMAX_TASK_NAME_LEN - 1U );
7477
7478                         /* Is there space left in the buffer? -1 is done because snprintf
7479                          * writes a terminating null character. So we are essentially
7480                          * checking if the buffer has space to write at least one non-null
7481                          * character. */
7482                         if( uxConsumedBufferLength < ( uxBufferLength - 1U ) )
7483                         {
7484                             if( ulStatsAsPercentage > 0UL )
7485                             {
7486                                 #ifdef portLU_PRINTF_SPECIFIER_REQUIRED
7487                                 {
7488                                     iSnprintfReturnValue = snprintf( pcWriteBuffer,
7489                                                                      uxBufferLength - uxConsumedBufferLength,
7490                                                                      "\t%lu\t\t%lu%%\r\n",
7491                                                                      pxTaskStatusArray[ x ].ulRunTimeCounter,
7492                                                                      ulStatsAsPercentage );
7493                                 }
7494                                 #else
7495                                 {
7496                                     /* sizeof( int ) == sizeof( long ) so a smaller
7497                                      * printf() library can be used. */
7498                                     iSnprintfReturnValue = snprintf( pcWriteBuffer,
7499                                                                      uxBufferLength - uxConsumedBufferLength,
7500                                                                      "\t%u\t\t%u%%\r\n",
7501                                                                      ( unsigned int ) pxTaskStatusArray[ x ].ulRunTimeCounter,
7502                                                                      ( 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. */
7503                                 }
7504                                 #endif /* ifdef portLU_PRINTF_SPECIFIER_REQUIRED */
7505                             }
7506                             else
7507                             {
7508                                 /* If the percentage is zero here then the task has
7509                                  * consumed less than 1% of the total run time. */
7510                                 #ifdef portLU_PRINTF_SPECIFIER_REQUIRED
7511                                 {
7512                                     iSnprintfReturnValue = snprintf( pcWriteBuffer,
7513                                                                      uxBufferLength - uxConsumedBufferLength,
7514                                                                      "\t%lu\t\t<1%%\r\n",
7515                                                                      pxTaskStatusArray[ x ].ulRunTimeCounter );
7516                                 }
7517                                 #else
7518                                 {
7519                                     /* sizeof( int ) == sizeof( long ) so a smaller
7520                                      * printf() library can be used. */
7521                                     iSnprintfReturnValue = snprintf( pcWriteBuffer,
7522                                                                      uxBufferLength - uxConsumedBufferLength,
7523                                                                      "\t%u\t\t<1%%\r\n",
7524                                                                      ( 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. */
7525                                 }
7526                                 #endif /* ifdef portLU_PRINTF_SPECIFIER_REQUIRED */
7527                             }
7528
7529                             uxCharsWrittenBySnprintf = prvSnprintfReturnValueToCharsWritten( iSnprintfReturnValue, uxBufferLength - uxConsumedBufferLength );
7530                             uxConsumedBufferLength += uxCharsWrittenBySnprintf;
7531                             pcWriteBuffer += uxCharsWrittenBySnprintf; /*lint !e9016 Pointer arithmetic ok on char pointers especially as in this case where it best denotes the intent of the code. */
7532                         }
7533                         else
7534                         {
7535                             xOutputBufferFull = pdTRUE;
7536                         }
7537                     }
7538                     else
7539                     {
7540                         xOutputBufferFull = pdTRUE;
7541                     }
7542
7543                     if( xOutputBufferFull == pdTRUE )
7544                     {
7545                         break;
7546                     }
7547                 }
7548             }
7549             else
7550             {
7551                 mtCOVERAGE_TEST_MARKER();
7552             }
7553
7554             /* Free the array again.  NOTE!  If configSUPPORT_DYNAMIC_ALLOCATION
7555              * is 0 then vPortFree() will be #defined to nothing. */
7556             vPortFree( pxTaskStatusArray );
7557         }
7558         else
7559         {
7560             mtCOVERAGE_TEST_MARKER();
7561         }
7562
7563         traceRETURN_vTaskGetRunTimeStatistics();
7564     }
7565
7566 #endif /* ( ( configGENERATE_RUN_TIME_STATS == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 ) ) */
7567 /*-----------------------------------------------------------*/
7568
7569 TickType_t uxTaskResetEventItemValue( void )
7570 {
7571     TickType_t uxReturn;
7572
7573     traceENTER_uxTaskResetEventItemValue();
7574
7575     uxReturn = listGET_LIST_ITEM_VALUE( &( pxCurrentTCB->xEventListItem ) );
7576
7577     /* Reset the event list item to its normal value - so it can be used with
7578      * queues and semaphores. */
7579     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. */
7580
7581     traceRETURN_uxTaskResetEventItemValue( uxReturn );
7582
7583     return uxReturn;
7584 }
7585 /*-----------------------------------------------------------*/
7586
7587 #if ( configUSE_MUTEXES == 1 )
7588
7589     TaskHandle_t pvTaskIncrementMutexHeldCount( void )
7590     {
7591         TCB_t * pxTCB;
7592
7593         traceENTER_pvTaskIncrementMutexHeldCount();
7594
7595         pxTCB = pxCurrentTCB;
7596
7597         /* If xSemaphoreCreateMutex() is called before any tasks have been created
7598          * then pxCurrentTCB will be NULL. */
7599         if( pxTCB != NULL )
7600         {
7601             ( pxTCB->uxMutexesHeld )++;
7602         }
7603
7604         traceRETURN_pvTaskIncrementMutexHeldCount( pxTCB );
7605
7606         return pxTCB;
7607     }
7608
7609 #endif /* configUSE_MUTEXES */
7610 /*-----------------------------------------------------------*/
7611
7612 #if ( configUSE_TASK_NOTIFICATIONS == 1 )
7613
7614     uint32_t ulTaskGenericNotifyTake( UBaseType_t uxIndexToWaitOn,
7615                                       BaseType_t xClearCountOnExit,
7616                                       TickType_t xTicksToWait )
7617     {
7618         uint32_t ulReturn;
7619         BaseType_t xAlreadyYielded;
7620
7621         traceENTER_ulTaskGenericNotifyTake( uxIndexToWaitOn, xClearCountOnExit, xTicksToWait );
7622
7623         configASSERT( uxIndexToWaitOn < configTASK_NOTIFICATION_ARRAY_ENTRIES );
7624
7625         taskENTER_CRITICAL();
7626
7627         /* Only block if the notification count is not already non-zero. */
7628         if( pxCurrentTCB->ulNotifiedValue[ uxIndexToWaitOn ] == 0UL )
7629         {
7630             /* Mark this task as waiting for a notification. */
7631             pxCurrentTCB->ucNotifyState[ uxIndexToWaitOn ] = taskWAITING_NOTIFICATION;
7632
7633             if( xTicksToWait > ( TickType_t ) 0 )
7634             {
7635                 traceTASK_NOTIFY_TAKE_BLOCK( uxIndexToWaitOn );
7636
7637                 /* We MUST suspend the scheduler before exiting the critical
7638                  * section (i.e. before enabling interrupts).
7639                  *
7640                  * If we do not do so, a notification sent from an ISR, which
7641                  * happens after exiting the critical section and before
7642                  * suspending the scheduler, will get lost. The sequence of
7643                  * events will be:
7644                  * 1. Exit critical section.
7645                  * 2. Interrupt - ISR calls xTaskNotifyFromISR which adds the
7646                  *    task to the Ready list.
7647                  * 3. Suspend scheduler.
7648                  * 4. prvAddCurrentTaskToDelayedList moves the task to the
7649                  *    delayed or suspended list.
7650                  * 5. Resume scheduler does not touch the task (because it is
7651                  *    not on the pendingReady list), effectively losing the
7652                  *    notification from the ISR.
7653                  *
7654                  * The same does not happen when we suspend the scheduler before
7655                  * exiting the critical section. The sequence of events in this
7656                  * case will be:
7657                  * 1. Suspend scheduler.
7658                  * 2. Exit critical section.
7659                  * 3. Interrupt - ISR calls xTaskNotifyFromISR which adds the
7660                  *    task to the pendingReady list as the scheduler is
7661                  *    suspended.
7662                  * 4. prvAddCurrentTaskToDelayedList adds the task to delayed or
7663                  *    suspended list. Note that this operation does not nullify
7664                  *    the add to pendingReady list done in the above step because
7665                  *    a different list item, namely xEventListItem, is used for
7666                  *    adding the task to the pendingReady list. In other words,
7667                  *    the task still remains on the pendingReady list.
7668                  * 5. Resume scheduler moves the task from pendingReady list to
7669                  *    the Ready list.
7670                  */
7671                 vTaskSuspendAll();
7672                 {
7673                     taskEXIT_CRITICAL();
7674
7675                     prvAddCurrentTaskToDelayedList( xTicksToWait, pdTRUE );
7676                 }
7677                 xAlreadyYielded = xTaskResumeAll();
7678
7679                 if( xAlreadyYielded == pdFALSE )
7680                 {
7681                     taskYIELD_WITHIN_API();
7682                 }
7683                 else
7684                 {
7685                     mtCOVERAGE_TEST_MARKER();
7686                 }
7687             }
7688             else
7689             {
7690                 taskEXIT_CRITICAL();
7691             }
7692         }
7693         else
7694         {
7695             taskEXIT_CRITICAL();
7696         }
7697
7698         taskENTER_CRITICAL();
7699         {
7700             traceTASK_NOTIFY_TAKE( uxIndexToWaitOn );
7701             ulReturn = pxCurrentTCB->ulNotifiedValue[ uxIndexToWaitOn ];
7702
7703             if( ulReturn != 0UL )
7704             {
7705                 if( xClearCountOnExit != pdFALSE )
7706                 {
7707                     pxCurrentTCB->ulNotifiedValue[ uxIndexToWaitOn ] = ( uint32_t ) 0UL;
7708                 }
7709                 else
7710                 {
7711                     pxCurrentTCB->ulNotifiedValue[ uxIndexToWaitOn ] = ulReturn - ( uint32_t ) 1;
7712                 }
7713             }
7714             else
7715             {
7716                 mtCOVERAGE_TEST_MARKER();
7717             }
7718
7719             pxCurrentTCB->ucNotifyState[ uxIndexToWaitOn ] = taskNOT_WAITING_NOTIFICATION;
7720         }
7721         taskEXIT_CRITICAL();
7722
7723         traceRETURN_ulTaskGenericNotifyTake( ulReturn );
7724
7725         return ulReturn;
7726     }
7727
7728 #endif /* configUSE_TASK_NOTIFICATIONS */
7729 /*-----------------------------------------------------------*/
7730
7731 #if ( configUSE_TASK_NOTIFICATIONS == 1 )
7732
7733     BaseType_t xTaskGenericNotifyWait( UBaseType_t uxIndexToWaitOn,
7734                                        uint32_t ulBitsToClearOnEntry,
7735                                        uint32_t ulBitsToClearOnExit,
7736                                        uint32_t * pulNotificationValue,
7737                                        TickType_t xTicksToWait )
7738     {
7739         BaseType_t xReturn, xAlreadyYielded;
7740
7741         traceENTER_xTaskGenericNotifyWait( uxIndexToWaitOn, ulBitsToClearOnEntry, ulBitsToClearOnExit, pulNotificationValue, xTicksToWait );
7742
7743         configASSERT( uxIndexToWaitOn < configTASK_NOTIFICATION_ARRAY_ENTRIES );
7744
7745         taskENTER_CRITICAL();
7746
7747         /* Only block if a notification is not already pending. */
7748         if( pxCurrentTCB->ucNotifyState[ uxIndexToWaitOn ] != taskNOTIFICATION_RECEIVED )
7749         {
7750             /* Clear bits in the task's notification value as bits may get
7751              * set  by the notifying task or interrupt.  This can be used to
7752              * clear the value to zero. */
7753             pxCurrentTCB->ulNotifiedValue[ uxIndexToWaitOn ] &= ~ulBitsToClearOnEntry;
7754
7755             /* Mark this task as waiting for a notification. */
7756             pxCurrentTCB->ucNotifyState[ uxIndexToWaitOn ] = taskWAITING_NOTIFICATION;
7757
7758             if( xTicksToWait > ( TickType_t ) 0 )
7759             {
7760                 traceTASK_NOTIFY_WAIT_BLOCK( uxIndexToWaitOn );
7761
7762                 /* We MUST suspend the scheduler before exiting the critical
7763                  * section (i.e. before enabling interrupts).
7764                  *
7765                  * If we do not do so, a notification sent from an ISR, which
7766                  * happens after exiting the critical section and before
7767                  * suspending the scheduler, will get lost. The sequence of
7768                  * events will be:
7769                  * 1. Exit critical section.
7770                  * 2. Interrupt - ISR calls xTaskNotifyFromISR which adds the
7771                  *    task to the Ready list.
7772                  * 3. Suspend scheduler.
7773                  * 4. prvAddCurrentTaskToDelayedList moves the task to the
7774                  *    delayed or suspended list.
7775                  * 5. Resume scheduler does not touch the task (because it is
7776                  *    not on the pendingReady list), effectively losing the
7777                  *    notification from the ISR.
7778                  *
7779                  * The same does not happen when we suspend the scheduler before
7780                  * exiting the critical section. The sequence of events in this
7781                  * case will be:
7782                  * 1. Suspend scheduler.
7783                  * 2. Exit critical section.
7784                  * 3. Interrupt - ISR calls xTaskNotifyFromISR which adds the
7785                  *    task to the pendingReady list as the scheduler is
7786                  *    suspended.
7787                  * 4. prvAddCurrentTaskToDelayedList adds the task to delayed or
7788                  *    suspended list. Note that this operation does not nullify
7789                  *    the add to pendingReady list done in the above step because
7790                  *    a different list item, namely xEventListItem, is used for
7791                  *    adding the task to the pendingReady list. In other words,
7792                  *    the task still remains on the pendingReady list.
7793                  * 5. Resume scheduler moves the task from pendingReady list to
7794                  *    the Ready list.
7795                  */
7796                 vTaskSuspendAll();
7797                 {
7798                     taskEXIT_CRITICAL();
7799
7800                     prvAddCurrentTaskToDelayedList( xTicksToWait, pdTRUE );
7801                 }
7802                 xAlreadyYielded = xTaskResumeAll();
7803
7804                 if( xAlreadyYielded == pdFALSE )
7805                 {
7806                     taskYIELD_WITHIN_API();
7807                 }
7808                 else
7809                 {
7810                     mtCOVERAGE_TEST_MARKER();
7811                 }
7812             }
7813             else
7814             {
7815                 taskEXIT_CRITICAL();
7816             }
7817         }
7818         else
7819         {
7820             taskEXIT_CRITICAL();
7821         }
7822
7823         taskENTER_CRITICAL();
7824         {
7825             traceTASK_NOTIFY_WAIT( uxIndexToWaitOn );
7826
7827             if( pulNotificationValue != NULL )
7828             {
7829                 /* Output the current notification value, which may or may not
7830                  * have changed. */
7831                 *pulNotificationValue = pxCurrentTCB->ulNotifiedValue[ uxIndexToWaitOn ];
7832             }
7833
7834             /* If ucNotifyValue is set then either the task never entered the
7835              * blocked state (because a notification was already pending) or the
7836              * task unblocked because of a notification.  Otherwise the task
7837              * unblocked because of a timeout. */
7838             if( pxCurrentTCB->ucNotifyState[ uxIndexToWaitOn ] != taskNOTIFICATION_RECEIVED )
7839             {
7840                 /* A notification was not received. */
7841                 xReturn = pdFALSE;
7842             }
7843             else
7844             {
7845                 /* A notification was already pending or a notification was
7846                  * received while the task was waiting. */
7847                 pxCurrentTCB->ulNotifiedValue[ uxIndexToWaitOn ] &= ~ulBitsToClearOnExit;
7848                 xReturn = pdTRUE;
7849             }
7850
7851             pxCurrentTCB->ucNotifyState[ uxIndexToWaitOn ] = taskNOT_WAITING_NOTIFICATION;
7852         }
7853         taskEXIT_CRITICAL();
7854
7855         traceRETURN_xTaskGenericNotifyWait( xReturn );
7856
7857         return xReturn;
7858     }
7859
7860 #endif /* configUSE_TASK_NOTIFICATIONS */
7861 /*-----------------------------------------------------------*/
7862
7863 #if ( configUSE_TASK_NOTIFICATIONS == 1 )
7864
7865     BaseType_t xTaskGenericNotify( TaskHandle_t xTaskToNotify,
7866                                    UBaseType_t uxIndexToNotify,
7867                                    uint32_t ulValue,
7868                                    eNotifyAction eAction,
7869                                    uint32_t * pulPreviousNotificationValue )
7870     {
7871         TCB_t * pxTCB;
7872         BaseType_t xReturn = pdPASS;
7873         uint8_t ucOriginalNotifyState;
7874
7875         traceENTER_xTaskGenericNotify( xTaskToNotify, uxIndexToNotify, ulValue, eAction, pulPreviousNotificationValue );
7876
7877         configASSERT( uxIndexToNotify < configTASK_NOTIFICATION_ARRAY_ENTRIES );
7878         configASSERT( xTaskToNotify );
7879         pxTCB = xTaskToNotify;
7880
7881         taskENTER_CRITICAL();
7882         {
7883             if( pulPreviousNotificationValue != NULL )
7884             {
7885                 *pulPreviousNotificationValue = pxTCB->ulNotifiedValue[ uxIndexToNotify ];
7886             }
7887
7888             ucOriginalNotifyState = pxTCB->ucNotifyState[ uxIndexToNotify ];
7889
7890             pxTCB->ucNotifyState[ uxIndexToNotify ] = taskNOTIFICATION_RECEIVED;
7891
7892             switch( eAction )
7893             {
7894                 case eSetBits:
7895                     pxTCB->ulNotifiedValue[ uxIndexToNotify ] |= ulValue;
7896                     break;
7897
7898                 case eIncrement:
7899                     ( pxTCB->ulNotifiedValue[ uxIndexToNotify ] )++;
7900                     break;
7901
7902                 case eSetValueWithOverwrite:
7903                     pxTCB->ulNotifiedValue[ uxIndexToNotify ] = ulValue;
7904                     break;
7905
7906                 case eSetValueWithoutOverwrite:
7907
7908                     if( ucOriginalNotifyState != taskNOTIFICATION_RECEIVED )
7909                     {
7910                         pxTCB->ulNotifiedValue[ uxIndexToNotify ] = ulValue;
7911                     }
7912                     else
7913                     {
7914                         /* The value could not be written to the task. */
7915                         xReturn = pdFAIL;
7916                     }
7917
7918                     break;
7919
7920                 case eNoAction:
7921
7922                     /* The task is being notified without its notify value being
7923                      * updated. */
7924                     break;
7925
7926                 default:
7927
7928                     /* Should not get here if all enums are handled.
7929                      * Artificially force an assert by testing a value the
7930                      * compiler can't assume is const. */
7931                     configASSERT( xTickCount == ( TickType_t ) 0 );
7932
7933                     break;
7934             }
7935
7936             traceTASK_NOTIFY( uxIndexToNotify );
7937
7938             /* If the task is in the blocked state specifically to wait for a
7939              * notification then unblock it now. */
7940             if( ucOriginalNotifyState == taskWAITING_NOTIFICATION )
7941             {
7942                 listREMOVE_ITEM( &( pxTCB->xStateListItem ) );
7943                 prvAddTaskToReadyList( pxTCB );
7944
7945                 /* The task should not have been on an event list. */
7946                 configASSERT( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) == NULL );
7947
7948                 #if ( configUSE_TICKLESS_IDLE != 0 )
7949                 {
7950                     /* If a task is blocked waiting for a notification then
7951                      * xNextTaskUnblockTime might be set to the blocked task's time
7952                      * out time.  If the task is unblocked for a reason other than
7953                      * a timeout xNextTaskUnblockTime is normally left unchanged,
7954                      * because it will automatically get reset to a new value when
7955                      * the tick count equals xNextTaskUnblockTime.  However if
7956                      * tickless idling is used it might be more important to enter
7957                      * sleep mode at the earliest possible time - so reset
7958                      * xNextTaskUnblockTime here to ensure it is updated at the
7959                      * earliest possible time. */
7960                     prvResetNextTaskUnblockTime();
7961                 }
7962                 #endif
7963
7964                 /* Check if the notified task has a priority above the currently
7965                  * executing task. */
7966                 taskYIELD_ANY_CORE_IF_USING_PREEMPTION( pxTCB );
7967             }
7968             else
7969             {
7970                 mtCOVERAGE_TEST_MARKER();
7971             }
7972         }
7973         taskEXIT_CRITICAL();
7974
7975         traceRETURN_xTaskGenericNotify( xReturn );
7976
7977         return xReturn;
7978     }
7979
7980 #endif /* configUSE_TASK_NOTIFICATIONS */
7981 /*-----------------------------------------------------------*/
7982
7983 #if ( configUSE_TASK_NOTIFICATIONS == 1 )
7984
7985     BaseType_t xTaskGenericNotifyFromISR( TaskHandle_t xTaskToNotify,
7986                                           UBaseType_t uxIndexToNotify,
7987                                           uint32_t ulValue,
7988                                           eNotifyAction eAction,
7989                                           uint32_t * pulPreviousNotificationValue,
7990                                           BaseType_t * pxHigherPriorityTaskWoken )
7991     {
7992         TCB_t * pxTCB;
7993         uint8_t ucOriginalNotifyState;
7994         BaseType_t xReturn = pdPASS;
7995         UBaseType_t uxSavedInterruptStatus;
7996
7997         traceENTER_xTaskGenericNotifyFromISR( xTaskToNotify, uxIndexToNotify, ulValue, eAction, pulPreviousNotificationValue, pxHigherPriorityTaskWoken );
7998
7999         configASSERT( xTaskToNotify );
8000         configASSERT( uxIndexToNotify < configTASK_NOTIFICATION_ARRAY_ENTRIES );
8001
8002         /* RTOS ports that support interrupt nesting have the concept of a
8003          * maximum  system call (or maximum API call) interrupt priority.
8004          * Interrupts that are  above the maximum system call priority are keep
8005          * permanently enabled, even when the RTOS kernel is in a critical section,
8006          * but cannot make any calls to FreeRTOS API functions.  If configASSERT()
8007          * is defined in FreeRTOSConfig.h then
8008          * portASSERT_IF_INTERRUPT_PRIORITY_INVALID() will result in an assertion
8009          * failure if a FreeRTOS API function is called from an interrupt that has
8010          * been assigned a priority above the configured maximum system call
8011          * priority.  Only FreeRTOS functions that end in FromISR can be called
8012          * from interrupts  that have been assigned a priority at or (logically)
8013          * below the maximum system call interrupt priority.  FreeRTOS maintains a
8014          * separate interrupt safe API to ensure interrupt entry is as fast and as
8015          * simple as possible.  More information (albeit Cortex-M specific) is
8016          * provided on the following link:
8017          * https://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html */
8018         portASSERT_IF_INTERRUPT_PRIORITY_INVALID();
8019
8020         pxTCB = xTaskToNotify;
8021
8022         uxSavedInterruptStatus = taskENTER_CRITICAL_FROM_ISR();
8023         {
8024             if( pulPreviousNotificationValue != NULL )
8025             {
8026                 *pulPreviousNotificationValue = pxTCB->ulNotifiedValue[ uxIndexToNotify ];
8027             }
8028
8029             ucOriginalNotifyState = pxTCB->ucNotifyState[ uxIndexToNotify ];
8030             pxTCB->ucNotifyState[ uxIndexToNotify ] = taskNOTIFICATION_RECEIVED;
8031
8032             switch( eAction )
8033             {
8034                 case eSetBits:
8035                     pxTCB->ulNotifiedValue[ uxIndexToNotify ] |= ulValue;
8036                     break;
8037
8038                 case eIncrement:
8039                     ( pxTCB->ulNotifiedValue[ uxIndexToNotify ] )++;
8040                     break;
8041
8042                 case eSetValueWithOverwrite:
8043                     pxTCB->ulNotifiedValue[ uxIndexToNotify ] = ulValue;
8044                     break;
8045
8046                 case eSetValueWithoutOverwrite:
8047
8048                     if( ucOriginalNotifyState != taskNOTIFICATION_RECEIVED )
8049                     {
8050                         pxTCB->ulNotifiedValue[ uxIndexToNotify ] = ulValue;
8051                     }
8052                     else
8053                     {
8054                         /* The value could not be written to the task. */
8055                         xReturn = pdFAIL;
8056                     }
8057
8058                     break;
8059
8060                 case eNoAction:
8061
8062                     /* The task is being notified without its notify value being
8063                      * updated. */
8064                     break;
8065
8066                 default:
8067
8068                     /* Should not get here if all enums are handled.
8069                      * Artificially force an assert by testing a value the
8070                      * compiler can't assume is const. */
8071                     configASSERT( xTickCount == ( TickType_t ) 0 );
8072                     break;
8073             }
8074
8075             traceTASK_NOTIFY_FROM_ISR( uxIndexToNotify );
8076
8077             /* If the task is in the blocked state specifically to wait for a
8078              * notification then unblock it now. */
8079             if( ucOriginalNotifyState == taskWAITING_NOTIFICATION )
8080             {
8081                 /* The task should not have been on an event list. */
8082                 configASSERT( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) == NULL );
8083
8084                 if( uxSchedulerSuspended == ( UBaseType_t ) 0U )
8085                 {
8086                     listREMOVE_ITEM( &( pxTCB->xStateListItem ) );
8087                     prvAddTaskToReadyList( pxTCB );
8088                 }
8089                 else
8090                 {
8091                     /* The delayed and ready lists cannot be accessed, so hold
8092                      * this task pending until the scheduler is resumed. */
8093                     listINSERT_END( &( xPendingReadyList ), &( pxTCB->xEventListItem ) );
8094                 }
8095
8096                 #if ( configNUMBER_OF_CORES == 1 )
8097                 {
8098                     if( pxTCB->uxPriority > pxCurrentTCB->uxPriority )
8099                     {
8100                         /* The notified task has a priority above the currently
8101                          * executing task so a yield is required. */
8102                         if( pxHigherPriorityTaskWoken != NULL )
8103                         {
8104                             *pxHigherPriorityTaskWoken = pdTRUE;
8105                         }
8106
8107                         /* Mark that a yield is pending in case the user is not
8108                          * using the "xHigherPriorityTaskWoken" parameter to an ISR
8109                          * safe FreeRTOS function. */
8110                         xYieldPendings[ 0 ] = pdTRUE;
8111                     }
8112                     else
8113                     {
8114                         mtCOVERAGE_TEST_MARKER();
8115                     }
8116                 }
8117                 #else /* #if ( configNUMBER_OF_CORES == 1 ) */
8118                 {
8119                     #if ( configUSE_PREEMPTION == 1 )
8120                     {
8121                         prvYieldForTask( pxTCB );
8122
8123                         if( xYieldPendings[ portGET_CORE_ID() ] == pdTRUE )
8124                         {
8125                             if( pxHigherPriorityTaskWoken != NULL )
8126                             {
8127                                 *pxHigherPriorityTaskWoken = pdTRUE;
8128                             }
8129                         }
8130                     }
8131                     #endif /* if ( configUSE_PREEMPTION == 1 ) */
8132                 }
8133                 #endif /* #if ( configNUMBER_OF_CORES == 1 ) */
8134             }
8135         }
8136         taskEXIT_CRITICAL_FROM_ISR( uxSavedInterruptStatus );
8137
8138         traceRETURN_xTaskGenericNotifyFromISR( xReturn );
8139
8140         return xReturn;
8141     }
8142
8143 #endif /* configUSE_TASK_NOTIFICATIONS */
8144 /*-----------------------------------------------------------*/
8145
8146 #if ( configUSE_TASK_NOTIFICATIONS == 1 )
8147
8148     void vTaskGenericNotifyGiveFromISR( TaskHandle_t xTaskToNotify,
8149                                         UBaseType_t uxIndexToNotify,
8150                                         BaseType_t * pxHigherPriorityTaskWoken )
8151     {
8152         TCB_t * pxTCB;
8153         uint8_t ucOriginalNotifyState;
8154         UBaseType_t uxSavedInterruptStatus;
8155
8156         traceENTER_vTaskGenericNotifyGiveFromISR( xTaskToNotify, uxIndexToNotify, pxHigherPriorityTaskWoken );
8157
8158         configASSERT( xTaskToNotify );
8159         configASSERT( uxIndexToNotify < configTASK_NOTIFICATION_ARRAY_ENTRIES );
8160
8161         /* RTOS ports that support interrupt nesting have the concept of a
8162          * maximum  system call (or maximum API call) interrupt priority.
8163          * Interrupts that are  above the maximum system call priority are keep
8164          * permanently enabled, even when the RTOS kernel is in a critical section,
8165          * but cannot make any calls to FreeRTOS API functions.  If configASSERT()
8166          * is defined in FreeRTOSConfig.h then
8167          * portASSERT_IF_INTERRUPT_PRIORITY_INVALID() will result in an assertion
8168          * failure if a FreeRTOS API function is called from an interrupt that has
8169          * been assigned a priority above the configured maximum system call
8170          * priority.  Only FreeRTOS functions that end in FromISR can be called
8171          * from interrupts  that have been assigned a priority at or (logically)
8172          * below the maximum system call interrupt priority.  FreeRTOS maintains a
8173          * separate interrupt safe API to ensure interrupt entry is as fast and as
8174          * simple as possible.  More information (albeit Cortex-M specific) is
8175          * provided on the following link:
8176          * https://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html */
8177         portASSERT_IF_INTERRUPT_PRIORITY_INVALID();
8178
8179         pxTCB = xTaskToNotify;
8180
8181         uxSavedInterruptStatus = taskENTER_CRITICAL_FROM_ISR();
8182         {
8183             ucOriginalNotifyState = pxTCB->ucNotifyState[ uxIndexToNotify ];
8184             pxTCB->ucNotifyState[ uxIndexToNotify ] = taskNOTIFICATION_RECEIVED;
8185
8186             /* 'Giving' is equivalent to incrementing a count in a counting
8187              * semaphore. */
8188             ( pxTCB->ulNotifiedValue[ uxIndexToNotify ] )++;
8189
8190             traceTASK_NOTIFY_GIVE_FROM_ISR( uxIndexToNotify );
8191
8192             /* If the task is in the blocked state specifically to wait for a
8193              * notification then unblock it now. */
8194             if( ucOriginalNotifyState == taskWAITING_NOTIFICATION )
8195             {
8196                 /* The task should not have been on an event list. */
8197                 configASSERT( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) == NULL );
8198
8199                 if( uxSchedulerSuspended == ( UBaseType_t ) 0U )
8200                 {
8201                     listREMOVE_ITEM( &( pxTCB->xStateListItem ) );
8202                     prvAddTaskToReadyList( pxTCB );
8203                 }
8204                 else
8205                 {
8206                     /* The delayed and ready lists cannot be accessed, so hold
8207                      * this task pending until the scheduler is resumed. */
8208                     listINSERT_END( &( xPendingReadyList ), &( pxTCB->xEventListItem ) );
8209                 }
8210
8211                 #if ( configNUMBER_OF_CORES == 1 )
8212                 {
8213                     if( pxTCB->uxPriority > pxCurrentTCB->uxPriority )
8214                     {
8215                         /* The notified task has a priority above the currently
8216                          * executing task so a yield is required. */
8217                         if( pxHigherPriorityTaskWoken != NULL )
8218                         {
8219                             *pxHigherPriorityTaskWoken = pdTRUE;
8220                         }
8221
8222                         /* Mark that a yield is pending in case the user is not
8223                          * using the "xHigherPriorityTaskWoken" parameter in an ISR
8224                          * safe FreeRTOS function. */
8225                         xYieldPendings[ 0 ] = pdTRUE;
8226                     }
8227                     else
8228                     {
8229                         mtCOVERAGE_TEST_MARKER();
8230                     }
8231                 }
8232                 #else /* #if ( configNUMBER_OF_CORES == 1 ) */
8233                 {
8234                     #if ( configUSE_PREEMPTION == 1 )
8235                     {
8236                         prvYieldForTask( pxTCB );
8237
8238                         if( xYieldPendings[ portGET_CORE_ID() ] == pdTRUE )
8239                         {
8240                             if( pxHigherPriorityTaskWoken != NULL )
8241                             {
8242                                 *pxHigherPriorityTaskWoken = pdTRUE;
8243                             }
8244                         }
8245                     }
8246                     #endif /* #if ( configUSE_PREEMPTION == 1 ) */
8247                 }
8248                 #endif /* #if ( configNUMBER_OF_CORES == 1 ) */
8249             }
8250         }
8251         taskEXIT_CRITICAL_FROM_ISR( uxSavedInterruptStatus );
8252
8253         traceRETURN_vTaskGenericNotifyGiveFromISR();
8254     }
8255
8256 #endif /* configUSE_TASK_NOTIFICATIONS */
8257 /*-----------------------------------------------------------*/
8258
8259 #if ( configUSE_TASK_NOTIFICATIONS == 1 )
8260
8261     BaseType_t xTaskGenericNotifyStateClear( TaskHandle_t xTask,
8262                                              UBaseType_t uxIndexToClear )
8263     {
8264         TCB_t * pxTCB;
8265         BaseType_t xReturn;
8266
8267         traceENTER_xTaskGenericNotifyStateClear( xTask, uxIndexToClear );
8268
8269         configASSERT( uxIndexToClear < configTASK_NOTIFICATION_ARRAY_ENTRIES );
8270
8271         /* If null is passed in here then it is the calling task that is having
8272          * its notification state cleared. */
8273         pxTCB = prvGetTCBFromHandle( xTask );
8274
8275         taskENTER_CRITICAL();
8276         {
8277             if( pxTCB->ucNotifyState[ uxIndexToClear ] == taskNOTIFICATION_RECEIVED )
8278             {
8279                 pxTCB->ucNotifyState[ uxIndexToClear ] = taskNOT_WAITING_NOTIFICATION;
8280                 xReturn = pdPASS;
8281             }
8282             else
8283             {
8284                 xReturn = pdFAIL;
8285             }
8286         }
8287         taskEXIT_CRITICAL();
8288
8289         traceRETURN_xTaskGenericNotifyStateClear( xReturn );
8290
8291         return xReturn;
8292     }
8293
8294 #endif /* configUSE_TASK_NOTIFICATIONS */
8295 /*-----------------------------------------------------------*/
8296
8297 #if ( configUSE_TASK_NOTIFICATIONS == 1 )
8298
8299     uint32_t ulTaskGenericNotifyValueClear( TaskHandle_t xTask,
8300                                             UBaseType_t uxIndexToClear,
8301                                             uint32_t ulBitsToClear )
8302     {
8303         TCB_t * pxTCB;
8304         uint32_t ulReturn;
8305
8306         traceENTER_ulTaskGenericNotifyValueClear( xTask, uxIndexToClear, ulBitsToClear );
8307
8308         configASSERT( uxIndexToClear < configTASK_NOTIFICATION_ARRAY_ENTRIES );
8309
8310         /* If null is passed in here then it is the calling task that is having
8311          * its notification state cleared. */
8312         pxTCB = prvGetTCBFromHandle( xTask );
8313
8314         taskENTER_CRITICAL();
8315         {
8316             /* Return the notification as it was before the bits were cleared,
8317              * then clear the bit mask. */
8318             ulReturn = pxTCB->ulNotifiedValue[ uxIndexToClear ];
8319             pxTCB->ulNotifiedValue[ uxIndexToClear ] &= ~ulBitsToClear;
8320         }
8321         taskEXIT_CRITICAL();
8322
8323         traceRETURN_ulTaskGenericNotifyValueClear( ulReturn );
8324
8325         return ulReturn;
8326     }
8327
8328 #endif /* configUSE_TASK_NOTIFICATIONS */
8329 /*-----------------------------------------------------------*/
8330
8331 #if ( configGENERATE_RUN_TIME_STATS == 1 )
8332
8333     configRUN_TIME_COUNTER_TYPE ulTaskGetRunTimeCounter( const TaskHandle_t xTask )
8334     {
8335         TCB_t * pxTCB;
8336
8337         traceENTER_ulTaskGetRunTimeCounter( xTask );
8338
8339         pxTCB = prvGetTCBFromHandle( xTask );
8340
8341         traceRETURN_ulTaskGetRunTimeCounter( pxTCB->ulRunTimeCounter );
8342
8343         return pxTCB->ulRunTimeCounter;
8344     }
8345
8346 #endif /* if ( configGENERATE_RUN_TIME_STATS == 1 ) */
8347 /*-----------------------------------------------------------*/
8348
8349 #if ( configGENERATE_RUN_TIME_STATS == 1 )
8350
8351     configRUN_TIME_COUNTER_TYPE ulTaskGetRunTimePercent( const TaskHandle_t xTask )
8352     {
8353         TCB_t * pxTCB;
8354         configRUN_TIME_COUNTER_TYPE ulTotalTime, ulReturn;
8355
8356         traceENTER_ulTaskGetRunTimePercent( xTask );
8357
8358         ulTotalTime = ( configRUN_TIME_COUNTER_TYPE ) portGET_RUN_TIME_COUNTER_VALUE();
8359
8360         /* For percentage calculations. */
8361         ulTotalTime /= ( configRUN_TIME_COUNTER_TYPE ) 100;
8362
8363         /* Avoid divide by zero errors. */
8364         if( ulTotalTime > ( configRUN_TIME_COUNTER_TYPE ) 0 )
8365         {
8366             pxTCB = prvGetTCBFromHandle( xTask );
8367             ulReturn = pxTCB->ulRunTimeCounter / ulTotalTime;
8368         }
8369         else
8370         {
8371             ulReturn = 0;
8372         }
8373
8374         traceRETURN_ulTaskGetRunTimePercent( ulReturn );
8375
8376         return ulReturn;
8377     }
8378
8379 #endif /* if ( configGENERATE_RUN_TIME_STATS == 1 ) */
8380 /*-----------------------------------------------------------*/
8381
8382 #if ( ( configGENERATE_RUN_TIME_STATS == 1 ) && ( INCLUDE_xTaskGetIdleTaskHandle == 1 ) )
8383
8384     configRUN_TIME_COUNTER_TYPE ulTaskGetIdleRunTimeCounter( void )
8385     {
8386         configRUN_TIME_COUNTER_TYPE ulReturn = 0;
8387         BaseType_t i;
8388
8389         traceENTER_ulTaskGetIdleRunTimeCounter();
8390
8391         for( i = 0; i < ( BaseType_t ) configNUMBER_OF_CORES; i++ )
8392         {
8393             ulReturn += xIdleTaskHandles[ i ]->ulRunTimeCounter;
8394         }
8395
8396         traceRETURN_ulTaskGetIdleRunTimeCounter( ulReturn );
8397
8398         return ulReturn;
8399     }
8400
8401 #endif /* if ( ( configGENERATE_RUN_TIME_STATS == 1 ) && ( INCLUDE_xTaskGetIdleTaskHandle == 1 ) ) */
8402 /*-----------------------------------------------------------*/
8403
8404 #if ( ( configGENERATE_RUN_TIME_STATS == 1 ) && ( INCLUDE_xTaskGetIdleTaskHandle == 1 ) )
8405
8406     configRUN_TIME_COUNTER_TYPE ulTaskGetIdleRunTimePercent( void )
8407     {
8408         configRUN_TIME_COUNTER_TYPE ulTotalTime, ulReturn;
8409         configRUN_TIME_COUNTER_TYPE ulRunTimeCounter = 0;
8410         BaseType_t i;
8411
8412         traceENTER_ulTaskGetIdleRunTimePercent();
8413
8414         ulTotalTime = portGET_RUN_TIME_COUNTER_VALUE() * configNUMBER_OF_CORES;
8415
8416         /* For percentage calculations. */
8417         ulTotalTime /= ( configRUN_TIME_COUNTER_TYPE ) 100;
8418
8419         /* Avoid divide by zero errors. */
8420         if( ulTotalTime > ( configRUN_TIME_COUNTER_TYPE ) 0 )
8421         {
8422             for( i = 0; i < ( BaseType_t ) configNUMBER_OF_CORES; i++ )
8423             {
8424                 ulRunTimeCounter += xIdleTaskHandles[ i ]->ulRunTimeCounter;
8425             }
8426
8427             ulReturn = ulRunTimeCounter / ulTotalTime;
8428         }
8429         else
8430         {
8431             ulReturn = 0;
8432         }
8433
8434         traceRETURN_ulTaskGetIdleRunTimePercent( ulReturn );
8435
8436         return ulReturn;
8437     }
8438
8439 #endif /* if ( ( configGENERATE_RUN_TIME_STATS == 1 ) && ( INCLUDE_xTaskGetIdleTaskHandle == 1 ) ) */
8440 /*-----------------------------------------------------------*/
8441
8442 static void prvAddCurrentTaskToDelayedList( TickType_t xTicksToWait,
8443                                             const BaseType_t xCanBlockIndefinitely )
8444 {
8445     TickType_t xTimeToWake;
8446     const TickType_t xConstTickCount = xTickCount;
8447
8448     #if ( INCLUDE_xTaskAbortDelay == 1 )
8449     {
8450         /* About to enter a delayed list, so ensure the ucDelayAborted flag is
8451          * reset to pdFALSE so it can be detected as having been set to pdTRUE
8452          * when the task leaves the Blocked state. */
8453         pxCurrentTCB->ucDelayAborted = pdFALSE;
8454     }
8455     #endif
8456
8457     /* Remove the task from the ready list before adding it to the blocked list
8458      * as the same list item is used for both lists. */
8459     if( uxListRemove( &( pxCurrentTCB->xStateListItem ) ) == ( UBaseType_t ) 0 )
8460     {
8461         /* The current task must be in a ready list, so there is no need to
8462          * check, and the port reset macro can be called directly. */
8463         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. */
8464     }
8465     else
8466     {
8467         mtCOVERAGE_TEST_MARKER();
8468     }
8469
8470     #if ( INCLUDE_vTaskSuspend == 1 )
8471     {
8472         if( ( xTicksToWait == portMAX_DELAY ) && ( xCanBlockIndefinitely != pdFALSE ) )
8473         {
8474             /* Add the task to the suspended task list instead of a delayed task
8475              * list to ensure it is not woken by a timing event.  It will block
8476              * indefinitely. */
8477             listINSERT_END( &xSuspendedTaskList, &( pxCurrentTCB->xStateListItem ) );
8478         }
8479         else
8480         {
8481             /* Calculate the time at which the task should be woken if the event
8482              * does not occur.  This may overflow but this doesn't matter, the
8483              * kernel will manage it correctly. */
8484             xTimeToWake = xConstTickCount + xTicksToWait;
8485
8486             /* The list item will be inserted in wake time order. */
8487             listSET_LIST_ITEM_VALUE( &( pxCurrentTCB->xStateListItem ), xTimeToWake );
8488
8489             if( xTimeToWake < xConstTickCount )
8490             {
8491                 /* Wake time has overflowed.  Place this item in the overflow
8492                  * list. */
8493                 traceMOVED_TASK_TO_OVERFLOW_DELAYED_LIST();
8494                 vListInsert( pxOverflowDelayedTaskList, &( pxCurrentTCB->xStateListItem ) );
8495             }
8496             else
8497             {
8498                 /* The wake time has not overflowed, so the current block list
8499                  * is used. */
8500                 traceMOVED_TASK_TO_DELAYED_LIST();
8501                 vListInsert( pxDelayedTaskList, &( pxCurrentTCB->xStateListItem ) );
8502
8503                 /* If the task entering the blocked state was placed at the
8504                  * head of the list of blocked tasks then xNextTaskUnblockTime
8505                  * needs to be updated too. */
8506                 if( xTimeToWake < xNextTaskUnblockTime )
8507                 {
8508                     xNextTaskUnblockTime = xTimeToWake;
8509                 }
8510                 else
8511                 {
8512                     mtCOVERAGE_TEST_MARKER();
8513                 }
8514             }
8515         }
8516     }
8517     #else /* INCLUDE_vTaskSuspend */
8518     {
8519         /* Calculate the time at which the task should be woken if the event
8520          * does not occur.  This may overflow but this doesn't matter, the kernel
8521          * will manage it correctly. */
8522         xTimeToWake = xConstTickCount + xTicksToWait;
8523
8524         /* The list item will be inserted in wake time order. */
8525         listSET_LIST_ITEM_VALUE( &( pxCurrentTCB->xStateListItem ), xTimeToWake );
8526
8527         if( xTimeToWake < xConstTickCount )
8528         {
8529             traceMOVED_TASK_TO_OVERFLOW_DELAYED_LIST();
8530             /* Wake time has overflowed.  Place this item in the overflow list. */
8531             vListInsert( pxOverflowDelayedTaskList, &( pxCurrentTCB->xStateListItem ) );
8532         }
8533         else
8534         {
8535             traceMOVED_TASK_TO_DELAYED_LIST();
8536             /* The wake time has not overflowed, so the current block list is used. */
8537             vListInsert( pxDelayedTaskList, &( pxCurrentTCB->xStateListItem ) );
8538
8539             /* If the task entering the blocked state was placed at the head of the
8540              * list of blocked tasks then xNextTaskUnblockTime needs to be updated
8541              * too. */
8542             if( xTimeToWake < xNextTaskUnblockTime )
8543             {
8544                 xNextTaskUnblockTime = xTimeToWake;
8545             }
8546             else
8547             {
8548                 mtCOVERAGE_TEST_MARKER();
8549             }
8550         }
8551
8552         /* Avoid compiler warning when INCLUDE_vTaskSuspend is not 1. */
8553         ( void ) xCanBlockIndefinitely;
8554     }
8555     #endif /* INCLUDE_vTaskSuspend */
8556 }
8557 /*-----------------------------------------------------------*/
8558
8559 #if ( portUSING_MPU_WRAPPERS == 1 )
8560
8561     xMPU_SETTINGS * xTaskGetMPUSettings( TaskHandle_t xTask )
8562     {
8563         TCB_t * pxTCB;
8564
8565         traceENTER_xTaskGetMPUSettings( xTask );
8566
8567         pxTCB = prvGetTCBFromHandle( xTask );
8568
8569         traceRETURN_xTaskGetMPUSettings( &( pxTCB->xMPUSettings ) );
8570
8571         return &( pxTCB->xMPUSettings );
8572     }
8573
8574 #endif /* portUSING_MPU_WRAPPERS */
8575 /*-----------------------------------------------------------*/
8576
8577 /* Code below here allows additional code to be inserted into this source file,
8578  * especially where access to file scope functions and data is needed (for example
8579  * when performing module tests). */
8580
8581 #ifdef FREERTOS_MODULE_TEST
8582     #include "tasks_test_access_functions.h"
8583 #endif
8584
8585
8586 #if ( configINCLUDE_FREERTOS_TASK_C_ADDITIONS_H == 1 )
8587
8588     #include "freertos_tasks_c_additions.h"
8589
8590     #ifdef FREERTOS_TASKS_C_ADDITIONS_INIT
8591         static void freertos_tasks_c_additions_init( void )
8592         {
8593             FREERTOS_TASKS_C_ADDITIONS_INIT();
8594         }
8595     #endif
8596
8597 #endif /* if ( configINCLUDE_FREERTOS_TASK_C_ADDITIONS_H == 1 ) */
8598 /*-----------------------------------------------------------*/
8599
8600 #if ( ( configSUPPORT_STATIC_ALLOCATION == 1 ) && ( configKERNEL_PROVIDED_STATIC_MEMORY == 1 ) && ( portUSING_MPU_WRAPPERS == 0 ) )
8601
8602 /*
8603  * This is the kernel provided implementation of vApplicationGetIdleTaskMemory()
8604  * to provide the memory that is used by the Idle task. It is used when
8605  * configKERNEL_PROVIDED_STATIC_MEMORY is set to 1. The application can provide
8606  * it's own implementation of vApplicationGetIdleTaskMemory by setting
8607  * configKERNEL_PROVIDED_STATIC_MEMORY to 0 or leaving it undefined.
8608  */
8609     void vApplicationGetIdleTaskMemory( StaticTask_t ** ppxIdleTaskTCBBuffer,
8610                                         StackType_t ** ppxIdleTaskStackBuffer,
8611                                         uint32_t * pulIdleTaskStackSize )
8612     {
8613         static StaticTask_t xIdleTaskTCB;
8614         static StackType_t uxIdleTaskStack[ configMINIMAL_STACK_SIZE ];
8615
8616         *ppxIdleTaskTCBBuffer = &( xIdleTaskTCB );
8617         *ppxIdleTaskStackBuffer = &( uxIdleTaskStack[ 0 ] );
8618         *pulIdleTaskStackSize = configMINIMAL_STACK_SIZE;
8619     }
8620
8621     #if ( configNUMBER_OF_CORES > 1 )
8622
8623         void vApplicationGetPassiveIdleTaskMemory( StaticTask_t ** ppxIdleTaskTCBBuffer,
8624                                                    StackType_t ** ppxIdleTaskStackBuffer,
8625                                                    uint32_t * pulIdleTaskStackSize,
8626                                                    BaseType_t xPassiveIdleTaskIndex )
8627         {
8628             static StaticTask_t xIdleTaskTCBs[ configNUMBER_OF_CORES - 1 ];
8629             static StackType_t uxIdleTaskStacks[ configNUMBER_OF_CORES - 1 ][ configMINIMAL_STACK_SIZE ];
8630
8631             *ppxIdleTaskTCBBuffer = &( xIdleTaskTCBs[ xPassiveIdleTaskIndex ] );
8632             *ppxIdleTaskStackBuffer = &( uxIdleTaskStacks[ xPassiveIdleTaskIndex ][ 0 ] );
8633             *pulIdleTaskStackSize = configMINIMAL_STACK_SIZE;
8634         }
8635
8636     #endif /* #if ( configNUMBER_OF_CORES > 1 ) */
8637
8638 #endif /* #if ( ( configSUPPORT_STATIC_ALLOCATION == 1 ) && ( configKERNEL_PROVIDED_STATIC_MEMORY == 1 ) && ( portUSING_MPU_WRAPPERS == 0 ) ) */
8639 /*-----------------------------------------------------------*/
8640
8641 #if ( ( configSUPPORT_STATIC_ALLOCATION == 1 ) && ( configKERNEL_PROVIDED_STATIC_MEMORY == 1 ) && ( portUSING_MPU_WRAPPERS == 0 ) )
8642
8643 /*
8644  * This is the kernel provided implementation of vApplicationGetTimerTaskMemory()
8645  * to provide the memory that is used by the Timer service task. It is used when
8646  * configKERNEL_PROVIDED_STATIC_MEMORY is set to 1. The application can provide
8647  * it's own implementation of vApplicationGetTimerTaskMemory by setting
8648  * configKERNEL_PROVIDED_STATIC_MEMORY to 0 or leaving it undefined.
8649  */
8650     void vApplicationGetTimerTaskMemory( StaticTask_t ** ppxTimerTaskTCBBuffer,
8651                                          StackType_t ** ppxTimerTaskStackBuffer,
8652                                          uint32_t * pulTimerTaskStackSize )
8653     {
8654         static StaticTask_t xTimerTaskTCB;
8655         static StackType_t uxTimerTaskStack[ configTIMER_TASK_STACK_DEPTH ];
8656
8657         *ppxTimerTaskTCBBuffer = &( xTimerTaskTCB );
8658         *ppxTimerTaskStackBuffer = &( uxTimerTaskStack[ 0 ] );
8659         *pulTimerTaskStackSize = configTIMER_TASK_STACK_DEPTH;
8660     }
8661
8662 #endif /* #if ( ( configSUPPORT_STATIC_ALLOCATION == 1 ) && ( configKERNEL_PROVIDED_STATIC_MEMORY == 1 ) && ( portUSING_MPU_WRAPPERS == 0 ) ) */
8663 /*-----------------------------------------------------------*/