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