# Thread
- [Basic Concepts](#section138411646175417)
- [Working Principles](#section1381918945512)
- [Development Guidelines](#section10649727135519)
- [Available APIs](#section78333315555)
- [How to Develop](#section16229657115514)
- [Development Example](#section2809723165612)
## Basic Concepts
Threads are the minimum running units that compete for system resources. They can use or wait to use CPUs and use system resources such as memory. They run independently from one another.
Threads in the processes of the same priority in the OpenHarmony kernel are scheduled and run in a unified manner.
Threads in the OpenHarmony kernel use the preemptive scheduling mechanism, either round-robin \(RR\) scheduling or First In First Out \(FIFO\) scheduling.
Threads in the OpenHarmony kernel are assigned 32 priorities, ranging from **0** \(highest\) to **31** \(lowest\).
In the same process, a higher-priority process can preempt resources of a lower-priority process. The lower-priority process can be scheduled only after the higher-priority process is blocked or terminated.
**Thread States:**
- Init: The thread is being created.
- Ready: The thread is in the Ready queue and waits for being scheduled by the CPU.
- Running: The thread is running.
- Blocked: The thread is blocked and suspended. The Blocked states include pending \(blocked due to lock, event, or semaphore issues\), suspended \(active pending\), delay \(blocked due to delays\), and pendtime \(blocked by waiting timeout of locks, events, or semaphores\).
- Exit: The thread stops running and waits for the parent thread to reclaim its control block resources.
**Figure 1** Thread state transition

**Thread State Transition:**
- Init→Ready:
When a thread is created, the thread obtains the control block and enters the Init state \(initialization\). After the initialization is complete, the thread is inserted into the scheduling queue and enters the Ready state.
- Ready→Running:
When a thread switching is triggered, the thread with the highest priority in the Ready queue is executed and enters the Running state. Then, this thread is deleted from the Ready queue.
- Running→Blocked:
When a running thread is blocked \(for example, is pended, delayed, or reading semaphores\), its state changes from Running to Blocked. Then, a thread switching is triggered to run the thread with the highest priority in the Ready queue.
- Blocked→Ready:
After the blocked thread is restored \(the thread is restored, the delay times out, the semaphore reading times out, or the semaphore is read\), the thread is added to the Ready queue and changes from the Blocked state to the Ready state.
- Ready→Blocked:
A thread may also be blocked \(suspended\) in the Ready state. The blocked thread will change from the Ready state to the Blocked state and is deleted from the Ready queue. The thread will not be scheduled until it is restored.
- Running→Ready:
After a thread with a higher priority is created or restored, threads will be scheduled. The thread with the highest priority in the Ready queue will change to the Running state. The originally running thread will change from the Running state to the Ready state and be added to the Ready queue.
- Running→Exit:
When a running thread is terminated, its state changes from Running to Exit. If the thread is set with a detach attribute \(**LOS\_TASK\_STATUS\_DETACHED**\), it will be directly destroyed after the running is complete.
## Working Principles
The OpenHarmony thread management module provides the following functions: creating, delaying, suspending, and restoring threads, locking and unlocking thread scheduling, and querying thread control block information by ID.
When a thread is created, the system initializes the thread stack and presets the context. The system places the thread entry function in the corresponding position so that the function will be executed when the thread enters the Running state for the first time.
## Development Guidelines
### Available APIs
Category
|
API
|
Description
|
Thread creation and deletion
|
LOS_TaskCreateOnly
|
Creates a thread and places the thread in the Init state but not be scheduled.
|
LOS_TaskCreate
|
Creates a thread and places the thread in the Init state and be scheduled.
|
LOS_TaskDelete
|
Deletes the specified thread.
|
Thread status control
|
LOS_TaskResume
|
Resumes a suspended thread.
|
LOS_TaskSuspend
|
Suspends the specified thread.
|
LOS_TaskDelay
|
Delays a thread.
|
LOS_TaskYield
|
Adjusts the scheduling sequence of threads that call the thread priority.
|
Thread scheduling control
|
LOS_TaskLock
|
Locks thread scheduling.
|
LOS_TaskUnlock
|
Unlocks thread scheduling.
|
Thread priority control
|
LOS_CurTaskPriSet
|
Sets the priority for the current thread.
|
LOS_TaskPriSet
|
Sets the priority of the specified thread.
|
LOS_TaskPriGet
|
Obtains the priority of the specified thread.
|
Obtaining thread information
|
LOS_CurTaskIDGet
|
Obtains the ID of the current thread.
|
LOS_TaskInfoGet
|
Obtains information about the specific thread.
|
Binding threads to CPU cores
|
LOS_TaskCpuAffiSet
|
Binds a specified thread to a specified CPU. It is used only in multi-core scenarios.
|
LOS_TaskCpuAffiGet
|
Obtains the core binding information of a specified thread. It is used only in multi-core scenarios.
|
Thread scheduling parameter control
|
LOS_GetTaskScheduler
|
Obtains the scheduling policy of the specified thread.
|
LOS_SetTaskScheduler
|
Sets the scheduling parameters, including the priority and scheduling policy, for the specified thread.
|
Maximum number of threads supported
|
LOS_GetSystemTaskMaximum
|
Obtains the maximum number of threads supported by the system.
|
### How to Develop
The typical thread development process is as follows:
1. Call **LOS\_TaskCreate** to create a thread.
- Specify the execution entry function for the thread.
- Specify the thread name.
- Specify the thread stack size.
- Specify the priority of the thread.
- Specify the thread attribute, that is, whether to support the **LOS\_TASK\_STATUS\_DETACHED** attribute.
- Specify the thread-core binding attribute for multi-core environment.
2. Run the service code to implement thread scheduling.
3. After the thread execution is complete, the thread resources are automatically reclaimed if the **LOS\_TASK\_STATUS\_DETACHED** attribute is set. If the **LOS\_TASK\_STATUS\_DETACHED** attribute is not set, call the **LOS\_TaskDelete** API to reclaim the thread resources.
> **NOTE:**
>- The kernel space has the highest permission and can operate threads in any process.
>- The thread created by calling a user-space process in the kernel space is a KProcess, not a user-space process.
### Development Example
The sample code is as follows:
```
UINT32 g_taskLoID;
UINT32 g_taskHiID;
#define TSK_PRIOR_HI 4
#define TSK_PRIOR_LO 5
UINT32 ExampleTaskHi(VOID)
{
UINT32 ret;
PRINTK("Enter TaskHi Handler.\n");
/* Delay the thread for 2 ticks. The task is then suspended, and the remaining task with the highest priority (g_taskLoID) will be executed.*/
ret = LOS_TaskDelay(2);
if (ret != LOS_OK) {
PRINTK("Delay Task Failed.\n");
return LOS_NOK;
}
/*After 2 ticks elapse, the task is resumed and executed.*/
PRINTK("TaskHi LOS_TaskDelay Done.\n");
/* Suspend the task.*/
ret = LOS_TaskSuspend(g_taskHiID);
if (ret != LOS_OK) {
PRINTK("Suspend TaskHi Failed.\n");
return LOS_NOK;
}
PRINTK("TaskHi LOS_TaskResume Success.\n");
return LOS_OK;
}
/* Entry function of the lower-priority task */
UINT32 ExampleTaskLo(VOID)
{
UINT32 ret;
PRINTK("Enter TaskLo Handler.\n");
/* Delay the thread for 2 ticks. The task is then suspended, and the remaining task with the highest priority (background task) will be executed.*/
ret = LOS_TaskDelay(2);
if (ret != LOS_OK) {
PRINTK("Delay TaskLo Failed.\n");
return LOS_NOK;
}
PRINTK("TaskHi LOS_TaskSuspend Success.\n");
/* Resume the suspended task g_taskHiID.*/
ret = LOS_TaskResume(g_taskHiID);
if (ret != LOS_OK) {
PRINTK("Resume TaskHi Failed.\n");
return LOS_NOK;
}
PRINTK("TaskHi LOS_TaskDelete Success.\n");
return LOS_OK;
}
/* Task test entry function, which is used to create two tasks with different priorities.*/
UINT32 ExampleTaskCaseEntry(VOID)
{
UINT32 ret;
TSK_INIT_PARAM_S initParam = {0};
/* Lock task scheduling.*/
LOS_TaskLock();
PRINTK("LOS_TaskLock() Success!\n");
initParam.pfnTaskEntry = (TSK_ENTRY_FUNC)ExampleTaskHi;
initParam.usTaskPrio = TSK_PRIOR_HI;
initParam.pcName = "HIGH_NAME";
initParam.uwStackSize = LOS_TASK_MIN_STACK_SIZE;
initParam.uwResved = LOS_TASK_STATUS_DETACHED;
/* Create a task with a higher priority. The task will not be executed immediately after being created, because task scheduling is locked.*/
ret = LOS_TaskCreate(&g_taskHiID, &initParam);
if (ret != LOS_OK) {
LOS_TaskUnlock();
PRINTK("ExampleTaskHi create Failed! ret=%d\n", ret);
return LOS_NOK;
}
PRINTK("ExampleTaskHi create Success!\n");
initParam.pfnTaskEntry = (TSK_ENTRY_FUNC)ExampleTaskLo;
initParam.usTaskPrio = TSK_PRIOR_LO;
initParam.pcName = "LOW_NAME";
initParam.uwStackSize = LOS_TASK_MIN_STACK_SIZE;
initParam.uwResved = LOS_TASK_STATUS_DETACHED;
/*Create a task with a lower priority. The task will not be executed immediately after being created, because task scheduling is locked.*/
ret = LOS_TaskCreate(&g_taskLoID, &initParam);
if (ret!= LOS_OK) {
LOS_TaskUnlock();
PRINTK("ExampleTaskLo create Failed!\n");
return LOS_NOK;
}
PRINTK("ExampleTaskLo create Success!\n");
/* Unlock task scheduling. The task with the highest priority in the Ready queue will be executed.*/
LOS_TaskUnlock();
while(1){};
return LOS_OK;
}
```
The development is successful if the return result is as follows:
```
LOS_TaskLock() Success!
ExampleTaskHi create Success!
ExampleTaskLo create Success!
Enter TaskHi Handler.
Enter TaskLo Handler.
TaskHi LOS_TaskDelay Done.
TaskHi LOS_TaskSuspend Success.
TaskHi LOS_TaskResume Success.
TaskHi LOS_TaskDelete Success.
```