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