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