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