FreeRTOS Advanced Article 2---freertos Task creation analysis

Source: Internet
Author: User
Tags mutex numeric value volatile

The Task Creation API function Xtaskcreate () is described in the FreeRTOS Basic series "FreeRTOS series 10th---freertos task creation and deletion ", and we'll review the declaration of this function here:

        basetype_t xtaskcreate (
                            taskfunction_tp vtaskcode,
                            const char * constpcname,
                            unsigned short usstackdepth,
                            void *pvparameters,
                            ubasetype_t uxpriority,
                            taskhandle_t *pvcreatedtask
                          );

The purpose of this API function is to create a new task and add it to the task readiness list, which means the function parameter is:

Pvtaskcode: The function pointer, which points to the entry of the task function. The task never returns (in the Dead Loop). The parameter type taskfunction_t is defined in file projdefs.h, defined as: typedef void (*taskfunction_t) (void *), which is a null pointer type and returns an empty type. Pcname: Task description. Mainly used for debugging. The maximum length of a string, including the string end character, is specified by the macro Configmax_task_name_len, which is located in the FreeRTOSConfig.h file. Usstackdepth: Specifies the task stack size, the number of stack variables (stack depth) that can be supported, rather than the number of bytes . For example, under a 16-bit-width stack, usstackdepth is defined as 100, which actually uses 200-byte stack storage space. The width of the stack multiplied by the depth must not exceed the maximum value that the size_t type can represent. For example, if the size_t is 16 bits, you can indicate that the maximum value of the stack is 65535 bytes. This is because the stack is in bytes at the time of application, the number of bytes requested is the stack width multiplied by the depth, if this product exceeds the range represented by size_t, it overflows, and the allocated stack space is not what we want. Pvparameters: pointer, which is passed to the task as a parameter when the task is created. Uxpriority: The priority of the task. Systems with MPU support can create tasks arbitrarily in privileged (System) mode by placing the portprivilege_bit bit of the priority parameter. For example, to create a privileged task with a priority of 2, the parameter uxpriority can be set to (2 | portprivilege_bit). Pvcreatedtask: Used to return a handle (ID), which can be used to refer to a task after the task is created.

Although Xtaskcreate () looks much like a function, it is actually a macro, the function that is actually called is xtaskgenericcreate (), and the Xtaskcreate () macro is defined as follows:

#define Xtaskcreate (Pvtaskcode, Pcname, Usstackdepth,pvparameters, uxpriority, pxcreatedtask)    \
      Xtaskgenericcreate (Pvtaskcode), (Pcname), (usstackdepth), (Pvparameters), (uxpriority), (Pxcreatedtask), (NUL L), (null), (NULL))

As you can see, Xtaskcreate has three fewer parameters than xtaskgenericcreate, and in the macro definition, these three parameters are set to null. These three parameters are used to allocate stacks, task TCB space, and set MPU-related parameters using a static variable method. In general, these three parameters are not used, so when the task creates macro xtaskcreate definition, these three parameters are hidden from the user. In the following chapters, for convenience, we call xtaskcreate () a function, although it is a macro definition.

Above we mentioned the task TCB (Task control block), which is a key point that needs to be highlighted. It is used to store the status information for the task, including the environment when the task is run. Each task has its own task TCB. Task TCB is a relatively large data structure, which is also reasonable, because the task-related code accounted for about half of the total FreeRTOS code, the code is mostly related to the task TCB, we first introduce the task TCB data structure definition:

