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