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