• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Task Management
2
3## Basic Concepts
4
5From the perspective of the operating system, tasks are the minimum running units that compete for system resources. They can use or wait for CPUs, use system resources such as memory, and run independently.
6
7The task module of the OpenHarmony LiteOS-M provides multiple tasks and supports switching between tasks, helping users manage business process procedures. The task module has the following features:
8
9-   Multiple tasks are supported.
10-   A task represents a thread.
11-   The preemptive scheduling mechanism is used for tasks. High-priority tasks can interrupt low-priority tasks. Low-priority tasks can be scheduled only after high-priority tasks are blocked or complete.
12-   Time slice round-robin is used to schedule tasks with the same priority.
13-   A total of 32 \(**0** to **31**\) priorities are defined. **0** is the highest priority, and **31** is the lowest.
14
15### Task-related Concepts
16
17**Task States**
18
19A task has multiple states. After the system initialization is complete, the created tasks can compete for certain resources in the system according to the scheduling procedure regulated by the kernel.
20
21A task can be in any of the following states:
22
23-   Ready: The task is in the ready queue, waiting for execution by a CPU.
24-   Running: The task is being executed.
25-   Blocked: The task is not in the ready queue. The task may be suspended, delayed, waiting for a semaphore, waiting to read from or write into a queue, or reading from or writing into an event.
26-   Dead: The task execution is complete and waiting for the system to reclaim resources.
27
28**Task State Transitions**
29
30**Figure 1** Task state transitions<a name="fig186971918162613"></a>
31![](figures/task-state-transitions.png "task-state-transitions")
32
33The task transition process is as follows:
34
35-   Ready → Running
36
37    A task enters Ready state once created. When task switching occurs, the task with the highest priority in the Ready queue will be executed. The task being executed enters the Running state and is removed from the Ready queue.
38
39-   Running → Blocked
40
41    When a running task is blocked \(suspended, delayed, or reading semaphores\), it will be inserted to the blocked task queue and changes from the Running state to the Blocked state. Then, task switching is triggered to run the task with the highest priority in the Ready queue.
42
43-   Blocked → Ready \(Blocked → Running\)
44
45    When a blocked task is recovered \(for example, the task is resumed, the delay period or semaphore read period times out, or the task successfully reads a semaphore\), the task will be added to the Ready queue and change from the Blocked state to the Ready state. If the priority of the recovered task is higher than that of the running task, task switching will be triggered to run the recovered task. Then, the task changes from the Ready state to the Running state.
46
47-   Ready → Blocked
48
49    When a task in the Ready state is blocked \(suspended\), the task changes to the Blocked state and is deleted from the Ready queue. The blocked task will not be scheduled until it is recovered.
50
51-   Running → Ready
52
53    When a task with a higher priority is created or recovered, tasks will be scheduled. The task with the highest priority in the Ready queue changes to the Running state. The originally running task changes to the Ready state and remains in the Ready queue.
54
55-   Running → Dead
56
57    When a running task is complete, it changes to the Dead state. The Dead state includes normal exit state as the task is complete and the Invalid state. For example, if a task is complete but is not automatically deleted, the task is in the Invalid state.
58
59-   Blocked → Dead
60
61    If an API is called to delete a blocked task, the task state change from Blocked to Dead.
62
63
64**Task ID**
65
66You will receive a task ID after successfully creating a task. The task IDs are unique in the operating system. You can suspend, restore, or query tasks by task ID.
67
68**Task Priority**
69
70Tasks are executed based on their priority. When task switching occurs, the task with the highest priority in the Ready queue will be executed.
71
72**Task Entry Function**
73
74Function to be executed when a task is scheduled. This function is implemented by users and set in the task creation structure when a task is created.
75
76**Task Stack**
77
78An independent memory space for each task. The stack stores information such as local variables, registers, function parameters, and function return addresses.
79
80**Task Context**
81
82Resources, such as registers, used during the running of a task. When a task is suspended, other running tasks might modify the register values of the suspended task. If the original task context is not saved when task switching occurs, an unknown error may occur when the task is recovered. The context information of switched-out tasks is saved into their own task stacks so that the context information can be resumed along with tasks and the system can start from the interrupted code after the tasks are resumed.
83
84**Task Control Block**
85
86Each task has a task control block \(TCB\). A TCB contains task information, such as context stack pointer, state, priority, ID, name, and stack size. The TCB reflects the running status of a task.
87
88**Task Switching**
89
90Task switching involves actions, such as obtaining the task with the highest priority in the Ready queue, saving the context of the switched-out task, and restoring the context of the switched-in task.
91
92### Task Running Mechanism<a name="section123321315152219"></a>
93
94When a task is created, the system initializes the task stack and presets the context. The system places the task entry function in the corresponding position so that the function is executed when the task enters the running state for the first time.
95
96## Available APIs
97
98The following table describes APIs available for the OpenHarmony LiteOS-M task module. For more details about the APIs, see the API reference.
99
100**Table 1** APIs of the task management module
101
102| Category| API| Description|
103| -------- | -------- | -------- |
104| Creating or deleting a task| LOS_TaskCreateOnly | Creates a task and suspends the task to disable scheduling of the task. To enable scheduling of the task, call **LOS_TaskResume** to make the task enter the Ready state.|
105|  | LOS_TaskCreate | Creates a task and places the task in the Ready state. If there is no task with a higher priority in the Ready queue, the task will be executed.|
106|  | LOS_TaskDelete | Deletes a task.|
107| Controlling task status| LOS_TaskResume | Resumes a suspended task to place it in the Ready state.|
108|  | LOS_TaskSuspend | Suspends the specified task and performs task switching.|
109|  | LOS_TaskJoin | Suspends this task till the specified task is complete and the task control block resources are reclaimed.|
110| | LOS_TaskDetach | Changes the task attribute from **joinable** to **detach**. After the task of the **detach** attribute is complete, the task control block resources will be automatically reclaimed.|
111|  | LOS_TaskDelay | Makes a task wait for a period of time (in ticks) and releases CPU resources. When the delay time expires, the task enters the Ready state again. The input parameter is the number of ticks.|
112|  | LOS_Msleep | Converts the input number of milliseconds into number of ticks, and use the result to call **LOS_TaskDelay**.|
113|  | LOS_TaskYield | Sets the time slice of the current task to **0** to release CPU resources and schedule the task with the highest priority in the Ready queue to run.|
114| Controlling task scheduling| LOS_TaskLock | Locks task scheduling. However, tasks can still be interrupted.|
115|  | LOS_TaskUnlock | Unlocks task scheduling.|
116|  | LOS_Schedule | Triggers task scheduling|
117| Controlling task priority| LOS_CurTaskPriSet | Sets the priority for the current task.|
118|  | LOS_TaskPriSet | Sets the priority for a specified task.|
119|  | LOS_TaskPriGet | Obtains the priority of a specified task.|
120| Obtaining Job information| LOS_CurTaskIDGet | Obtains the ID of the current task.|
121|  | LOS_NextTaskIDGet | Obtains the ID of the task with the highest priority in the Ready queue.|
122|  | LOS_NewTaskIDGet | Same as **LOS_NextTaskIDGet**.|
123|  | LOS_CurTaskNameGet | Obtains the name of the current task.|
124|  | LOS_TaskNameGet | Obtains the name of a specified task.|
125|  | LOS_TaskStatusGet | Obtains the state of a specified task.|
126|  | LOS_TaskInfoGet | Obtains information about a specified task, including the task state, priority, stack size, stack pointer (SP), task entry function, and used stack space.|
127|  | LOS_TaskIsRunning | Checks whether the task module has started scheduling.|
128| Updating task information| LOS_TaskSwitchInfoGet | Obtains task switching information. The macro **LOSCFG_BASE_CORE_EXC_TSK_SWITCH** must be enabled.|
129| Reclaiming task stack resources| LOS_TaskResRecycle | Reclaims all task stack resources.|
130
131
132## How to Develop
133
134The typical development process of the task module is as follows:
135
1361.  Use **LOS\_TaskLock** to lock task scheduling and prevent high-priority tasks from being scheduled.
1372.  Use **LOS\_TaskCreate** to create a task.
1383.  Use **LOS\_TaskUnlock** to unlock task scheduling so that tasks can be scheduled by priority.
1394.  Use **LOS\_TaskDelay** to delay a task.
1405.  Use **LOS\_TaskSuspend** to suspend a task.
1416.  Use **LOS\_TaskResume** to resume the suspended task.
142
143>![](../public_sys-resources/icon-note.gif) **NOTE**<br/>
144>-   Running idle tasks reclaims the TCBs and stacks in the to-be-recycled linked list.
145>-   The task name is a pointer without memory space allocated. When setting the task name, do not assign the local variable address to the task name pointer.
146>-   The task stack size is 8-byte aligned. Follow the "nothing more and nothing less" principle while determining the task stack size.
147>-   A running task cannot be suspended if task scheduling is locked.
148>-   Idle tasks and software timer tasks cannot be suspended or deleted.
149>-   In an interrupt handler or when a task is locked, the operation of calling **LOS\_TaskDelay** fails.
150>-   Locking task scheduling does not disable interrupts. Tasks can still be interrupted while task scheduling is locked.
151>-   Locking task scheduling must be used together with unlocking task scheduling.
152>-   Task scheduling may occur while a task priority is being set.
153>-   The maximum number of tasks that can be set for the operating system is the total number of tasks of the operating system, not the number of tasks available to users. For example, if the system software timer occupies one more task resource, the number of task resources available to users decreases by one.
154>-   **LOS\_CurTaskPriSet** and **LOS\_TaskPriSet** cannot be used in interrupts or used to modify the priorities of software timer tasks.
155>-   If the task corresponding to the task ID sent to **LOS\_TaskPriGet** has not been created or the task ID exceeds the maximum number of tasks, **-1** will be returned.
156>-   Resources such as a mutex or a semaphore allocated to a task must have been released before the task is deleted.
157
158## Development Example
159
160This example describes the priority-based task scheduling and use of task-related APIs, including creating, delaying, suspending, and resuming two tasks with different priorities, and locking/unlocking task scheduling. The sample code is as follows:
161
162```
163UINT32 g_taskHiId;
164UINT32 g_taskLoId;
165#define TSK_PRIOR_HI 4
166#define TSK_PRIOR_LO 5
167
168UINT32 Example_TaskHi(VOID)
169{
170    UINT32 ret;
171
172    printf("Enter TaskHi Handler.\n");
173
174    /* Delay the task for 100 ticks. The task is then suspended, and the remaining task with the highest priority (TaskLo) will be executed. */
175    ret = LOS_TaskDelay(100);
176    if (ret != LOS_OK) {
177        printf("Delay TaskHi Failed.\n");
178        return LOS_NOK;
179    }
180
181    /*After 100 ticks elapse, the task is resumed. */
182    printf("TaskHi LOS_TaskDelay Done.\n");
183
184    /* Suspend the task. */
185    ret = LOS_TaskSuspend(g_taskHiId);
186    if (ret != LOS_OK) {
187        printf("Suspend TaskHi Failed.\n");
188        return LOS_NOK;
189    }
190    printf("TaskHi LOS_TaskResume Success.\n");
191    return ret;
192}
193
194/* Entry function of low-priority tasks */
195UINT32 Example_TaskLo(VOID)
196{
197    UINT32 ret;
198
199    printf("Enter TaskLo Handler.\n");
200
201    /* Delay the task for 100 ticks. The task is then suspended, and the remaining task with the highest priority will be executed. */
202    ret = LOS_TaskDelay(100);
203    if (ret != LOS_OK) {
204        printf("Delay TaskLo Failed.\n");
205        return LOS_NOK;
206    }
207
208    printf("TaskHi LOS_TaskSuspend Success.\n");
209
210    /* Resume the suspended task g_taskHiId. */
211    ret = LOS_TaskResume(g_taskHiId);
212    if (ret != LOS_OK) {
213        printf("Resume TaskHi Failed.\n");
214        return LOS_NOK;
215    }
216    return ret;
217}
218
219/* Task entry function used to create two tasks with different priorities */
220UINT32 Example_TskCaseEntry(VOID)
221{
222    UINT32 ret;
223    TSK_INIT_PARAM_S initParam;
224
225    /* Lock task scheduling to prevent newly created tasks from being scheduled prior to this task due to higher priority. */
226    LOS_TaskLock();
227
228    printf("LOS_TaskLock() Success!\n");
229
230    initParam.pfnTaskEntry = (TSK_ENTRY_FUNC)Example_TaskHi;
231    initParam.usTaskPrio = TSK_PRIOR_HI;
232    initParam.pcName = "TaskHi";
233    initParam.uwStackSize = LOSCFG_BASE_CORE_TSK_DEFAULT_STACK_SIZE;
234    initParam.uwResved = 0; /* Detach attributes. */
235
236    /* Create a task with higher priority. The task will not be executed immediately after being created, because task scheduling is locked. */
237    ret = LOS_TaskCreate(&g_taskHiId, &initParam);
238    if (ret != LOS_OK) {
239        LOS_TaskUnlock();
240
241        printf("Example_TaskHi create Failed!\n");
242        return LOS_NOK;
243    }
244
245    printf("Example_TaskHi create Success!\n");
246
247    initParam.pfnTaskEntry = (TSK_ENTRY_FUNC)Example_TaskLo;
248    initParam.usTaskPrio = TSK_PRIOR_LO;
249    initParam.pcName = "TaskLo";
250    initParam.uwStackSize = LOSCFG_BASE_CORE_TSK_DEFAULT_STACK_SIZE;
251
252    /*Create a low-priority task. The task will not be executed immediately after being created, because task scheduling is locked. */
253    ret = LOS_TaskCreate(&g_taskLoId, &initParam);
254    if (ret != LOS_OK) {
255        LOS_TaskUnlock();
256        printf("Example_TaskLo create Failed!\n");
257        return LOS_NOK;
258    }
259
260    printf("Example_TaskLo create Success!\n");
261
262    /* Unlock task scheduling. The task with the highest priority in the Ready queue will be executed. */
263    LOS_TaskUnlock();
264    ret = LOS_TaskJoin(g_taskHiId, NULL);
265    if (ret != LOS_OK) {
266        printf("Join Example_TaskHi Failed!\n");
267    } else {
268        printf("Join Example_TaskHi Success!\n");
269    }
270    return LOS_OK;
271}
272```
273
274### Verification
275
276The development is successful if the return result is as follows:
277
278```
279LOS_TaskLock() Success!
280Example_TaskHi create Success!
281Example_TaskLo create Success!
282Enter TaskHi Handler.
283Enter TaskLo Handler.
284TaskHi LOS_TaskDelay Done.
285TaskHi LOS_TaskSuspend Success.
286TaskHi LOS_TaskResume Success.
287Join Example_TaskHi Success!
288```
289