typedef struct TSKTASKCONTROLBLOCK {volatile stacktype_t *pxtopofstack;/* Stack top of the current stack, must be in the first item of struct/#if (Portus      Ing_mpu_wrappers = = 1) xmpu_settings xmpusettings; /*mpu setting, must be located in the structure of the second item */#endif listitem_t Xstatelistitem;    /* Status list item for the task, representing the status of the task as a reference */listitem_t Xeventlistitem;        /* Event list item to attach the task to the list of events as a reference */ubasetype_t uxpriority;           /* Save Task Priority, 0 = Lowest priority */stacktype_t *pxstack;
        /* point to start position of stack */char pctaskname[configmax_task_name_len];/* Task Name */#if (portstack_growth > 0)     stacktype_t *pxendofstack; /* point to the tail of the stack */#endif #if (PORTCRITICAL_NESTING_IN_TCB = = 1) ubasetype_t uxcriticalnesting;       /* Save critical section nesting depth */#endif #if (configuse_trace_facility = = 1) ubasetype_t uxtcbnumber;      /* Save a value, each task has a unique value */ubasetype_t uxtasknumber; /* Store a specific value */#endif #if (configuse_mutexes = = 1) ubasetype_t uxbasepriority;
    /* Base priority for saving tasks */ubasetype_t Uxmutexesheld;
    #endif #if (Configuse_application_task_tag = = 1) taskhookfunction_t Pxtasktag; #endif #if (confignum_thread_local_storage_pointers > 0) void *pvthreadlocalstoragepointers[confignum_th
    Read_local_storage_pointers];  #endif #if (Configgenerate_run_time_stats = = 1) uint32_t ulruntimecounter; /* Records the total time that the task was executed in the running state */#endif #if (configuse_newlib_reentrant = = 1)/* Assigns a newlibreent struct variable to the task. Newlib is a C library function, not freertos maintenance, and FreeRTOS is not responsible for using the results.
    If the user uses newlib, must be familiar with newlib details */struct _reent xnewlib_reent; #endif #if (configuse_task_notifications = = 1) volatile uint32_t ulnotifiedvalue;
    /* Related to task notification */volatile uint8_t ucnotifystate; #endif #if (configsupport_static_allocation = = 1) uint8_t ucstaticallocationflags; /* If the stack is assigned by a static array, set to Pdtrue if the stack is dynamically allocated, set to pdfalse*/#endif #if (includE_xtaskabortdelay = = 1) uint8_t ucdelayaborted;
 
#endif} TSKTCB; typedef TSKTCB TCB_T;

Here we describe in detail the main members of this data structure:

The pointer pxtopofstack must be in the first item of the struct, pointing to the top of the stack at the current stack, and pxtopofstack always points to the last item in the stack for a downward-growing stack.

If you use Mpu,xmpusettings, you must be in the second item of the struct for the MPU setting.

Next is the status list item Xstatelistitem and the Event list item Xeventlistitem, which we mentioned in the article on the list and list items in the previous chapter: The list is used by the FreeRTOS scheduler to track tasks, tasks that are ready, suspended, and deferred. will be attached to the respective list. The scheduler does this by hooking the status list item Xstatelistitem and the event list item Xeventlistitem in the task TCB to a different list. In task.c, some static list variables are defined, with ready, blocked, pending lists, such as when a task is in the ready state, the scheduler hooks up the Xstatelistitem list item of the task TCB to the Ready list. The event list item also resembles this, when the queue is full and the task is blocked by a queued operation, the event list item is attached to the queue's waiting queue table.

The uxpriority is used to hold the priority of the task, with 0 being the lowest priority. When a task is created, the specified task priority is saved to the variable.

The pointer pxstack points to the starting position of the stack, which assigns a specified number of task stacks when the task is created, and the pointer that the request stack memory function returns is assigned to the variable. A lot of people just contact FreeRTOS will not know the difference between the pointer pxtopofstack and Pxstack, here briefly: Pxtopofstack point to the top of the current stack, with the stack out of the stack, the location of the Pxtopofstack point will change Pxstack points to the starting position of the current stack, once allocated, the stack start position is fixed and will not be changed. So why do you need the pxstack variable, because as the task runs, the stack can overflow, and in a system that is growing on the stack, this variable can be used to check if the stack is overflowing, and if you want to determine if the stack is overflowing in a system that is growing on the stack, Another variable, pxendofstack, is needed to aid in diagnosing a stack overflow, as described later in this variable.

The character array pctaskname is used to hold the description or name of the task, which is specified by the parameter when the task is created. The length of the name is specified by the macro Configmax_task_name_len (located in FreeRTOSConfig.h) and contains the string end flag.

If the stack grows up (portstack_growth > 0), the pointer pxendofstack points to the end of the stack and is used to verify that the stack overflows.

The variable uxcriticalnesting is used to hold the critical section nesting depth, with an initial value of 0.

The next two variables are used for visual tracking only if the macro configuse_trace_facility (located in FreeRTOSConfig.h) is 1 o'clock valid. The variable Uxtcbnumber stores a numeric value that is automatically assigned by the kernel when the task is created (typically, the value is incremented by 1 for each task), and the Uxtcbnumber value for each task is different, primarily for debugging. Variable uxtasknumber is used to store a specific value, unlike the variable uxtcbnumber, the value of Uxtasknumber is not allocated by the kernel, but is set by the API function Vtasksettasknumber (), and the value is specified by the function parameter.

