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