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