If a mutex is used (configuse_mutexes = = 1) and the task priority is temporarily raised, the variable uxbasepriority is used to save the task's original priority.

Variable ucstaticallocationflags also need to explain, we said earlier task Creation API function Xtaskcreate () can only use dynamic memory allocation to create the task stack and task TCB, If you are using static variables to implement the task stack and task TCB, you need to use function xtaskgenericcreate () to implement it. If the task stack or task TCB is implemented by a static array and a static variable, the variable is set to Pdtrue (when the task stack space is implemented by a static array variable, when the task TCB is implemented as 0x02 by a static variable, and when the task stack and task TCB are implemented by static variables 0x03), If the stack is dynamically allocated, set the variable to Pdfalse.

Here is the task of the TCB data structure is finished, below we use an example to tell the process of task creation, for the sake of convenience, assume that the task created is called "Task A", the task function is vtask_a ():

    taskhandle_t xhandle;
    xtaskcreate (Vtask_a, "Task A", 120,null,1,&xhandle);

This creates a task with a task priority of 1, because the hardware platform is 32 schema, so the 120*4=480 byte task stack is specified, the parameter passed to the task function vtask_a () is empty (null), and the task handle is saved by the variable xhandle. When this statement executes, task A is created and joins the Ready task list, and the main purpose of our chapter is to see what happens during the execution of this statement. 1. Creating Task Stacks and Task TCB

Call the function Prvallocatetcbandstack () to create the task stack and task TCB. There are two ways to create task stacks and task TCB, one is to use the dynamic memory allocation method, so that when a task is deleted, the task stack and the task control block space are freed for other tasks, and the other is implemented by using static variables that define global or static stack arrays and task control block variables before creating the task. When you invoke the Create Task API function, pass these two variables as arguments to the task creation function xtaskgenericcreate (). If you create a task function using the default xtaskcreate (), dynamic memory allocation is used because the parameters related to static memory allocation are not visible (at the beginning of this article we said that Xtaskcreate () is actually a macro definition with parameters, The function that is actually executed is xtaskgenericcreate (), the definition of reference macro xtaskcreate () can be known, xtaskcreate () hides the parameters that use static memory allocation, and when Xtaskgenericcreate () is called, These parameters are set to null).

After the task stack is successfully allocated, the aligned stack start address is saved to the Pxstack field of the task TCB. If you enable stack overflow checking or use visual tracking, use a fixed value of Tskstack_fill_byte (0XA5) to populate the stack.

The source code removal assertions for the function prvallocatetcbandstack () and the infrequently used conditions are compiled as follows:

Static tcb_t *prvallocatetcbandstack (const uint16_t usstackdepth, stacktype_t * Const PUXSTACKBUFFER, tcb_t * Const PXTAS
Kbuffer) {tcb_t *PXNEWTCB;
 
    stacktype_t *pxstack; /* Allocate stack space */pxstack = (stacktype_t *) pvportmallocaligned ((((size_t) usstackdepth) * sizeof (stacktype_t)),
    Puxstackbuffer); if (pxstack! = NULL) {/* Allocates TCB space */PXNEWTCB = (tcb_t *) pvportmallocaligned (sizeof (tcb_t), PxT
 
        Askbuffer);
        if (PXNEWTCB! = NULL) {/* The stack start position is stored tcb*/pxnewtcb->pxstack = pxstack;
                } else {/* If the TCB allocation fails, free the previously requested stack space */if (Puxstackbuffer = = NULL) {
            Vportfree (Pxstack);
    }}}} else {PXNEWTCB = NULL;  if (PXNEWTCB! = NULL) {/* Fill the stack with fixed values if required */#if ((configcheck_for_stack_overflow> 1) | | (configuse_trace_facility = = 1) | | (Include_uxtaskgetstackhighwatermark== 1)) {/* for debugging only */(void) memset (pxnewtcb->pxstack, (int) tskstack
        _fill_byte, (size_t) usstackdepth * sizeof (stacktype_t));
} #endif} return PXNEWTCB; }

2. Initialize the task TCB necessary fields

