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