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