Call function Prvinitialisetcbvariables () to initialize task TCB necessary fields. When you invoke the Create Task API function Xtaskcreate (), the parameter Pcname (task description), uxpriority (Task priority) are written to the corresponding field of the task TCB. The Xstatelistitem and Xeventlistitem list items in the TCB field are also initialized, as shown in Figure 2-1 in the initialized list item. In Figure 2-1, the list item Xeventlistitem member list item value Xitemvalue is initially 4, because the maximum number of priorities (configmax_priorities) that I set in the app is 5, and Xeventlistitem. Xitemvalue equals configmax_priorities minus the priority of task A (1), which is 5-1=4. This is important, where Xitemvalue does not directly save the task priority, but instead saves the priority of the complement, which means that the greater the value of Xitemvalue, the smaller the corresponding task priority. The FreeRTOS kernel uses the Vlistinsert function (see Advanced chapter I) to insert an event list item into a list, which is inserted according to the order of size of the Xitemvalue value. Using macro listget_owner_of_head_entry to get the Xtiemvalue value of the first list item in the list is always minimal, which is the task with the highest priority.


Figure 2-1: Initializing state and Event list items

In addition, some other fields of the TCB are initialized, such as critical section nesting times, runtime counters, task notification values, task notification states, and so on, and the source code for function Prvinitialisetcbvariables () is as follows:

static void Prvinitialisetcbvariables (tcb_t * Const PXTCB, const char * const PCNAME, ubasetype_t uxpriority, \
 
    Const MEMORYREGION_T * Const xregions, const uint16_t usstackdepth) {ubasetype_t x; /* Save the task description in the TCB */for (x = (ubasetype_t) 0; x < (ubasetype_t) Configmax_task_name_len; × x + +) {PXTCB
        ->pctaskname[x] = pcname[x];
        if (pcname[x] = = 0x00) {break;
 
    }}/* Make sure the string has an end */pxtcb->pctaskname[configmax_task_name_len-1] = ' + ';
    /* Adjust priority, macro Configmax_priorities value set in FreeRTOSConfig.h */if (uxpriority >= (ubasetype_t) configmax_priorities)
    {uxpriority = (ubasetype_t) configmax_priorities-(ubasetype_t) 1U;
    } pxtcb->uxpriority = uxpriority;
        #if (configuse_mutexes = = 1)/* Use Mutex */{pxtcb->uxbasepriority = uxpriority;
    Pxtcb->uxmutexesheld = 0; } #endif/* Configuse_muteXES */* Initialize list items */Vlistinitialiseitem (& (Pxtcb->xstatelistitem));
 
    Vlistinitialiseitem (& (Pxtcb->xeventlistitem));
 
    /* Set list item Xstatelistitem member Pvowner point to Current task control block */Listset_list_item_owner (& (Pxtcb->xstatelistitem), PXTCB); /* Set list item Xeventlistitem member xitemvalue*/Listset_list_item_value (& (Pxtcb->xeventlistitem), (ticktype_t) CO
    Nfigmax_priorities-(ticktype_t) uxpriority);
 
    /* Set list item Xeventlistitem member Pvowner point to Current task control block */Listset_list_item_owner (& (Pxtcb->xeventlistitem), PXTCB); #if (PORTCRITICAL_NESTING_IN_TCB ==1)/* Enable critical section nesting function */{pxtcb->uxcriticalnesting = (ubasetype_t)
    0U;  
        } #endif/* PORTCRITICAL_NESTING_IN_TCB */#if (Configuse_application_task_tag = = 1)/* Enable task label function */{
    Pxtcb->pxtasktag = NULL;
        } #endif/* Configuse_application_task_tag */#if (configgenerate_run_time_stats = = 1)/* Enable event statistics function */{ Pxtcb->uLruntimecounter = 0UL;
        } #endif/* configgenerate_run_time_stats */#if (portusing_mpu_wrappers = = 1)/* Use MPU function */{
    Vportstoretaskmpusettings (& (Pxtcb->xmpusettings), Xregions, Pxtcb->pxstack, usstackdepth);
        } #else/* Portusing_mpu_wrappers */{(void) xregions;
    (void) usstackdepth;
        } #endif/* portusing_mpu_wrappers */#if (Confignum_thread_local_storage_pointers! = 0)/* Enable thread to store pointer locally */{ for (x = 0; x < (ubasetype_t) confignum_thread_local_storage_pointers; × x + +) {PXTCB-&GT;PVT
        hreadlocalstoragepointers[x] = NULL; }} #endif #if (configuse_task_notifications = = 1)/* Enable task notification function */{Pxtcb->ulnotifiedvalue
        = 0;
    Pxtcb->ucnotifystate = tasknot_waiting_notification; } #endif #if (configuse_newlib_reentrant = = 1)/* Use newlib*/{_reent_init_ptr (& (pxtcb- >xnewlib_reent)));
    } #endif #if (include_xtaskabortdelay = = 1) {pxtcb->ucdelayaborted = Pdfalse; } #endif}

