]> begriffs open source - freertos/blob - tasks.c
Update equal priority task preemption (#603)
[freertos] / tasks.c
1 /*
2  * FreeRTOS Kernel <DEVELOPMENT BRANCH>
3  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates.  All Rights Reserved.
4  *
5  * SPDX-License-Identifier: MIT
6  *
7  * Permission is hereby granted, free of charge, to any person obtaining a copy of
8  * this software and associated documentation files (the "Software"), to deal in
9  * the Software without restriction, including without limitation the rights to
10  * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
11  * the Software, and to permit persons to whom the Software is furnished to do so,
12  * subject to the following conditions:
13  *
14  * The above copyright notice and this permission notice shall be included in all
15  * copies or substantial portions of the Software.
16  *
17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
19  * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
20  * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
21  * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23  *
24  * https://www.FreeRTOS.org
25  * https://github.com/FreeRTOS
26  *
27  */
28
29 /* Standard includes. */
30 #include <stdlib.h>
31 #include <string.h>
32
33 /* Defining MPU_WRAPPERS_INCLUDED_FROM_API_FILE prevents task.h from redefining
34  * all the API functions to use the MPU wrappers.  That should only be done when
35  * task.h is included from an application file. */
36 #define MPU_WRAPPERS_INCLUDED_FROM_API_FILE
37
38 /* FreeRTOS includes. */
39 #include "FreeRTOS.h"
40 #include "task.h"
41 #include "timers.h"
42 #include "stack_macros.h"
43
44 /* Lint e9021, e961 and e750 are suppressed as a MISRA exception justified
45  * because the MPU ports require MPU_WRAPPERS_INCLUDED_FROM_API_FILE to be defined
46  * for the header files above, but not in this file, in order to generate the
47  * correct privileged Vs unprivileged linkage and placement. */
48 #undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE /*lint !e961 !e750 !e9021. */
49
50 /* Set configUSE_STATS_FORMATTING_FUNCTIONS to 2 to include the stats formatting
51  * functions but without including stdio.h here. */
52 #if ( configUSE_STATS_FORMATTING_FUNCTIONS == 1 )
53
54 /* At the bottom of this file are two optional functions that can be used
55  * to generate human readable text from the raw data generated by the
56  * uxTaskGetSystemState() function.  Note the formatting functions are provided
57  * for convenience only, and are NOT considered part of the kernel. */
58     #include <stdio.h>
59 #endif /* configUSE_STATS_FORMATTING_FUNCTIONS == 1 ) */
60
61 #if ( configUSE_PREEMPTION == 0 )
62
63 /* If the cooperative scheduler is being used then a yield should not be
64  * performed just because a higher priority task has been woken. */
65     #define taskYIELD_IF_USING_PREEMPTION()
66 #else
67     #define taskYIELD_IF_USING_PREEMPTION()    portYIELD_WITHIN_API()
68 #endif
69
70 /* Values that can be assigned to the ucNotifyState member of the TCB. */
71 #define taskNOT_WAITING_NOTIFICATION              ( ( uint8_t ) 0 ) /* Must be zero as it is the initialised value. */
72 #define taskWAITING_NOTIFICATION                  ( ( uint8_t ) 1 )
73 #define taskNOTIFICATION_RECEIVED                 ( ( uint8_t ) 2 )
74
75 /*
76  * The value used to fill the stack of a task when the task is created.  This
77  * is used purely for checking the high water mark for tasks.
78  */
79 #define tskSTACK_FILL_BYTE                        ( 0xa5U )
80
81 /* Bits used to record how a task's stack and TCB were allocated. */
82 #define tskDYNAMICALLY_ALLOCATED_STACK_AND_TCB    ( ( uint8_t ) 0 )
83 #define tskSTATICALLY_ALLOCATED_STACK_ONLY        ( ( uint8_t ) 1 )
84 #define tskSTATICALLY_ALLOCATED_STACK_AND_TCB     ( ( uint8_t ) 2 )
85
86 /* If any of the following are set then task stacks are filled with a known
87  * value so the high water mark can be determined.  If none of the following are
88  * set then don't fill the stack so there is no unnecessary dependency on memset. */
89 #if ( ( configCHECK_FOR_STACK_OVERFLOW > 1 ) || ( configUSE_TRACE_FACILITY == 1 ) || ( INCLUDE_uxTaskGetStackHighWaterMark == 1 ) || ( INCLUDE_uxTaskGetStackHighWaterMark2 == 1 ) )
90     #define tskSET_NEW_STACKS_TO_KNOWN_VALUE    1
91 #else
92     #define tskSET_NEW_STACKS_TO_KNOWN_VALUE    0
93 #endif
94
95 /*
96  * Macros used by vListTask to indicate which state a task is in.
97  */
98 #define tskRUNNING_CHAR      ( 'X' )
99 #define tskBLOCKED_CHAR      ( 'B' )
100 #define tskREADY_CHAR        ( 'R' )
101 #define tskDELETED_CHAR      ( 'D' )
102 #define tskSUSPENDED_CHAR    ( 'S' )
103
104 /*
105  * Some kernel aware debuggers require the data the debugger needs access to to
106  * be global, rather than file scope.
107  */
108 #ifdef portREMOVE_STATIC_QUALIFIER
109     #define static
110 #endif
111
112 /* The name allocated to the Idle task.  This can be overridden by defining
113  * configIDLE_TASK_NAME in FreeRTOSConfig.h. */
114 #ifndef configIDLE_TASK_NAME
115     #define configIDLE_TASK_NAME    "IDLE"
116 #endif
117
118 #if ( configUSE_PORT_OPTIMISED_TASK_SELECTION == 0 )
119
120 /* If configUSE_PORT_OPTIMISED_TASK_SELECTION is 0 then task selection is
121  * performed in a generic way that is not optimised to any particular
122  * microcontroller architecture. */
123
124 /* uxTopReadyPriority holds the priority of the highest priority ready
125  * state task. */
126     #define taskRECORD_READY_PRIORITY( uxPriority ) \
127     {                                               \
128         if( ( uxPriority ) > uxTopReadyPriority )   \
129         {                                           \
130             uxTopReadyPriority = ( uxPriority );    \
131         }                                           \
132     } /* taskRECORD_READY_PRIORITY */
133
134 /*-----------------------------------------------------------*/
135
136     #define taskSELECT_HIGHEST_PRIORITY_TASK()                                \
137     {                                                                         \
138         UBaseType_t uxTopPriority = uxTopReadyPriority;                       \
139                                                                               \
140         /* Find the highest priority queue that contains ready tasks. */      \
141         while( listLIST_IS_EMPTY( &( pxReadyTasksLists[ uxTopPriority ] ) ) ) \
142         {                                                                     \
143             configASSERT( uxTopPriority );                                    \
144             --uxTopPriority;                                                  \
145         }                                                                     \
146                                                                               \
147         /* listGET_OWNER_OF_NEXT_ENTRY indexes through the list, so the tasks of \
148          * the  same priority get an equal share of the processor time. */                    \
149         listGET_OWNER_OF_NEXT_ENTRY( pxCurrentTCB, &( pxReadyTasksLists[ uxTopPriority ] ) ); \
150         uxTopReadyPriority = uxTopPriority;                                                   \
151     } /* taskSELECT_HIGHEST_PRIORITY_TASK */
152
153 /*-----------------------------------------------------------*/
154
155 /* Define away taskRESET_READY_PRIORITY() and portRESET_READY_PRIORITY() as
156  * they are only required when a port optimised method of task selection is
157  * being used. */
158     #define taskRESET_READY_PRIORITY( uxPriority )
159     #define portRESET_READY_PRIORITY( uxPriority, uxTopReadyPriority )
160
161 #else /* configUSE_PORT_OPTIMISED_TASK_SELECTION */
162
163 /* If configUSE_PORT_OPTIMISED_TASK_SELECTION is 1 then task selection is
164  * performed in a way that is tailored to the particular microcontroller
165  * architecture being used. */
166
167 /* A port optimised version is provided.  Call the port defined macros. */
168     #define taskRECORD_READY_PRIORITY( uxPriority )    portRECORD_READY_PRIORITY( ( uxPriority ), uxTopReadyPriority )
169
170 /*-----------------------------------------------------------*/
171
172     #define taskSELECT_HIGHEST_PRIORITY_TASK()                                                  \
173     {                                                                                           \
174         UBaseType_t uxTopPriority;                                                              \
175                                                                                                 \
176         /* Find the highest priority list that contains ready tasks. */                         \
177         portGET_HIGHEST_PRIORITY( uxTopPriority, uxTopReadyPriority );                          \
178         configASSERT( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ uxTopPriority ] ) ) > 0 ); \
179         listGET_OWNER_OF_NEXT_ENTRY( pxCurrentTCB, &( pxReadyTasksLists[ uxTopPriority ] ) );   \
180     } /* taskSELECT_HIGHEST_PRIORITY_TASK() */
181
182 /*-----------------------------------------------------------*/
183
184 /* A port optimised version is provided, call it only if the TCB being reset
185  * is being referenced from a ready list.  If it is referenced from a delayed
186  * or suspended list then it won't be in a ready list. */
187     #define taskRESET_READY_PRIORITY( uxPriority )                                                     \
188     {                                                                                                  \
189         if( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ ( uxPriority ) ] ) ) == ( UBaseType_t ) 0 ) \
190         {                                                                                              \
191             portRESET_READY_PRIORITY( ( uxPriority ), ( uxTopReadyPriority ) );                        \
192         }                                                                                              \
193     }
194
195 #endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */
196
197 /*-----------------------------------------------------------*/
198
199 /* pxDelayedTaskList and pxOverflowDelayedTaskList are switched when the tick
200  * count overflows. */
201 #define taskSWITCH_DELAYED_LISTS()                                                \
202     {                                                                             \
203         List_t * pxTemp;                                                          \
204                                                                                   \
205         /* The delayed tasks list should be empty when the lists are switched. */ \
206         configASSERT( ( listLIST_IS_EMPTY( pxDelayedTaskList ) ) );               \
207                                                                                   \
208         pxTemp = pxDelayedTaskList;                                               \
209         pxDelayedTaskList = pxOverflowDelayedTaskList;                            \
210         pxOverflowDelayedTaskList = pxTemp;                                       \
211         xNumOfOverflows++;                                                        \
212         prvResetNextTaskUnblockTime();                                            \
213     }
214
215 /*-----------------------------------------------------------*/
216
217 /*
218  * Place the task represented by pxTCB into the appropriate ready list for
219  * the task.  It is inserted at the end of the list.
220  */
221 #define prvAddTaskToReadyList( pxTCB )                                                                 \
222     traceMOVED_TASK_TO_READY_STATE( pxTCB );                                                           \
223     taskRECORD_READY_PRIORITY( ( pxTCB )->uxPriority );                                                \
224     listINSERT_END( &( pxReadyTasksLists[ ( pxTCB )->uxPriority ] ), &( ( pxTCB )->xStateListItem ) ); \
225     tracePOST_MOVED_TASK_TO_READY_STATE( pxTCB )
226 /*-----------------------------------------------------------*/
227
228 /*
229  * Several functions take a TaskHandle_t parameter that can optionally be NULL,
230  * where NULL is used to indicate that the handle of the currently executing
231  * task should be used in place of the parameter.  This macro simply checks to
232  * see if the parameter is NULL and returns a pointer to the appropriate TCB.
233  */
234 #define prvGetTCBFromHandle( pxHandle )    ( ( ( pxHandle ) == NULL ) ? pxCurrentTCB : ( pxHandle ) )
235
236 /* The item value of the event list item is normally used to hold the priority
237  * of the task to which it belongs (coded to allow it to be held in reverse
238  * priority order).  However, it is occasionally borrowed for other purposes.  It
239  * is important its value is not updated due to a task priority change while it is
240  * being used for another purpose.  The following bit definition is used to inform
241  * the scheduler that the value should not be changed - in which case it is the
242  * responsibility of whichever module is using the value to ensure it gets set back
243  * to its original value when it is released. */
244 #if ( configUSE_16_BIT_TICKS == 1 )
245     #define taskEVENT_LIST_ITEM_VALUE_IN_USE    0x8000U
246 #else
247     #define taskEVENT_LIST_ITEM_VALUE_IN_USE    0x80000000UL
248 #endif
249
250 /*
251  * Task control block.  A task control block (TCB) is allocated for each task,
252  * and stores task state information, including a pointer to the task's context
253  * (the task's run time environment, including register values)
254  */
255 typedef struct tskTaskControlBlock       /* The old naming convention is used to prevent breaking kernel aware debuggers. */
256 {
257     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. */
258
259     #if ( portUSING_MPU_WRAPPERS == 1 )
260         xMPU_SETTINGS xMPUSettings; /*< The MPU settings are defined as part of the port layer.  THIS MUST BE THE SECOND MEMBER OF THE TCB STRUCT. */
261     #endif
262
263     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 ). */
264     ListItem_t xEventListItem;                  /*< Used to reference a task from an event list. */
265     UBaseType_t uxPriority;                     /*< The priority of the task.  0 is the lowest priority. */
266     StackType_t * pxStack;                      /*< Points to the start of the stack. */
267     char pcTaskName[ configMAX_TASK_NAME_LEN ]; /*< Descriptive name given to the task when created.  Facilitates debugging only. */ /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
268
269     #if ( ( portSTACK_GROWTH > 0 ) || ( configRECORD_STACK_HIGH_ADDRESS == 1 ) )
270         StackType_t * pxEndOfStack; /*< Points to the highest valid address for the stack. */
271     #endif
272
273     #if ( portCRITICAL_NESTING_IN_TCB == 1 )
274         UBaseType_t uxCriticalNesting; /*< Holds the critical section nesting depth for ports that do not maintain their own count in the port layer. */
275     #endif
276
277     #if ( configUSE_TRACE_FACILITY == 1 )
278         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. */
279         UBaseType_t uxTaskNumber; /*< Stores a number specifically for use by third party trace code. */
280     #endif
281
282     #if ( configUSE_MUTEXES == 1 )
283         UBaseType_t uxBasePriority; /*< The priority last assigned to the task - used by the priority inheritance mechanism. */
284         UBaseType_t uxMutexesHeld;
285     #endif
286
287     #if ( configUSE_APPLICATION_TASK_TAG == 1 )
288         TaskHookFunction_t pxTaskTag;
289     #endif
290
291     #if ( configNUM_THREAD_LOCAL_STORAGE_POINTERS > 0 )
292         void * pvThreadLocalStoragePointers[ configNUM_THREAD_LOCAL_STORAGE_POINTERS ];
293     #endif
294
295     #if ( configGENERATE_RUN_TIME_STATS == 1 )
296         configRUN_TIME_COUNTER_TYPE ulRunTimeCounter; /*< Stores the amount of time the task has spent in the Running state. */
297     #endif
298
299     #if ( ( configUSE_NEWLIB_REENTRANT == 1 ) || ( configUSE_C_RUNTIME_TLS_SUPPORT == 1 ) )
300         configTLS_BLOCK_TYPE xTLSBlock; /*< Memory block used as Thread Local Storage (TLS) Block for the task. */
301     #endif
302
303     #if ( configUSE_TASK_NOTIFICATIONS == 1 )
304         volatile uint32_t ulNotifiedValue[ configTASK_NOTIFICATION_ARRAY_ENTRIES ];
305         volatile uint8_t ucNotifyState[ configTASK_NOTIFICATION_ARRAY_ENTRIES ];
306     #endif
307
308     /* See the comments in FreeRTOS.h with the definition of
309      * tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE. */
310     #if ( tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE != 0 ) /*lint !e731 !e9029 Macro has been consolidated for readability reasons. */
311         uint8_t ucStaticallyAllocated;                     /*< Set to pdTRUE if the task is a statically allocated to ensure no attempt is made to free the memory. */
312     #endif
313
314     #if ( INCLUDE_xTaskAbortDelay == 1 )
315         uint8_t ucDelayAborted;
316     #endif
317
318     #if ( configUSE_POSIX_ERRNO == 1 )
319         int iTaskErrno;
320     #endif
321 } tskTCB;
322
323 /* The old tskTCB name is maintained above then typedefed to the new TCB_t name
324  * below to enable the use of older kernel aware debuggers. */
325 typedef tskTCB TCB_t;
326
327 /*lint -save -e956 A manual analysis and inspection has been used to determine
328  * which static variables must be declared volatile. */
329 portDONT_DISCARD PRIVILEGED_DATA TCB_t * volatile pxCurrentTCB = NULL;
330
331 /* Lists for ready and blocked tasks. --------------------
332  * xDelayedTaskList1 and xDelayedTaskList2 could be moved to function scope but
333  * doing so breaks some kernel aware debuggers and debuggers that rely on removing
334  * the static qualifier. */
335 PRIVILEGED_DATA static List_t pxReadyTasksLists[ configMAX_PRIORITIES ]; /*< Prioritised ready tasks. */
336 PRIVILEGED_DATA static List_t xDelayedTaskList1;                         /*< Delayed tasks. */
337 PRIVILEGED_DATA static List_t xDelayedTaskList2;                         /*< Delayed tasks (two lists are used - one for delays that have overflowed the current tick count. */
338 PRIVILEGED_DATA static List_t * volatile pxDelayedTaskList;              /*< Points to the delayed task list currently being used. */
339 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. */
340 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. */
341
342 #if ( INCLUDE_vTaskDelete == 1 )
343
344     PRIVILEGED_DATA static List_t xTasksWaitingTermination; /*< Tasks that have been deleted - but their memory not yet freed. */
345     PRIVILEGED_DATA static volatile UBaseType_t uxDeletedTasksWaitingCleanUp = ( UBaseType_t ) 0U;
346
347 #endif
348
349 #if ( INCLUDE_vTaskSuspend == 1 )
350
351     PRIVILEGED_DATA static List_t xSuspendedTaskList; /*< Tasks that are currently suspended. */
352
353 #endif
354
355 /* Global POSIX errno. Its value is changed upon context switching to match
356  * the errno of the currently running task. */
357 #if ( configUSE_POSIX_ERRNO == 1 )
358     int FreeRTOS_errno = 0;
359 #endif
360
361 /* Other file private variables. --------------------------------*/
362 PRIVILEGED_DATA static volatile UBaseType_t uxCurrentNumberOfTasks = ( UBaseType_t ) 0U;
363 PRIVILEGED_DATA static volatile TickType_t xTickCount = ( TickType_t ) configINITIAL_TICK_COUNT;
364 PRIVILEGED_DATA static volatile UBaseType_t uxTopReadyPriority = tskIDLE_PRIORITY;
365 PRIVILEGED_DATA static volatile BaseType_t xSchedulerRunning = pdFALSE;
366 PRIVILEGED_DATA static volatile TickType_t xPendedTicks = ( TickType_t ) 0U;
367 PRIVILEGED_DATA static volatile BaseType_t xYieldPending = pdFALSE;
368 PRIVILEGED_DATA static volatile BaseType_t xNumOfOverflows = ( BaseType_t ) 0;
369 PRIVILEGED_DATA static UBaseType_t uxTaskNumber = ( UBaseType_t ) 0U;
370 PRIVILEGED_DATA static volatile TickType_t xNextTaskUnblockTime = ( TickType_t ) 0U; /* Initialised to portMAX_DELAY before the scheduler starts. */
371 PRIVILEGED_DATA static TaskHandle_t xIdleTaskHandle = NULL;                          /*< Holds the handle of the idle task.  The idle task is created automatically when the scheduler is started. */
372
373 /* Improve support for OpenOCD. The kernel tracks Ready tasks via priority lists.
374  * For tracking the state of remote threads, OpenOCD uses uxTopUsedPriority
375  * to determine the number of priority lists to read back from the remote target. */
376 const volatile UBaseType_t uxTopUsedPriority = configMAX_PRIORITIES - 1U;
377
378 /* Context switches are held pending while the scheduler is suspended.  Also,
379  * interrupts must not manipulate the xStateListItem of a TCB, or any of the
380  * lists the xStateListItem can be referenced from, if the scheduler is suspended.
381  * If an interrupt needs to unblock a task while the scheduler is suspended then it
382  * moves the task's event list item into the xPendingReadyList, ready for the
383  * kernel to move the task from the pending ready list into the real ready list
384  * when the scheduler is unsuspended.  The pending ready list itself can only be
385  * accessed from a critical section. */
386 PRIVILEGED_DATA static volatile UBaseType_t uxSchedulerSuspended = ( UBaseType_t ) pdFALSE;
387
388 #if ( configGENERATE_RUN_TIME_STATS == 1 )
389
390 /* Do not move these variables to function scope as doing so prevents the
391  * code working with debuggers that need to remove the static qualifier. */
392     PRIVILEGED_DATA static configRUN_TIME_COUNTER_TYPE ulTaskSwitchedInTime = 0UL;    /*< Holds the value of a timer/counter the last time a task was switched in. */
393     PRIVILEGED_DATA static volatile configRUN_TIME_COUNTER_TYPE ulTotalRunTime = 0UL; /*< Holds the total amount of execution time as defined by the run time counter clock. */
394
395 #endif
396
397 /*lint -restore */
398
399 /*-----------------------------------------------------------*/
400
401 /* File private functions. --------------------------------*/
402
403 /**
404  * Utility task that simply returns pdTRUE if the task referenced by xTask is
405  * currently in the Suspended state, or pdFALSE if the task referenced by xTask
406  * is in any other state.
407  */
408 #if ( INCLUDE_vTaskSuspend == 1 )
409
410     static BaseType_t prvTaskIsTaskSuspended( const TaskHandle_t xTask ) PRIVILEGED_FUNCTION;
411
412 #endif /* INCLUDE_vTaskSuspend */
413
414 /*
415  * Utility to ready all the lists used by the scheduler.  This is called
416  * automatically upon the creation of the first task.
417  */
418 static void prvInitialiseTaskLists( void ) PRIVILEGED_FUNCTION;
419
420 /*
421  * The idle task, which as all tasks is implemented as a never ending loop.
422  * The idle task is automatically created and added to the ready lists upon
423  * creation of the first user task.
424  *
425  * The portTASK_FUNCTION_PROTO() macro is used to allow port/compiler specific
426  * language extensions.  The equivalent prototype for this function is:
427  *
428  * void prvIdleTask( void *pvParameters );
429  *
430  */
431 static portTASK_FUNCTION_PROTO( prvIdleTask, pvParameters ) PRIVILEGED_FUNCTION;
432
433 /*
434  * Utility to free all memory allocated by the scheduler to hold a TCB,
435  * including the stack pointed to by the TCB.
436  *
437  * This does not free memory allocated by the task itself (i.e. memory
438  * allocated by calls to pvPortMalloc from within the tasks application code).
439  */
440 #if ( INCLUDE_vTaskDelete == 1 )
441
442     static void prvDeleteTCB( TCB_t * pxTCB ) PRIVILEGED_FUNCTION;
443
444 #endif
445
446 /*
447  * Used only by the idle task.  This checks to see if anything has been placed
448  * in the list of tasks waiting to be deleted.  If so the task is cleaned up
449  * and its TCB deleted.
450  */
451 static void prvCheckTasksWaitingTermination( void ) PRIVILEGED_FUNCTION;
452
453 /*
454  * The currently executing task is entering the Blocked state.  Add the task to
455  * either the current or the overflow delayed task list.
456  */
457 static void prvAddCurrentTaskToDelayedList( TickType_t xTicksToWait,
458                                             const BaseType_t xCanBlockIndefinitely ) PRIVILEGED_FUNCTION;
459
460 /*
461  * Fills an TaskStatus_t structure with information on each task that is
462  * referenced from the pxList list (which may be a ready list, a delayed list,
463  * a suspended list, etc.).
464  *
465  * THIS FUNCTION IS INTENDED FOR DEBUGGING ONLY, AND SHOULD NOT BE CALLED FROM
466  * NORMAL APPLICATION CODE.
467  */
468 #if ( configUSE_TRACE_FACILITY == 1 )
469
470     static UBaseType_t prvListTasksWithinSingleList( TaskStatus_t * pxTaskStatusArray,
471                                                      List_t * pxList,
472                                                      eTaskState eState ) PRIVILEGED_FUNCTION;
473
474 #endif
475
476 /*
477  * Searches pxList for a task with name pcNameToQuery - returning a handle to
478  * the task if it is found, or NULL if the task is not found.
479  */
480 #if ( INCLUDE_xTaskGetHandle == 1 )
481
482     static TCB_t * prvSearchForNameWithinSingleList( List_t * pxList,
483                                                      const char pcNameToQuery[] ) PRIVILEGED_FUNCTION;
484
485 #endif
486
487 /*
488  * When a task is created, the stack of the task is filled with a known value.
489  * This function determines the 'high water mark' of the task stack by
490  * determining how much of the stack remains at the original preset value.
491  */
492 #if ( ( configUSE_TRACE_FACILITY == 1 ) || ( INCLUDE_uxTaskGetStackHighWaterMark == 1 ) || ( INCLUDE_uxTaskGetStackHighWaterMark2 == 1 ) )
493
494     static configSTACK_DEPTH_TYPE prvTaskCheckFreeStackSpace( const uint8_t * pucStackByte ) PRIVILEGED_FUNCTION;
495
496 #endif
497
498 /*
499  * Return the amount of time, in ticks, that will pass before the kernel will
500  * next move a task from the Blocked state to the Running state.
501  *
502  * This conditional compilation should use inequality to 0, not equality to 1.
503  * This is to ensure portSUPPRESS_TICKS_AND_SLEEP() can be called when user
504  * defined low power mode implementations require configUSE_TICKLESS_IDLE to be
505  * set to a value other than 1.
506  */
507 #if ( configUSE_TICKLESS_IDLE != 0 )
508
509     static TickType_t prvGetExpectedIdleTime( void ) PRIVILEGED_FUNCTION;
510
511 #endif
512
513 /*
514  * Set xNextTaskUnblockTime to the time at which the next Blocked state task
515  * will exit the Blocked state.
516  */
517 static void prvResetNextTaskUnblockTime( void ) PRIVILEGED_FUNCTION;
518
519 #if ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 )
520
521 /*
522  * Helper function used to pad task names with spaces when printing out
523  * human readable tables of task information.
524  */
525     static char * prvWriteNameToBuffer( char * pcBuffer,
526                                         const char * pcTaskName ) PRIVILEGED_FUNCTION;
527
528 #endif
529
530 /*
531  * Called after a Task_t structure has been allocated either statically or
532  * dynamically to fill in the structure's members.
533  */
534 static void prvInitialiseNewTask( TaskFunction_t pxTaskCode,
535                                   const char * const pcName, /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
536                                   const uint32_t ulStackDepth,
537                                   void * const pvParameters,
538                                   UBaseType_t uxPriority,
539                                   TaskHandle_t * const pxCreatedTask,
540                                   TCB_t * pxNewTCB,
541                                   const MemoryRegion_t * const xRegions ) PRIVILEGED_FUNCTION;
542
543 /*
544  * Called after a new task has been created and initialised to place the task
545  * under the control of the scheduler.
546  */
547 static void prvAddNewTaskToReadyList( TCB_t * pxNewTCB ) PRIVILEGED_FUNCTION;
548
549 /*
550  * freertos_tasks_c_additions_init() should only be called if the user definable
551  * macro FREERTOS_TASKS_C_ADDITIONS_INIT() is defined, as that is the only macro
552  * called by the function.
553  */
554 #ifdef FREERTOS_TASKS_C_ADDITIONS_INIT
555
556     static void freertos_tasks_c_additions_init( void ) PRIVILEGED_FUNCTION;
557
558 #endif
559
560 /*-----------------------------------------------------------*/
561
562 #if ( configSUPPORT_STATIC_ALLOCATION == 1 )
563
564     TaskHandle_t xTaskCreateStatic( TaskFunction_t pxTaskCode,
565                                     const char * const pcName, /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
566                                     const uint32_t ulStackDepth,
567                                     void * const pvParameters,
568                                     UBaseType_t uxPriority,
569                                     StackType_t * const puxStackBuffer,
570                                     StaticTask_t * const pxTaskBuffer )
571     {
572         TCB_t * pxNewTCB;
573         TaskHandle_t xReturn;
574
575         configASSERT( puxStackBuffer != NULL );
576         configASSERT( pxTaskBuffer != NULL );
577
578         #if ( configASSERT_DEFINED == 1 )
579         {
580             /* Sanity check that the size of the structure used to declare a
581              * variable of type StaticTask_t equals the size of the real task
582              * structure. */
583             volatile size_t xSize = sizeof( StaticTask_t );
584             configASSERT( xSize == sizeof( TCB_t ) );
585             ( void ) xSize; /* Prevent lint warning when configASSERT() is not used. */
586         }
587         #endif /* configASSERT_DEFINED */
588
589         if( ( pxTaskBuffer != NULL ) && ( puxStackBuffer != NULL ) )
590         {
591             /* The memory used for the task's TCB and stack are passed into this
592              * function - use them. */
593             pxNewTCB = ( TCB_t * ) pxTaskBuffer; /*lint !e740 !e9087 Unusual cast is ok as the structures are designed to have the same alignment, and the size is checked by an assert. */
594             memset( ( void * ) pxNewTCB, 0x00, sizeof( TCB_t ) );
595             pxNewTCB->pxStack = ( StackType_t * ) puxStackBuffer;
596
597             #if ( tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE != 0 ) /*lint !e731 !e9029 Macro has been consolidated for readability reasons. */
598             {
599                 /* Tasks can be created statically or dynamically, so note this
600                  * task was created statically in case the task is later deleted. */
601                 pxNewTCB->ucStaticallyAllocated = tskSTATICALLY_ALLOCATED_STACK_AND_TCB;
602             }
603             #endif /* tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE */
604
605             prvInitialiseNewTask( pxTaskCode, pcName, ulStackDepth, pvParameters, uxPriority, &xReturn, pxNewTCB, NULL );
606             prvAddNewTaskToReadyList( pxNewTCB );
607         }
608         else
609         {
610             xReturn = NULL;
611         }
612
613         return xReturn;
614     }
615
616 #endif /* SUPPORT_STATIC_ALLOCATION */
617 /*-----------------------------------------------------------*/
618
619 #if ( ( portUSING_MPU_WRAPPERS == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 1 ) )
620
621     BaseType_t xTaskCreateRestrictedStatic( const TaskParameters_t * const pxTaskDefinition,
622                                             TaskHandle_t * pxCreatedTask )
623     {
624         TCB_t * pxNewTCB;
625         BaseType_t xReturn = errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY;
626
627         configASSERT( pxTaskDefinition->puxStackBuffer != NULL );
628         configASSERT( pxTaskDefinition->pxTaskBuffer != NULL );
629
630         if( ( pxTaskDefinition->puxStackBuffer != NULL ) && ( pxTaskDefinition->pxTaskBuffer != NULL ) )
631         {
632             /* Allocate space for the TCB.  Where the memory comes from depends
633              * on the implementation of the port malloc function and whether or
634              * not static allocation is being used. */
635             pxNewTCB = ( TCB_t * ) pxTaskDefinition->pxTaskBuffer;
636             memset( ( void * ) pxNewTCB, 0x00, sizeof( TCB_t ) );
637
638             /* Store the stack location in the TCB. */
639             pxNewTCB->pxStack = pxTaskDefinition->puxStackBuffer;
640
641             #if ( tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE != 0 )
642             {
643                 /* Tasks can be created statically or dynamically, so note this
644                  * task was created statically in case the task is later deleted. */
645                 pxNewTCB->ucStaticallyAllocated = tskSTATICALLY_ALLOCATED_STACK_AND_TCB;
646             }
647             #endif /* tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE */
648
649             prvInitialiseNewTask( pxTaskDefinition->pvTaskCode,
650                                   pxTaskDefinition->pcName,
651                                   ( uint32_t ) pxTaskDefinition->usStackDepth,
652                                   pxTaskDefinition->pvParameters,
653                                   pxTaskDefinition->uxPriority,
654                                   pxCreatedTask, pxNewTCB,
655                                   pxTaskDefinition->xRegions );
656
657             prvAddNewTaskToReadyList( pxNewTCB );
658             xReturn = pdPASS;
659         }
660
661         return xReturn;
662     }
663
664 #endif /* ( portUSING_MPU_WRAPPERS == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 1 ) */
665 /*-----------------------------------------------------------*/
666
667 #if ( ( portUSING_MPU_WRAPPERS == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) )
668
669     BaseType_t xTaskCreateRestricted( const TaskParameters_t * const pxTaskDefinition,
670                                       TaskHandle_t * pxCreatedTask )
671     {
672         TCB_t * pxNewTCB;
673         BaseType_t xReturn = errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY;
674
675         configASSERT( pxTaskDefinition->puxStackBuffer );
676
677         if( pxTaskDefinition->puxStackBuffer != NULL )
678         {
679             /* Allocate space for the TCB.  Where the memory comes from depends
680              * on the implementation of the port malloc function and whether or
681              * not static allocation is being used. */
682             pxNewTCB = ( TCB_t * ) pvPortMalloc( sizeof( TCB_t ) );
683
684             if( pxNewTCB != NULL )
685             {
686                 memset( ( void * ) pxNewTCB, 0x00, sizeof( TCB_t ) );
687
688                 /* Store the stack location in the TCB. */
689                 pxNewTCB->pxStack = pxTaskDefinition->puxStackBuffer;
690
691                 #if ( tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE != 0 )
692                 {
693                     /* Tasks can be created statically or dynamically, so note
694                      * this task had a statically allocated stack in case it is
695                      * later deleted.  The TCB was allocated dynamically. */
696                     pxNewTCB->ucStaticallyAllocated = tskSTATICALLY_ALLOCATED_STACK_ONLY;
697                 }
698                 #endif /* tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE */
699
700                 prvInitialiseNewTask( pxTaskDefinition->pvTaskCode,
701                                       pxTaskDefinition->pcName,
702                                       ( uint32_t ) pxTaskDefinition->usStackDepth,
703                                       pxTaskDefinition->pvParameters,
704                                       pxTaskDefinition->uxPriority,
705                                       pxCreatedTask, pxNewTCB,
706                                       pxTaskDefinition->xRegions );
707
708                 prvAddNewTaskToReadyList( pxNewTCB );
709                 xReturn = pdPASS;
710             }
711         }
712
713         return xReturn;
714     }
715
716 #endif /* portUSING_MPU_WRAPPERS */
717 /*-----------------------------------------------------------*/
718
719 #if ( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
720
721     BaseType_t xTaskCreate( TaskFunction_t pxTaskCode,
722                             const char * const pcName, /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
723                             const configSTACK_DEPTH_TYPE usStackDepth,
724                             void * const pvParameters,
725                             UBaseType_t uxPriority,
726                             TaskHandle_t * const pxCreatedTask )
727     {
728         TCB_t * pxNewTCB;
729         BaseType_t xReturn;
730
731         /* If the stack grows down then allocate the stack then the TCB so the stack
732          * does not grow into the TCB.  Likewise if the stack grows up then allocate
733          * the TCB then the stack. */
734         #if ( portSTACK_GROWTH > 0 )
735         {
736             /* Allocate space for the TCB.  Where the memory comes from depends on
737              * the implementation of the port malloc function and whether or not static
738              * allocation is being used. */
739             pxNewTCB = ( TCB_t * ) pvPortMalloc( sizeof( TCB_t ) );
740
741             if( pxNewTCB != NULL )
742             {
743                 memset( ( void * ) pxNewTCB, 0x00, sizeof( TCB_t ) );
744
745                 /* Allocate space for the stack used by the task being created.
746                  * The base of the stack memory stored in the TCB so the task can
747                  * be deleted later if required. */
748                 pxNewTCB->pxStack = ( StackType_t * ) pvPortMallocStack( ( ( ( size_t ) usStackDepth ) * sizeof( StackType_t ) ) ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */
749
750                 if( pxNewTCB->pxStack == NULL )
751                 {
752                     /* Could not allocate the stack.  Delete the allocated TCB. */
753                     vPortFree( pxNewTCB );
754                     pxNewTCB = NULL;
755                 }
756             }
757         }
758         #else /* portSTACK_GROWTH */
759         {
760             StackType_t * pxStack;
761
762             /* Allocate space for the stack used by the task being created. */
763             pxStack = pvPortMallocStack( ( ( ( size_t ) usStackDepth ) * sizeof( StackType_t ) ) ); /*lint !e9079 All values returned by pvPortMalloc() have at least the alignment required by the MCU's stack and this allocation is the stack. */
764
765             if( pxStack != NULL )
766             {
767                 /* Allocate space for the TCB. */
768                 pxNewTCB = ( TCB_t * ) pvPortMalloc( sizeof( TCB_t ) ); /*lint !e9087 !e9079 All values returned by pvPortMalloc() have at least the alignment required by the MCU's stack, and the first member of TCB_t is always a pointer to the task's stack. */
769
770                 if( pxNewTCB != NULL )
771                 {
772                     memset( ( void * ) pxNewTCB, 0x00, sizeof( TCB_t ) );
773
774                     /* Store the stack location in the TCB. */
775                     pxNewTCB->pxStack = pxStack;
776                 }
777                 else
778                 {
779                     /* The stack cannot be used as the TCB was not created.  Free
780                      * it again. */
781                     vPortFreeStack( pxStack );
782                 }
783             }
784             else
785             {
786                 pxNewTCB = NULL;
787             }
788         }
789         #endif /* portSTACK_GROWTH */
790
791         if( pxNewTCB != NULL )
792         {
793             #if ( tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE != 0 ) /*lint !e9029 !e731 Macro has been consolidated for readability reasons. */
794             {
795                 /* Tasks can be created statically or dynamically, so note this
796                  * task was created dynamically in case it is later deleted. */
797                 pxNewTCB->ucStaticallyAllocated = tskDYNAMICALLY_ALLOCATED_STACK_AND_TCB;
798             }
799             #endif /* tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE */
800
801             prvInitialiseNewTask( pxTaskCode, pcName, ( uint32_t ) usStackDepth, pvParameters, uxPriority, pxCreatedTask, pxNewTCB, NULL );
802             prvAddNewTaskToReadyList( pxNewTCB );
803             xReturn = pdPASS;
804         }
805         else
806         {
807             xReturn = errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY;
808         }
809
810         return xReturn;
811     }
812
813 #endif /* configSUPPORT_DYNAMIC_ALLOCATION */
814 /*-----------------------------------------------------------*/
815
816 static void prvInitialiseNewTask( TaskFunction_t pxTaskCode,
817                                   const char * const pcName, /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
818                                   const uint32_t ulStackDepth,
819                                   void * const pvParameters,
820                                   UBaseType_t uxPriority,
821                                   TaskHandle_t * const pxCreatedTask,
822                                   TCB_t * pxNewTCB,
823                                   const MemoryRegion_t * const xRegions )
824 {
825     StackType_t * pxTopOfStack;
826     UBaseType_t x;
827
828     #if ( portUSING_MPU_WRAPPERS == 1 )
829         /* Should the task be created in privileged mode? */
830         BaseType_t xRunPrivileged;
831
832         if( ( uxPriority & portPRIVILEGE_BIT ) != 0U )
833         {
834             xRunPrivileged = pdTRUE;
835         }
836         else
837         {
838             xRunPrivileged = pdFALSE;
839         }
840         uxPriority &= ~portPRIVILEGE_BIT;
841     #endif /* portUSING_MPU_WRAPPERS == 1 */
842
843     /* Avoid dependency on memset() if it is not required. */
844     #if ( tskSET_NEW_STACKS_TO_KNOWN_VALUE == 1 )
845     {
846         /* Fill the stack with a known value to assist debugging. */
847         ( void ) memset( pxNewTCB->pxStack, ( int ) tskSTACK_FILL_BYTE, ( size_t ) ulStackDepth * sizeof( StackType_t ) );
848     }
849     #endif /* tskSET_NEW_STACKS_TO_KNOWN_VALUE */
850
851     /* Calculate the top of stack address.  This depends on whether the stack
852      * grows from high memory to low (as per the 80x86) or vice versa.
853      * portSTACK_GROWTH is used to make the result positive or negative as required
854      * by the port. */
855     #if ( portSTACK_GROWTH < 0 )
856     {
857         pxTopOfStack = &( pxNewTCB->pxStack[ ulStackDepth - ( uint32_t ) 1 ] );
858         pxTopOfStack = ( StackType_t * ) ( ( ( portPOINTER_SIZE_TYPE ) pxTopOfStack ) & ( ~( ( portPOINTER_SIZE_TYPE ) portBYTE_ALIGNMENT_MASK ) ) ); /*lint !e923 !e9033 !e9078 MISRA exception.  Avoiding casts between pointers and integers is not practical.  Size differences accounted for using portPOINTER_SIZE_TYPE type.  Checked by assert(). */
859
860         /* Check the alignment of the calculated top of stack is correct. */
861         configASSERT( ( ( ( portPOINTER_SIZE_TYPE ) pxTopOfStack & ( portPOINTER_SIZE_TYPE ) portBYTE_ALIGNMENT_MASK ) == 0UL ) );
862
863         #if ( configRECORD_STACK_HIGH_ADDRESS == 1 )
864         {
865             /* Also record the stack's high address, which may assist
866              * debugging. */
867             pxNewTCB->pxEndOfStack = pxTopOfStack;
868         }
869         #endif /* configRECORD_STACK_HIGH_ADDRESS */
870     }
871     #else /* portSTACK_GROWTH */
872     {
873         pxTopOfStack = pxNewTCB->pxStack;
874
875         /* Check the alignment of the stack buffer is correct. */
876         configASSERT( ( ( ( portPOINTER_SIZE_TYPE ) pxNewTCB->pxStack & ( portPOINTER_SIZE_TYPE ) portBYTE_ALIGNMENT_MASK ) == 0UL ) );
877
878         /* The other extreme of the stack space is required if stack checking is
879          * performed. */
880         pxNewTCB->pxEndOfStack = pxNewTCB->pxStack + ( ulStackDepth - ( uint32_t ) 1 );
881     }
882     #endif /* portSTACK_GROWTH */
883
884     /* Store the task name in the TCB. */
885     if( pcName != NULL )
886     {
887         for( x = ( UBaseType_t ) 0; x < ( UBaseType_t ) configMAX_TASK_NAME_LEN; x++ )
888         {
889             pxNewTCB->pcTaskName[ x ] = pcName[ x ];
890
891             /* Don't copy all configMAX_TASK_NAME_LEN if the string is shorter than
892              * configMAX_TASK_NAME_LEN characters just in case the memory after the
893              * string is not accessible (extremely unlikely). */
894             if( pcName[ x ] == ( char ) 0x00 )
895             {
896                 break;
897             }
898             else
899             {
900                 mtCOVERAGE_TEST_MARKER();
901             }
902         }
903
904         /* Ensure the name string is terminated in the case that the string length
905          * was greater or equal to configMAX_TASK_NAME_LEN. */
906         pxNewTCB->pcTaskName[ configMAX_TASK_NAME_LEN - 1 ] = '\0';
907     }
908     else
909     {
910         mtCOVERAGE_TEST_MARKER();
911     }
912
913     /* This is used as an array index so must ensure it's not too large. */
914     configASSERT( uxPriority < configMAX_PRIORITIES );
915
916     if( uxPriority >= ( UBaseType_t ) configMAX_PRIORITIES )
917     {
918         uxPriority = ( UBaseType_t ) configMAX_PRIORITIES - ( UBaseType_t ) 1U;
919     }
920     else
921     {
922         mtCOVERAGE_TEST_MARKER();
923     }
924
925     pxNewTCB->uxPriority = uxPriority;
926     #if ( configUSE_MUTEXES == 1 )
927     {
928         pxNewTCB->uxBasePriority = uxPriority;
929     }
930     #endif /* configUSE_MUTEXES */
931
932     vListInitialiseItem( &( pxNewTCB->xStateListItem ) );
933     vListInitialiseItem( &( pxNewTCB->xEventListItem ) );
934
935     /* Set the pxNewTCB as a link back from the ListItem_t.  This is so we can get
936      * back to  the containing TCB from a generic item in a list. */
937     listSET_LIST_ITEM_OWNER( &( pxNewTCB->xStateListItem ), pxNewTCB );
938
939     /* Event lists are always in priority order. */
940     listSET_LIST_ITEM_VALUE( &( pxNewTCB->xEventListItem ), ( TickType_t ) configMAX_PRIORITIES - ( TickType_t ) uxPriority ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */
941     listSET_LIST_ITEM_OWNER( &( pxNewTCB->xEventListItem ), pxNewTCB );
942
943     #if ( portUSING_MPU_WRAPPERS == 1 )
944     {
945         vPortStoreTaskMPUSettings( &( pxNewTCB->xMPUSettings ), xRegions, pxNewTCB->pxStack, ulStackDepth );
946     }
947     #else
948     {
949         /* Avoid compiler warning about unreferenced parameter. */
950         ( void ) xRegions;
951     }
952     #endif
953
954     #if ( ( configUSE_NEWLIB_REENTRANT == 1 ) || ( configUSE_C_RUNTIME_TLS_SUPPORT == 1 ) )
955     {
956         /* Allocate and initialize memory for the task's TLS Block. */
957         configINIT_TLS_BLOCK( pxNewTCB->xTLSBlock );
958     }
959     #endif
960
961     /* Initialize the TCB stack to look as if the task was already running,
962      * but had been interrupted by the scheduler.  The return address is set
963      * to the start of the task function. Once the stack has been initialised
964      * the top of stack variable is updated. */
965     #if ( portUSING_MPU_WRAPPERS == 1 )
966     {
967         /* If the port has capability to detect stack overflow,
968          * pass the stack end address to the stack initialization
969          * function as well. */
970         #if ( portHAS_STACK_OVERFLOW_CHECKING == 1 )
971         {
972             #if ( portSTACK_GROWTH < 0 )
973             {
974                 pxNewTCB->pxTopOfStack = pxPortInitialiseStack( pxTopOfStack, pxNewTCB->pxStack, pxTaskCode, pvParameters, xRunPrivileged );
975             }
976             #else /* portSTACK_GROWTH */
977             {
978                 pxNewTCB->pxTopOfStack = pxPortInitialiseStack( pxTopOfStack, pxNewTCB->pxEndOfStack, pxTaskCode, pvParameters, xRunPrivileged );
979             }
980             #endif /* portSTACK_GROWTH */
981         }
982         #else /* portHAS_STACK_OVERFLOW_CHECKING */
983         {
984             pxNewTCB->pxTopOfStack = pxPortInitialiseStack( pxTopOfStack, pxTaskCode, pvParameters, xRunPrivileged );
985         }
986         #endif /* portHAS_STACK_OVERFLOW_CHECKING */
987     }
988     #else /* portUSING_MPU_WRAPPERS */
989     {
990         /* If the port has capability to detect stack overflow,
991          * pass the stack end address to the stack initialization
992          * function as well. */
993         #if ( portHAS_STACK_OVERFLOW_CHECKING == 1 )
994         {
995             #if ( portSTACK_GROWTH < 0 )
996             {
997                 pxNewTCB->pxTopOfStack = pxPortInitialiseStack( pxTopOfStack, pxNewTCB->pxStack, pxTaskCode, pvParameters );
998             }
999             #else /* portSTACK_GROWTH */
1000             {
1001                 pxNewTCB->pxTopOfStack = pxPortInitialiseStack( pxTopOfStack, pxNewTCB->pxEndOfStack, pxTaskCode, pvParameters );
1002             }
1003             #endif /* portSTACK_GROWTH */
1004         }
1005         #else /* portHAS_STACK_OVERFLOW_CHECKING */
1006         {
1007             pxNewTCB->pxTopOfStack = pxPortInitialiseStack( pxTopOfStack, pxTaskCode, pvParameters );
1008         }
1009         #endif /* portHAS_STACK_OVERFLOW_CHECKING */
1010     }
1011     #endif /* portUSING_MPU_WRAPPERS */
1012
1013     if( pxCreatedTask != NULL )
1014     {
1015         /* Pass the handle out in an anonymous way.  The handle can be used to
1016          * change the created task's priority, delete the created task, etc.*/
1017         *pxCreatedTask = ( TaskHandle_t ) pxNewTCB;
1018     }
1019     else
1020     {
1021         mtCOVERAGE_TEST_MARKER();
1022     }
1023 }
1024 /*-----------------------------------------------------------*/
1025
1026 static void prvAddNewTaskToReadyList( TCB_t * pxNewTCB )
1027 {
1028     /* Ensure interrupts don't access the task lists while the lists are being
1029      * updated. */
1030     taskENTER_CRITICAL();
1031     {
1032         uxCurrentNumberOfTasks++;
1033
1034         if( pxCurrentTCB == NULL )
1035         {
1036             /* There are no other tasks, or all the other tasks are in
1037              * the suspended state - make this the current task. */
1038             pxCurrentTCB = pxNewTCB;
1039
1040             if( uxCurrentNumberOfTasks == ( UBaseType_t ) 1 )
1041             {
1042                 /* This is the first task to be created so do the preliminary
1043                  * initialisation required.  We will not recover if this call
1044                  * fails, but we will report the failure. */
1045                 prvInitialiseTaskLists();
1046             }
1047             else
1048             {
1049                 mtCOVERAGE_TEST_MARKER();
1050             }
1051         }
1052         else
1053         {
1054             /* If the scheduler is not already running, make this task the
1055              * current task if it is the highest priority task to be created
1056              * so far. */
1057             if( xSchedulerRunning == pdFALSE )
1058             {
1059                 if( pxCurrentTCB->uxPriority <= pxNewTCB->uxPriority )
1060                 {
1061                     pxCurrentTCB = pxNewTCB;
1062                 }
1063                 else
1064                 {
1065                     mtCOVERAGE_TEST_MARKER();
1066                 }
1067             }
1068             else
1069             {
1070                 mtCOVERAGE_TEST_MARKER();
1071             }
1072         }
1073
1074         uxTaskNumber++;
1075
1076         #if ( configUSE_TRACE_FACILITY == 1 )
1077         {
1078             /* Add a counter into the TCB for tracing only. */
1079             pxNewTCB->uxTCBNumber = uxTaskNumber;
1080         }
1081         #endif /* configUSE_TRACE_FACILITY */
1082         traceTASK_CREATE( pxNewTCB );
1083
1084         prvAddTaskToReadyList( pxNewTCB );
1085
1086         portSETUP_TCB( pxNewTCB );
1087     }
1088     taskEXIT_CRITICAL();
1089
1090     if( xSchedulerRunning != pdFALSE )
1091     {
1092         /* If the created task is of a higher priority than the current task
1093          * then it should run now. */
1094         if( pxCurrentTCB->uxPriority < pxNewTCB->uxPriority )
1095         {
1096             taskYIELD_IF_USING_PREEMPTION();
1097         }
1098         else
1099         {
1100             mtCOVERAGE_TEST_MARKER();
1101         }
1102     }
1103     else
1104     {
1105         mtCOVERAGE_TEST_MARKER();
1106     }
1107 }
1108 /*-----------------------------------------------------------*/
1109
1110 #if ( INCLUDE_vTaskDelete == 1 )
1111
1112     void vTaskDelete( TaskHandle_t xTaskToDelete )
1113     {
1114         TCB_t * pxTCB;
1115
1116         taskENTER_CRITICAL();
1117         {
1118             /* If null is passed in here then it is the calling task that is
1119              * being deleted. */
1120             pxTCB = prvGetTCBFromHandle( xTaskToDelete );
1121
1122             /* Remove task from the ready/delayed list. */
1123             if( uxListRemove( &( pxTCB->xStateListItem ) ) == ( UBaseType_t ) 0 )
1124             {
1125                 taskRESET_READY_PRIORITY( pxTCB->uxPriority );
1126             }
1127             else
1128             {
1129                 mtCOVERAGE_TEST_MARKER();
1130             }
1131
1132             /* Is the task waiting on an event also? */
1133             if( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) != NULL )
1134             {
1135                 ( void ) uxListRemove( &( pxTCB->xEventListItem ) );
1136             }
1137             else
1138             {
1139                 mtCOVERAGE_TEST_MARKER();
1140             }
1141
1142             /* Increment the uxTaskNumber also so kernel aware debuggers can
1143              * detect that the task lists need re-generating.  This is done before
1144              * portPRE_TASK_DELETE_HOOK() as in the Windows port that macro will
1145              * not return. */
1146             uxTaskNumber++;
1147
1148             if( pxTCB == pxCurrentTCB )
1149             {
1150                 /* A task is deleting itself.  This cannot complete within the
1151                  * task itself, as a context switch to another task is required.
1152                  * Place the task in the termination list.  The idle task will
1153                  * check the termination list and free up any memory allocated by
1154                  * the scheduler for the TCB and stack of the deleted task. */
1155                 vListInsertEnd( &xTasksWaitingTermination, &( pxTCB->xStateListItem ) );
1156
1157                 /* Increment the ucTasksDeleted variable so the idle task knows
1158                  * there is a task that has been deleted and that it should therefore
1159                  * check the xTasksWaitingTermination list. */
1160                 ++uxDeletedTasksWaitingCleanUp;
1161
1162                 /* Call the delete hook before portPRE_TASK_DELETE_HOOK() as
1163                  * portPRE_TASK_DELETE_HOOK() does not return in the Win32 port. */
1164                 traceTASK_DELETE( pxTCB );
1165
1166                 /* The pre-delete hook is primarily for the Windows simulator,
1167                  * in which Windows specific clean up operations are performed,
1168                  * after which it is not possible to yield away from this task -
1169                  * hence xYieldPending is used to latch that a context switch is
1170                  * required. */
1171                 portPRE_TASK_DELETE_HOOK( pxTCB, &xYieldPending );
1172             }
1173             else
1174             {
1175                 --uxCurrentNumberOfTasks;
1176                 traceTASK_DELETE( pxTCB );
1177
1178                 /* Reset the next expected unblock time in case it referred to
1179                  * the task that has just been deleted. */
1180                 prvResetNextTaskUnblockTime();
1181             }
1182         }
1183         taskEXIT_CRITICAL();
1184
1185         /* If the task is not deleting itself, call prvDeleteTCB from outside of
1186          * critical section. If a task deletes itself, prvDeleteTCB is called
1187          * from prvCheckTasksWaitingTermination which is called from Idle task. */
1188         if( pxTCB != pxCurrentTCB )
1189         {
1190             prvDeleteTCB( pxTCB );
1191         }
1192
1193         /* Force a reschedule if it is the currently running task that has just
1194          * been deleted. */
1195         if( xSchedulerRunning != pdFALSE )
1196         {
1197             if( pxTCB == pxCurrentTCB )
1198             {
1199                 configASSERT( uxSchedulerSuspended == 0 );
1200                 portYIELD_WITHIN_API();
1201             }
1202             else
1203             {
1204                 mtCOVERAGE_TEST_MARKER();
1205             }
1206         }
1207     }
1208
1209 #endif /* INCLUDE_vTaskDelete */
1210 /*-----------------------------------------------------------*/
1211
1212 #if ( INCLUDE_xTaskDelayUntil == 1 )
1213
1214     BaseType_t xTaskDelayUntil( TickType_t * const pxPreviousWakeTime,
1215                                 const TickType_t xTimeIncrement )
1216     {
1217         TickType_t xTimeToWake;
1218         BaseType_t xAlreadyYielded, xShouldDelay = pdFALSE;
1219
1220         configASSERT( pxPreviousWakeTime );
1221         configASSERT( ( xTimeIncrement > 0U ) );
1222         configASSERT( uxSchedulerSuspended == 0 );
1223
1224         vTaskSuspendAll();
1225         {
1226             /* Minor optimisation.  The tick count cannot change in this
1227              * block. */
1228             const TickType_t xConstTickCount = xTickCount;
1229
1230             /* Generate the tick time at which the task wants to wake. */
1231             xTimeToWake = *pxPreviousWakeTime + xTimeIncrement;
1232
1233             if( xConstTickCount < *pxPreviousWakeTime )
1234             {
1235                 /* The tick count has overflowed since this function was
1236                  * lasted called.  In this case the only time we should ever
1237                  * actually delay is if the wake time has also  overflowed,
1238                  * and the wake time is greater than the tick time.  When this
1239                  * is the case it is as if neither time had overflowed. */
1240                 if( ( xTimeToWake < *pxPreviousWakeTime ) && ( xTimeToWake > xConstTickCount ) )
1241                 {
1242                     xShouldDelay = pdTRUE;
1243                 }
1244                 else
1245                 {
1246                     mtCOVERAGE_TEST_MARKER();
1247                 }
1248             }
1249             else
1250             {
1251                 /* The tick time has not overflowed.  In this case we will
1252                  * delay if either the wake time has overflowed, and/or the
1253                  * tick time is less than the wake time. */
1254                 if( ( xTimeToWake < *pxPreviousWakeTime ) || ( xTimeToWake > xConstTickCount ) )
1255                 {
1256                     xShouldDelay = pdTRUE;
1257                 }
1258                 else
1259                 {
1260                     mtCOVERAGE_TEST_MARKER();
1261                 }
1262             }
1263
1264             /* Update the wake time ready for the next call. */
1265             *pxPreviousWakeTime = xTimeToWake;
1266
1267             if( xShouldDelay != pdFALSE )
1268             {
1269                 traceTASK_DELAY_UNTIL( xTimeToWake );
1270
1271                 /* prvAddCurrentTaskToDelayedList() needs the block time, not
1272                  * the time to wake, so subtract the current tick count. */
1273                 prvAddCurrentTaskToDelayedList( xTimeToWake - xConstTickCount, pdFALSE );
1274             }
1275             else
1276             {
1277                 mtCOVERAGE_TEST_MARKER();
1278             }
1279         }
1280         xAlreadyYielded = xTaskResumeAll();
1281
1282         /* Force a reschedule if xTaskResumeAll has not already done so, we may
1283          * have put ourselves to sleep. */
1284         if( xAlreadyYielded == pdFALSE )
1285         {
1286             portYIELD_WITHIN_API();
1287         }
1288         else
1289         {
1290             mtCOVERAGE_TEST_MARKER();
1291         }
1292
1293         return xShouldDelay;
1294     }
1295
1296 #endif /* INCLUDE_xTaskDelayUntil */
1297 /*-----------------------------------------------------------*/
1298
1299 #if ( INCLUDE_vTaskDelay == 1 )
1300
1301     void vTaskDelay( const TickType_t xTicksToDelay )
1302     {
1303         BaseType_t xAlreadyYielded = pdFALSE;
1304
1305         /* A delay time of zero just forces a reschedule. */
1306         if( xTicksToDelay > ( TickType_t ) 0U )
1307         {
1308             configASSERT( uxSchedulerSuspended == 0 );
1309             vTaskSuspendAll();
1310             {
1311                 traceTASK_DELAY();
1312
1313                 /* A task that is removed from the event list while the
1314                  * scheduler is suspended will not get placed in the ready
1315                  * list or removed from the blocked list until the scheduler
1316                  * is resumed.
1317                  *
1318                  * This task cannot be in an event list as it is the currently
1319                  * executing task. */
1320                 prvAddCurrentTaskToDelayedList( xTicksToDelay, pdFALSE );
1321             }
1322             xAlreadyYielded = xTaskResumeAll();
1323         }
1324         else
1325         {
1326             mtCOVERAGE_TEST_MARKER();
1327         }
1328
1329         /* Force a reschedule if xTaskResumeAll has not already done so, we may
1330          * have put ourselves to sleep. */
1331         if( xAlreadyYielded == pdFALSE )
1332         {
1333             portYIELD_WITHIN_API();
1334         }
1335         else
1336         {
1337             mtCOVERAGE_TEST_MARKER();
1338         }
1339     }
1340
1341 #endif /* INCLUDE_vTaskDelay */
1342 /*-----------------------------------------------------------*/
1343
1344 #if ( ( INCLUDE_eTaskGetState == 1 ) || ( configUSE_TRACE_FACILITY == 1 ) || ( INCLUDE_xTaskAbortDelay == 1 ) )
1345
1346     eTaskState eTaskGetState( TaskHandle_t xTask )
1347     {
1348         eTaskState eReturn;
1349         List_t const * pxStateList;
1350         List_t const * pxDelayedList;
1351         List_t const * pxOverflowedDelayedList;
1352         const TCB_t * const pxTCB = xTask;
1353
1354         configASSERT( pxTCB );
1355
1356         if( pxTCB == pxCurrentTCB )
1357         {
1358             /* The task calling this function is querying its own state. */
1359             eReturn = eRunning;
1360         }
1361         else
1362         {
1363             taskENTER_CRITICAL();
1364             {
1365                 pxStateList = listLIST_ITEM_CONTAINER( &( pxTCB->xStateListItem ) );
1366                 pxDelayedList = pxDelayedTaskList;
1367                 pxOverflowedDelayedList = pxOverflowDelayedTaskList;
1368             }
1369             taskEXIT_CRITICAL();
1370
1371             if( ( pxStateList == pxDelayedList ) || ( pxStateList == pxOverflowedDelayedList ) )
1372             {
1373                 /* The task being queried is referenced from one of the Blocked
1374                  * lists. */
1375                 eReturn = eBlocked;
1376             }
1377
1378             #if ( INCLUDE_vTaskSuspend == 1 )
1379                 else if( pxStateList == &xSuspendedTaskList )
1380                 {
1381                     /* The task being queried is referenced from the suspended
1382                      * list.  Is it genuinely suspended or is it blocked
1383                      * indefinitely? */
1384                     if( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) == NULL )
1385                     {
1386                         #if ( configUSE_TASK_NOTIFICATIONS == 1 )
1387                         {
1388                             BaseType_t x;
1389
1390                             /* The task does not appear on the event list item of
1391                              * and of the RTOS objects, but could still be in the
1392                              * blocked state if it is waiting on its notification
1393                              * rather than waiting on an object.  If not, is
1394                              * suspended. */
1395                             eReturn = eSuspended;
1396
1397                             for( x = 0; x < configTASK_NOTIFICATION_ARRAY_ENTRIES; x++ )
1398                             {
1399                                 if( pxTCB->ucNotifyState[ x ] == taskWAITING_NOTIFICATION )
1400                                 {
1401                                     eReturn = eBlocked;
1402                                     break;
1403                                 }
1404                             }
1405                         }
1406                         #else /* if ( configUSE_TASK_NOTIFICATIONS == 1 ) */
1407                         {
1408                             eReturn = eSuspended;
1409                         }
1410                         #endif /* if ( configUSE_TASK_NOTIFICATIONS == 1 ) */
1411                     }
1412                     else
1413                     {
1414                         eReturn = eBlocked;
1415                     }
1416                 }
1417             #endif /* if ( INCLUDE_vTaskSuspend == 1 ) */
1418
1419             #if ( INCLUDE_vTaskDelete == 1 )
1420                 else if( ( pxStateList == &xTasksWaitingTermination ) || ( pxStateList == NULL ) )
1421                 {
1422                     /* The task being queried is referenced from the deleted
1423                      * tasks list, or it is not referenced from any lists at
1424                      * all. */
1425                     eReturn = eDeleted;
1426                 }
1427             #endif
1428
1429             else /*lint !e525 Negative indentation is intended to make use of pre-processor clearer. */
1430             {
1431                 /* If the task is not in any other state, it must be in the
1432                  * Ready (including pending ready) state. */
1433                 eReturn = eReady;
1434             }
1435         }
1436
1437         return eReturn;
1438     } /*lint !e818 xTask cannot be a pointer to const because it is a typedef. */
1439
1440 #endif /* INCLUDE_eTaskGetState */
1441 /*-----------------------------------------------------------*/
1442
1443 #if ( INCLUDE_uxTaskPriorityGet == 1 )
1444
1445     UBaseType_t uxTaskPriorityGet( const TaskHandle_t xTask )
1446     {
1447         TCB_t const * pxTCB;
1448         UBaseType_t uxReturn;
1449
1450         taskENTER_CRITICAL();
1451         {
1452             /* If null is passed in here then it is the priority of the task
1453              * that called uxTaskPriorityGet() that is being queried. */
1454             pxTCB = prvGetTCBFromHandle( xTask );
1455             uxReturn = pxTCB->uxPriority;
1456         }
1457         taskEXIT_CRITICAL();
1458
1459         return uxReturn;
1460     }
1461
1462 #endif /* INCLUDE_uxTaskPriorityGet */
1463 /*-----------------------------------------------------------*/
1464
1465 #if ( INCLUDE_uxTaskPriorityGet == 1 )
1466
1467     UBaseType_t uxTaskPriorityGetFromISR( const TaskHandle_t xTask )
1468     {
1469         TCB_t const * pxTCB;
1470         UBaseType_t uxReturn, uxSavedInterruptState;
1471
1472         /* RTOS ports that support interrupt nesting have the concept of a
1473          * maximum  system call (or maximum API call) interrupt priority.
1474          * Interrupts that are  above the maximum system call priority are keep
1475          * permanently enabled, even when the RTOS kernel is in a critical section,
1476          * but cannot make any calls to FreeRTOS API functions.  If configASSERT()
1477          * is defined in FreeRTOSConfig.h then
1478          * portASSERT_IF_INTERRUPT_PRIORITY_INVALID() will result in an assertion
1479          * failure if a FreeRTOS API function is called from an interrupt that has
1480          * been assigned a priority above the configured maximum system call
1481          * priority.  Only FreeRTOS functions that end in FromISR can be called
1482          * from interrupts  that have been assigned a priority at or (logically)
1483          * below the maximum system call interrupt priority.  FreeRTOS maintains a
1484          * separate interrupt safe API to ensure interrupt entry is as fast and as
1485          * simple as possible.  More information (albeit Cortex-M specific) is
1486          * provided on the following link:
1487          * https://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html */
1488         portASSERT_IF_INTERRUPT_PRIORITY_INVALID();
1489
1490         uxSavedInterruptState = portSET_INTERRUPT_MASK_FROM_ISR();
1491         {
1492             /* If null is passed in here then it is the priority of the calling
1493              * task that is being queried. */
1494             pxTCB = prvGetTCBFromHandle( xTask );
1495             uxReturn = pxTCB->uxPriority;
1496         }
1497         portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptState );
1498
1499         return uxReturn;
1500     }
1501
1502 #endif /* INCLUDE_uxTaskPriorityGet */
1503 /*-----------------------------------------------------------*/
1504
1505 #if ( INCLUDE_vTaskPrioritySet == 1 )
1506
1507     void vTaskPrioritySet( TaskHandle_t xTask,
1508                            UBaseType_t uxNewPriority )
1509     {
1510         TCB_t * pxTCB;
1511         UBaseType_t uxCurrentBasePriority, uxPriorityUsedOnEntry;
1512         BaseType_t xYieldRequired = pdFALSE;
1513
1514         configASSERT( uxNewPriority < configMAX_PRIORITIES );
1515
1516         /* Ensure the new priority is valid. */
1517         if( uxNewPriority >= ( UBaseType_t ) configMAX_PRIORITIES )
1518         {
1519             uxNewPriority = ( UBaseType_t ) configMAX_PRIORITIES - ( UBaseType_t ) 1U;
1520         }
1521         else
1522         {
1523             mtCOVERAGE_TEST_MARKER();
1524         }
1525
1526         taskENTER_CRITICAL();
1527         {
1528             /* If null is passed in here then it is the priority of the calling
1529              * task that is being changed. */
1530             pxTCB = prvGetTCBFromHandle( xTask );
1531
1532             traceTASK_PRIORITY_SET( pxTCB, uxNewPriority );
1533
1534             #if ( configUSE_MUTEXES == 1 )
1535             {
1536                 uxCurrentBasePriority = pxTCB->uxBasePriority;
1537             }
1538             #else
1539             {
1540                 uxCurrentBasePriority = pxTCB->uxPriority;
1541             }
1542             #endif
1543
1544             if( uxCurrentBasePriority != uxNewPriority )
1545             {
1546                 /* The priority change may have readied a task of higher
1547                  * priority than the calling task. */
1548                 if( uxNewPriority > uxCurrentBasePriority )
1549                 {
1550                     if( pxTCB != pxCurrentTCB )
1551                     {
1552                         /* The priority of a task other than the currently
1553                          * running task is being raised.  Is the priority being
1554                          * raised above that of the running task? */
1555                         if( uxNewPriority > pxCurrentTCB->uxPriority )
1556                         {
1557                             xYieldRequired = pdTRUE;
1558                         }
1559                         else
1560                         {
1561                             mtCOVERAGE_TEST_MARKER();
1562                         }
1563                     }
1564                     else
1565                     {
1566                         /* The priority of the running task is being raised,
1567                          * but the running task must already be the highest
1568                          * priority task able to run so no yield is required. */
1569                     }
1570                 }
1571                 else if( pxTCB == pxCurrentTCB )
1572                 {
1573                     /* Setting the priority of the running task down means
1574                      * there may now be another task of higher priority that
1575                      * is ready to execute. */
1576                     xYieldRequired = pdTRUE;
1577                 }
1578                 else
1579                 {
1580                     /* Setting the priority of any other task down does not
1581                      * require a yield as the running task must be above the
1582                      * new priority of the task being modified. */
1583                 }
1584
1585                 /* Remember the ready list the task might be referenced from
1586                  * before its uxPriority member is changed so the
1587                  * taskRESET_READY_PRIORITY() macro can function correctly. */
1588                 uxPriorityUsedOnEntry = pxTCB->uxPriority;
1589
1590                 #if ( configUSE_MUTEXES == 1 )
1591                 {
1592                     /* Only change the priority being used if the task is not
1593                      * currently using an inherited priority. */
1594                     if( pxTCB->uxBasePriority == pxTCB->uxPriority )
1595                     {
1596                         pxTCB->uxPriority = uxNewPriority;
1597                     }
1598                     else
1599                     {
1600                         mtCOVERAGE_TEST_MARKER();
1601                     }
1602
1603                     /* The base priority gets set whatever. */
1604                     pxTCB->uxBasePriority = uxNewPriority;
1605                 }
1606                 #else /* if ( configUSE_MUTEXES == 1 ) */
1607                 {
1608                     pxTCB->uxPriority = uxNewPriority;
1609                 }
1610                 #endif /* if ( configUSE_MUTEXES == 1 ) */
1611
1612                 /* Only reset the event list item value if the value is not
1613                  * being used for anything else. */
1614                 if( ( listGET_LIST_ITEM_VALUE( &( pxTCB->xEventListItem ) ) & taskEVENT_LIST_ITEM_VALUE_IN_USE ) == 0UL )
1615                 {
1616                     listSET_LIST_ITEM_VALUE( &( pxTCB->xEventListItem ), ( ( TickType_t ) configMAX_PRIORITIES - ( TickType_t ) uxNewPriority ) ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */
1617                 }
1618                 else
1619                 {
1620                     mtCOVERAGE_TEST_MARKER();
1621                 }
1622
1623                 /* If the task is in the blocked or suspended list we need do
1624                  * nothing more than change its priority variable. However, if
1625                  * the task is in a ready list it needs to be removed and placed
1626                  * in the list appropriate to its new priority. */
1627                 if( listIS_CONTAINED_WITHIN( &( pxReadyTasksLists[ uxPriorityUsedOnEntry ] ), &( pxTCB->xStateListItem ) ) != pdFALSE )
1628                 {
1629                     /* The task is currently in its ready list - remove before
1630                      * adding it to its new ready list.  As we are in a critical
1631                      * section we can do this even if the scheduler is suspended. */
1632                     if( uxListRemove( &( pxTCB->xStateListItem ) ) == ( UBaseType_t ) 0 )
1633                     {
1634                         /* It is known that the task is in its ready list so
1635                          * there is no need to check again and the port level
1636                          * reset macro can be called directly. */
1637                         portRESET_READY_PRIORITY( uxPriorityUsedOnEntry, uxTopReadyPriority );
1638                     }
1639                     else
1640                     {
1641                         mtCOVERAGE_TEST_MARKER();
1642                     }
1643
1644                     prvAddTaskToReadyList( pxTCB );
1645                 }
1646                 else
1647                 {
1648                     mtCOVERAGE_TEST_MARKER();
1649                 }
1650
1651                 if( xYieldRequired != pdFALSE )
1652                 {
1653                     taskYIELD_IF_USING_PREEMPTION();
1654                 }
1655                 else
1656                 {
1657                     mtCOVERAGE_TEST_MARKER();
1658                 }
1659
1660                 /* Remove compiler warning about unused variables when the port
1661                  * optimised task selection is not being used. */
1662                 ( void ) uxPriorityUsedOnEntry;
1663             }
1664         }
1665         taskEXIT_CRITICAL();
1666     }
1667
1668 #endif /* INCLUDE_vTaskPrioritySet */
1669 /*-----------------------------------------------------------*/
1670
1671 #if ( INCLUDE_vTaskSuspend == 1 )
1672
1673     void vTaskSuspend( TaskHandle_t xTaskToSuspend )
1674     {
1675         TCB_t * pxTCB;
1676
1677         taskENTER_CRITICAL();
1678         {
1679             /* If null is passed in here then it is the running task that is
1680              * being suspended. */
1681             pxTCB = prvGetTCBFromHandle( xTaskToSuspend );
1682
1683             traceTASK_SUSPEND( pxTCB );
1684
1685             /* Remove task from the ready/delayed list and place in the
1686              * suspended list. */
1687             if( uxListRemove( &( pxTCB->xStateListItem ) ) == ( UBaseType_t ) 0 )
1688             {
1689                 taskRESET_READY_PRIORITY( pxTCB->uxPriority );
1690             }
1691             else
1692             {
1693                 mtCOVERAGE_TEST_MARKER();
1694             }
1695
1696             /* Is the task waiting on an event also? */
1697             if( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) != NULL )
1698             {
1699                 ( void ) uxListRemove( &( pxTCB->xEventListItem ) );
1700             }
1701             else
1702             {
1703                 mtCOVERAGE_TEST_MARKER();
1704             }
1705
1706             vListInsertEnd( &xSuspendedTaskList, &( pxTCB->xStateListItem ) );
1707
1708             #if ( configUSE_TASK_NOTIFICATIONS == 1 )
1709             {
1710                 BaseType_t x;
1711
1712                 for( x = 0; x < configTASK_NOTIFICATION_ARRAY_ENTRIES; x++ )
1713                 {
1714                     if( pxTCB->ucNotifyState[ x ] == taskWAITING_NOTIFICATION )
1715                     {
1716                         /* The task was blocked to wait for a notification, but is
1717                          * now suspended, so no notification was received. */
1718                         pxTCB->ucNotifyState[ x ] = taskNOT_WAITING_NOTIFICATION;
1719                     }
1720                 }
1721             }
1722             #endif /* if ( configUSE_TASK_NOTIFICATIONS == 1 ) */
1723         }
1724         taskEXIT_CRITICAL();
1725
1726         if( xSchedulerRunning != pdFALSE )
1727         {
1728             /* Reset the next expected unblock time in case it referred to the
1729              * task that is now in the Suspended state. */
1730             taskENTER_CRITICAL();
1731             {
1732                 prvResetNextTaskUnblockTime();
1733             }
1734             taskEXIT_CRITICAL();
1735         }
1736         else
1737         {
1738             mtCOVERAGE_TEST_MARKER();
1739         }
1740
1741         if( pxTCB == pxCurrentTCB )
1742         {
1743             if( xSchedulerRunning != pdFALSE )
1744             {
1745                 /* The current task has just been suspended. */
1746                 configASSERT( uxSchedulerSuspended == 0 );
1747                 portYIELD_WITHIN_API();
1748             }
1749             else
1750             {
1751                 /* The scheduler is not running, but the task that was pointed
1752                  * to by pxCurrentTCB has just been suspended and pxCurrentTCB
1753                  * must be adjusted to point to a different task. */
1754                 if( listCURRENT_LIST_LENGTH( &xSuspendedTaskList ) == uxCurrentNumberOfTasks ) /*lint !e931 Right has no side effect, just volatile. */
1755                 {
1756                     /* No other tasks are ready, so set pxCurrentTCB back to
1757                      * NULL so when the next task is created pxCurrentTCB will
1758                      * be set to point to it no matter what its relative priority
1759                      * is. */
1760                     pxCurrentTCB = NULL;
1761                 }
1762                 else
1763                 {
1764                     vTaskSwitchContext();
1765                 }
1766             }
1767         }
1768         else
1769         {
1770             mtCOVERAGE_TEST_MARKER();
1771         }
1772     }
1773
1774 #endif /* INCLUDE_vTaskSuspend */
1775 /*-----------------------------------------------------------*/
1776
1777 #if ( INCLUDE_vTaskSuspend == 1 )
1778
1779     static BaseType_t prvTaskIsTaskSuspended( const TaskHandle_t xTask )
1780     {
1781         BaseType_t xReturn = pdFALSE;
1782         const TCB_t * const pxTCB = xTask;
1783
1784         /* Accesses xPendingReadyList so must be called from a critical
1785          * section. */
1786
1787         /* It does not make sense to check if the calling task is suspended. */
1788         configASSERT( xTask );
1789
1790         /* Is the task being resumed actually in the suspended list? */
1791         if( listIS_CONTAINED_WITHIN( &xSuspendedTaskList, &( pxTCB->xStateListItem ) ) != pdFALSE )
1792         {
1793             /* Has the task already been resumed from within an ISR? */
1794             if( listIS_CONTAINED_WITHIN( &xPendingReadyList, &( pxTCB->xEventListItem ) ) == pdFALSE )
1795             {
1796                 /* Is it in the suspended list because it is in the Suspended
1797                  * state, or because is is blocked with no timeout? */
1798                 if( listIS_CONTAINED_WITHIN( NULL, &( pxTCB->xEventListItem ) ) != pdFALSE ) /*lint !e961.  The cast is only redundant when NULL is used. */
1799                 {
1800                     xReturn = pdTRUE;
1801                 }
1802                 else
1803                 {
1804                     mtCOVERAGE_TEST_MARKER();
1805                 }
1806             }
1807             else
1808             {
1809                 mtCOVERAGE_TEST_MARKER();
1810             }
1811         }
1812         else
1813         {
1814             mtCOVERAGE_TEST_MARKER();
1815         }
1816
1817         return xReturn;
1818     } /*lint !e818 xTask cannot be a pointer to const because it is a typedef. */
1819
1820 #endif /* INCLUDE_vTaskSuspend */
1821 /*-----------------------------------------------------------*/
1822
1823 #if ( INCLUDE_vTaskSuspend == 1 )
1824
1825     void vTaskResume( TaskHandle_t xTaskToResume )
1826     {
1827         TCB_t * const pxTCB = xTaskToResume;
1828
1829         /* It does not make sense to resume the calling task. */
1830         configASSERT( xTaskToResume );
1831
1832         /* The parameter cannot be NULL as it is impossible to resume the
1833          * currently executing task. */
1834         if( ( pxTCB != pxCurrentTCB ) && ( pxTCB != NULL ) )
1835         {
1836             taskENTER_CRITICAL();
1837             {
1838                 if( prvTaskIsTaskSuspended( pxTCB ) != pdFALSE )
1839                 {
1840                     traceTASK_RESUME( pxTCB );
1841
1842                     /* The ready list can be accessed even if the scheduler is
1843                      * suspended because this is inside a critical section. */
1844                     ( void ) uxListRemove( &( pxTCB->xStateListItem ) );
1845                     prvAddTaskToReadyList( pxTCB );
1846
1847                     /* A higher priority task may have just been resumed. */
1848                     if( pxTCB->uxPriority > pxCurrentTCB->uxPriority )
1849                     {
1850                         /* This yield may not cause the task just resumed to run,
1851                          * but will leave the lists in the correct state for the
1852                          * next yield. */
1853                         taskYIELD_IF_USING_PREEMPTION();
1854                     }
1855                     else
1856                     {
1857                         mtCOVERAGE_TEST_MARKER();
1858                     }
1859                 }
1860                 else
1861                 {
1862                     mtCOVERAGE_TEST_MARKER();
1863                 }
1864             }
1865             taskEXIT_CRITICAL();
1866         }
1867         else
1868         {
1869             mtCOVERAGE_TEST_MARKER();
1870         }
1871     }
1872
1873 #endif /* INCLUDE_vTaskSuspend */
1874
1875 /*-----------------------------------------------------------*/
1876
1877 #if ( ( INCLUDE_xTaskResumeFromISR == 1 ) && ( INCLUDE_vTaskSuspend == 1 ) )
1878
1879     BaseType_t xTaskResumeFromISR( TaskHandle_t xTaskToResume )
1880     {
1881         BaseType_t xYieldRequired = pdFALSE;
1882         TCB_t * const pxTCB = xTaskToResume;
1883         UBaseType_t uxSavedInterruptStatus;
1884
1885         configASSERT( xTaskToResume );
1886
1887         /* RTOS ports that support interrupt nesting have the concept of a
1888          * maximum  system call (or maximum API call) interrupt priority.
1889          * Interrupts that are  above the maximum system call priority are keep
1890          * permanently enabled, even when the RTOS kernel is in a critical section,
1891          * but cannot make any calls to FreeRTOS API functions.  If configASSERT()
1892          * is defined in FreeRTOSConfig.h then
1893          * portASSERT_IF_INTERRUPT_PRIORITY_INVALID() will result in an assertion
1894          * failure if a FreeRTOS API function is called from an interrupt that has
1895          * been assigned a priority above the configured maximum system call
1896          * priority.  Only FreeRTOS functions that end in FromISR can be called
1897          * from interrupts  that have been assigned a priority at or (logically)
1898          * below the maximum system call interrupt priority.  FreeRTOS maintains a
1899          * separate interrupt safe API to ensure interrupt entry is as fast and as
1900          * simple as possible.  More information (albeit Cortex-M specific) is
1901          * provided on the following link:
1902          * https://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html */
1903         portASSERT_IF_INTERRUPT_PRIORITY_INVALID();
1904
1905         uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR();
1906         {
1907             if( prvTaskIsTaskSuspended( pxTCB ) != pdFALSE )
1908             {
1909                 traceTASK_RESUME_FROM_ISR( pxTCB );
1910
1911                 /* Check the ready lists can be accessed. */
1912                 if( uxSchedulerSuspended == ( UBaseType_t ) pdFALSE )
1913                 {
1914                     /* Ready lists can be accessed so move the task from the
1915                      * suspended list to the ready list directly. */
1916                     if( pxTCB->uxPriority > pxCurrentTCB->uxPriority )
1917                     {
1918                         xYieldRequired = pdTRUE;
1919
1920                         /* Mark that a yield is pending in case the user is not
1921                          * using the return value to initiate a context switch
1922                          * from the ISR using portYIELD_FROM_ISR. */
1923                         xYieldPending = pdTRUE;
1924                     }
1925                     else
1926                     {
1927                         mtCOVERAGE_TEST_MARKER();
1928                     }
1929
1930                     ( void ) uxListRemove( &( pxTCB->xStateListItem ) );
1931                     prvAddTaskToReadyList( pxTCB );
1932                 }
1933                 else
1934                 {
1935                     /* The delayed or ready lists cannot be accessed so the task
1936                      * is held in the pending ready list until the scheduler is
1937                      * unsuspended. */
1938                     vListInsertEnd( &( xPendingReadyList ), &( pxTCB->xEventListItem ) );
1939                 }
1940             }
1941             else
1942             {
1943                 mtCOVERAGE_TEST_MARKER();
1944             }
1945         }
1946         portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus );
1947
1948         return xYieldRequired;
1949     }
1950
1951 #endif /* ( ( INCLUDE_xTaskResumeFromISR == 1 ) && ( INCLUDE_vTaskSuspend == 1 ) ) */
1952 /*-----------------------------------------------------------*/
1953
1954 void vTaskStartScheduler( void )
1955 {
1956     BaseType_t xReturn;
1957
1958     /* Add the idle task at the lowest priority. */
1959     #if ( configSUPPORT_STATIC_ALLOCATION == 1 )
1960     {
1961         StaticTask_t * pxIdleTaskTCBBuffer = NULL;
1962         StackType_t * pxIdleTaskStackBuffer = NULL;
1963         uint32_t ulIdleTaskStackSize;
1964
1965         /* The Idle task is created using user provided RAM - obtain the
1966          * address of the RAM then create the idle task. */
1967         vApplicationGetIdleTaskMemory( &pxIdleTaskTCBBuffer, &pxIdleTaskStackBuffer, &ulIdleTaskStackSize );
1968         xIdleTaskHandle = xTaskCreateStatic( prvIdleTask,
1969                                              configIDLE_TASK_NAME,
1970                                              ulIdleTaskStackSize,
1971                                              ( void * ) NULL,       /*lint !e961.  The cast is not redundant for all compilers. */
1972                                              portPRIVILEGE_BIT,     /* In effect ( tskIDLE_PRIORITY | portPRIVILEGE_BIT ), but tskIDLE_PRIORITY is zero. */
1973                                              pxIdleTaskStackBuffer,
1974                                              pxIdleTaskTCBBuffer ); /*lint !e961 MISRA exception, justified as it is not a redundant explicit cast to all supported compilers. */
1975
1976         if( xIdleTaskHandle != NULL )
1977         {
1978             xReturn = pdPASS;
1979         }
1980         else
1981         {
1982             xReturn = pdFAIL;
1983         }
1984     }
1985     #else /* if ( configSUPPORT_STATIC_ALLOCATION == 1 ) */
1986     {
1987         /* The Idle task is being created using dynamically allocated RAM. */
1988         xReturn = xTaskCreate( prvIdleTask,
1989                                configIDLE_TASK_NAME,
1990                                configMINIMAL_STACK_SIZE,
1991                                ( void * ) NULL,
1992                                portPRIVILEGE_BIT,  /* In effect ( tskIDLE_PRIORITY | portPRIVILEGE_BIT ), but tskIDLE_PRIORITY is zero. */
1993                                &xIdleTaskHandle ); /*lint !e961 MISRA exception, justified as it is not a redundant explicit cast to all supported compilers. */
1994     }
1995     #endif /* configSUPPORT_STATIC_ALLOCATION */
1996
1997     #if ( configUSE_TIMERS == 1 )
1998     {
1999         if( xReturn == pdPASS )
2000         {
2001             xReturn = xTimerCreateTimerTask();
2002         }
2003         else
2004         {
2005             mtCOVERAGE_TEST_MARKER();
2006         }
2007     }
2008     #endif /* configUSE_TIMERS */
2009
2010     if( xReturn == pdPASS )
2011     {
2012         /* freertos_tasks_c_additions_init() should only be called if the user
2013          * definable macro FREERTOS_TASKS_C_ADDITIONS_INIT() is defined, as that is
2014          * the only macro called by the function. */
2015         #ifdef FREERTOS_TASKS_C_ADDITIONS_INIT
2016         {
2017             freertos_tasks_c_additions_init();
2018         }
2019         #endif
2020
2021         /* Interrupts are turned off here, to ensure a tick does not occur
2022          * before or during the call to xPortStartScheduler().  The stacks of
2023          * the created tasks contain a status word with interrupts switched on
2024          * so interrupts will automatically get re-enabled when the first task
2025          * starts to run. */
2026         portDISABLE_INTERRUPTS();
2027
2028         #if ( ( configUSE_NEWLIB_REENTRANT == 1 ) || ( configUSE_C_RUNTIME_TLS_SUPPORT == 1 ) )
2029         {
2030             /* Switch C-Runtime's TLS Block to point to the TLS
2031              * block specific to the task that will run first. */
2032             configSET_TLS_BLOCK( pxCurrentTCB->xTLSBlock );
2033         }
2034         #endif
2035
2036         xNextTaskUnblockTime = portMAX_DELAY;
2037         xSchedulerRunning = pdTRUE;
2038         xTickCount = ( TickType_t ) configINITIAL_TICK_COUNT;
2039
2040         /* If configGENERATE_RUN_TIME_STATS is defined then the following
2041          * macro must be defined to configure the timer/counter used to generate
2042          * the run time counter time base.   NOTE:  If configGENERATE_RUN_TIME_STATS
2043          * is set to 0 and the following line fails to build then ensure you do not
2044          * have portCONFIGURE_TIMER_FOR_RUN_TIME_STATS() defined in your
2045          * FreeRTOSConfig.h file. */
2046         portCONFIGURE_TIMER_FOR_RUN_TIME_STATS();
2047
2048         traceTASK_SWITCHED_IN();
2049
2050         /* Setting up the timer tick is hardware specific and thus in the
2051          * portable interface. */
2052         xPortStartScheduler();
2053
2054         /* In most cases, xPortStartScheduler() will not return. If it
2055          * returns pdTRUE then there was not enough heap memory available
2056          * to create either the Idle or the Timer task. If it returned
2057          * pdFALSE, then the application called xTaskEndScheduler().
2058          * Most ports don't implement xTaskEndScheduler() as there is
2059          * nothing to return to. */
2060     }
2061     else
2062     {
2063         /* This line will only be reached if the kernel could not be started,
2064          * because there was not enough FreeRTOS heap to create the idle task
2065          * or the timer task. */
2066         configASSERT( xReturn != errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY );
2067     }
2068
2069     /* Prevent compiler warnings if INCLUDE_xTaskGetIdleTaskHandle is set to 0,
2070      * meaning xIdleTaskHandle is not used anywhere else. */
2071     ( void ) xIdleTaskHandle;
2072
2073     /* OpenOCD makes use of uxTopUsedPriority for thread debugging. Prevent uxTopUsedPriority
2074      * from getting optimized out as it is no longer used by the kernel. */
2075     ( void ) uxTopUsedPriority;
2076 }
2077 /*-----------------------------------------------------------*/
2078
2079 void vTaskEndScheduler( void )
2080 {
2081     /* Stop the scheduler interrupts and call the portable scheduler end
2082      * routine so the original ISRs can be restored if necessary.  The port
2083      * layer must ensure interrupts enable  bit is left in the correct state. */
2084     portDISABLE_INTERRUPTS();
2085     xSchedulerRunning = pdFALSE;
2086     vPortEndScheduler();
2087 }
2088 /*----------------------------------------------------------*/
2089
2090 void vTaskSuspendAll( void )
2091 {
2092     /* A critical section is not required as the variable is of type
2093      * BaseType_t.  Please read Richard Barry's reply in the following link to a
2094      * post in the FreeRTOS support forum before reporting this as a bug! -
2095      * https://goo.gl/wu4acr */
2096
2097     /* portSOFTWARE_BARRIER() is only implemented for emulated/simulated ports that
2098      * do not otherwise exhibit real time behaviour. */
2099     portSOFTWARE_BARRIER();
2100
2101     /* The scheduler is suspended if uxSchedulerSuspended is non-zero.  An increment
2102      * is used to allow calls to vTaskSuspendAll() to nest. */
2103     ++uxSchedulerSuspended;
2104
2105     /* Enforces ordering for ports and optimised compilers that may otherwise place
2106      * the above increment elsewhere. */
2107     portMEMORY_BARRIER();
2108 }
2109 /*----------------------------------------------------------*/
2110
2111 #if ( configUSE_TICKLESS_IDLE != 0 )
2112
2113     static TickType_t prvGetExpectedIdleTime( void )
2114     {
2115         TickType_t xReturn;
2116         UBaseType_t uxHigherPriorityReadyTasks = pdFALSE;
2117
2118         /* uxHigherPriorityReadyTasks takes care of the case where
2119          * configUSE_PREEMPTION is 0, so there may be tasks above the idle priority
2120          * task that are in the Ready state, even though the idle task is
2121          * running. */
2122         #if ( configUSE_PORT_OPTIMISED_TASK_SELECTION == 0 )
2123         {
2124             if( uxTopReadyPriority > tskIDLE_PRIORITY )
2125             {
2126                 uxHigherPriorityReadyTasks = pdTRUE;
2127             }
2128         }
2129         #else
2130         {
2131             const UBaseType_t uxLeastSignificantBit = ( UBaseType_t ) 0x01;
2132
2133             /* When port optimised task selection is used the uxTopReadyPriority
2134              * variable is used as a bit map.  If bits other than the least
2135              * significant bit are set then there are tasks that have a priority
2136              * above the idle priority that are in the Ready state.  This takes
2137              * care of the case where the co-operative scheduler is in use. */
2138             if( uxTopReadyPriority > uxLeastSignificantBit )
2139             {
2140                 uxHigherPriorityReadyTasks = pdTRUE;
2141             }
2142         }
2143         #endif /* if ( configUSE_PORT_OPTIMISED_TASK_SELECTION == 0 ) */
2144
2145         if( pxCurrentTCB->uxPriority > tskIDLE_PRIORITY )
2146         {
2147             xReturn = 0;
2148         }
2149         else if( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ tskIDLE_PRIORITY ] ) ) > 1 )
2150         {
2151             /* There are other idle priority tasks in the ready state.  If
2152              * time slicing is used then the very next tick interrupt must be
2153              * processed. */
2154             xReturn = 0;
2155         }
2156         else if( uxHigherPriorityReadyTasks != pdFALSE )
2157         {
2158             /* There are tasks in the Ready state that have a priority above the
2159              * idle priority.  This path can only be reached if
2160              * configUSE_PREEMPTION is 0. */
2161             xReturn = 0;
2162         }
2163         else
2164         {
2165             xReturn = xNextTaskUnblockTime - xTickCount;
2166         }
2167
2168         return xReturn;
2169     }
2170
2171 #endif /* configUSE_TICKLESS_IDLE */
2172 /*----------------------------------------------------------*/
2173
2174 BaseType_t xTaskResumeAll( void )
2175 {
2176     TCB_t * pxTCB = NULL;
2177     BaseType_t xAlreadyYielded = pdFALSE;
2178
2179     /* If uxSchedulerSuspended is zero then this function does not match a
2180      * previous call to vTaskSuspendAll(). */
2181     configASSERT( uxSchedulerSuspended );
2182
2183     /* It is possible that an ISR caused a task to be removed from an event
2184      * list while the scheduler was suspended.  If this was the case then the
2185      * removed task will have been added to the xPendingReadyList.  Once the
2186      * scheduler has been resumed it is safe to move all the pending ready
2187      * tasks from this list into their appropriate ready list. */
2188     taskENTER_CRITICAL();
2189     {
2190         --uxSchedulerSuspended;
2191
2192         if( uxSchedulerSuspended == ( UBaseType_t ) pdFALSE )
2193         {
2194             if( uxCurrentNumberOfTasks > ( UBaseType_t ) 0U )
2195             {
2196                 /* Move any readied tasks from the pending list into the
2197                  * appropriate ready list. */
2198                 while( listLIST_IS_EMPTY( &xPendingReadyList ) == pdFALSE )
2199                 {
2200                     pxTCB = listGET_OWNER_OF_HEAD_ENTRY( ( &xPendingReadyList ) ); /*lint !e9079 void * is used as this macro is used with timers too.  Alignment is known to be fine as the type of the pointer stored and retrieved is the same. */
2201                     listREMOVE_ITEM( &( pxTCB->xEventListItem ) );
2202                     portMEMORY_BARRIER();
2203                     listREMOVE_ITEM( &( pxTCB->xStateListItem ) );
2204                     prvAddTaskToReadyList( pxTCB );
2205
2206                     /* If the moved task has a priority higher than the current
2207                      * task then a yield must be performed. */
2208                     if( pxTCB->uxPriority > pxCurrentTCB->uxPriority )
2209                     {
2210                         xYieldPending = pdTRUE;
2211                     }
2212                     else
2213                     {
2214                         mtCOVERAGE_TEST_MARKER();
2215                     }
2216                 }
2217
2218                 if( pxTCB != NULL )
2219                 {
2220                     /* A task was unblocked while the scheduler was suspended,
2221                      * which may have prevented the next unblock time from being
2222                      * re-calculated, in which case re-calculate it now.  Mainly
2223                      * important for low power tickless implementations, where
2224                      * this can prevent an unnecessary exit from low power
2225                      * state. */
2226                     prvResetNextTaskUnblockTime();
2227                 }
2228
2229                 /* If any ticks occurred while the scheduler was suspended then
2230                  * they should be processed now.  This ensures the tick count does
2231                  * not  slip, and that any delayed tasks are resumed at the correct
2232                  * time. */
2233                 {
2234                     TickType_t xPendedCounts = xPendedTicks; /* Non-volatile copy. */
2235
2236                     if( xPendedCounts > ( TickType_t ) 0U )
2237                     {
2238                         do
2239                         {
2240                             if( xTaskIncrementTick() != pdFALSE )
2241                             {
2242                                 xYieldPending = pdTRUE;
2243                             }
2244                             else
2245                             {
2246                                 mtCOVERAGE_TEST_MARKER();
2247                             }
2248
2249                             --xPendedCounts;
2250                         } while( xPendedCounts > ( TickType_t ) 0U );
2251
2252                         xPendedTicks = 0;
2253                     }
2254                     else
2255                     {
2256                         mtCOVERAGE_TEST_MARKER();
2257                     }
2258                 }
2259
2260                 if( xYieldPending != pdFALSE )
2261                 {
2262                     #if ( configUSE_PREEMPTION != 0 )
2263                     {
2264                         xAlreadyYielded = pdTRUE;
2265                     }
2266                     #endif
2267                     taskYIELD_IF_USING_PREEMPTION();
2268                 }
2269                 else
2270                 {
2271                     mtCOVERAGE_TEST_MARKER();
2272                 }
2273             }
2274         }
2275         else
2276         {
2277             mtCOVERAGE_TEST_MARKER();
2278         }
2279     }
2280     taskEXIT_CRITICAL();
2281
2282     return xAlreadyYielded;
2283 }
2284 /*-----------------------------------------------------------*/
2285
2286 TickType_t xTaskGetTickCount( void )
2287 {
2288     TickType_t xTicks;
2289
2290     /* Critical section required if running on a 16 bit processor. */
2291     portTICK_TYPE_ENTER_CRITICAL();
2292     {
2293         xTicks = xTickCount;
2294     }
2295     portTICK_TYPE_EXIT_CRITICAL();
2296
2297     return xTicks;
2298 }
2299 /*-----------------------------------------------------------*/
2300
2301 TickType_t xTaskGetTickCountFromISR( void )
2302 {
2303     TickType_t xReturn;
2304     UBaseType_t uxSavedInterruptStatus;
2305
2306     /* RTOS ports that support interrupt nesting have the concept of a maximum
2307      * system call (or maximum API call) interrupt priority.  Interrupts that are
2308      * above the maximum system call priority are kept permanently enabled, even
2309      * when the RTOS kernel is in a critical section, but cannot make any calls to
2310      * FreeRTOS API functions.  If configASSERT() is defined in FreeRTOSConfig.h
2311      * then portASSERT_IF_INTERRUPT_PRIORITY_INVALID() will result in an assertion
2312      * failure if a FreeRTOS API function is called from an interrupt that has been
2313      * assigned a priority above the configured maximum system call priority.
2314      * Only FreeRTOS functions that end in FromISR can be called from interrupts
2315      * that have been assigned a priority at or (logically) below the maximum
2316      * system call  interrupt priority.  FreeRTOS maintains a separate interrupt
2317      * safe API to ensure interrupt entry is as fast and as simple as possible.
2318      * More information (albeit Cortex-M specific) is provided on the following
2319      * link: https://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html */
2320     portASSERT_IF_INTERRUPT_PRIORITY_INVALID();
2321
2322     uxSavedInterruptStatus = portTICK_TYPE_SET_INTERRUPT_MASK_FROM_ISR();
2323     {
2324         xReturn = xTickCount;
2325     }
2326     portTICK_TYPE_CLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus );
2327
2328     return xReturn;
2329 }
2330 /*-----------------------------------------------------------*/
2331
2332 UBaseType_t uxTaskGetNumberOfTasks( void )
2333 {
2334     /* A critical section is not required because the variables are of type
2335      * BaseType_t. */
2336     return uxCurrentNumberOfTasks;
2337 }
2338 /*-----------------------------------------------------------*/
2339
2340 char * pcTaskGetName( TaskHandle_t xTaskToQuery ) /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
2341 {
2342     TCB_t * pxTCB;
2343
2344     /* If null is passed in here then the name of the calling task is being
2345      * queried. */
2346     pxTCB = prvGetTCBFromHandle( xTaskToQuery );
2347     configASSERT( pxTCB );
2348     return &( pxTCB->pcTaskName[ 0 ] );
2349 }
2350 /*-----------------------------------------------------------*/
2351
2352 #if ( INCLUDE_xTaskGetHandle == 1 )
2353
2354     static TCB_t * prvSearchForNameWithinSingleList( List_t * pxList,
2355                                                      const char pcNameToQuery[] )
2356     {
2357         TCB_t * pxNextTCB;
2358         TCB_t * pxFirstTCB;
2359         TCB_t * pxReturn = NULL;
2360         UBaseType_t x;
2361         char cNextChar;
2362         BaseType_t xBreakLoop;
2363
2364         /* This function is called with the scheduler suspended. */
2365
2366         if( listCURRENT_LIST_LENGTH( pxList ) > ( UBaseType_t ) 0 )
2367         {
2368             listGET_OWNER_OF_NEXT_ENTRY( pxFirstTCB, pxList ); /*lint !e9079 void * is used as this macro is used with timers too.  Alignment is known to be fine as the type of the pointer stored and retrieved is the same. */
2369
2370             do
2371             {
2372                 listGET_OWNER_OF_NEXT_ENTRY( pxNextTCB, pxList ); /*lint !e9079 void * is used as this macro is used with timers too.  Alignment is known to be fine as the type of the pointer stored and retrieved is the same. */
2373
2374                 /* Check each character in the name looking for a match or
2375                  * mismatch. */
2376                 xBreakLoop = pdFALSE;
2377
2378                 for( x = ( UBaseType_t ) 0; x < ( UBaseType_t ) configMAX_TASK_NAME_LEN; x++ )
2379                 {
2380                     cNextChar = pxNextTCB->pcTaskName[ x ];
2381
2382                     if( cNextChar != pcNameToQuery[ x ] )
2383                     {
2384                         /* Characters didn't match. */
2385                         xBreakLoop = pdTRUE;
2386                     }
2387                     else if( cNextChar == ( char ) 0x00 )
2388                     {
2389                         /* Both strings terminated, a match must have been
2390                          * found. */
2391                         pxReturn = pxNextTCB;
2392                         xBreakLoop = pdTRUE;
2393                     }
2394                     else
2395                     {
2396                         mtCOVERAGE_TEST_MARKER();
2397                     }
2398
2399                     if( xBreakLoop != pdFALSE )
2400                     {
2401                         break;
2402                     }
2403                 }
2404
2405                 if( pxReturn != NULL )
2406                 {
2407                     /* The handle has been found. */
2408                     break;
2409                 }
2410             } while( pxNextTCB != pxFirstTCB );
2411         }
2412         else
2413         {
2414             mtCOVERAGE_TEST_MARKER();
2415         }
2416
2417         return pxReturn;
2418     }
2419
2420 #endif /* INCLUDE_xTaskGetHandle */
2421 /*-----------------------------------------------------------*/
2422
2423 #if ( INCLUDE_xTaskGetHandle == 1 )
2424
2425     TaskHandle_t xTaskGetHandle( const char * pcNameToQuery ) /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
2426     {
2427         UBaseType_t uxQueue = configMAX_PRIORITIES;
2428         TCB_t * pxTCB;
2429
2430         /* Task names will be truncated to configMAX_TASK_NAME_LEN - 1 bytes. */
2431         configASSERT( strlen( pcNameToQuery ) < configMAX_TASK_NAME_LEN );
2432
2433         vTaskSuspendAll();
2434         {
2435             /* Search the ready lists. */
2436             do
2437             {
2438                 uxQueue--;
2439                 pxTCB = prvSearchForNameWithinSingleList( ( List_t * ) &( pxReadyTasksLists[ uxQueue ] ), pcNameToQuery );
2440
2441                 if( pxTCB != NULL )
2442                 {
2443                     /* Found the handle. */
2444                     break;
2445                 }
2446             } while( uxQueue > ( UBaseType_t ) tskIDLE_PRIORITY ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */
2447
2448             /* Search the delayed lists. */
2449             if( pxTCB == NULL )
2450             {
2451                 pxTCB = prvSearchForNameWithinSingleList( ( List_t * ) pxDelayedTaskList, pcNameToQuery );
2452             }
2453
2454             if( pxTCB == NULL )
2455             {
2456                 pxTCB = prvSearchForNameWithinSingleList( ( List_t * ) pxOverflowDelayedTaskList, pcNameToQuery );
2457             }
2458
2459             #if ( INCLUDE_vTaskSuspend == 1 )
2460             {
2461                 if( pxTCB == NULL )
2462                 {
2463                     /* Search the suspended list. */
2464                     pxTCB = prvSearchForNameWithinSingleList( &xSuspendedTaskList, pcNameToQuery );
2465                 }
2466             }
2467             #endif
2468
2469             #if ( INCLUDE_vTaskDelete == 1 )
2470             {
2471                 if( pxTCB == NULL )
2472                 {
2473                     /* Search the deleted list. */
2474                     pxTCB = prvSearchForNameWithinSingleList( &xTasksWaitingTermination, pcNameToQuery );
2475                 }
2476             }
2477             #endif
2478         }
2479         ( void ) xTaskResumeAll();
2480
2481         return pxTCB;
2482     }
2483
2484 #endif /* INCLUDE_xTaskGetHandle */
2485 /*-----------------------------------------------------------*/
2486
2487 #if ( configUSE_TRACE_FACILITY == 1 )
2488
2489     UBaseType_t uxTaskGetSystemState( TaskStatus_t * const pxTaskStatusArray,
2490                                       const UBaseType_t uxArraySize,
2491                                       configRUN_TIME_COUNTER_TYPE * const pulTotalRunTime )
2492     {
2493         UBaseType_t uxTask = 0, uxQueue = configMAX_PRIORITIES;
2494
2495         vTaskSuspendAll();
2496         {
2497             /* Is there a space in the array for each task in the system? */
2498             if( uxArraySize >= uxCurrentNumberOfTasks )
2499             {
2500                 /* Fill in an TaskStatus_t structure with information on each
2501                  * task in the Ready state. */
2502                 do
2503                 {
2504                     uxQueue--;
2505                     uxTask += prvListTasksWithinSingleList( &( pxTaskStatusArray[ uxTask ] ), &( pxReadyTasksLists[ uxQueue ] ), eReady );
2506                 } while( uxQueue > ( UBaseType_t ) tskIDLE_PRIORITY ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */
2507
2508                 /* Fill in an TaskStatus_t structure with information on each
2509                  * task in the Blocked state. */
2510                 uxTask += prvListTasksWithinSingleList( &( pxTaskStatusArray[ uxTask ] ), ( List_t * ) pxDelayedTaskList, eBlocked );
2511                 uxTask += prvListTasksWithinSingleList( &( pxTaskStatusArray[ uxTask ] ), ( List_t * ) pxOverflowDelayedTaskList, eBlocked );
2512
2513                 #if ( INCLUDE_vTaskDelete == 1 )
2514                 {
2515                     /* Fill in an TaskStatus_t structure with information on
2516                      * each task that has been deleted but not yet cleaned up. */
2517                     uxTask += prvListTasksWithinSingleList( &( pxTaskStatusArray[ uxTask ] ), &xTasksWaitingTermination, eDeleted );
2518                 }
2519                 #endif
2520
2521                 #if ( INCLUDE_vTaskSuspend == 1 )
2522                 {
2523                     /* Fill in an TaskStatus_t structure with information on
2524                      * each task in the Suspended state. */
2525                     uxTask += prvListTasksWithinSingleList( &( pxTaskStatusArray[ uxTask ] ), &xSuspendedTaskList, eSuspended );
2526                 }
2527                 #endif
2528
2529                 #if ( configGENERATE_RUN_TIME_STATS == 1 )
2530                 {
2531                     if( pulTotalRunTime != NULL )
2532                     {
2533                         #ifdef portALT_GET_RUN_TIME_COUNTER_VALUE
2534                             portALT_GET_RUN_TIME_COUNTER_VALUE( ( *pulTotalRunTime ) );
2535                         #else
2536                             *pulTotalRunTime = portGET_RUN_TIME_COUNTER_VALUE();
2537                         #endif
2538                     }
2539                 }
2540                 #else /* if ( configGENERATE_RUN_TIME_STATS == 1 ) */
2541                 {
2542                     if( pulTotalRunTime != NULL )
2543                     {
2544                         *pulTotalRunTime = 0;
2545                     }
2546                 }
2547                 #endif /* if ( configGENERATE_RUN_TIME_STATS == 1 ) */
2548             }
2549             else
2550             {
2551                 mtCOVERAGE_TEST_MARKER();
2552             }
2553         }
2554         ( void ) xTaskResumeAll();
2555
2556         return uxTask;
2557     }
2558
2559 #endif /* configUSE_TRACE_FACILITY */
2560 /*----------------------------------------------------------*/
2561
2562 #if ( INCLUDE_xTaskGetIdleTaskHandle == 1 )
2563
2564     TaskHandle_t xTaskGetIdleTaskHandle( void )
2565     {
2566         /* If xTaskGetIdleTaskHandle() is called before the scheduler has been
2567          * started, then xIdleTaskHandle will be NULL. */
2568         configASSERT( ( xIdleTaskHandle != NULL ) );
2569         return xIdleTaskHandle;
2570     }
2571
2572 #endif /* INCLUDE_xTaskGetIdleTaskHandle */
2573 /*----------------------------------------------------------*/
2574
2575 /* This conditional compilation should use inequality to 0, not equality to 1.
2576  * This is to ensure vTaskStepTick() is available when user defined low power mode
2577  * implementations require configUSE_TICKLESS_IDLE to be set to a value other than
2578  * 1. */
2579 #if ( configUSE_TICKLESS_IDLE != 0 )
2580
2581     void vTaskStepTick( TickType_t xTicksToJump )
2582     {
2583         /* Correct the tick count value after a period during which the tick
2584          * was suppressed.  Note this does *not* call the tick hook function for
2585          * each stepped tick. */
2586         configASSERT( ( xTickCount + xTicksToJump ) <= xNextTaskUnblockTime );
2587
2588         if( ( xTickCount + xTicksToJump ) == xNextTaskUnblockTime )
2589         {
2590             /* Arrange for xTickCount to reach xNextTaskUnblockTime in
2591              * xTaskIncrementTick() when the scheduler resumes.  This ensures
2592              * that any delayed tasks are resumed at the correct time. */
2593             configASSERT( uxSchedulerSuspended );
2594             configASSERT( xTicksToJump != ( TickType_t ) 0 );
2595
2596             /* Prevent the tick interrupt modifying xPendedTicks simultaneously. */
2597             taskENTER_CRITICAL();
2598             {
2599                 xPendedTicks++;
2600             }
2601             taskEXIT_CRITICAL();
2602             xTicksToJump--;
2603         }
2604         else
2605         {
2606             mtCOVERAGE_TEST_MARKER();
2607         }
2608
2609         xTickCount += xTicksToJump;
2610         traceINCREASE_TICK_COUNT( xTicksToJump );
2611     }
2612
2613 #endif /* configUSE_TICKLESS_IDLE */
2614 /*----------------------------------------------------------*/
2615
2616 BaseType_t xTaskCatchUpTicks( TickType_t xTicksToCatchUp )
2617 {
2618     BaseType_t xYieldOccurred;
2619
2620     /* Must not be called with the scheduler suspended as the implementation
2621      * relies on xPendedTicks being wound down to 0 in xTaskResumeAll(). */
2622     configASSERT( uxSchedulerSuspended == 0 );
2623
2624     /* Use xPendedTicks to mimic xTicksToCatchUp number of ticks occurring when
2625      * the scheduler is suspended so the ticks are executed in xTaskResumeAll(). */
2626     vTaskSuspendAll();
2627
2628     /* Prevent the tick interrupt modifying xPendedTicks simultaneously. */
2629     taskENTER_CRITICAL();
2630     {
2631         xPendedTicks += xTicksToCatchUp;
2632     }
2633     taskEXIT_CRITICAL();
2634     xYieldOccurred = xTaskResumeAll();
2635
2636     return xYieldOccurred;
2637 }
2638 /*----------------------------------------------------------*/
2639
2640 #if ( INCLUDE_xTaskAbortDelay == 1 )
2641
2642     BaseType_t xTaskAbortDelay( TaskHandle_t xTask )
2643     {
2644         TCB_t * pxTCB = xTask;
2645         BaseType_t xReturn;
2646
2647         configASSERT( pxTCB );
2648
2649         vTaskSuspendAll();
2650         {
2651             /* A task can only be prematurely removed from the Blocked state if
2652              * it is actually in the Blocked state. */
2653             if( eTaskGetState( xTask ) == eBlocked )
2654             {
2655                 xReturn = pdPASS;
2656
2657                 /* Remove the reference to the task from the blocked list.  An
2658                  * interrupt won't touch the xStateListItem because the
2659                  * scheduler is suspended. */
2660                 ( void ) uxListRemove( &( pxTCB->xStateListItem ) );
2661
2662                 /* Is the task waiting on an event also?  If so remove it from
2663                  * the event list too.  Interrupts can touch the event list item,
2664                  * even though the scheduler is suspended, so a critical section
2665                  * is used. */
2666                 taskENTER_CRITICAL();
2667                 {
2668                     if( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) != NULL )
2669                     {
2670                         ( void ) uxListRemove( &( pxTCB->xEventListItem ) );
2671
2672                         /* This lets the task know it was forcibly removed from the
2673                          * blocked state so it should not re-evaluate its block time and
2674                          * then block again. */
2675                         pxTCB->ucDelayAborted = pdTRUE;
2676                     }
2677                     else
2678                     {
2679                         mtCOVERAGE_TEST_MARKER();
2680                     }
2681                 }
2682                 taskEXIT_CRITICAL();
2683
2684                 /* Place the unblocked task into the appropriate ready list. */
2685                 prvAddTaskToReadyList( pxTCB );
2686
2687                 /* A task being unblocked cannot cause an immediate context
2688                  * switch if preemption is turned off. */
2689                 #if ( configUSE_PREEMPTION == 1 )
2690                 {
2691                     /* Preemption is on, but a context switch should only be
2692                      * performed if the unblocked task has a priority that is
2693                      * higher than the currently executing task. */
2694                     if( pxTCB->uxPriority > pxCurrentTCB->uxPriority )
2695                     {
2696                         /* Pend the yield to be performed when the scheduler
2697                          * is unsuspended. */
2698                         xYieldPending = pdTRUE;
2699                     }
2700                     else
2701                     {
2702                         mtCOVERAGE_TEST_MARKER();
2703                     }
2704                 }
2705                 #endif /* configUSE_PREEMPTION */
2706             }
2707             else
2708             {
2709                 xReturn = pdFAIL;
2710             }
2711         }
2712         ( void ) xTaskResumeAll();
2713
2714         return xReturn;
2715     }
2716
2717 #endif /* INCLUDE_xTaskAbortDelay */
2718 /*----------------------------------------------------------*/
2719
2720 BaseType_t xTaskIncrementTick( void )
2721 {
2722     TCB_t * pxTCB;
2723     TickType_t xItemValue;
2724     BaseType_t xSwitchRequired = pdFALSE;
2725
2726     /* Called by the portable layer each time a tick interrupt occurs.
2727      * Increments the tick then checks to see if the new tick value will cause any
2728      * tasks to be unblocked. */
2729     traceTASK_INCREMENT_TICK( xTickCount );
2730
2731     if( uxSchedulerSuspended == ( UBaseType_t ) pdFALSE )
2732     {
2733         /* Minor optimisation.  The tick count cannot change in this
2734          * block. */
2735         const TickType_t xConstTickCount = xTickCount + ( TickType_t ) 1;
2736
2737         /* Increment the RTOS tick, switching the delayed and overflowed
2738          * delayed lists if it wraps to 0. */
2739         xTickCount = xConstTickCount;
2740
2741         if( xConstTickCount == ( TickType_t ) 0U ) /*lint !e774 'if' does not always evaluate to false as it is looking for an overflow. */
2742         {
2743             taskSWITCH_DELAYED_LISTS();
2744         }
2745         else
2746         {
2747             mtCOVERAGE_TEST_MARKER();
2748         }
2749
2750         /* See if this tick has made a timeout expire.  Tasks are stored in
2751          * the  queue in the order of their wake time - meaning once one task
2752          * has been found whose block time has not expired there is no need to
2753          * look any further down the list. */
2754         if( xConstTickCount >= xNextTaskUnblockTime )
2755         {
2756             for( ; ; )
2757             {
2758                 if( listLIST_IS_EMPTY( pxDelayedTaskList ) != pdFALSE )
2759                 {
2760                     /* The delayed list is empty.  Set xNextTaskUnblockTime
2761                      * to the maximum possible value so it is extremely
2762                      * unlikely that the
2763                      * if( xTickCount >= xNextTaskUnblockTime ) test will pass
2764                      * next time through. */
2765                     xNextTaskUnblockTime = portMAX_DELAY; /*lint !e961 MISRA exception as the casts are only redundant for some ports. */
2766                     break;
2767                 }
2768                 else
2769                 {
2770                     /* The delayed list is not empty, get the value of the
2771                      * item at the head of the delayed list.  This is the time
2772                      * at which the task at the head of the delayed list must
2773                      * be removed from the Blocked state. */
2774                     pxTCB = listGET_OWNER_OF_HEAD_ENTRY( pxDelayedTaskList ); /*lint !e9079 void * is used as this macro is used with timers too.  Alignment is known to be fine as the type of the pointer stored and retrieved is the same. */
2775                     xItemValue = listGET_LIST_ITEM_VALUE( &( pxTCB->xStateListItem ) );
2776
2777                     if( xConstTickCount < xItemValue )
2778                     {
2779                         /* It is not time to unblock this item yet, but the
2780                          * item value is the time at which the task at the head
2781                          * of the blocked list must be removed from the Blocked
2782                          * state -  so record the item value in
2783                          * xNextTaskUnblockTime. */
2784                         xNextTaskUnblockTime = xItemValue;
2785                         break; /*lint !e9011 Code structure here is deemed easier to understand with multiple breaks. */
2786                     }
2787                     else
2788                     {
2789                         mtCOVERAGE_TEST_MARKER();
2790                     }
2791
2792                     /* It is time to remove the item from the Blocked state. */
2793                     listREMOVE_ITEM( &( pxTCB->xStateListItem ) );
2794
2795                     /* Is the task waiting on an event also?  If so remove
2796                      * it from the event list. */
2797                     if( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) != NULL )
2798                     {
2799                         listREMOVE_ITEM( &( pxTCB->xEventListItem ) );
2800                     }
2801                     else
2802                     {
2803                         mtCOVERAGE_TEST_MARKER();
2804                     }
2805
2806                     /* Place the unblocked task into the appropriate ready
2807                      * list. */
2808                     prvAddTaskToReadyList( pxTCB );
2809
2810                     /* A task being unblocked cannot cause an immediate
2811                      * context switch if preemption is turned off. */
2812                     #if ( configUSE_PREEMPTION == 1 )
2813                     {
2814                         /* Preemption is on, but a context switch should
2815                          * only be performed if the unblocked task's
2816                          * priority is higher than the currently executing
2817                          * task.
2818                          * The case of equal priority tasks sharing
2819                          * processing time (which happens when both
2820                          * preemption and time slicing are on) is
2821                          * handled below.*/
2822                         if( pxTCB->uxPriority > pxCurrentTCB->uxPriority )
2823                         {
2824                             xSwitchRequired = pdTRUE;
2825                         }
2826                         else
2827                         {
2828                             mtCOVERAGE_TEST_MARKER();
2829                         }
2830                     }
2831                     #endif /* configUSE_PREEMPTION */
2832                 }
2833             }
2834         }
2835
2836         /* Tasks of equal priority to the currently running task will share
2837          * processing time (time slice) if preemption is on, and the application
2838          * writer has not explicitly turned time slicing off. */
2839         #if ( ( configUSE_PREEMPTION == 1 ) && ( configUSE_TIME_SLICING == 1 ) )
2840         {
2841             if( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ pxCurrentTCB->uxPriority ] ) ) > ( UBaseType_t ) 1 )
2842             {
2843                 xSwitchRequired = pdTRUE;
2844             }
2845             else
2846             {
2847                 mtCOVERAGE_TEST_MARKER();
2848             }
2849         }
2850         #endif /* ( ( configUSE_PREEMPTION == 1 ) && ( configUSE_TIME_SLICING == 1 ) ) */
2851
2852         #if ( configUSE_TICK_HOOK == 1 )
2853         {
2854             /* Guard against the tick hook being called when the pended tick
2855              * count is being unwound (when the scheduler is being unlocked). */
2856             if( xPendedTicks == ( TickType_t ) 0 )
2857             {
2858                 vApplicationTickHook();
2859             }
2860             else
2861             {
2862                 mtCOVERAGE_TEST_MARKER();
2863             }
2864         }
2865         #endif /* configUSE_TICK_HOOK */
2866
2867         #if ( configUSE_PREEMPTION == 1 )
2868         {
2869             if( xYieldPending != pdFALSE )
2870             {
2871                 xSwitchRequired = pdTRUE;
2872             }
2873             else
2874             {
2875                 mtCOVERAGE_TEST_MARKER();
2876             }
2877         }
2878         #endif /* configUSE_PREEMPTION */
2879     }
2880     else
2881     {
2882         ++xPendedTicks;
2883
2884         /* The tick hook gets called at regular intervals, even if the
2885          * scheduler is locked. */
2886         #if ( configUSE_TICK_HOOK == 1 )
2887         {
2888             vApplicationTickHook();
2889         }
2890         #endif
2891     }
2892
2893     return xSwitchRequired;
2894 }
2895 /*-----------------------------------------------------------*/
2896
2897 #if ( configUSE_APPLICATION_TASK_TAG == 1 )
2898
2899     void vTaskSetApplicationTaskTag( TaskHandle_t xTask,
2900                                      TaskHookFunction_t pxHookFunction )
2901     {
2902         TCB_t * xTCB;
2903
2904         /* If xTask is NULL then it is the task hook of the calling task that is
2905          * getting set. */
2906         if( xTask == NULL )
2907         {
2908             xTCB = ( TCB_t * ) pxCurrentTCB;
2909         }
2910         else
2911         {
2912             xTCB = xTask;
2913         }
2914
2915         /* Save the hook function in the TCB.  A critical section is required as
2916          * the value can be accessed from an interrupt. */
2917         taskENTER_CRITICAL();
2918         {
2919             xTCB->pxTaskTag = pxHookFunction;
2920         }
2921         taskEXIT_CRITICAL();
2922     }
2923
2924 #endif /* configUSE_APPLICATION_TASK_TAG */
2925 /*-----------------------------------------------------------*/
2926
2927 #if ( configUSE_APPLICATION_TASK_TAG == 1 )
2928
2929     TaskHookFunction_t xTaskGetApplicationTaskTag( TaskHandle_t xTask )
2930     {
2931         TCB_t * pxTCB;
2932         TaskHookFunction_t xReturn;
2933
2934         /* If xTask is NULL then set the calling task's hook. */
2935         pxTCB = prvGetTCBFromHandle( xTask );
2936
2937         /* Save the hook function in the TCB.  A critical section is required as
2938          * the value can be accessed from an interrupt. */
2939         taskENTER_CRITICAL();
2940         {
2941             xReturn = pxTCB->pxTaskTag;
2942         }
2943         taskEXIT_CRITICAL();
2944
2945         return xReturn;
2946     }
2947
2948 #endif /* configUSE_APPLICATION_TASK_TAG */
2949 /*-----------------------------------------------------------*/
2950
2951 #if ( configUSE_APPLICATION_TASK_TAG == 1 )
2952
2953     TaskHookFunction_t xTaskGetApplicationTaskTagFromISR( TaskHandle_t xTask )
2954     {
2955         TCB_t * pxTCB;
2956         TaskHookFunction_t xReturn;
2957         UBaseType_t uxSavedInterruptStatus;
2958
2959         /* If xTask is NULL then set the calling task's hook. */
2960         pxTCB = prvGetTCBFromHandle( xTask );
2961
2962         /* Save the hook function in the TCB.  A critical section is required as
2963          * the value can be accessed from an interrupt. */
2964         uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR();
2965         {
2966             xReturn = pxTCB->pxTaskTag;
2967         }
2968         portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus );
2969
2970         return xReturn;
2971     }
2972
2973 #endif /* configUSE_APPLICATION_TASK_TAG */
2974 /*-----------------------------------------------------------*/
2975
2976 #if ( configUSE_APPLICATION_TASK_TAG == 1 )
2977
2978     BaseType_t xTaskCallApplicationTaskHook( TaskHandle_t xTask,
2979                                              void * pvParameter )
2980     {
2981         TCB_t * xTCB;
2982         BaseType_t xReturn;
2983
2984         /* If xTask is NULL then we are calling our own task hook. */
2985         if( xTask == NULL )
2986         {
2987             xTCB = pxCurrentTCB;
2988         }
2989         else
2990         {
2991             xTCB = xTask;
2992         }
2993
2994         if( xTCB->pxTaskTag != NULL )
2995         {
2996             xReturn = xTCB->pxTaskTag( pvParameter );
2997         }
2998         else
2999         {
3000             xReturn = pdFAIL;
3001         }
3002
3003         return xReturn;
3004     }
3005
3006 #endif /* configUSE_APPLICATION_TASK_TAG */
3007 /*-----------------------------------------------------------*/
3008
3009 void vTaskSwitchContext( void )
3010 {
3011     if( uxSchedulerSuspended != ( UBaseType_t ) pdFALSE )
3012     {
3013         /* The scheduler is currently suspended - do not allow a context
3014          * switch. */
3015         xYieldPending = pdTRUE;
3016     }
3017     else
3018     {
3019         xYieldPending = pdFALSE;
3020         traceTASK_SWITCHED_OUT();
3021
3022         #if ( configGENERATE_RUN_TIME_STATS == 1 )
3023         {
3024             #ifdef portALT_GET_RUN_TIME_COUNTER_VALUE
3025                 portALT_GET_RUN_TIME_COUNTER_VALUE( ulTotalRunTime );
3026             #else
3027                 ulTotalRunTime = portGET_RUN_TIME_COUNTER_VALUE();
3028             #endif
3029
3030             /* Add the amount of time the task has been running to the
3031              * accumulated time so far.  The time the task started running was
3032              * stored in ulTaskSwitchedInTime.  Note that there is no overflow
3033              * protection here so count values are only valid until the timer
3034              * overflows.  The guard against negative values is to protect
3035              * against suspect run time stat counter implementations - which
3036              * are provided by the application, not the kernel. */
3037             if( ulTotalRunTime > ulTaskSwitchedInTime )
3038             {
3039                 pxCurrentTCB->ulRunTimeCounter += ( ulTotalRunTime - ulTaskSwitchedInTime );
3040             }
3041             else
3042             {
3043                 mtCOVERAGE_TEST_MARKER();
3044             }
3045
3046             ulTaskSwitchedInTime = ulTotalRunTime;
3047         }
3048         #endif /* configGENERATE_RUN_TIME_STATS */
3049
3050         /* Check for stack overflow, if configured. */
3051         taskCHECK_FOR_STACK_OVERFLOW();
3052
3053         /* Before the currently running task is switched out, save its errno. */
3054         #if ( configUSE_POSIX_ERRNO == 1 )
3055         {
3056             pxCurrentTCB->iTaskErrno = FreeRTOS_errno;
3057         }
3058         #endif
3059
3060         /* Select a new task to run using either the generic C or port
3061          * optimised asm code. */
3062         taskSELECT_HIGHEST_PRIORITY_TASK(); /*lint !e9079 void * is used as this macro is used with timers too.  Alignment is known to be fine as the type of the pointer stored and retrieved is the same. */
3063         traceTASK_SWITCHED_IN();
3064
3065         /* After the new task is switched in, update the global errno. */
3066         #if ( configUSE_POSIX_ERRNO == 1 )
3067         {
3068             FreeRTOS_errno = pxCurrentTCB->iTaskErrno;
3069         }
3070         #endif
3071
3072         #if ( ( configUSE_NEWLIB_REENTRANT == 1 ) || ( configUSE_C_RUNTIME_TLS_SUPPORT == 1 ) )
3073         {
3074             /* Switch C-Runtime's TLS Block to point to the TLS
3075              * Block specific to this task. */
3076             configSET_TLS_BLOCK( pxCurrentTCB->xTLSBlock );
3077         }
3078         #endif
3079     }
3080 }
3081 /*-----------------------------------------------------------*/
3082
3083 void vTaskPlaceOnEventList( List_t * const pxEventList,
3084                             const TickType_t xTicksToWait )
3085 {
3086     configASSERT( pxEventList );
3087
3088     /* THIS FUNCTION MUST BE CALLED WITH EITHER INTERRUPTS DISABLED OR THE
3089      * SCHEDULER SUSPENDED AND THE QUEUE BEING ACCESSED LOCKED. */
3090
3091     /* Place the event list item of the TCB in the appropriate event list.
3092      * This is placed in the list in priority order so the highest priority task
3093      * is the first to be woken by the event.
3094      *
3095      * Note: Lists are sorted in ascending order by ListItem_t.xItemValue.
3096      * Normally, the xItemValue of a TCB's ListItem_t members is:
3097      *      xItemValue = ( configMAX_PRIORITIES - uxPriority )
3098      * Therefore, the event list is sorted in descending priority order.
3099      *
3100      * The queue that contains the event list is locked, preventing
3101      * simultaneous access from interrupts. */
3102     vListInsert( pxEventList, &( pxCurrentTCB->xEventListItem ) );
3103
3104     prvAddCurrentTaskToDelayedList( xTicksToWait, pdTRUE );
3105 }
3106 /*-----------------------------------------------------------*/
3107
3108 void vTaskPlaceOnUnorderedEventList( List_t * pxEventList,
3109                                      const TickType_t xItemValue,
3110                                      const TickType_t xTicksToWait )
3111 {
3112     configASSERT( pxEventList );
3113
3114     /* THIS FUNCTION MUST BE CALLED WITH THE SCHEDULER SUSPENDED.  It is used by
3115      * the event groups implementation. */
3116     configASSERT( uxSchedulerSuspended != 0 );
3117
3118     /* Store the item value in the event list item.  It is safe to access the
3119      * event list item here as interrupts won't access the event list item of a
3120      * task that is not in the Blocked state. */
3121     listSET_LIST_ITEM_VALUE( &( pxCurrentTCB->xEventListItem ), xItemValue | taskEVENT_LIST_ITEM_VALUE_IN_USE );
3122
3123     /* Place the event list item of the TCB at the end of the appropriate event
3124      * list.  It is safe to access the event list here because it is part of an
3125      * event group implementation - and interrupts don't access event groups
3126      * directly (instead they access them indirectly by pending function calls to
3127      * the task level). */
3128     listINSERT_END( pxEventList, &( pxCurrentTCB->xEventListItem ) );
3129
3130     prvAddCurrentTaskToDelayedList( xTicksToWait, pdTRUE );
3131 }
3132 /*-----------------------------------------------------------*/
3133
3134 #if ( configUSE_TIMERS == 1 )
3135
3136     void vTaskPlaceOnEventListRestricted( List_t * const pxEventList,
3137                                           TickType_t xTicksToWait,
3138                                           const BaseType_t xWaitIndefinitely )
3139     {
3140         configASSERT( pxEventList );
3141
3142         /* This function should not be called by application code hence the
3143          * 'Restricted' in its name.  It is not part of the public API.  It is
3144          * designed for use by kernel code, and has special calling requirements -
3145          * it should be called with the scheduler suspended. */
3146
3147
3148         /* Place the event list item of the TCB in the appropriate event list.
3149          * In this case it is assume that this is the only task that is going to
3150          * be waiting on this event list, so the faster vListInsertEnd() function
3151          * can be used in place of vListInsert. */
3152         listINSERT_END( pxEventList, &( pxCurrentTCB->xEventListItem ) );
3153
3154         /* If the task should block indefinitely then set the block time to a
3155          * value that will be recognised as an indefinite delay inside the
3156          * prvAddCurrentTaskToDelayedList() function. */
3157         if( xWaitIndefinitely != pdFALSE )
3158         {
3159             xTicksToWait = portMAX_DELAY;
3160         }
3161
3162         traceTASK_DELAY_UNTIL( ( xTickCount + xTicksToWait ) );
3163         prvAddCurrentTaskToDelayedList( xTicksToWait, xWaitIndefinitely );
3164     }
3165
3166 #endif /* configUSE_TIMERS */
3167 /*-----------------------------------------------------------*/
3168
3169 BaseType_t xTaskRemoveFromEventList( const List_t * const pxEventList )
3170 {
3171     TCB_t * pxUnblockedTCB;
3172     BaseType_t xReturn;
3173
3174     /* THIS FUNCTION MUST BE CALLED FROM A CRITICAL SECTION.  It can also be
3175      * called from a critical section within an ISR. */
3176
3177     /* The event list is sorted in priority order, so the first in the list can
3178      * be removed as it is known to be the highest priority.  Remove the TCB from
3179      * the delayed list, and add it to the ready list.
3180      *
3181      * If an event is for a queue that is locked then this function will never
3182      * get called - the lock count on the queue will get modified instead.  This
3183      * means exclusive access to the event list is guaranteed here.
3184      *
3185      * This function assumes that a check has already been made to ensure that
3186      * pxEventList is not empty. */
3187     pxUnblockedTCB = listGET_OWNER_OF_HEAD_ENTRY( pxEventList ); /*lint !e9079 void * is used as this macro is used with timers too.  Alignment is known to be fine as the type of the pointer stored and retrieved is the same. */
3188     configASSERT( pxUnblockedTCB );
3189     listREMOVE_ITEM( &( pxUnblockedTCB->xEventListItem ) );
3190
3191     if( uxSchedulerSuspended == ( UBaseType_t ) pdFALSE )
3192     {
3193         listREMOVE_ITEM( &( pxUnblockedTCB->xStateListItem ) );
3194         prvAddTaskToReadyList( pxUnblockedTCB );
3195
3196         #if ( configUSE_TICKLESS_IDLE != 0 )
3197         {
3198             /* If a task is blocked on a kernel object then xNextTaskUnblockTime
3199              * might be set to the blocked task's time out time.  If the task is
3200              * unblocked for a reason other than a timeout xNextTaskUnblockTime is
3201              * normally left unchanged, because it is automatically reset to a new
3202              * value when the tick count equals xNextTaskUnblockTime.  However if
3203              * tickless idling is used it might be more important to enter sleep mode
3204              * at the earliest possible time - so reset xNextTaskUnblockTime here to
3205              * ensure it is updated at the earliest possible time. */
3206             prvResetNextTaskUnblockTime();
3207         }
3208         #endif
3209     }
3210     else
3211     {
3212         /* The delayed and ready lists cannot be accessed, so hold this task
3213          * pending until the scheduler is resumed. */
3214         listINSERT_END( &( xPendingReadyList ), &( pxUnblockedTCB->xEventListItem ) );
3215     }
3216
3217     if( pxUnblockedTCB->uxPriority > pxCurrentTCB->uxPriority )
3218     {
3219         /* Return true if the task removed from the event list has a higher
3220          * priority than the calling task.  This allows the calling task to know if
3221          * it should force a context switch now. */
3222         xReturn = pdTRUE;
3223
3224         /* Mark that a yield is pending in case the user is not using the
3225          * "xHigherPriorityTaskWoken" parameter to an ISR safe FreeRTOS function. */
3226         xYieldPending = pdTRUE;
3227     }
3228     else
3229     {
3230         xReturn = pdFALSE;
3231     }
3232
3233     return xReturn;
3234 }
3235 /*-----------------------------------------------------------*/
3236
3237 void vTaskRemoveFromUnorderedEventList( ListItem_t * pxEventListItem,
3238                                         const TickType_t xItemValue )
3239 {
3240     TCB_t * pxUnblockedTCB;
3241
3242     /* THIS FUNCTION MUST BE CALLED WITH THE SCHEDULER SUSPENDED.  It is used by
3243      * the event flags implementation. */
3244     configASSERT( uxSchedulerSuspended != pdFALSE );
3245
3246     /* Store the new item value in the event list. */
3247     listSET_LIST_ITEM_VALUE( pxEventListItem, xItemValue | taskEVENT_LIST_ITEM_VALUE_IN_USE );
3248
3249     /* Remove the event list form the event flag.  Interrupts do not access
3250      * event flags. */
3251     pxUnblockedTCB = listGET_LIST_ITEM_OWNER( pxEventListItem ); /*lint !e9079 void * is used as this macro is used with timers too.  Alignment is known to be fine as the type of the pointer stored and retrieved is the same. */
3252     configASSERT( pxUnblockedTCB );
3253     listREMOVE_ITEM( pxEventListItem );
3254
3255     #if ( configUSE_TICKLESS_IDLE != 0 )
3256     {
3257         /* If a task is blocked on a kernel object then xNextTaskUnblockTime
3258          * might be set to the blocked task's time out time.  If the task is
3259          * unblocked for a reason other than a timeout xNextTaskUnblockTime is
3260          * normally left unchanged, because it is automatically reset to a new
3261          * value when the tick count equals xNextTaskUnblockTime.  However if
3262          * tickless idling is used it might be more important to enter sleep mode
3263          * at the earliest possible time - so reset xNextTaskUnblockTime here to
3264          * ensure it is updated at the earliest possible time. */
3265         prvResetNextTaskUnblockTime();
3266     }
3267     #endif
3268
3269     /* Remove the task from the delayed list and add it to the ready list.  The
3270      * scheduler is suspended so interrupts will not be accessing the ready
3271      * lists. */
3272     listREMOVE_ITEM( &( pxUnblockedTCB->xStateListItem ) );
3273     prvAddTaskToReadyList( pxUnblockedTCB );
3274
3275     if( pxUnblockedTCB->uxPriority > pxCurrentTCB->uxPriority )
3276     {
3277         /* The unblocked task has a priority above that of the calling task, so
3278          * a context switch is required.  This function is called with the
3279          * scheduler suspended so xYieldPending is set so the context switch
3280          * occurs immediately that the scheduler is resumed (unsuspended). */
3281         xYieldPending = pdTRUE;
3282     }
3283 }
3284 /*-----------------------------------------------------------*/
3285
3286 void vTaskSetTimeOutState( TimeOut_t * const pxTimeOut )
3287 {
3288     configASSERT( pxTimeOut );
3289     taskENTER_CRITICAL();
3290     {
3291         pxTimeOut->xOverflowCount = xNumOfOverflows;
3292         pxTimeOut->xTimeOnEntering = xTickCount;
3293     }
3294     taskEXIT_CRITICAL();
3295 }
3296 /*-----------------------------------------------------------*/
3297
3298 void vTaskInternalSetTimeOutState( TimeOut_t * const pxTimeOut )
3299 {
3300     /* For internal use only as it does not use a critical section. */
3301     pxTimeOut->xOverflowCount = xNumOfOverflows;
3302     pxTimeOut->xTimeOnEntering = xTickCount;
3303 }
3304 /*-----------------------------------------------------------*/
3305
3306 BaseType_t xTaskCheckForTimeOut( TimeOut_t * const pxTimeOut,
3307                                  TickType_t * const pxTicksToWait )
3308 {
3309     BaseType_t xReturn;
3310
3311     configASSERT( pxTimeOut );
3312     configASSERT( pxTicksToWait );
3313
3314     taskENTER_CRITICAL();
3315     {
3316         /* Minor optimisation.  The tick count cannot change in this block. */
3317         const TickType_t xConstTickCount = xTickCount;
3318         const TickType_t xElapsedTime = xConstTickCount - pxTimeOut->xTimeOnEntering;
3319
3320         #if ( INCLUDE_xTaskAbortDelay == 1 )
3321             if( pxCurrentTCB->ucDelayAborted != ( uint8_t ) pdFALSE )
3322             {
3323                 /* The delay was aborted, which is not the same as a time out,
3324                  * but has the same result. */
3325                 pxCurrentTCB->ucDelayAborted = pdFALSE;
3326                 xReturn = pdTRUE;
3327             }
3328             else
3329         #endif
3330
3331         #if ( INCLUDE_vTaskSuspend == 1 )
3332             if( *pxTicksToWait == portMAX_DELAY )
3333             {
3334                 /* If INCLUDE_vTaskSuspend is set to 1 and the block time
3335                  * specified is the maximum block time then the task should block
3336                  * indefinitely, and therefore never time out. */
3337                 xReturn = pdFALSE;
3338             }
3339             else
3340         #endif
3341
3342         if( ( xNumOfOverflows != pxTimeOut->xOverflowCount ) && ( xConstTickCount >= pxTimeOut->xTimeOnEntering ) ) /*lint !e525 Indentation preferred as is to make code within pre-processor directives clearer. */
3343         {
3344             /* The tick count is greater than the time at which
3345              * vTaskSetTimeout() was called, but has also overflowed since
3346              * vTaskSetTimeOut() was called.  It must have wrapped all the way
3347              * around and gone past again. This passed since vTaskSetTimeout()
3348              * was called. */
3349             xReturn = pdTRUE;
3350             *pxTicksToWait = ( TickType_t ) 0;
3351         }
3352         else if( xElapsedTime < *pxTicksToWait ) /*lint !e961 Explicit casting is only redundant with some compilers, whereas others require it to prevent integer conversion errors. */
3353         {
3354             /* Not a genuine timeout. Adjust parameters for time remaining. */
3355             *pxTicksToWait -= xElapsedTime;
3356             vTaskInternalSetTimeOutState( pxTimeOut );
3357             xReturn = pdFALSE;
3358         }
3359         else
3360         {
3361             *pxTicksToWait = ( TickType_t ) 0;
3362             xReturn = pdTRUE;
3363         }
3364     }
3365     taskEXIT_CRITICAL();
3366
3367     return xReturn;
3368 }
3369 /*-----------------------------------------------------------*/
3370
3371 void vTaskMissedYield( void )
3372 {
3373     xYieldPending = pdTRUE;
3374 }
3375 /*-----------------------------------------------------------*/
3376
3377 #if ( configUSE_TRACE_FACILITY == 1 )
3378
3379     UBaseType_t uxTaskGetTaskNumber( TaskHandle_t xTask )
3380     {
3381         UBaseType_t uxReturn;
3382         TCB_t const * pxTCB;
3383
3384         if( xTask != NULL )
3385         {
3386             pxTCB = xTask;
3387             uxReturn = pxTCB->uxTaskNumber;
3388         }
3389         else
3390         {
3391             uxReturn = 0U;
3392         }
3393
3394         return uxReturn;
3395     }
3396
3397 #endif /* configUSE_TRACE_FACILITY */
3398 /*-----------------------------------------------------------*/
3399
3400 #if ( configUSE_TRACE_FACILITY == 1 )
3401
3402     void vTaskSetTaskNumber( TaskHandle_t xTask,
3403                              const UBaseType_t uxHandle )
3404     {
3405         TCB_t * pxTCB;
3406
3407         if( xTask != NULL )
3408         {
3409             pxTCB = xTask;
3410             pxTCB->uxTaskNumber = uxHandle;
3411         }
3412     }
3413
3414 #endif /* configUSE_TRACE_FACILITY */
3415
3416 /*
3417  * -----------------------------------------------------------
3418  * The Idle task.
3419  * ----------------------------------------------------------
3420  *
3421  * The portTASK_FUNCTION() macro is used to allow port/compiler specific
3422  * language extensions.  The equivalent prototype for this function is:
3423  *
3424  * void prvIdleTask( void *pvParameters );
3425  *
3426  */
3427 static portTASK_FUNCTION( prvIdleTask, pvParameters )
3428 {
3429     /* Stop warnings. */
3430     ( void ) pvParameters;
3431
3432     /** THIS IS THE RTOS IDLE TASK - WHICH IS CREATED AUTOMATICALLY WHEN THE
3433      * SCHEDULER IS STARTED. **/
3434
3435     /* In case a task that has a secure context deletes itself, in which case
3436      * the idle task is responsible for deleting the task's secure context, if
3437      * any. */
3438     portALLOCATE_SECURE_CONTEXT( configMINIMAL_SECURE_STACK_SIZE );
3439
3440     for( ; ; )
3441     {
3442         /* See if any tasks have deleted themselves - if so then the idle task
3443          * is responsible for freeing the deleted task's TCB and stack. */
3444         prvCheckTasksWaitingTermination();
3445
3446         #if ( configUSE_PREEMPTION == 0 )
3447         {
3448             /* If we are not using preemption we keep forcing a task switch to
3449              * see if any other task has become available.  If we are using
3450              * preemption we don't need to do this as any task becoming available
3451              * will automatically get the processor anyway. */
3452             taskYIELD();
3453         }
3454         #endif /* configUSE_PREEMPTION */
3455
3456         #if ( ( configUSE_PREEMPTION == 1 ) && ( configIDLE_SHOULD_YIELD == 1 ) )
3457         {
3458             /* When using preemption tasks of equal priority will be
3459              * timesliced.  If a task that is sharing the idle priority is ready
3460              * to run then the idle task should yield before the end of the
3461              * timeslice.
3462              *
3463              * A critical region is not required here as we are just reading from
3464              * the list, and an occasional incorrect value will not matter.  If
3465              * the ready list at the idle priority contains more than one task
3466              * then a task other than the idle task is ready to execute. */
3467             if( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ tskIDLE_PRIORITY ] ) ) > ( UBaseType_t ) 1 )
3468             {
3469                 taskYIELD();
3470             }
3471             else
3472             {
3473                 mtCOVERAGE_TEST_MARKER();
3474             }
3475         }
3476         #endif /* ( ( configUSE_PREEMPTION == 1 ) && ( configIDLE_SHOULD_YIELD == 1 ) ) */
3477
3478         #if ( configUSE_IDLE_HOOK == 1 )
3479         {
3480             /* Call the user defined function from within the idle task. */
3481             vApplicationIdleHook();
3482         }
3483         #endif /* configUSE_IDLE_HOOK */
3484
3485         /* This conditional compilation should use inequality to 0, not equality
3486          * to 1.  This is to ensure portSUPPRESS_TICKS_AND_SLEEP() is called when
3487          * user defined low power mode  implementations require
3488          * configUSE_TICKLESS_IDLE to be set to a value other than 1. */
3489         #if ( configUSE_TICKLESS_IDLE != 0 )
3490         {
3491             TickType_t xExpectedIdleTime;
3492
3493             /* It is not desirable to suspend then resume the scheduler on
3494              * each iteration of the idle task.  Therefore, a preliminary
3495              * test of the expected idle time is performed without the
3496              * scheduler suspended.  The result here is not necessarily
3497              * valid. */
3498             xExpectedIdleTime = prvGetExpectedIdleTime();
3499
3500             if( xExpectedIdleTime >= configEXPECTED_IDLE_TIME_BEFORE_SLEEP )
3501             {
3502                 vTaskSuspendAll();
3503                 {
3504                     /* Now the scheduler is suspended, the expected idle
3505                      * time can be sampled again, and this time its value can
3506                      * be used. */
3507                     configASSERT( xNextTaskUnblockTime >= xTickCount );
3508                     xExpectedIdleTime = prvGetExpectedIdleTime();
3509
3510                     /* Define the following macro to set xExpectedIdleTime to 0
3511                      * if the application does not want
3512                      * portSUPPRESS_TICKS_AND_SLEEP() to be called. */
3513                     configPRE_SUPPRESS_TICKS_AND_SLEEP_PROCESSING( xExpectedIdleTime );
3514
3515                     if( xExpectedIdleTime >= configEXPECTED_IDLE_TIME_BEFORE_SLEEP )
3516                     {
3517                         traceLOW_POWER_IDLE_BEGIN();
3518                         portSUPPRESS_TICKS_AND_SLEEP( xExpectedIdleTime );
3519                         traceLOW_POWER_IDLE_END();
3520                     }
3521                     else
3522                     {
3523                         mtCOVERAGE_TEST_MARKER();
3524                     }
3525                 }
3526                 ( void ) xTaskResumeAll();
3527             }
3528             else
3529             {
3530                 mtCOVERAGE_TEST_MARKER();
3531             }
3532         }
3533         #endif /* configUSE_TICKLESS_IDLE */
3534     }
3535 }
3536 /*-----------------------------------------------------------*/
3537
3538 #if ( configUSE_TICKLESS_IDLE != 0 )
3539
3540     eSleepModeStatus eTaskConfirmSleepModeStatus( void )
3541     {
3542         #if ( INCLUDE_vTaskSuspend == 1 )
3543             /* The idle task exists in addition to the application tasks. */
3544             const UBaseType_t uxNonApplicationTasks = 1;
3545         #endif /* INCLUDE_vTaskSuspend */
3546
3547         eSleepModeStatus eReturn = eStandardSleep;
3548
3549         /* This function must be called from a critical section. */
3550
3551         if( listCURRENT_LIST_LENGTH( &xPendingReadyList ) != 0 )
3552         {
3553             /* A task was made ready while the scheduler was suspended. */
3554             eReturn = eAbortSleep;
3555         }
3556         else if( xYieldPending != pdFALSE )
3557         {
3558             /* A yield was pended while the scheduler was suspended. */
3559             eReturn = eAbortSleep;
3560         }
3561         else if( xPendedTicks != 0 )
3562         {
3563             /* A tick interrupt has already occurred but was held pending
3564              * because the scheduler is suspended. */
3565             eReturn = eAbortSleep;
3566         }
3567
3568         #if ( INCLUDE_vTaskSuspend == 1 )
3569             else if( listCURRENT_LIST_LENGTH( &xSuspendedTaskList ) == ( uxCurrentNumberOfTasks - uxNonApplicationTasks ) )
3570             {
3571                 /* If all the tasks are in the suspended list (which might mean they
3572                  * have an infinite block time rather than actually being suspended)
3573                  * then it is safe to turn all clocks off and just wait for external
3574                  * interrupts. */
3575                 eReturn = eNoTasksWaitingTimeout;
3576             }
3577         #endif /* INCLUDE_vTaskSuspend */
3578         else
3579         {
3580             mtCOVERAGE_TEST_MARKER();
3581         }
3582
3583         return eReturn;
3584     }
3585
3586 #endif /* configUSE_TICKLESS_IDLE */
3587 /*-----------------------------------------------------------*/
3588
3589 #if ( configNUM_THREAD_LOCAL_STORAGE_POINTERS != 0 )
3590
3591     void vTaskSetThreadLocalStoragePointer( TaskHandle_t xTaskToSet,
3592                                             BaseType_t xIndex,
3593                                             void * pvValue )
3594     {
3595         TCB_t * pxTCB;
3596
3597         if( ( xIndex >= 0 ) &&
3598             ( xIndex < configNUM_THREAD_LOCAL_STORAGE_POINTERS ) )
3599         {
3600             pxTCB = prvGetTCBFromHandle( xTaskToSet );
3601             configASSERT( pxTCB != NULL );
3602             pxTCB->pvThreadLocalStoragePointers[ xIndex ] = pvValue;
3603         }
3604     }
3605
3606 #endif /* configNUM_THREAD_LOCAL_STORAGE_POINTERS */
3607 /*-----------------------------------------------------------*/
3608
3609 #if ( configNUM_THREAD_LOCAL_STORAGE_POINTERS != 0 )
3610
3611     void * pvTaskGetThreadLocalStoragePointer( TaskHandle_t xTaskToQuery,
3612                                                BaseType_t xIndex )
3613     {
3614         void * pvReturn = NULL;
3615         TCB_t * pxTCB;
3616
3617         if( ( xIndex >= 0 ) &&
3618             ( xIndex < configNUM_THREAD_LOCAL_STORAGE_POINTERS ) )
3619         {
3620             pxTCB = prvGetTCBFromHandle( xTaskToQuery );
3621             pvReturn = pxTCB->pvThreadLocalStoragePointers[ xIndex ];
3622         }
3623         else
3624         {
3625             pvReturn = NULL;
3626         }
3627
3628         return pvReturn;
3629     }
3630
3631 #endif /* configNUM_THREAD_LOCAL_STORAGE_POINTERS */
3632 /*-----------------------------------------------------------*/
3633
3634 #if ( portUSING_MPU_WRAPPERS == 1 )
3635
3636     void vTaskAllocateMPURegions( TaskHandle_t xTaskToModify,
3637                                   const MemoryRegion_t * const xRegions )
3638     {
3639         TCB_t * pxTCB;
3640
3641         /* If null is passed in here then we are modifying the MPU settings of
3642          * the calling task. */
3643         pxTCB = prvGetTCBFromHandle( xTaskToModify );
3644
3645         vPortStoreTaskMPUSettings( &( pxTCB->xMPUSettings ), xRegions, NULL, 0 );
3646     }
3647
3648 #endif /* portUSING_MPU_WRAPPERS */
3649 /*-----------------------------------------------------------*/
3650
3651 static void prvInitialiseTaskLists( void )
3652 {
3653     UBaseType_t uxPriority;
3654
3655     for( uxPriority = ( UBaseType_t ) 0U; uxPriority < ( UBaseType_t ) configMAX_PRIORITIES; uxPriority++ )
3656     {
3657         vListInitialise( &( pxReadyTasksLists[ uxPriority ] ) );
3658     }
3659
3660     vListInitialise( &xDelayedTaskList1 );
3661     vListInitialise( &xDelayedTaskList2 );
3662     vListInitialise( &xPendingReadyList );
3663
3664     #if ( INCLUDE_vTaskDelete == 1 )
3665     {
3666         vListInitialise( &xTasksWaitingTermination );
3667     }
3668     #endif /* INCLUDE_vTaskDelete */
3669
3670     #if ( INCLUDE_vTaskSuspend == 1 )
3671     {
3672         vListInitialise( &xSuspendedTaskList );
3673     }
3674     #endif /* INCLUDE_vTaskSuspend */
3675
3676     /* Start with pxDelayedTaskList using list1 and the pxOverflowDelayedTaskList
3677      * using list2. */
3678     pxDelayedTaskList = &xDelayedTaskList1;
3679     pxOverflowDelayedTaskList = &xDelayedTaskList2;
3680 }
3681 /*-----------------------------------------------------------*/
3682
3683 static void prvCheckTasksWaitingTermination( void )
3684 {
3685     /** THIS FUNCTION IS CALLED FROM THE RTOS IDLE TASK **/
3686
3687     #if ( INCLUDE_vTaskDelete == 1 )
3688     {
3689         TCB_t * pxTCB;
3690
3691         /* uxDeletedTasksWaitingCleanUp is used to prevent taskENTER_CRITICAL()
3692          * being called too often in the idle task. */
3693         while( uxDeletedTasksWaitingCleanUp > ( UBaseType_t ) 0U )
3694         {
3695             taskENTER_CRITICAL();
3696             {
3697                 pxTCB = listGET_OWNER_OF_HEAD_ENTRY( ( &xTasksWaitingTermination ) ); /*lint !e9079 void * is used as this macro is used with timers too.  Alignment is known to be fine as the type of the pointer stored and retrieved is the same. */
3698                 ( void ) uxListRemove( &( pxTCB->xStateListItem ) );
3699                 --uxCurrentNumberOfTasks;
3700                 --uxDeletedTasksWaitingCleanUp;
3701             }
3702             taskEXIT_CRITICAL();
3703
3704             prvDeleteTCB( pxTCB );
3705         }
3706     }
3707     #endif /* INCLUDE_vTaskDelete */
3708 }
3709 /*-----------------------------------------------------------*/
3710
3711 #if ( configUSE_TRACE_FACILITY == 1 )
3712
3713     void vTaskGetInfo( TaskHandle_t xTask,
3714                        TaskStatus_t * pxTaskStatus,
3715                        BaseType_t xGetFreeStackSpace,
3716                        eTaskState eState )
3717     {
3718         TCB_t * pxTCB;
3719
3720         /* xTask is NULL then get the state of the calling task. */
3721         pxTCB = prvGetTCBFromHandle( xTask );
3722
3723         pxTaskStatus->xHandle = ( TaskHandle_t ) pxTCB;
3724         pxTaskStatus->pcTaskName = ( const char * ) &( pxTCB->pcTaskName[ 0 ] );
3725         pxTaskStatus->uxCurrentPriority = pxTCB->uxPriority;
3726         pxTaskStatus->pxStackBase = pxTCB->pxStack;
3727         #if ( ( portSTACK_GROWTH > 0 ) && ( configRECORD_STACK_HIGH_ADDRESS == 1 ) )
3728             pxTaskStatus->pxTopOfStack = pxTCB->pxTopOfStack;
3729             pxTaskStatus->pxEndOfStack = pxTCB->pxEndOfStack;
3730         #endif
3731         pxTaskStatus->xTaskNumber = pxTCB->uxTCBNumber;
3732
3733         #if ( configUSE_MUTEXES == 1 )
3734         {
3735             pxTaskStatus->uxBasePriority = pxTCB->uxBasePriority;
3736         }
3737         #else
3738         {
3739             pxTaskStatus->uxBasePriority = 0;
3740         }
3741         #endif
3742
3743         #if ( configGENERATE_RUN_TIME_STATS == 1 )
3744         {
3745             pxTaskStatus->ulRunTimeCounter = pxTCB->ulRunTimeCounter;
3746         }
3747         #else
3748         {
3749             pxTaskStatus->ulRunTimeCounter = ( configRUN_TIME_COUNTER_TYPE ) 0;
3750         }
3751         #endif
3752
3753         /* Obtaining the task state is a little fiddly, so is only done if the
3754          * value of eState passed into this function is eInvalid - otherwise the
3755          * state is just set to whatever is passed in. */
3756         if( eState != eInvalid )
3757         {
3758             if( pxTCB == pxCurrentTCB )
3759             {
3760                 pxTaskStatus->eCurrentState = eRunning;
3761             }
3762             else
3763             {
3764                 pxTaskStatus->eCurrentState = eState;
3765
3766                 #if ( INCLUDE_vTaskSuspend == 1 )
3767                 {
3768                     /* If the task is in the suspended list then there is a
3769                      *  chance it is actually just blocked indefinitely - so really
3770                      *  it should be reported as being in the Blocked state. */
3771                     if( eState == eSuspended )
3772                     {
3773                         vTaskSuspendAll();
3774                         {
3775                             if( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) != NULL )
3776                             {
3777                                 pxTaskStatus->eCurrentState = eBlocked;
3778                             }
3779                         }
3780                         ( void ) xTaskResumeAll();
3781                     }
3782                 }
3783                 #endif /* INCLUDE_vTaskSuspend */
3784             }
3785         }
3786         else
3787         {
3788             pxTaskStatus->eCurrentState = eTaskGetState( pxTCB );
3789         }
3790
3791         /* Obtaining the stack space takes some time, so the xGetFreeStackSpace
3792          * parameter is provided to allow it to be skipped. */
3793         if( xGetFreeStackSpace != pdFALSE )
3794         {
3795             #if ( portSTACK_GROWTH > 0 )
3796             {
3797                 pxTaskStatus->usStackHighWaterMark = prvTaskCheckFreeStackSpace( ( uint8_t * ) pxTCB->pxEndOfStack );
3798             }
3799             #else
3800             {
3801                 pxTaskStatus->usStackHighWaterMark = prvTaskCheckFreeStackSpace( ( uint8_t * ) pxTCB->pxStack );
3802             }
3803             #endif
3804         }
3805         else
3806         {
3807             pxTaskStatus->usStackHighWaterMark = 0;
3808         }
3809     }
3810
3811 #endif /* configUSE_TRACE_FACILITY */
3812 /*-----------------------------------------------------------*/
3813
3814 #if ( configUSE_TRACE_FACILITY == 1 )
3815
3816     static UBaseType_t prvListTasksWithinSingleList( TaskStatus_t * pxTaskStatusArray,
3817                                                      List_t * pxList,
3818                                                      eTaskState eState )
3819     {
3820         configLIST_VOLATILE TCB_t * pxNextTCB;
3821         configLIST_VOLATILE TCB_t * pxFirstTCB;
3822         UBaseType_t uxTask = 0;
3823
3824         if( listCURRENT_LIST_LENGTH( pxList ) > ( UBaseType_t ) 0 )
3825         {
3826             listGET_OWNER_OF_NEXT_ENTRY( pxFirstTCB, pxList ); /*lint !e9079 void * is used as this macro is used with timers too.  Alignment is known to be fine as the type of the pointer stored and retrieved is the same. */
3827
3828             /* Populate an TaskStatus_t structure within the
3829              * pxTaskStatusArray array for each task that is referenced from
3830              * pxList.  See the definition of TaskStatus_t in task.h for the
3831              * meaning of each TaskStatus_t structure member. */
3832             do
3833             {
3834                 listGET_OWNER_OF_NEXT_ENTRY( pxNextTCB, pxList ); /*lint !e9079 void * is used as this macro is used with timers too.  Alignment is known to be fine as the type of the pointer stored and retrieved is the same. */
3835                 vTaskGetInfo( ( TaskHandle_t ) pxNextTCB, &( pxTaskStatusArray[ uxTask ] ), pdTRUE, eState );
3836                 uxTask++;
3837             } while( pxNextTCB != pxFirstTCB );
3838         }
3839         else
3840         {
3841             mtCOVERAGE_TEST_MARKER();
3842         }
3843
3844         return uxTask;
3845     }
3846
3847 #endif /* configUSE_TRACE_FACILITY */
3848 /*-----------------------------------------------------------*/
3849
3850 #if ( ( configUSE_TRACE_FACILITY == 1 ) || ( INCLUDE_uxTaskGetStackHighWaterMark == 1 ) || ( INCLUDE_uxTaskGetStackHighWaterMark2 == 1 ) )
3851
3852     static configSTACK_DEPTH_TYPE prvTaskCheckFreeStackSpace( const uint8_t * pucStackByte )
3853     {
3854         uint32_t ulCount = 0U;
3855
3856         while( *pucStackByte == ( uint8_t ) tskSTACK_FILL_BYTE )
3857         {
3858             pucStackByte -= portSTACK_GROWTH;
3859             ulCount++;
3860         }
3861
3862         ulCount /= ( uint32_t ) sizeof( StackType_t ); /*lint !e961 Casting is not redundant on smaller architectures. */
3863
3864         return ( configSTACK_DEPTH_TYPE ) ulCount;
3865     }
3866
3867 #endif /* ( ( configUSE_TRACE_FACILITY == 1 ) || ( INCLUDE_uxTaskGetStackHighWaterMark == 1 ) || ( INCLUDE_uxTaskGetStackHighWaterMark2 == 1 ) ) */
3868 /*-----------------------------------------------------------*/
3869
3870 #if ( INCLUDE_uxTaskGetStackHighWaterMark2 == 1 )
3871
3872 /* uxTaskGetStackHighWaterMark() and uxTaskGetStackHighWaterMark2() are the
3873  * same except for their return type.  Using configSTACK_DEPTH_TYPE allows the
3874  * user to determine the return type.  It gets around the problem of the value
3875  * overflowing on 8-bit types without breaking backward compatibility for
3876  * applications that expect an 8-bit return type. */
3877     configSTACK_DEPTH_TYPE uxTaskGetStackHighWaterMark2( TaskHandle_t xTask )
3878     {
3879         TCB_t * pxTCB;
3880         uint8_t * pucEndOfStack;
3881         configSTACK_DEPTH_TYPE uxReturn;
3882
3883         /* uxTaskGetStackHighWaterMark() and uxTaskGetStackHighWaterMark2() are
3884          * the same except for their return type.  Using configSTACK_DEPTH_TYPE
3885          * allows the user to determine the return type.  It gets around the
3886          * problem of the value overflowing on 8-bit types without breaking
3887          * backward compatibility for applications that expect an 8-bit return
3888          * type. */
3889
3890         pxTCB = prvGetTCBFromHandle( xTask );
3891
3892         #if portSTACK_GROWTH < 0
3893         {
3894             pucEndOfStack = ( uint8_t * ) pxTCB->pxStack;
3895         }
3896         #else
3897         {
3898             pucEndOfStack = ( uint8_t * ) pxTCB->pxEndOfStack;
3899         }
3900         #endif
3901
3902         uxReturn = prvTaskCheckFreeStackSpace( pucEndOfStack );
3903
3904         return uxReturn;
3905     }
3906
3907 #endif /* INCLUDE_uxTaskGetStackHighWaterMark2 */
3908 /*-----------------------------------------------------------*/
3909
3910 #if ( INCLUDE_uxTaskGetStackHighWaterMark == 1 )
3911
3912     UBaseType_t uxTaskGetStackHighWaterMark( TaskHandle_t xTask )
3913     {
3914         TCB_t * pxTCB;
3915         uint8_t * pucEndOfStack;
3916         UBaseType_t uxReturn;
3917
3918         pxTCB = prvGetTCBFromHandle( xTask );
3919
3920         #if portSTACK_GROWTH < 0
3921         {
3922             pucEndOfStack = ( uint8_t * ) pxTCB->pxStack;
3923         }
3924         #else
3925         {
3926             pucEndOfStack = ( uint8_t * ) pxTCB->pxEndOfStack;
3927         }
3928         #endif
3929
3930         uxReturn = ( UBaseType_t ) prvTaskCheckFreeStackSpace( pucEndOfStack );
3931
3932         return uxReturn;
3933     }
3934
3935 #endif /* INCLUDE_uxTaskGetStackHighWaterMark */
3936 /*-----------------------------------------------------------*/
3937
3938 #if ( INCLUDE_vTaskDelete == 1 )
3939
3940     static void prvDeleteTCB( TCB_t * pxTCB )
3941     {
3942         /* This call is required specifically for the TriCore port.  It must be
3943          * above the vPortFree() calls.  The call is also used by ports/demos that
3944          * want to allocate and clean RAM statically. */
3945         portCLEAN_UP_TCB( pxTCB );
3946
3947         #if ( ( configUSE_NEWLIB_REENTRANT == 1 ) || ( configUSE_C_RUNTIME_TLS_SUPPORT == 1 ) )
3948         {
3949             /* Free up the memory allocated for the task's TLS Block. */
3950             configDEINIT_TLS_BLOCK( pxCurrentTCB->xTLSBlock );
3951         }
3952         #endif
3953
3954         #if ( ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 0 ) && ( portUSING_MPU_WRAPPERS == 0 ) )
3955         {
3956             /* The task can only have been allocated dynamically - free both
3957              * the stack and TCB. */
3958             vPortFreeStack( pxTCB->pxStack );
3959             vPortFree( pxTCB );
3960         }
3961         #elif ( tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE != 0 ) /*lint !e731 !e9029 Macro has been consolidated for readability reasons. */
3962         {
3963             /* The task could have been allocated statically or dynamically, so
3964              * check what was statically allocated before trying to free the
3965              * memory. */
3966             if( pxTCB->ucStaticallyAllocated == tskDYNAMICALLY_ALLOCATED_STACK_AND_TCB )
3967             {
3968                 /* Both the stack and TCB were allocated dynamically, so both
3969                  * must be freed. */
3970                 vPortFreeStack( pxTCB->pxStack );
3971                 vPortFree( pxTCB );
3972             }
3973             else if( pxTCB->ucStaticallyAllocated == tskSTATICALLY_ALLOCATED_STACK_ONLY )
3974             {
3975                 /* Only the stack was statically allocated, so the TCB is the
3976                  * only memory that must be freed. */
3977                 vPortFree( pxTCB );
3978             }
3979             else
3980             {
3981                 /* Neither the stack nor the TCB were allocated dynamically, so
3982                  * nothing needs to be freed. */
3983                 configASSERT( pxTCB->ucStaticallyAllocated == tskSTATICALLY_ALLOCATED_STACK_AND_TCB );
3984                 mtCOVERAGE_TEST_MARKER();
3985             }
3986         }
3987         #endif /* configSUPPORT_DYNAMIC_ALLOCATION */
3988     }
3989
3990 #endif /* INCLUDE_vTaskDelete */
3991 /*-----------------------------------------------------------*/
3992
3993 static void prvResetNextTaskUnblockTime( void )
3994 {
3995     if( listLIST_IS_EMPTY( pxDelayedTaskList ) != pdFALSE )
3996     {
3997         /* The new current delayed list is empty.  Set xNextTaskUnblockTime to
3998          * the maximum possible value so it is  extremely unlikely that the
3999          * if( xTickCount >= xNextTaskUnblockTime ) test will pass until
4000          * there is an item in the delayed list. */
4001         xNextTaskUnblockTime = portMAX_DELAY;
4002     }
4003     else
4004     {
4005         /* The new current delayed list is not empty, get the value of
4006          * the item at the head of the delayed list.  This is the time at
4007          * which the task at the head of the delayed list should be removed
4008          * from the Blocked state. */
4009         xNextTaskUnblockTime = listGET_ITEM_VALUE_OF_HEAD_ENTRY( pxDelayedTaskList );
4010     }
4011 }
4012 /*-----------------------------------------------------------*/
4013
4014 #if ( ( INCLUDE_xTaskGetCurrentTaskHandle == 1 ) || ( configUSE_MUTEXES == 1 ) )
4015
4016     TaskHandle_t xTaskGetCurrentTaskHandle( void )
4017     {
4018         TaskHandle_t xReturn;
4019
4020         /* A critical section is not required as this is not called from
4021          * an interrupt and the current TCB will always be the same for any
4022          * individual execution thread. */
4023         xReturn = pxCurrentTCB;
4024
4025         return xReturn;
4026     }
4027
4028 #endif /* ( ( INCLUDE_xTaskGetCurrentTaskHandle == 1 ) || ( configUSE_MUTEXES == 1 ) ) */
4029 /*-----------------------------------------------------------*/
4030
4031 #if ( ( INCLUDE_xTaskGetSchedulerState == 1 ) || ( configUSE_TIMERS == 1 ) )
4032
4033     BaseType_t xTaskGetSchedulerState( void )
4034     {
4035         BaseType_t xReturn;
4036
4037         if( xSchedulerRunning == pdFALSE )
4038         {
4039             xReturn = taskSCHEDULER_NOT_STARTED;
4040         }
4041         else
4042         {
4043             if( uxSchedulerSuspended == ( UBaseType_t ) pdFALSE )
4044             {
4045                 xReturn = taskSCHEDULER_RUNNING;
4046             }
4047             else
4048             {
4049                 xReturn = taskSCHEDULER_SUSPENDED;
4050             }
4051         }
4052
4053         return xReturn;
4054     }
4055
4056 #endif /* ( ( INCLUDE_xTaskGetSchedulerState == 1 ) || ( configUSE_TIMERS == 1 ) ) */
4057 /*-----------------------------------------------------------*/
4058
4059 #if ( configUSE_MUTEXES == 1 )
4060
4061     BaseType_t xTaskPriorityInherit( TaskHandle_t const pxMutexHolder )
4062     {
4063         TCB_t * const pxMutexHolderTCB = pxMutexHolder;
4064         BaseType_t xReturn = pdFALSE;
4065
4066         /* If the mutex was given back by an interrupt while the queue was
4067          * locked then the mutex holder might now be NULL.  _RB_ Is this still
4068          * needed as interrupts can no longer use mutexes? */
4069         if( pxMutexHolder != NULL )
4070         {
4071             /* If the holder of the mutex has a priority below the priority of
4072              * the task attempting to obtain the mutex then it will temporarily
4073              * inherit the priority of the task attempting to obtain the mutex. */
4074             if( pxMutexHolderTCB->uxPriority < pxCurrentTCB->uxPriority )
4075             {
4076                 /* Adjust the mutex holder state to account for its new
4077                  * priority.  Only reset the event list item value if the value is
4078                  * not being used for anything else. */
4079                 if( ( listGET_LIST_ITEM_VALUE( &( pxMutexHolderTCB->xEventListItem ) ) & taskEVENT_LIST_ITEM_VALUE_IN_USE ) == 0UL )
4080                 {
4081                     listSET_LIST_ITEM_VALUE( &( pxMutexHolderTCB->xEventListItem ), ( TickType_t ) configMAX_PRIORITIES - ( TickType_t ) pxCurrentTCB->uxPriority ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */
4082                 }
4083                 else
4084                 {
4085                     mtCOVERAGE_TEST_MARKER();
4086                 }
4087
4088                 /* If the task being modified is in the ready state it will need
4089                  * to be moved into a new list. */
4090                 if( listIS_CONTAINED_WITHIN( &( pxReadyTasksLists[ pxMutexHolderTCB->uxPriority ] ), &( pxMutexHolderTCB->xStateListItem ) ) != pdFALSE )
4091                 {
4092                     if( uxListRemove( &( pxMutexHolderTCB->xStateListItem ) ) == ( UBaseType_t ) 0 )
4093                     {
4094                         /* It is known that the task is in its ready list so
4095                          * there is no need to check again and the port level
4096                          * reset macro can be called directly. */
4097                         portRESET_READY_PRIORITY( pxMutexHolderTCB->uxPriority, uxTopReadyPriority );
4098                     }
4099                     else
4100                     {
4101                         mtCOVERAGE_TEST_MARKER();
4102                     }
4103
4104                     /* Inherit the priority before being moved into the new list. */
4105                     pxMutexHolderTCB->uxPriority = pxCurrentTCB->uxPriority;
4106                     prvAddTaskToReadyList( pxMutexHolderTCB );
4107                 }
4108                 else
4109                 {
4110                     /* Just inherit the priority. */
4111                     pxMutexHolderTCB->uxPriority = pxCurrentTCB->uxPriority;
4112                 }
4113
4114                 traceTASK_PRIORITY_INHERIT( pxMutexHolderTCB, pxCurrentTCB->uxPriority );
4115
4116                 /* Inheritance occurred. */
4117                 xReturn = pdTRUE;
4118             }
4119             else
4120             {
4121                 if( pxMutexHolderTCB->uxBasePriority < pxCurrentTCB->uxPriority )
4122                 {
4123                     /* The base priority of the mutex holder is lower than the
4124                      * priority of the task attempting to take the mutex, but the
4125                      * current priority of the mutex holder is not lower than the
4126                      * priority of the task attempting to take the mutex.
4127                      * Therefore the mutex holder must have already inherited a
4128                      * priority, but inheritance would have occurred if that had
4129                      * not been the case. */
4130                     xReturn = pdTRUE;
4131                 }
4132                 else
4133                 {
4134                     mtCOVERAGE_TEST_MARKER();
4135                 }
4136             }
4137         }
4138         else
4139         {
4140             mtCOVERAGE_TEST_MARKER();
4141         }
4142
4143         return xReturn;
4144     }
4145
4146 #endif /* configUSE_MUTEXES */
4147 /*-----------------------------------------------------------*/
4148
4149 #if ( configUSE_MUTEXES == 1 )
4150
4151     BaseType_t xTaskPriorityDisinherit( TaskHandle_t const pxMutexHolder )
4152     {
4153         TCB_t * const pxTCB = pxMutexHolder;
4154         BaseType_t xReturn = pdFALSE;
4155
4156         if( pxMutexHolder != NULL )
4157         {
4158             /* A task can only have an inherited priority if it holds the mutex.
4159              * If the mutex is held by a task then it cannot be given from an
4160              * interrupt, and if a mutex is given by the holding task then it must
4161              * be the running state task. */
4162             configASSERT( pxTCB == pxCurrentTCB );
4163             configASSERT( pxTCB->uxMutexesHeld );
4164             ( pxTCB->uxMutexesHeld )--;
4165
4166             /* Has the holder of the mutex inherited the priority of another
4167              * task? */
4168             if( pxTCB->uxPriority != pxTCB->uxBasePriority )
4169             {
4170                 /* Only disinherit if no other mutexes are held. */
4171                 if( pxTCB->uxMutexesHeld == ( UBaseType_t ) 0 )
4172                 {
4173                     /* A task can only have an inherited priority if it holds
4174                      * the mutex.  If the mutex is held by a task then it cannot be
4175                      * given from an interrupt, and if a mutex is given by the
4176                      * holding task then it must be the running state task.  Remove
4177                      * the holding task from the ready list. */
4178                     if( uxListRemove( &( pxTCB->xStateListItem ) ) == ( UBaseType_t ) 0 )
4179                     {
4180                         portRESET_READY_PRIORITY( pxTCB->uxPriority, uxTopReadyPriority );
4181                     }
4182                     else
4183                     {
4184                         mtCOVERAGE_TEST_MARKER();
4185                     }
4186
4187                     /* Disinherit the priority before adding the task into the
4188                      * new  ready list. */
4189                     traceTASK_PRIORITY_DISINHERIT( pxTCB, pxTCB->uxBasePriority );
4190                     pxTCB->uxPriority = pxTCB->uxBasePriority;
4191
4192                     /* Reset the event list item value.  It cannot be in use for
4193                      * any other purpose if this task is running, and it must be
4194                      * running to give back the mutex. */
4195                     listSET_LIST_ITEM_VALUE( &( pxTCB->xEventListItem ), ( TickType_t ) configMAX_PRIORITIES - ( TickType_t ) pxTCB->uxPriority ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */
4196                     prvAddTaskToReadyList( pxTCB );
4197
4198                     /* Return true to indicate that a context switch is required.
4199                      * This is only actually required in the corner case whereby
4200                      * multiple mutexes were held and the mutexes were given back
4201                      * in an order different to that in which they were taken.
4202                      * If a context switch did not occur when the first mutex was
4203                      * returned, even if a task was waiting on it, then a context
4204                      * switch should occur when the last mutex is returned whether
4205                      * a task is waiting on it or not. */
4206                     xReturn = pdTRUE;
4207                 }
4208                 else
4209                 {
4210                     mtCOVERAGE_TEST_MARKER();
4211                 }
4212             }
4213             else
4214             {
4215                 mtCOVERAGE_TEST_MARKER();
4216             }
4217         }
4218         else
4219         {
4220             mtCOVERAGE_TEST_MARKER();
4221         }
4222
4223         return xReturn;
4224     }
4225
4226 #endif /* configUSE_MUTEXES */
4227 /*-----------------------------------------------------------*/
4228
4229 #if ( configUSE_MUTEXES == 1 )
4230
4231     void vTaskPriorityDisinheritAfterTimeout( TaskHandle_t const pxMutexHolder,
4232                                               UBaseType_t uxHighestPriorityWaitingTask )
4233     {
4234         TCB_t * const pxTCB = pxMutexHolder;
4235         UBaseType_t uxPriorityUsedOnEntry, uxPriorityToUse;
4236         const UBaseType_t uxOnlyOneMutexHeld = ( UBaseType_t ) 1;
4237
4238         if( pxMutexHolder != NULL )
4239         {
4240             /* If pxMutexHolder is not NULL then the holder must hold at least
4241              * one mutex. */
4242             configASSERT( pxTCB->uxMutexesHeld );
4243
4244             /* Determine the priority to which the priority of the task that
4245              * holds the mutex should be set.  This will be the greater of the
4246              * holding task's base priority and the priority of the highest
4247              * priority task that is waiting to obtain the mutex. */
4248             if( pxTCB->uxBasePriority < uxHighestPriorityWaitingTask )
4249             {
4250                 uxPriorityToUse = uxHighestPriorityWaitingTask;
4251             }
4252             else
4253             {
4254                 uxPriorityToUse = pxTCB->uxBasePriority;
4255             }
4256
4257             /* Does the priority need to change? */
4258             if( pxTCB->uxPriority != uxPriorityToUse )
4259             {
4260                 /* Only disinherit if no other mutexes are held.  This is a
4261                  * simplification in the priority inheritance implementation.  If
4262                  * the task that holds the mutex is also holding other mutexes then
4263                  * the other mutexes may have caused the priority inheritance. */
4264                 if( pxTCB->uxMutexesHeld == uxOnlyOneMutexHeld )
4265                 {
4266                     /* If a task has timed out because it already holds the
4267                      * mutex it was trying to obtain then it cannot of inherited
4268                      * its own priority. */
4269                     configASSERT( pxTCB != pxCurrentTCB );
4270
4271                     /* Disinherit the priority, remembering the previous
4272                      * priority to facilitate determining the subject task's
4273                      * state. */
4274                     traceTASK_PRIORITY_DISINHERIT( pxTCB, uxPriorityToUse );
4275                     uxPriorityUsedOnEntry = pxTCB->uxPriority;
4276                     pxTCB->uxPriority = uxPriorityToUse;
4277
4278                     /* Only reset the event list item value if the value is not
4279                      * being used for anything else. */
4280                     if( ( listGET_LIST_ITEM_VALUE( &( pxTCB->xEventListItem ) ) & taskEVENT_LIST_ITEM_VALUE_IN_USE ) == 0UL )
4281                     {
4282                         listSET_LIST_ITEM_VALUE( &( pxTCB->xEventListItem ), ( TickType_t ) configMAX_PRIORITIES - ( TickType_t ) uxPriorityToUse ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */
4283                     }
4284                     else
4285                     {
4286                         mtCOVERAGE_TEST_MARKER();
4287                     }
4288
4289                     /* If the running task is not the task that holds the mutex
4290                      * then the task that holds the mutex could be in either the
4291                      * Ready, Blocked or Suspended states.  Only remove the task
4292                      * from its current state list if it is in the Ready state as
4293                      * the task's priority is going to change and there is one
4294                      * Ready list per priority. */
4295                     if( listIS_CONTAINED_WITHIN( &( pxReadyTasksLists[ uxPriorityUsedOnEntry ] ), &( pxTCB->xStateListItem ) ) != pdFALSE )
4296                     {
4297                         if( uxListRemove( &( pxTCB->xStateListItem ) ) == ( UBaseType_t ) 0 )
4298                         {
4299                             /* It is known that the task is in its ready list so
4300                              * there is no need to check again and the port level
4301                              * reset macro can be called directly. */
4302                             portRESET_READY_PRIORITY( pxTCB->uxPriority, uxTopReadyPriority );
4303                         }
4304                         else
4305                         {
4306                             mtCOVERAGE_TEST_MARKER();
4307                         }
4308
4309                         prvAddTaskToReadyList( pxTCB );
4310                     }
4311                     else
4312                     {
4313                         mtCOVERAGE_TEST_MARKER();
4314                     }
4315                 }
4316                 else
4317                 {
4318                     mtCOVERAGE_TEST_MARKER();
4319                 }
4320             }
4321             else
4322             {
4323                 mtCOVERAGE_TEST_MARKER();
4324             }
4325         }
4326         else
4327         {
4328             mtCOVERAGE_TEST_MARKER();
4329         }
4330     }
4331
4332 #endif /* configUSE_MUTEXES */
4333 /*-----------------------------------------------------------*/
4334
4335 #if ( portCRITICAL_NESTING_IN_TCB == 1 )
4336
4337     void vTaskEnterCritical( void )
4338     {
4339         portDISABLE_INTERRUPTS();
4340
4341         if( xSchedulerRunning != pdFALSE )
4342         {
4343             ( pxCurrentTCB->uxCriticalNesting )++;
4344
4345             /* This is not the interrupt safe version of the enter critical
4346              * function so  assert() if it is being called from an interrupt
4347              * context.  Only API functions that end in "FromISR" can be used in an
4348              * interrupt.  Only assert if the critical nesting count is 1 to
4349              * protect against recursive calls if the assert function also uses a
4350              * critical section. */
4351             if( pxCurrentTCB->uxCriticalNesting == 1 )
4352             {
4353                 portASSERT_IF_IN_ISR();
4354             }
4355         }
4356         else
4357         {
4358             mtCOVERAGE_TEST_MARKER();
4359         }
4360     }
4361
4362 #endif /* portCRITICAL_NESTING_IN_TCB */
4363 /*-----------------------------------------------------------*/
4364
4365 #if ( portCRITICAL_NESTING_IN_TCB == 1 )
4366
4367     void vTaskExitCritical( void )
4368     {
4369         if( xSchedulerRunning != pdFALSE )
4370         {
4371             if( pxCurrentTCB->uxCriticalNesting > 0U )
4372             {
4373                 ( pxCurrentTCB->uxCriticalNesting )--;
4374
4375                 if( pxCurrentTCB->uxCriticalNesting == 0U )
4376                 {
4377                     portENABLE_INTERRUPTS();
4378                 }
4379                 else
4380                 {
4381                     mtCOVERAGE_TEST_MARKER();
4382                 }
4383             }
4384             else
4385             {
4386                 mtCOVERAGE_TEST_MARKER();
4387             }
4388         }
4389         else
4390         {
4391             mtCOVERAGE_TEST_MARKER();
4392         }
4393     }
4394
4395 #endif /* portCRITICAL_NESTING_IN_TCB */
4396 /*-----------------------------------------------------------*/
4397
4398 #if ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 )
4399
4400     static char * prvWriteNameToBuffer( char * pcBuffer,
4401                                         const char * pcTaskName )
4402     {
4403         size_t x;
4404
4405         /* Start by copying the entire string. */
4406         strcpy( pcBuffer, pcTaskName );
4407
4408         /* Pad the end of the string with spaces to ensure columns line up when
4409          * printed out. */
4410         for( x = strlen( pcBuffer ); x < ( size_t ) ( configMAX_TASK_NAME_LEN - 1 ); x++ )
4411         {
4412             pcBuffer[ x ] = ' ';
4413         }
4414
4415         /* Terminate. */
4416         pcBuffer[ x ] = ( char ) 0x00;
4417
4418         /* Return the new end of string. */
4419         return &( pcBuffer[ x ] );
4420     }
4421
4422 #endif /* ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 ) */
4423 /*-----------------------------------------------------------*/
4424
4425 #if ( ( configUSE_TRACE_FACILITY == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 ) )
4426
4427     void vTaskList( char * pcWriteBuffer )
4428     {
4429         TaskStatus_t * pxTaskStatusArray;
4430         UBaseType_t uxArraySize, x;
4431         char cStatus;
4432
4433         /*
4434          * PLEASE NOTE:
4435          *
4436          * This function is provided for convenience only, and is used by many
4437          * of the demo applications.  Do not consider it to be part of the
4438          * scheduler.
4439          *
4440          * vTaskList() calls uxTaskGetSystemState(), then formats part of the
4441          * uxTaskGetSystemState() output into a human readable table that
4442          * displays task: names, states, priority, stack usage and task number.
4443          * Stack usage specified as the number of unused StackType_t words stack can hold
4444          * on top of stack - not the number of bytes.
4445          *
4446          * vTaskList() has a dependency on the sprintf() C library function that
4447          * might bloat the code size, use a lot of stack, and provide different
4448          * results on different platforms.  An alternative, tiny, third party,
4449          * and limited functionality implementation of sprintf() is provided in
4450          * many of the FreeRTOS/Demo sub-directories in a file called
4451          * printf-stdarg.c (note printf-stdarg.c does not provide a full
4452          * snprintf() implementation!).
4453          *
4454          * It is recommended that production systems call uxTaskGetSystemState()
4455          * directly to get access to raw stats data, rather than indirectly
4456          * through a call to vTaskList().
4457          */
4458
4459
4460         /* Make sure the write buffer does not contain a string. */
4461         *pcWriteBuffer = ( char ) 0x00;
4462
4463         /* Take a snapshot of the number of tasks in case it changes while this
4464          * function is executing. */
4465         uxArraySize = uxCurrentNumberOfTasks;
4466
4467         /* Allocate an array index for each task.  NOTE!  if
4468          * configSUPPORT_DYNAMIC_ALLOCATION is set to 0 then pvPortMalloc() will
4469          * equate to NULL. */
4470         pxTaskStatusArray = pvPortMalloc( uxCurrentNumberOfTasks * sizeof( TaskStatus_t ) ); /*lint !e9079 All values returned by pvPortMalloc() have at least the alignment required by the MCU's stack and this allocation allocates a struct that has the alignment requirements of a pointer. */
4471
4472         if( pxTaskStatusArray != NULL )
4473         {
4474             /* Generate the (binary) data. */
4475             uxArraySize = uxTaskGetSystemState( pxTaskStatusArray, uxArraySize, NULL );
4476
4477             /* Create a human readable table from the binary data. */
4478             for( x = 0; x < uxArraySize; x++ )
4479             {
4480                 switch( pxTaskStatusArray[ x ].eCurrentState )
4481                 {
4482                     case eRunning:
4483                         cStatus = tskRUNNING_CHAR;
4484                         break;
4485
4486                     case eReady:
4487                         cStatus = tskREADY_CHAR;
4488                         break;
4489
4490                     case eBlocked:
4491                         cStatus = tskBLOCKED_CHAR;
4492                         break;
4493
4494                     case eSuspended:
4495                         cStatus = tskSUSPENDED_CHAR;
4496                         break;
4497
4498                     case eDeleted:
4499                         cStatus = tskDELETED_CHAR;
4500                         break;
4501
4502                     case eInvalid: /* Fall through. */
4503                     default:       /* Should not get here, but it is included
4504                                     * to prevent static checking errors. */
4505                         cStatus = ( char ) 0x00;
4506                         break;
4507                 }
4508
4509                 /* Write the task name to the string, padding with spaces so it
4510                  * can be printed in tabular form more easily. */
4511                 pcWriteBuffer = prvWriteNameToBuffer( pcWriteBuffer, pxTaskStatusArray[ x ].pcTaskName );
4512
4513                 /* Write the rest of the string. */
4514                 sprintf( pcWriteBuffer, "\t%c\t%u\t%u\t%u\r\n", cStatus, ( unsigned int ) pxTaskStatusArray[ x ].uxCurrentPriority, ( unsigned int ) pxTaskStatusArray[ x ].usStackHighWaterMark, ( unsigned int ) pxTaskStatusArray[ x ].xTaskNumber ); /*lint !e586 sprintf() allowed as this is compiled with many compilers and this is a utility function only - not part of the core kernel implementation. */
4515                 pcWriteBuffer += strlen( pcWriteBuffer );                                                                                                                                                                                                /*lint !e9016 Pointer arithmetic ok on char pointers especially as in this case where it best denotes the intent of the code. */
4516             }
4517
4518             /* Free the array again.  NOTE!  If configSUPPORT_DYNAMIC_ALLOCATION
4519              * is 0 then vPortFree() will be #defined to nothing. */
4520             vPortFree( pxTaskStatusArray );
4521         }
4522         else
4523         {
4524             mtCOVERAGE_TEST_MARKER();
4525         }
4526     }
4527
4528 #endif /* ( ( configUSE_TRACE_FACILITY == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 ) ) */
4529 /*----------------------------------------------------------*/
4530
4531 #if ( ( configGENERATE_RUN_TIME_STATS == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 ) && ( configUSE_TRACE_FACILITY == 1 ) )
4532
4533     void vTaskGetRunTimeStats( char * pcWriteBuffer )
4534     {
4535         TaskStatus_t * pxTaskStatusArray;
4536         UBaseType_t uxArraySize, x;
4537         configRUN_TIME_COUNTER_TYPE ulTotalTime, ulStatsAsPercentage;
4538
4539         /*
4540          * PLEASE NOTE:
4541          *
4542          * This function is provided for convenience only, and is used by many
4543          * of the demo applications.  Do not consider it to be part of the
4544          * scheduler.
4545          *
4546          * vTaskGetRunTimeStats() calls uxTaskGetSystemState(), then formats part
4547          * of the uxTaskGetSystemState() output into a human readable table that
4548          * displays the amount of time each task has spent in the Running state
4549          * in both absolute and percentage terms.
4550          *
4551          * vTaskGetRunTimeStats() has a dependency on the sprintf() C library
4552          * function that might bloat the code size, use a lot of stack, and
4553          * provide different results on different platforms.  An alternative,
4554          * tiny, third party, and limited functionality implementation of
4555          * sprintf() is provided in many of the FreeRTOS/Demo sub-directories in
4556          * a file called printf-stdarg.c (note printf-stdarg.c does not provide
4557          * a full snprintf() implementation!).
4558          *
4559          * It is recommended that production systems call uxTaskGetSystemState()
4560          * directly to get access to raw stats data, rather than indirectly
4561          * through a call to vTaskGetRunTimeStats().
4562          */
4563
4564         /* Make sure the write buffer does not contain a string. */
4565         *pcWriteBuffer = ( char ) 0x00;
4566
4567         /* Take a snapshot of the number of tasks in case it changes while this
4568          * function is executing. */
4569         uxArraySize = uxCurrentNumberOfTasks;
4570
4571         /* Allocate an array index for each task.  NOTE!  If
4572          * configSUPPORT_DYNAMIC_ALLOCATION is set to 0 then pvPortMalloc() will
4573          * equate to NULL. */
4574         pxTaskStatusArray = pvPortMalloc( uxCurrentNumberOfTasks * sizeof( TaskStatus_t ) ); /*lint !e9079 All values returned by pvPortMalloc() have at least the alignment required by the MCU's stack and this allocation allocates a struct that has the alignment requirements of a pointer. */
4575
4576         if( pxTaskStatusArray != NULL )
4577         {
4578             /* Generate the (binary) data. */
4579             uxArraySize = uxTaskGetSystemState( pxTaskStatusArray, uxArraySize, &ulTotalTime );
4580
4581             /* For percentage calculations. */
4582             ulTotalTime /= 100UL;
4583
4584             /* Avoid divide by zero errors. */
4585             if( ulTotalTime > 0UL )
4586             {
4587                 /* Create a human readable table from the binary data. */
4588                 for( x = 0; x < uxArraySize; x++ )
4589                 {
4590                     /* What percentage of the total run time has the task used?
4591                      * This will always be rounded down to the nearest integer.
4592                      * ulTotalRunTime has already been divided by 100. */
4593                     ulStatsAsPercentage = pxTaskStatusArray[ x ].ulRunTimeCounter / ulTotalTime;
4594
4595                     /* Write the task name to the string, padding with
4596                      * spaces so it can be printed in tabular form more
4597                      * easily. */
4598                     pcWriteBuffer = prvWriteNameToBuffer( pcWriteBuffer, pxTaskStatusArray[ x ].pcTaskName );
4599
4600                     if( ulStatsAsPercentage > 0UL )
4601                     {
4602                         #ifdef portLU_PRINTF_SPECIFIER_REQUIRED
4603                         {
4604                             sprintf( pcWriteBuffer, "\t%lu\t\t%lu%%\r\n", pxTaskStatusArray[ x ].ulRunTimeCounter, ulStatsAsPercentage );
4605                         }
4606                         #else
4607                         {
4608                             /* sizeof( int ) == sizeof( long ) so a smaller
4609                              * printf() library can be used. */
4610                             sprintf( pcWriteBuffer, "\t%u\t\t%u%%\r\n", ( unsigned int ) pxTaskStatusArray[ x ].ulRunTimeCounter, ( unsigned int ) ulStatsAsPercentage ); /*lint !e586 sprintf() allowed as this is compiled with many compilers and this is a utility function only - not part of the core kernel implementation. */
4611                         }
4612                         #endif
4613                     }
4614                     else
4615                     {
4616                         /* If the percentage is zero here then the task has
4617                          * consumed less than 1% of the total run time. */
4618                         #ifdef portLU_PRINTF_SPECIFIER_REQUIRED
4619                         {
4620                             sprintf( pcWriteBuffer, "\t%lu\t\t<1%%\r\n", pxTaskStatusArray[ x ].ulRunTimeCounter );
4621                         }
4622                         #else
4623                         {
4624                             /* sizeof( int ) == sizeof( long ) so a smaller
4625                              * printf() library can be used. */
4626                             sprintf( pcWriteBuffer, "\t%u\t\t<1%%\r\n", ( unsigned int ) pxTaskStatusArray[ x ].ulRunTimeCounter ); /*lint !e586 sprintf() allowed as this is compiled with many compilers and this is a utility function only - not part of the core kernel implementation. */
4627                         }
4628                         #endif
4629                     }
4630
4631                     pcWriteBuffer += strlen( pcWriteBuffer ); /*lint !e9016 Pointer arithmetic ok on char pointers especially as in this case where it best denotes the intent of the code. */
4632                 }
4633             }
4634             else
4635             {
4636                 mtCOVERAGE_TEST_MARKER();
4637             }
4638
4639             /* Free the array again.  NOTE!  If configSUPPORT_DYNAMIC_ALLOCATION
4640              * is 0 then vPortFree() will be #defined to nothing. */
4641             vPortFree( pxTaskStatusArray );
4642         }
4643         else
4644         {
4645             mtCOVERAGE_TEST_MARKER();
4646         }
4647     }
4648
4649 #endif /* ( ( configGENERATE_RUN_TIME_STATS == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 ) ) */
4650 /*-----------------------------------------------------------*/
4651
4652 TickType_t uxTaskResetEventItemValue( void )
4653 {
4654     TickType_t uxReturn;
4655
4656     uxReturn = listGET_LIST_ITEM_VALUE( &( pxCurrentTCB->xEventListItem ) );
4657
4658     /* Reset the event list item to its normal value - so it can be used with
4659      * queues and semaphores. */
4660     listSET_LIST_ITEM_VALUE( &( pxCurrentTCB->xEventListItem ), ( ( TickType_t ) configMAX_PRIORITIES - ( TickType_t ) pxCurrentTCB->uxPriority ) ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */
4661
4662     return uxReturn;
4663 }
4664 /*-----------------------------------------------------------*/
4665
4666 #if ( configUSE_MUTEXES == 1 )
4667
4668     TaskHandle_t pvTaskIncrementMutexHeldCount( void )
4669     {
4670         /* If xSemaphoreCreateMutex() is called before any tasks have been created
4671          * then pxCurrentTCB will be NULL. */
4672         if( pxCurrentTCB != NULL )
4673         {
4674             ( pxCurrentTCB->uxMutexesHeld )++;
4675         }
4676
4677         return pxCurrentTCB;
4678     }
4679
4680 #endif /* configUSE_MUTEXES */
4681 /*-----------------------------------------------------------*/
4682
4683 #if ( configUSE_TASK_NOTIFICATIONS == 1 )
4684
4685     uint32_t ulTaskGenericNotifyTake( UBaseType_t uxIndexToWait,
4686                                       BaseType_t xClearCountOnExit,
4687                                       TickType_t xTicksToWait )
4688     {
4689         uint32_t ulReturn;
4690
4691         configASSERT( uxIndexToWait < configTASK_NOTIFICATION_ARRAY_ENTRIES );
4692
4693         taskENTER_CRITICAL();
4694         {
4695             /* Only block if the notification count is not already non-zero. */
4696             if( pxCurrentTCB->ulNotifiedValue[ uxIndexToWait ] == 0UL )
4697             {
4698                 /* Mark this task as waiting for a notification. */
4699                 pxCurrentTCB->ucNotifyState[ uxIndexToWait ] = taskWAITING_NOTIFICATION;
4700
4701                 if( xTicksToWait > ( TickType_t ) 0 )
4702                 {
4703                     prvAddCurrentTaskToDelayedList( xTicksToWait, pdTRUE );
4704                     traceTASK_NOTIFY_TAKE_BLOCK( uxIndexToWait );
4705
4706                     /* All ports are written to allow a yield in a critical
4707                      * section (some will yield immediately, others wait until the
4708                      * critical section exits) - but it is not something that
4709                      * application code should ever do. */
4710                     portYIELD_WITHIN_API();
4711                 }
4712                 else
4713                 {
4714                     mtCOVERAGE_TEST_MARKER();
4715                 }
4716             }
4717             else
4718             {
4719                 mtCOVERAGE_TEST_MARKER();
4720             }
4721         }
4722         taskEXIT_CRITICAL();
4723
4724         taskENTER_CRITICAL();
4725         {
4726             traceTASK_NOTIFY_TAKE( uxIndexToWait );
4727             ulReturn = pxCurrentTCB->ulNotifiedValue[ uxIndexToWait ];
4728
4729             if( ulReturn != 0UL )
4730             {
4731                 if( xClearCountOnExit != pdFALSE )
4732                 {
4733                     pxCurrentTCB->ulNotifiedValue[ uxIndexToWait ] = 0UL;
4734                 }
4735                 else
4736                 {
4737                     pxCurrentTCB->ulNotifiedValue[ uxIndexToWait ] = ulReturn - ( uint32_t ) 1;
4738                 }
4739             }
4740             else
4741             {
4742                 mtCOVERAGE_TEST_MARKER();
4743             }
4744
4745             pxCurrentTCB->ucNotifyState[ uxIndexToWait ] = taskNOT_WAITING_NOTIFICATION;
4746         }
4747         taskEXIT_CRITICAL();
4748
4749         return ulReturn;
4750     }
4751
4752 #endif /* configUSE_TASK_NOTIFICATIONS */
4753 /*-----------------------------------------------------------*/
4754
4755 #if ( configUSE_TASK_NOTIFICATIONS == 1 )
4756
4757     BaseType_t xTaskGenericNotifyWait( UBaseType_t uxIndexToWait,
4758                                        uint32_t ulBitsToClearOnEntry,
4759                                        uint32_t ulBitsToClearOnExit,
4760                                        uint32_t * pulNotificationValue,
4761                                        TickType_t xTicksToWait )
4762     {
4763         BaseType_t xReturn;
4764
4765         configASSERT( uxIndexToWait < configTASK_NOTIFICATION_ARRAY_ENTRIES );
4766
4767         taskENTER_CRITICAL();
4768         {
4769             /* Only block if a notification is not already pending. */
4770             if( pxCurrentTCB->ucNotifyState[ uxIndexToWait ] != taskNOTIFICATION_RECEIVED )
4771             {
4772                 /* Clear bits in the task's notification value as bits may get
4773                  * set  by the notifying task or interrupt.  This can be used to
4774                  * clear the value to zero. */
4775                 pxCurrentTCB->ulNotifiedValue[ uxIndexToWait ] &= ~ulBitsToClearOnEntry;
4776
4777                 /* Mark this task as waiting for a notification. */
4778                 pxCurrentTCB->ucNotifyState[ uxIndexToWait ] = taskWAITING_NOTIFICATION;
4779
4780                 if( xTicksToWait > ( TickType_t ) 0 )
4781                 {
4782                     prvAddCurrentTaskToDelayedList( xTicksToWait, pdTRUE );
4783                     traceTASK_NOTIFY_WAIT_BLOCK( uxIndexToWait );
4784
4785                     /* All ports are written to allow a yield in a critical
4786                      * section (some will yield immediately, others wait until the
4787                      * critical section exits) - but it is not something that
4788                      * application code should ever do. */
4789                     portYIELD_WITHIN_API();
4790                 }
4791                 else
4792                 {
4793                     mtCOVERAGE_TEST_MARKER();
4794                 }
4795             }
4796             else
4797             {
4798                 mtCOVERAGE_TEST_MARKER();
4799             }
4800         }
4801         taskEXIT_CRITICAL();
4802
4803         taskENTER_CRITICAL();
4804         {
4805             traceTASK_NOTIFY_WAIT( uxIndexToWait );
4806
4807             if( pulNotificationValue != NULL )
4808             {
4809                 /* Output the current notification value, which may or may not
4810                  * have changed. */
4811                 *pulNotificationValue = pxCurrentTCB->ulNotifiedValue[ uxIndexToWait ];
4812             }
4813
4814             /* If ucNotifyValue is set then either the task never entered the
4815              * blocked state (because a notification was already pending) or the
4816              * task unblocked because of a notification.  Otherwise the task
4817              * unblocked because of a timeout. */
4818             if( pxCurrentTCB->ucNotifyState[ uxIndexToWait ] != taskNOTIFICATION_RECEIVED )
4819             {
4820                 /* A notification was not received. */
4821                 xReturn = pdFALSE;
4822             }
4823             else
4824             {
4825                 /* A notification was already pending or a notification was
4826                  * received while the task was waiting. */
4827                 pxCurrentTCB->ulNotifiedValue[ uxIndexToWait ] &= ~ulBitsToClearOnExit;
4828                 xReturn = pdTRUE;
4829             }
4830
4831             pxCurrentTCB->ucNotifyState[ uxIndexToWait ] = taskNOT_WAITING_NOTIFICATION;
4832         }
4833         taskEXIT_CRITICAL();
4834
4835         return xReturn;
4836     }
4837
4838 #endif /* configUSE_TASK_NOTIFICATIONS */
4839 /*-----------------------------------------------------------*/
4840
4841 #if ( configUSE_TASK_NOTIFICATIONS == 1 )
4842
4843     BaseType_t xTaskGenericNotify( TaskHandle_t xTaskToNotify,
4844                                    UBaseType_t uxIndexToNotify,
4845                                    uint32_t ulValue,
4846                                    eNotifyAction eAction,
4847                                    uint32_t * pulPreviousNotificationValue )
4848     {
4849         TCB_t * pxTCB;
4850         BaseType_t xReturn = pdPASS;
4851         uint8_t ucOriginalNotifyState;
4852
4853         configASSERT( uxIndexToNotify < configTASK_NOTIFICATION_ARRAY_ENTRIES );
4854         configASSERT( xTaskToNotify );
4855         pxTCB = xTaskToNotify;
4856
4857         taskENTER_CRITICAL();
4858         {
4859             if( pulPreviousNotificationValue != NULL )
4860             {
4861                 *pulPreviousNotificationValue = pxTCB->ulNotifiedValue[ uxIndexToNotify ];
4862             }
4863
4864             ucOriginalNotifyState = pxTCB->ucNotifyState[ uxIndexToNotify ];
4865
4866             pxTCB->ucNotifyState[ uxIndexToNotify ] = taskNOTIFICATION_RECEIVED;
4867
4868             switch( eAction )
4869             {
4870                 case eSetBits:
4871                     pxTCB->ulNotifiedValue[ uxIndexToNotify ] |= ulValue;
4872                     break;
4873
4874                 case eIncrement:
4875                     ( pxTCB->ulNotifiedValue[ uxIndexToNotify ] )++;
4876                     break;
4877
4878                 case eSetValueWithOverwrite:
4879                     pxTCB->ulNotifiedValue[ uxIndexToNotify ] = ulValue;
4880                     break;
4881
4882                 case eSetValueWithoutOverwrite:
4883
4884                     if( ucOriginalNotifyState != taskNOTIFICATION_RECEIVED )
4885                     {
4886                         pxTCB->ulNotifiedValue[ uxIndexToNotify ] = ulValue;
4887                     }
4888                     else
4889                     {
4890                         /* The value could not be written to the task. */
4891                         xReturn = pdFAIL;
4892                     }
4893
4894                     break;
4895
4896                 case eNoAction:
4897
4898                     /* The task is being notified without its notify value being
4899                      * updated. */
4900                     break;
4901
4902                 default:
4903
4904                     /* Should not get here if all enums are handled.
4905                      * Artificially force an assert by testing a value the
4906                      * compiler can't assume is const. */
4907                     configASSERT( xTickCount == ( TickType_t ) 0 );
4908
4909                     break;
4910             }
4911
4912             traceTASK_NOTIFY( uxIndexToNotify );
4913
4914             /* If the task is in the blocked state specifically to wait for a
4915              * notification then unblock it now. */
4916             if( ucOriginalNotifyState == taskWAITING_NOTIFICATION )
4917             {
4918                 listREMOVE_ITEM( &( pxTCB->xStateListItem ) );
4919                 prvAddTaskToReadyList( pxTCB );
4920
4921                 /* The task should not have been on an event list. */
4922                 configASSERT( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) == NULL );
4923
4924                 #if ( configUSE_TICKLESS_IDLE != 0 )
4925                 {
4926                     /* If a task is blocked waiting for a notification then
4927                      * xNextTaskUnblockTime might be set to the blocked task's time
4928                      * out time.  If the task is unblocked for a reason other than
4929                      * a timeout xNextTaskUnblockTime is normally left unchanged,
4930                      * because it will automatically get reset to a new value when
4931                      * the tick count equals xNextTaskUnblockTime.  However if
4932                      * tickless idling is used it might be more important to enter
4933                      * sleep mode at the earliest possible time - so reset
4934                      * xNextTaskUnblockTime here to ensure it is updated at the
4935                      * earliest possible time. */
4936                     prvResetNextTaskUnblockTime();
4937                 }
4938                 #endif
4939
4940                 if( pxTCB->uxPriority > pxCurrentTCB->uxPriority )
4941                 {
4942                     /* The notified task has a priority above the currently
4943                      * executing task so a yield is required. */
4944                     taskYIELD_IF_USING_PREEMPTION();
4945                 }
4946                 else
4947                 {
4948                     mtCOVERAGE_TEST_MARKER();
4949                 }
4950             }
4951             else
4952             {
4953                 mtCOVERAGE_TEST_MARKER();
4954             }
4955         }
4956         taskEXIT_CRITICAL();
4957
4958         return xReturn;
4959     }
4960
4961 #endif /* configUSE_TASK_NOTIFICATIONS */
4962 /*-----------------------------------------------------------*/
4963
4964 #if ( configUSE_TASK_NOTIFICATIONS == 1 )
4965
4966     BaseType_t xTaskGenericNotifyFromISR( TaskHandle_t xTaskToNotify,
4967                                           UBaseType_t uxIndexToNotify,
4968                                           uint32_t ulValue,
4969                                           eNotifyAction eAction,
4970                                           uint32_t * pulPreviousNotificationValue,
4971                                           BaseType_t * pxHigherPriorityTaskWoken )
4972     {
4973         TCB_t * pxTCB;
4974         uint8_t ucOriginalNotifyState;
4975         BaseType_t xReturn = pdPASS;
4976         UBaseType_t uxSavedInterruptStatus;
4977
4978         configASSERT( xTaskToNotify );
4979         configASSERT( uxIndexToNotify < configTASK_NOTIFICATION_ARRAY_ENTRIES );
4980
4981         /* RTOS ports that support interrupt nesting have the concept of a
4982          * maximum  system call (or maximum API call) interrupt priority.
4983          * Interrupts that are  above the maximum system call priority are keep
4984          * permanently enabled, even when the RTOS kernel is in a critical section,
4985          * but cannot make any calls to FreeRTOS API functions.  If configASSERT()
4986          * is defined in FreeRTOSConfig.h then
4987          * portASSERT_IF_INTERRUPT_PRIORITY_INVALID() will result in an assertion
4988          * failure if a FreeRTOS API function is called from an interrupt that has
4989          * been assigned a priority above the configured maximum system call
4990          * priority.  Only FreeRTOS functions that end in FromISR can be called
4991          * from interrupts  that have been assigned a priority at or (logically)
4992          * below the maximum system call interrupt priority.  FreeRTOS maintains a
4993          * separate interrupt safe API to ensure interrupt entry is as fast and as
4994          * simple as possible.  More information (albeit Cortex-M specific) is
4995          * provided on the following link:
4996          * https://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html */
4997         portASSERT_IF_INTERRUPT_PRIORITY_INVALID();
4998
4999         pxTCB = xTaskToNotify;
5000
5001         uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR();
5002         {
5003             if( pulPreviousNotificationValue != NULL )
5004             {
5005                 *pulPreviousNotificationValue = pxTCB->ulNotifiedValue[ uxIndexToNotify ];
5006             }
5007
5008             ucOriginalNotifyState = pxTCB->ucNotifyState[ uxIndexToNotify ];
5009             pxTCB->ucNotifyState[ uxIndexToNotify ] = taskNOTIFICATION_RECEIVED;
5010
5011             switch( eAction )
5012             {
5013                 case eSetBits:
5014                     pxTCB->ulNotifiedValue[ uxIndexToNotify ] |= ulValue;
5015                     break;
5016
5017                 case eIncrement:
5018                     ( pxTCB->ulNotifiedValue[ uxIndexToNotify ] )++;
5019                     break;
5020
5021                 case eSetValueWithOverwrite:
5022                     pxTCB->ulNotifiedValue[ uxIndexToNotify ] = ulValue;
5023                     break;
5024
5025                 case eSetValueWithoutOverwrite:
5026
5027                     if( ucOriginalNotifyState != taskNOTIFICATION_RECEIVED )
5028                     {
5029                         pxTCB->ulNotifiedValue[ uxIndexToNotify ] = ulValue;
5030                     }
5031                     else
5032                     {
5033                         /* The value could not be written to the task. */
5034                         xReturn = pdFAIL;
5035                     }
5036
5037                     break;
5038
5039                 case eNoAction:
5040
5041                     /* The task is being notified without its notify value being
5042                      * updated. */
5043                     break;
5044
5045                 default:
5046
5047                     /* Should not get here if all enums are handled.
5048                      * Artificially force an assert by testing a value the
5049                      * compiler can't assume is const. */
5050                     configASSERT( xTickCount == ( TickType_t ) 0 );
5051                     break;
5052             }
5053
5054             traceTASK_NOTIFY_FROM_ISR( uxIndexToNotify );
5055
5056             /* If the task is in the blocked state specifically to wait for a
5057              * notification then unblock it now. */
5058             if( ucOriginalNotifyState == taskWAITING_NOTIFICATION )
5059             {
5060                 /* The task should not have been on an event list. */
5061                 configASSERT( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) == NULL );
5062
5063                 if( uxSchedulerSuspended == ( UBaseType_t ) pdFALSE )
5064                 {
5065                     listREMOVE_ITEM( &( pxTCB->xStateListItem ) );
5066                     prvAddTaskToReadyList( pxTCB );
5067                 }
5068                 else
5069                 {
5070                     /* The delayed and ready lists cannot be accessed, so hold
5071                      * this task pending until the scheduler is resumed. */
5072                     listINSERT_END( &( xPendingReadyList ), &( pxTCB->xEventListItem ) );
5073                 }
5074
5075                 if( pxTCB->uxPriority > pxCurrentTCB->uxPriority )
5076                 {
5077                     /* The notified task has a priority above the currently
5078                      * executing task so a yield is required. */
5079                     if( pxHigherPriorityTaskWoken != NULL )
5080                     {
5081                         *pxHigherPriorityTaskWoken = pdTRUE;
5082                     }
5083
5084                     /* Mark that a yield is pending in case the user is not
5085                      * using the "xHigherPriorityTaskWoken" parameter to an ISR
5086                      * safe FreeRTOS function. */
5087                     xYieldPending = pdTRUE;
5088                 }
5089                 else
5090                 {
5091                     mtCOVERAGE_TEST_MARKER();
5092                 }
5093             }
5094         }
5095         portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus );
5096
5097         return xReturn;
5098     }
5099
5100 #endif /* configUSE_TASK_NOTIFICATIONS */
5101 /*-----------------------------------------------------------*/
5102
5103 #if ( configUSE_TASK_NOTIFICATIONS == 1 )
5104
5105     void vTaskGenericNotifyGiveFromISR( TaskHandle_t xTaskToNotify,
5106                                         UBaseType_t uxIndexToNotify,
5107                                         BaseType_t * pxHigherPriorityTaskWoken )
5108     {
5109         TCB_t * pxTCB;
5110         uint8_t ucOriginalNotifyState;
5111         UBaseType_t uxSavedInterruptStatus;
5112
5113         configASSERT( xTaskToNotify );
5114         configASSERT( uxIndexToNotify < configTASK_NOTIFICATION_ARRAY_ENTRIES );
5115
5116         /* RTOS ports that support interrupt nesting have the concept of a
5117          * maximum  system call (or maximum API call) interrupt priority.
5118          * Interrupts that are  above the maximum system call priority are keep
5119          * permanently enabled, even when the RTOS kernel is in a critical section,
5120          * but cannot make any calls to FreeRTOS API functions.  If configASSERT()
5121          * is defined in FreeRTOSConfig.h then
5122          * portASSERT_IF_INTERRUPT_PRIORITY_INVALID() will result in an assertion
5123          * failure if a FreeRTOS API function is called from an interrupt that has
5124          * been assigned a priority above the configured maximum system call
5125          * priority.  Only FreeRTOS functions that end in FromISR can be called
5126          * from interrupts  that have been assigned a priority at or (logically)
5127          * below the maximum system call interrupt priority.  FreeRTOS maintains a
5128          * separate interrupt safe API to ensure interrupt entry is as fast and as
5129          * simple as possible.  More information (albeit Cortex-M specific) is
5130          * provided on the following link:
5131          * https://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html */
5132         portASSERT_IF_INTERRUPT_PRIORITY_INVALID();
5133
5134         pxTCB = xTaskToNotify;
5135
5136         uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR();
5137         {
5138             ucOriginalNotifyState = pxTCB->ucNotifyState[ uxIndexToNotify ];
5139             pxTCB->ucNotifyState[ uxIndexToNotify ] = taskNOTIFICATION_RECEIVED;
5140
5141             /* 'Giving' is equivalent to incrementing a count in a counting
5142              * semaphore. */
5143             ( pxTCB->ulNotifiedValue[ uxIndexToNotify ] )++;
5144
5145             traceTASK_NOTIFY_GIVE_FROM_ISR( uxIndexToNotify );
5146
5147             /* If the task is in the blocked state specifically to wait for a
5148              * notification then unblock it now. */
5149             if( ucOriginalNotifyState == taskWAITING_NOTIFICATION )
5150             {
5151                 /* The task should not have been on an event list. */
5152                 configASSERT( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) == NULL );
5153
5154                 if( uxSchedulerSuspended == ( UBaseType_t ) pdFALSE )
5155                 {
5156                     listREMOVE_ITEM( &( pxTCB->xStateListItem ) );
5157                     prvAddTaskToReadyList( pxTCB );
5158                 }
5159                 else
5160                 {
5161                     /* The delayed and ready lists cannot be accessed, so hold
5162                      * this task pending until the scheduler is resumed. */
5163                     listINSERT_END( &( xPendingReadyList ), &( pxTCB->xEventListItem ) );
5164                 }
5165
5166                 if( pxTCB->uxPriority > pxCurrentTCB->uxPriority )
5167                 {
5168                     /* The notified task has a priority above the currently
5169                      * executing task so a yield is required. */
5170                     if( pxHigherPriorityTaskWoken != NULL )
5171                     {
5172                         *pxHigherPriorityTaskWoken = pdTRUE;
5173                     }
5174
5175                     /* Mark that a yield is pending in case the user is not
5176                      * using the "xHigherPriorityTaskWoken" parameter in an ISR
5177                      * safe FreeRTOS function. */
5178                     xYieldPending = pdTRUE;
5179                 }
5180                 else
5181                 {
5182                     mtCOVERAGE_TEST_MARKER();
5183                 }
5184             }
5185         }
5186         portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus );
5187     }
5188
5189 #endif /* configUSE_TASK_NOTIFICATIONS */
5190 /*-----------------------------------------------------------*/
5191
5192 #if ( configUSE_TASK_NOTIFICATIONS == 1 )
5193
5194     BaseType_t xTaskGenericNotifyStateClear( TaskHandle_t xTask,
5195                                              UBaseType_t uxIndexToClear )
5196     {
5197         TCB_t * pxTCB;
5198         BaseType_t xReturn;
5199
5200         configASSERT( uxIndexToClear < configTASK_NOTIFICATION_ARRAY_ENTRIES );
5201
5202         /* If null is passed in here then it is the calling task that is having
5203          * its notification state cleared. */
5204         pxTCB = prvGetTCBFromHandle( xTask );
5205
5206         taskENTER_CRITICAL();
5207         {
5208             if( pxTCB->ucNotifyState[ uxIndexToClear ] == taskNOTIFICATION_RECEIVED )
5209             {
5210                 pxTCB->ucNotifyState[ uxIndexToClear ] = taskNOT_WAITING_NOTIFICATION;
5211                 xReturn = pdPASS;
5212             }
5213             else
5214             {
5215                 xReturn = pdFAIL;
5216             }
5217         }
5218         taskEXIT_CRITICAL();
5219
5220         return xReturn;
5221     }
5222
5223 #endif /* configUSE_TASK_NOTIFICATIONS */
5224 /*-----------------------------------------------------------*/
5225
5226 #if ( configUSE_TASK_NOTIFICATIONS == 1 )
5227
5228     uint32_t ulTaskGenericNotifyValueClear( TaskHandle_t xTask,
5229                                             UBaseType_t uxIndexToClear,
5230                                             uint32_t ulBitsToClear )
5231     {
5232         TCB_t * pxTCB;
5233         uint32_t ulReturn;
5234
5235         /* If null is passed in here then it is the calling task that is having
5236          * its notification state cleared. */
5237         pxTCB = prvGetTCBFromHandle( xTask );
5238
5239         taskENTER_CRITICAL();
5240         {
5241             /* Return the notification as it was before the bits were cleared,
5242              * then clear the bit mask. */
5243             ulReturn = pxTCB->ulNotifiedValue[ uxIndexToClear ];
5244             pxTCB->ulNotifiedValue[ uxIndexToClear ] &= ~ulBitsToClear;
5245         }
5246         taskEXIT_CRITICAL();
5247
5248         return ulReturn;
5249     }
5250
5251 #endif /* configUSE_TASK_NOTIFICATIONS */
5252 /*-----------------------------------------------------------*/
5253
5254 #if ( ( configGENERATE_RUN_TIME_STATS == 1 ) && ( INCLUDE_xTaskGetIdleTaskHandle == 1 ) )
5255
5256     configRUN_TIME_COUNTER_TYPE ulTaskGetIdleRunTimeCounter( void )
5257     {
5258         return xIdleTaskHandle->ulRunTimeCounter;
5259     }
5260
5261 #endif
5262 /*-----------------------------------------------------------*/
5263
5264 #if ( ( configGENERATE_RUN_TIME_STATS == 1 ) && ( INCLUDE_xTaskGetIdleTaskHandle == 1 ) )
5265
5266     configRUN_TIME_COUNTER_TYPE ulTaskGetIdleRunTimePercent( void )
5267     {
5268         configRUN_TIME_COUNTER_TYPE ulTotalTime, ulReturn;
5269
5270         ulTotalTime = portGET_RUN_TIME_COUNTER_VALUE();
5271
5272         /* For percentage calculations. */
5273         ulTotalTime /= ( configRUN_TIME_COUNTER_TYPE ) 100;
5274
5275         /* Avoid divide by zero errors. */
5276         if( ulTotalTime > ( configRUN_TIME_COUNTER_TYPE ) 0 )
5277         {
5278             ulReturn = xIdleTaskHandle->ulRunTimeCounter / ulTotalTime;
5279         }
5280         else
5281         {
5282             ulReturn = 0;
5283         }
5284
5285         return ulReturn;
5286     }
5287
5288 #endif /* if ( ( configGENERATE_RUN_TIME_STATS == 1 ) && ( INCLUDE_xTaskGetIdleTaskHandle == 1 ) ) */
5289 /*-----------------------------------------------------------*/
5290
5291 static void prvAddCurrentTaskToDelayedList( TickType_t xTicksToWait,
5292                                             const BaseType_t xCanBlockIndefinitely )
5293 {
5294     TickType_t xTimeToWake;
5295     const TickType_t xConstTickCount = xTickCount;
5296
5297     #if ( INCLUDE_xTaskAbortDelay == 1 )
5298     {
5299         /* About to enter a delayed list, so ensure the ucDelayAborted flag is
5300          * reset to pdFALSE so it can be detected as having been set to pdTRUE
5301          * when the task leaves the Blocked state. */
5302         pxCurrentTCB->ucDelayAborted = pdFALSE;
5303     }
5304     #endif
5305
5306     /* Remove the task from the ready list before adding it to the blocked list
5307      * as the same list item is used for both lists. */
5308     if( uxListRemove( &( pxCurrentTCB->xStateListItem ) ) == ( UBaseType_t ) 0 )
5309     {
5310         /* The current task must be in a ready list, so there is no need to
5311          * check, and the port reset macro can be called directly. */
5312         portRESET_READY_PRIORITY( pxCurrentTCB->uxPriority, uxTopReadyPriority ); /*lint !e931 pxCurrentTCB cannot change as it is the calling task.  pxCurrentTCB->uxPriority and uxTopReadyPriority cannot change as called with scheduler suspended or in a critical section. */
5313     }
5314     else
5315     {
5316         mtCOVERAGE_TEST_MARKER();
5317     }
5318
5319     #if ( INCLUDE_vTaskSuspend == 1 )
5320     {
5321         if( ( xTicksToWait == portMAX_DELAY ) && ( xCanBlockIndefinitely != pdFALSE ) )
5322         {
5323             /* Add the task to the suspended task list instead of a delayed task
5324              * list to ensure it is not woken by a timing event.  It will block
5325              * indefinitely. */
5326             listINSERT_END( &xSuspendedTaskList, &( pxCurrentTCB->xStateListItem ) );
5327         }
5328         else
5329         {
5330             /* Calculate the time at which the task should be woken if the event
5331              * does not occur.  This may overflow but this doesn't matter, the
5332              * kernel will manage it correctly. */
5333             xTimeToWake = xConstTickCount + xTicksToWait;
5334
5335             /* The list item will be inserted in wake time order. */
5336             listSET_LIST_ITEM_VALUE( &( pxCurrentTCB->xStateListItem ), xTimeToWake );
5337
5338             if( xTimeToWake < xConstTickCount )
5339             {
5340                 /* Wake time has overflowed.  Place this item in the overflow
5341                  * list. */
5342                 vListInsert( pxOverflowDelayedTaskList, &( pxCurrentTCB->xStateListItem ) );
5343             }
5344             else
5345             {
5346                 /* The wake time has not overflowed, so the current block list
5347                  * is used. */
5348                 vListInsert( pxDelayedTaskList, &( pxCurrentTCB->xStateListItem ) );
5349
5350                 /* If the task entering the blocked state was placed at the
5351                  * head of the list of blocked tasks then xNextTaskUnblockTime
5352                  * needs to be updated too. */
5353                 if( xTimeToWake < xNextTaskUnblockTime )
5354                 {
5355                     xNextTaskUnblockTime = xTimeToWake;
5356                 }
5357                 else
5358                 {
5359                     mtCOVERAGE_TEST_MARKER();
5360                 }
5361             }
5362         }
5363     }
5364     #else /* INCLUDE_vTaskSuspend */
5365     {
5366         /* Calculate the time at which the task should be woken if the event
5367          * does not occur.  This may overflow but this doesn't matter, the kernel
5368          * will manage it correctly. */
5369         xTimeToWake = xConstTickCount + xTicksToWait;
5370
5371         /* The list item will be inserted in wake time order. */
5372         listSET_LIST_ITEM_VALUE( &( pxCurrentTCB->xStateListItem ), xTimeToWake );
5373
5374         if( xTimeToWake < xConstTickCount )
5375         {
5376             /* Wake time has overflowed.  Place this item in the overflow list. */
5377             vListInsert( pxOverflowDelayedTaskList, &( pxCurrentTCB->xStateListItem ) );
5378         }
5379         else
5380         {
5381             /* The wake time has not overflowed, so the current block list is used. */
5382             vListInsert( pxDelayedTaskList, &( pxCurrentTCB->xStateListItem ) );
5383
5384             /* If the task entering the blocked state was placed at the head of the
5385              * list of blocked tasks then xNextTaskUnblockTime needs to be updated
5386              * too. */
5387             if( xTimeToWake < xNextTaskUnblockTime )
5388             {
5389                 xNextTaskUnblockTime = xTimeToWake;
5390             }
5391             else
5392             {
5393                 mtCOVERAGE_TEST_MARKER();
5394             }
5395         }
5396
5397         /* Avoid compiler warning when INCLUDE_vTaskSuspend is not 1. */
5398         ( void ) xCanBlockIndefinitely;
5399     }
5400     #endif /* INCLUDE_vTaskSuspend */
5401 }
5402
5403 /* Code below here allows additional code to be inserted into this source file,
5404  * especially where access to file scope functions and data is needed (for example
5405  * when performing module tests). */
5406
5407 #ifdef FREERTOS_MODULE_TEST
5408     #include "tasks_test_access_functions.h"
5409 #endif
5410
5411
5412 #if ( configINCLUDE_FREERTOS_TASK_C_ADDITIONS_H == 1 )
5413
5414     #include "freertos_tasks_c_additions.h"
5415
5416     #ifdef FREERTOS_TASKS_C_ADDITIONS_INIT
5417         static void freertos_tasks_c_additions_init( void )
5418         {
5419             FREERTOS_TASKS_C_ADDITIONS_INIT();
5420         }
5421     #endif
5422
5423 #endif /* if ( configINCLUDE_FREERTOS_TASK_C_ADDITIONS_H == 1 ) */