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