3. Initializing the task stack

The Call function Pxportinitialisestack () initializes the task stack and assigns the most recent stack-top pointer to the Pxtopofstack field of the task TCB.

After calling the function Pxportinitialisestack (), it is equivalent to performing a system beat clock interrupt: Put some important registers into the stack. Although the task has not yet started, there is no interruption, but it looks like the register has been stacked, and the partial stack value has been modified to the known value we need. For different hardware architectures, the registers of the stacks are not the same, so we see that this function is provided by the porting layer. For the CORTEX-M3 architecture, you need to go into the stack xpsr, PC, LR, R12, R3~r0, R11~R4, assuming the stack is growing downward, and the initialized stack is shown in Figure 3-1.

In Figure 3-1 We see that the register XPSR is initially 0x01000000, where the Bit24 is set to 1, which means the thumb instruction is used, and the register PC is initialized to the task function pointer vtask_a, so that when a task is switched, task A gets CPU control, The task function vtask_a is stacked to the PC register and then executes the task A's code; The LR register is initialized to function pointer Prvtaskexiterror, which is an error handler provided by the migration layer. When an interrupt occurs, the LR is set to the address to be returned, but each task is a dead loop and normally should not exit the task function, so once exiting from the task function, it indicates that there is an error, and this time it invokes the function that the register LR points to to handle the error. that is prvtaskexiterror; according to Atpcs (Arm-thumb procedure Call Standard), we know that a child function call passes a parameter through a register R0~R3, when the Xtaskcreate () function is at the very beginning of the story, Referring to this function has a null pointer type parameter pvparameters, when the task is created, it is passed as a parameter to the task, so this parameter is saved to the R0, which is used to pass parameters to the task.

The task TCB struct member Pxtopofstack represents the stack top of the current stack, which points to the last item in the stack, so in the diagram it points to the R4,TCB struct another member Pxstack represents the starting position of the stack, so in the diagram it points to the beginning of the stack.


Figure 3-1: Initializing the task Stack 4. Enter the critical section

Call Taskenter_critical () into the critical section, which is a macro definition, and the code that eventually enters the critical section is provided by the migration layer. 5. Increase the number of current tasks by 1

In TASKS.C, a number of static private variables are defined to track the number or state of a task, and the variable uxcurrentnumberoftasks represents the total number of current tasks, which increases by 1 for each task created. 6. Do the necessary initialization for the first run

If this is the first task (Uxcurrentnumberoftasks equals 1), the function prvinitialisetasklists () is called to initialize the task list. FreeRTOS uses lists to track tasks, and in tasks.c, a list variable of static type is defined:

Privileged_datastatic list_t pxreadytaskslists[configmax_priorities];/* Order of readiness tasks by priority */
Privileged_datastatic list_t XDelayedTaskList1;                        /* Delayed task */
privileged_datastatic list_t xDelayedTaskList2;                        /* Delayed task */
privileged_datastatic list_t xpendingreadylist;                        /* The task is ready, but the scheduler is suspended *
 
/#if (Include_vtaskdelete = = 1)
    privileged_data static list_t xtaskswaitingtermination;             /* Task has been deleted, but memory has not been released *
 
/#endif #if (include_vtasksuspend = = 1)
    privileged_data static list_t Xsuspendedtasklist;                   /* Current Pending task */
#endif

Now that the lists are initialized, the API function vlistinitialise () initialization list is called, which is described in theFreeRTOS advanced 1---freertos list and list items . Each list is initialized in the same way, with the Ready state list pxreadytaskslists[0] as an example, as shown in Figure 6-1 after initialization:


Figure 6-1: The list after initialization

The source code for the function prvinitialisetasklists () is as follows:

