• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Task Management
2
3
4## Basic Concepts
5
6From 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.
7
8The task module of the OpenHarmony LiteOS-M supports switching between tasks to help users manage business process procedures. The task module has the following features:
9
10- Multiple tasks are supported.
11
12- A task represents a thread.
13
14- 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.
15
16- Time slice round-robin is used to schedule tasks with the same priority.
17
18- A total of 32 (**0** to **31**) priorities are defined. **0** is the highest priority, and **31** is the lowest.
19
20
21### Task-related Concepts
22
23**Task States**
24
25A 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.
26
27A task can be in any of the following states:
28
29- Ready: The task is in the ready queue, waiting for execution by a CPU.
30
31- Running: The task is being executed.
32
33- 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.
34
35- Dead: The task execution is complete and waiting for the system to reclaim resources.
36
37**Task State Transitions**
38
39**Figure 1** Task state transitions
40
41![](figures/task-state-transitions.png "task-state-transitions")
42
43A system may have multiple tasks at the same time. Therefore, tasks in the Ready state and Blocked state are added to the **Ready** queue and **Blocked** queue respectively. A queue is a collection of tasks in the same state. The sequence of adding tasks to a queue is irrelevant to the sequence of task status transition. There is only one task running at a time. Therefore, there is no queue for the running task.
44
45The task state transition process is as follows:
46
47- Ready → Running
48
49  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.
50- Running → Blocked
51
52  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.
53- Blocked -> Ready (Prerequisites for Blocked -> Running)
54
55  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.
56- Ready → Blocked
57
58  When a task in the Ready state is blocked (suspended), the task changes to the Blocked state and is removed from the Ready queue. The blocked task will not be scheduled until it is recovered.
59- Running → Ready
60
61  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.
62- Running → Dead
63
64  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.
65- Blocked → Dead
66
67  If an API is called to delete a blocked task, the task state change from Blocked to Dead.
68
69**Task ID**
70
71A task ID is returned when a task is created. The task ID uniquely identifies a task in the system. You can suspend, restore, or query tasks by task ID.
72
73**Task Priority**
74
75Tasks are executed based on their priority. When task switching occurs, the task with the highest priority in the Ready queue will be executed.
76
77**Task Entry Function**
78
79Function 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.
80
81**Task Stack**
82
83An independent memory space for each task. The stack stores information such as local variables, registers, function parameters, and function return addresses.
84
85**Task Context**
86
87Resources, 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.
88
89**TCB**
90
91Each 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.
92
93**Task Switching**
94
95Task 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.
96
97
98### Task Running Mechanism
99
100When 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 can be executed when the task enters the running state for the first time.
101
102
103## Available APIs
104
105The following table describes APIs available for the OpenHarmony LiteOS-M task module. For more details about the APIs, see the API reference.
106
107**Table 1** APIs of the task management module
108
109| Category| Description|
110| -------- | -------- |
111| Creating or deleting a task| **LOS_TaskCreateOnly**: creates a task and places the task in the Blocked state.<br>**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.<br>**LOS_TaskDelete**: deletes a task.|
112| Controlling task status| **LOS_TaskResume**: resumes a suspended task to place the task in the Ready state.<br>**LOS_TaskSuspend**: suspends the specified task and performs task switching.<br>**LOS_TaskJoin**: suspends this task till the specified task is complete and the task control block resources are reclaimed.<br>**LOS_TaskDelay**: makes a task wait for a period of time (in ticks) and releases CPU resources. When the delay timer expires, the task enters the Ready state again. The input parameter is the number of ticks.<br>**LOS_Msleep**: makes a task wait for a period of time and releases CPU resources. When the delay timer expires, the task enters the Ready state again. The input parameter is the number of milliseconds.<br>**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.|
113| Controlling task scheduling| **LOS_TaskLock**: locks task scheduling. However, tasks can still be interrupted.<br>**LOS_TaskUnlock**: unlocks task scheduling.<br>**LOS_Schedule**: triggers task scheduling.|
114| Controlling task priority| **LOS_CurTaskPriSet**: sets the priority for the current task.<br>**LOS_TaskPriSet**: sets the priority for a specified task.<br>**LOS_TaskPriGet**: obtains the priority of a specified task.|
115| Obtaining Job information| **LOS_CurTaskIDGet**: obtains the ID of the current task.<br>**LOS_NextTaskIDGet**: obtains the ID of the task with the highest priority in the Ready queue.<br>**LOS_NewTaskIDGet**: equivalent to **LOS_NextTaskIDGet**.<br>**LOS_CurTaskNameGet**: obtains the name of the current task.<br>**LOS_TaskNameGet**: obtains the name of a task.<br>**LOS_TaskStatusGet**: obtains the state of a task.<br>**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.<br>**LOS_TaskIsRunning**: checks whether the task module has started scheduling.|
116| Updating task information| **LOS_TaskSwitchInfoGet**: obtains the task switching information. The macro **LOSCFG_BASE_CORE_EXC_TSK_SWITCH** must be enabled.|
117
118## How to Develop
119
120The typical development process of the task module is as follows:
121
1221. Use **LOS_TaskLock** to lock task scheduling and prevent high-priority tasks from being scheduled.
123
1242. Use **LOS_TaskCreate** to create a task.
125
1263. Use **LOS_TaskUnlock** to unlock task scheduling so that tasks can be scheduled by priority.
127
1284. Use **LOS_TaskDelay** to delay a task.
129
1305. Use **LOS_TaskSuspend** to suspend a task.
131
1326. Use **LOS_TaskResume** to resume the suspended task.
133
134> **NOTE**
135> - Running idle tasks reclaims the TCBs and stacks in the to-be-recycled linked list.
136>
137> - 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.
138>
139> - The task stack size is 8-byte aligned. Follow the "nothing more and nothing less" principle while determining the task stack size.
140>
141> - A running task cannot be suspended if task scheduling is locked.
142>
143> - Idle tasks and software timer tasks cannot be suspended or deleted.
144>
145> - In an interrupt handler or when a task is locked, the operation of calling **LOS_TaskDelay** fails.
146>
147> - Locking task scheduling does not disable interrupts. Tasks can still be interrupted while task scheduling is locked.
148>
149> - Locking task scheduling must be used together with unlocking task scheduling.
150>
151> - Task scheduling may occur while a task priority is being set.
152>
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>
155> - **LOS_CurTaskPriSet** and **LOS_TaskPriSet** cannot be used in interrupts or used to modify the priorities of software timer tasks.
156>
157> - 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.
158>
159> - Resources such as a mutex or a semaphore allocated to a task must have been released before the task is deleted.
160
161
162## Development Example
163
164This 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.
165
166The sample code is compiled and verified in **./kernel/liteos_m/testsuites/src/osTest.c**. Call **ExampleTask** in **TestTaskEntry**.
167
168
169```
170#include "los_task.h"
171
172UINT32 g_taskHiId;
173UINT32 g_taskLoId;
174#define TSK_PRIOR_HI 3 /* Priority of a high-priority task. */
175#define TSK_PRIOR_LO 4 /* Priority of a low-priority task. */
176
177UINT32 ExampleTaskHi(VOID)
178{
179    UINT32 ret;
180
181    printf("Enter TaskHi Handler.\n");
182
183    /* Delay the task for 100 ticks. The task is then suspended, and the remaining task with the highest priority (TaskLo) will be executed. */
184    ret = LOS_TaskDelay(100);
185    if (ret != LOS_OK) {
186        printf("Delay TaskHi Failed.\n");
187        return LOS_NOK;
188    }
189
190    /* After 100 ticks elapse, the task is resumed. */
191    printf("TaskHi LOS_TaskDelay Done.\n");
192
193    /* Suspend the task. */
194    ret = LOS_TaskSuspend(g_taskHiId);
195    if (ret != LOS_OK) {
196        printf("Suspend TaskHi Failed.\n");
197        return LOS_NOK;
198    }
199    printf("TaskHi LOS_TaskResume Success.\n");
200    return ret;
201}
202
203/* Entry function of low-priority tasks */
204UINT32 ExampleTaskLo(VOID)
205{
206    UINT32 ret;
207
208    printf("Enter TaskLo Handler.\n");
209
210    /* Delay the task for 100 ticks. The task is then suspended, and the remaining task with the highest priority will be executed. */
211    ret = LOS_TaskDelay(100);
212    if (ret != LOS_OK) {
213        printf("Delay TaskLo Failed.\n");
214        return LOS_NOK;
215    }
216
217    printf("TaskHi LOS_TaskSuspend Success.\n");
218
219    /* Resume the suspended task g_taskHiId. */
220    ret = LOS_TaskResume(g_taskHiId);
221    if (ret != LOS_OK) {
222        printf("Resume TaskHi Failed.\n");
223        return LOS_NOK;
224    }
225    return ret;
226}
227
228/* Task entry function used to create two tasks with different priorities. */
229UINT32 ExampleTask(VOID)
230{
231    UINT32 ret;
232    TSK_INIT_PARAM_S taskParam1 = { 0 };
233    TSK_INIT_PARAM_S taskParam2 = { 0 };
234
235    /* Lock task scheduling to prevent newly created tasks from being scheduled prior to this task due to higher priority. */
236    LOS_TaskLock();
237
238    printf("LOS_TaskLock() Success!\n");
239
240    taskParam1.pfnTaskEntry = (TSK_ENTRY_FUNC)ExampleTaskHi;
241    taskParam1.usTaskPrio = TSK_PRIOR_HI;
242    taskParam1.pcName = "TaskHi";
243    taskParam1.uwStackSize = LOSCFG_BASE_CORE_TSK_DEFAULT_STACK_SIZE;
244    taskParam1.uwResved = LOS_TASK_ATTR_JOINABLE; /* Detach attribute. */
245
246    /* Create a task with higher priority. The task will not be executed immediately after being created, because task scheduling is locked. */
247    ret = LOS_TaskCreate(&g_taskHiId, &taskParam1);
248    if (ret != LOS_OK) {
249        LOS_TaskUnlock();
250
251        printf("Example_TaskHi create Failed!\n");
252        return LOS_NOK;
253    }
254
255    printf("Example_TaskHi create Success!\n");
256
257    taskParam2.pfnTaskEntry = (TSK_ENTRY_FUNC)ExampleTaskLo;
258    taskParam2.usTaskPrio = TSK_PRIOR_LO;
259    taskParam2.pcName = "TaskLo";
260    taskParam2.uwStackSize = LOSCFG_BASE_CORE_TSK_DEFAULT_STACK_SIZE;
261
262    /* Create a low-priority task. The task will not be executed immediately after being created, because task scheduling is locked. */
263    ret = LOS_TaskCreate(&g_taskLoId, &taskParam2);
264    if (ret != LOS_OK) {
265        LOS_TaskUnlock();
266        printf("Example_TaskLo create Failed!\n");
267        return LOS_NOK;
268    }
269
270    printf("Example_TaskLo create Success!\n");
271
272    /* Unlock task scheduling. The task with the highest priority in the Ready queue will be executed. */
273    LOS_TaskUnlock();
274    ret = LOS_TaskJoin(g_taskHiId, NULL);
275    if (ret != LOS_OK) {
276        printf("Join Example_TaskHi Failed!, 0x%x\n", ret);
277    } else {
278        printf("Join Example_TaskHi Success!\n");
279    }
280    return LOS_OK;
281}
282```
283
284**Verification**
285
286The development is successful if the return result is as follows:
287
288
289```
290LOS_TaskLock() Success!
291Example_TaskHi create Success!
292Example_TaskLo create Success!
293Enter TaskHi Handler.
294Enter TaskLo Handler.
295TaskHi LOS_TaskDelay Done.
296TaskHi LOS_TaskSuspend Success.
297TaskHi LOS_TaskResume Success.
298Join Example_TaskHi Success!
299```
300