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