static void Prvinitialisetasklists (void)
{
ubasetype_tuxpriority;
 
    for (uxpriority = (ubasetype_t) 0U; uxpriority < (ubasetype_t) configmax_priorities; uxpriority++)
    {
        vList Initialise (& (pxreadytaskslists[uxpriority));
    }
 
    Vlistinitialise (&xdelayedtasklist1);
    Vlistinitialise (&XDELAYEDTASKLIST2);
    Vlistinitialise (&xpendingreadylist);
 
    #if (Include_vtaskdelete = = 1)
    {
        vlistinitialise (&xtaskswaitingtermination);
    }
    #endif/* Include_vtaskdelete *
 
    /#if (include_vtasksuspend = = 1)
    {
        vlistinitialise (& xsuspendedtasklist);
    }
    #endif/* Include_vtasksuspend */
 
    * Start with Pxdelayedtasklist using List1 and the pxoverflowdelayedtasklistusing List2. */
    pxdelayedtasklist = &xDelayedTaskList1;
    Pxoverflowdelayedtasklist = &xDelayedTaskList2;
}

7. Update the currently running task TCB pointer

A task TCB pointer-type variable is defined in TASKS.C:

Privileged_data tcb_t * volatile pxcurrenttcb= NULL;

This is a global variable, and only this global variable is defined in TASKS.C. This variable is used to point to the currently running task TCB, and we need to know more about this variable. The core of FreeRTOS is to ensure that the highest priority readiness task gets the CPU running power. In the next chapter on task switching, it is known that task switching is finding the highest priority readiness task, and the TCB of the highest priority task identified is assigned to the variable PXCURRENTTCB.

If the scheduler is not ready (a few tasks may be created first before the scheduler is started), and the newly created task priority is greater than the task priority that the variable PXCURRENTTCB points to. Set PXCURRENTTCB to the currently newly created task TCB (make sure PXCURRENTTCB points to the highest priority readiness task).

if (xschedulerrunning = = Pdfalse)
{
    if (pxcurrenttcb->uxpriority <= uxpriority)
    {
        PXCURRENTTCB = PXNEWTCB;
    }
    else
    {
        mtcoverage_test_marker ();
    }
}

8. Add the newly created task to the Ready list array

Calling Prvaddtasktoreadylist (PXNEWTCB) adds the created task TCB to the Ready list array, and the task's priority determines which subscript to add to the Ready-list array. For example, if our newly created task priority is 1, this task is added to the list pxreadytaskslists[1].

Prvaddtasktoreadylist () is actually a macro that consists of a series of statements that remove the trace macro, which is defined as follows:

#defineprvAddTaskToReadyList (PXTCB)                        \
    taskrecord_ready_priority ((PXTCB)->uxpriority);       \
    vlistinsertend (& (pxreadytaskslists[(PXTCB)->uxpriority]), & ((PXTCB)->xstatelistitem));

Macro taskrecord_ready_priority () is used to update the variable uxtopreadypriority, which is defined as a static variable in TASKS.C and records the highest task priority in the ready state. This variable participates in the core code of the FreeRTOS: Ensure that the highest priority ready task gets the CPU running power. It is here to take part in how to find the highest priority readiness task as quickly as possible. For the fastest, different architectures are recount, and some architectures have special instructions available, so this macro is provided by the porting layer. We'll cover task switching in the next chapter, taking the CORTEX-M3 architecture as an example, detailing how to find the highest-priority readiness tasks the quickest.

The function vlistinsertend () Inserts the list item at the end of the list, as already mentioned in theFreeRTOS advanced 1---freertos list and list items , which is combined with an example to see the function. From the front we until, before calling the function Vlistinsertend (), the Ready list pxreadytaskslists[1] and the task TCB state list item Xstatelistitem are already initialized, as shown in Figure 6-1 and figure 2-1, for easy viewing, We will synthesize these two pictures as shown in Figure 8-1.


Figure 8-1: List and list items after initialization

The call to Vlistinsertend (A, A, B) Inserts the list item B. After the list A, and after the function finishes, the relationship of the list and list items is shown in Figure 8-2.


Figure 8-2: List after inserting a list item

On this basis, assuming that task B is created, task A and task B have the same priority, which is 1. As with task A, Task B also has its own task TCB, where the Status list item field Xstatelistitem is also inserted into the list pxreadytaskslists[1], and the new list and list items are shown in Figure 8-3.


Figure 8-3: The same priority-ready list hooks two list items 9. Exit the critical section

Call Taskexit_critical () to exit the critical section, which is a macro definition, and the code that eventually exits the critical section is provided by the migration layer. 10. Performing Context Switches

If the above steps are performed correctly and the scheduler starts to work, then the priority of the current task is determined to be greater than the newly created task priority. If the newly created task has a higher priority, call Taskyield_if_using_preemption () to force a context switch, and after switching, the newly created task will gain CPU control, as shown in the condensed code.

if (Xreturn = = Pdpass)
    {if
        (xschedulerrunning! = Pdfalse)
        {/
            * If the newly created task priority is greater than the current task priority, the newly created task should be executed immediately. *
            /if (Pxcurrenttcb->uxpriority < uxpriority)
            {
                taskyield_if_using_preemption ()
            ;
    }}}

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.