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