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