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