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