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