An interrupt is a signal to the processor emitted by hardware or software indicating an event that needs immediate attention. An interrupt alerts the processor of a high-priority condition requiring interruption of the code being executed by the processor. In this way, the CPU does not need to spend a lot of time in waiting and querying the peripheral status, which effectively improves the real-time performance and execution efficiency of the system.
Exception handling involves a series of actions taken by the OS to respond to exceptions \(chip hardware faults\) that occurred during the OS running, for example, printing the call stack information of the current function, CPU information, and call stack information of tasks when the virtual memory page is missing.
OpenHarmony supports the following interrupt operations:
## Working Principles<a name="section2792838318"></a>
+ Initializing an interrupt.
+ Creating an interrupt.
+ Enabling or disabling interrupts.
+ Restoring the system status before interrupts are disabled.
+ Deleting an interrupt.
Peripherals can complete certain work without the intervention of the CPU. In some cases, however, the CPU needs to perform certain work for peripherals. With the interrupt mechanism, the CPU responds to the interrupt request from a peripheral only when required, and execute other tasks when the peripherals do not require the CPU. The interrupt controller receives the input of other peripheral interrupt pins and sends interrupt signals to the CPU. You can enable or disable the interrupt source and set the priority and trigger mode of the interrupt source by programming the interrupt controller. Common interrupt controllers include vector interrupt controllers \(VICs\) and general interrupt controllers \(GICs\). The ARM Cortex-A7 uses GICs. After receiving an interrupt signal sent by the interrupt controller, the CPU interrupts the current task to respond to the interrupt request.
Exception handling involves a series of actions taken by the OS to respond to exceptions (chip hardware faults) that occurred during the OS running, for example, printing the call stack information of the current function, CPU information, and call stack information of tasks when the virtual memory page is missing.
Exception handling interrupts the normal running process of the CPU to handle exceptions, such as, undefined instructions, an attempt to modify read-only data, and unaligned address access. When an exception occurs, the CPU suspends the current program, handles the exception, and then continues to execute the program interrupted by the exception.
## Working Principles
Peripherals can complete certain work without the intervention of the CPU. In some cases, however, the CPU needs to perform certain work for peripherals. With the interrupt mechanism, the CPU responds to the interrupt request from a peripheral only when required, and execute other tasks when the peripherals do not require the CPU.
The interrupt controller receives the input from the interrupt pins of other peripherals and sends interrupt signals to the CPU. You can enable or disable the interrupt source and set the priority and trigger mode of the interrupt source by programming the interrupt controller. Common interrupt controllers include vector interrupt controllers (VICs) and general interrupt controllers (GICs). The ARM Cortex-A7 uses GICs.
After receiving an interrupt signal sent by the interrupt controller, the CPU interrupts the current task to respond to the interrupt request.
An exception interrupts the normal running process of the CPU to handle exceptions, such as, undefined instructions, an attempt to modify read-only data, and unaligned address access. When an exception occurs, the CPU suspends the current program, handles the exception, and then continues to execute the program interrupted by the exception.
The following uses the ARMv7-a architecture as an example. The interrupt vector table is the entry for interrupt and exception handling. The interrupt vector table contains the entry function for each interrupt and exception handling.
<tbody><trid="row8706123317311"><tdclass="cellrowborder"rowspan="2"valign="top"width="19.900000000000002%"headers="mcps1.1.4.1.1 "><pid="p4706193319318"><aname="p4706193319318"></a><aname="p4706193319318"></a>Creating or deleting interrupts</p>
<tdclass="cellrowborder"valign="top"width="61.67%"headers="mcps1.1.4.1.3 "><pid="p15706833163110"><aname="p15706833163110"></a><aname="p15706833163110"></a>Creates an interrupt and registers the interrupt ID, interrupt triggering mode, interrupt priority, and interrupt handler. When an interrupt is triggered, the interrupt handler will be called.</p>
<tdclass="cellrowborder"valign="top"headers="mcps1.1.4.1.2 "><pid="p770616333313"><aname="p770616333313"></a><aname="p770616333313"></a>Deletes an interrupt.</p>
</td>
</tr>
<trid="row1370633316316"><tdclass="cellrowborder"rowspan="3"valign="top"width="19.900000000000002%"headers="mcps1.1.4.1.1 "><pid="p970611333318"><aname="p970611333318"></a><aname="p970611333318"></a>Enabling and disabling all interrupts</p>
<tdclass="cellrowborder"valign="top"width="61.67%"headers="mcps1.1.4.1.3 "><pid="p93681327171713"><aname="p93681327171713"></a><aname="p93681327171713"></a>Enables all interrupts of the current processor.</p>
<tdclass="cellrowborder"valign="top"headers="mcps1.1.4.1.2 "><pid="p1161283971712"><aname="p1161283971712"></a><aname="p1161283971712"></a>Disables all interrupts for the current processor.</p>
<tdclass="cellrowborder"valign="top"headers="mcps1.1.4.1.2 "><pid="p1470643323112"><aname="p1470643323112"></a><aname="p1470643323112"></a>Restores to the status before all interrupts are disabled by using <strongid="b354311504226"><aname="b354311504226"></a><aname="b354311504226"></a>LOS_IntLock</strong>.</p>
</td>
</tr>
<trid="row870793320317"><tdclass="cellrowborder"valign="top"width="19.900000000000002%"headers="mcps1.1.4.1.1 "><pid="p1970763318316"><aname="p1970763318316"></a><aname="p1970763318316"></a>Obtaining the maximum number of interrupts supported</p>
<tdclass="cellrowborder"valign="top"width="61.67%"headers="mcps1.1.4.1.3 "><pid="p4707173323111"><aname="p4707173323111"></a><aname="p4707173323111"></a>Obtains the maximum number of interrupts supported by the system.</p>
</td>
</tr>
</tbody>
</table>
### How to Develop<a name="section64332181221"></a>
1. Call **LOS\_HwiCreate** to create an interrupt.
2. Call **LOS\_HwiDelete** to delete the specified interrupt. Use this API based on actual requirements.
### Development Example<a name="section204698276478"></a>
## Development Guidelines
### Available APIs
Exception handling is an internal mechanism and does not provide external APIs. The following tables describe the APIs available for the interrupt module.
| LOS_HwiCreate | Creates an interrupt and registers the interrupt ID, triggering mode, priority, and interrupt handler. When the interrupt is triggered, the interrupt handler will be called.|
| LOS_HwiDelete | Deletes an interrupt based on the interrupt number. |
| LOS_GetSystemHwiMaximum | Obtains the maximum number of interrupts supported by the system.|
### How to Develop
1. Call **LOS_HwiCreate** to create an interrupt.
2. Call **LOS_HwiDelete** to delete the specified interrupt. Use this API based on actual requirements.
### Development Example
This example implements the following:
1. Create an interrupt.
2. Delete an interrupt.
The following sample code shows how to create and delete an interrupt. When the interrupt **HWI\_NUM\_TEST** is generated, the interrupt handler function will be called.
The following sample code demostrates how to create and delete an interrupt, and call the interrupt handler when the specified interrupt **HWI_NUM_TEST** is triggered. You can add the test function of the sample code to **TestTaskEntry** in **kernel/liteos_a/testsuites/kernel/src/osTest.c** for testing.
```
The sample code is as follows:
```c
#include "los_hwi.h"
/* Interrupt handler function*/
STATICVOIDHwiUsrIrq(VOID)
{
printf("in the func HwiUsrIrq \n");
PRINTK("in the func HwiUsrIrq \n");
}
staticUINT32Example_Interrupt(VOID)
{
UINT32ret;
HWI_HANDLE_T hwiNum = 7;
HWI_PRIOR_T hwiPrio = 3;
HWI_HANDLE_ThwiNum=7;// The interrupt number is 7.
HWI_PRIOR_ThwiPrio=3;// The interrupt priority is 3.
A process is the minimum unit for system resource management. The process module provided by the OpenHarmony LiteOS-A kernel is used to isolate user-mode processes. The kernel mode is considered as a process space and does not have other processes except KIdle, which is an idle process provided by the system and shares the same process space with KProcess.
A process is the minimum unit for system resource management. The process module provided by the OpenHarmony LiteOS-A kernel isolates user-mode processes. The kernel mode is considered as a process space and does not have other processes except KIdle, which is an idle process provided by the system and shares the same process space with KProcess. KProcess is the root process of kernel-mode processes, and KIdle is its child process.
- The process module provides multiple processes for users and implements switching and communication between processes, facilitating your management over service programs.
- The processes use the preemption scheduling mechanism. The processes with a higher priority are scheduled first, and the processes with the same priority are scheduled using the time slice polling.
- The processes are assigned 32 priorities \(**0** to **31**\). Among them, user processes can be configured with 22 priorities from **10**\(highest\) to **31**\(lowest\).
- The processes use the preemption scheduling mechanism. The processes with a higher priority are scheduled first, and the processes with the same priority are scheduled using the time slice round robin.
- The processes are assigned 32 priorities (**0** to **31**). Among them, user processes can be configured with 22 priorities from **10** (highest) to **31** (lowest).
- A higher-priority process can preempt the resources of a lower-priority process. The lower-priority process can be scheduled only after the higher-priority process is blocked or terminated.
- Each user-mode process has its own memory space, which is invisible to other processes. In this way, processes are isolated from each other.
- The user-mode root process **init** is created by the kernel. Other user-mode processes are created by the **init** process via the **fork** call.
**Process States:**
**Process States**
- Init: The process is being created.
- Ready: The process is in the Ready queue and waits for scheduling by the CPU.
- Running: The process is running.
- Pending: The process is blocked and suspended. When all threads in a process are blocked, the process is blocked and suspended.
- Zombies: The process stops running and waits for the parent process to reclaim its control block resources.
**Figure 1** Process state transition<aname="fig536823565718"></a>
When a process is created, the process enters the Init state after obtaining the process control block to start initialization. After the process is initialized, the process is inserted into the scheduling queue and therefore enters the Ready state.
- Init→Ready:
When a process is created or forked, the process enters the Init state after obtaining the process control block. When the process initialization is complete, the process is added to the scheduling queue, and the process enters the Ready state.
- Ready→Running:
When a process switchover is triggered, the process with the highest priority in the Ready queue is executed and enters the Running state. If this process has no thread in the Ready state, the process is deleted from the Ready queue and resides only in the Running state. If it has threads in the Ready state, the process still stays in the Ready queue. In this case, the process is in both the Ready and Running states, but presented as the Running state.
When process switching occurs, the process that has the highest priority and time slice in the Ready queue is executed and enters the Running state. If this process has no thread in the Ready state, the process is deleted from the Ready queue and resides only in the Running state. If it has threads in the Ready state, the process still stays in the Ready queue. In this case, the process is in both the Ready and Running states, but presented as the Running state.
- Running→Pending:
When the last thread of a process enters the Pending state, all threads in the process are in the Pending state. Then, the process enters the Pending state, and process switching occurs.
- Pending→Ready:
When any thread in a Pending process restores to the Ready state, the process is added to the Ready queue and changes to the Ready state.
- Ready→Pending:
When the last ready thread in a process enters the Pending state, the process is deleted from the Ready queue, and the process changes from the Ready state to the Pending state.
- Running→Ready:
A process may change from the Running state to the Ready state in either of the following scenarios:
1. After a process with a higher priority is created or restored, processes will be scheduled. The process with the highest priority in the Ready queue will change to the Running state, and the originally running process will change from the Running state to the Ready state.
2. If scheduling policy for a process is **LOS\_SCHED\_RR** and its priority is the same as that of another process in the Ready state, this process will change from the Running state to the Ready state after its time slices are used up, and the other process with the same priority will change from the Ready state to the Running state.
2. If scheduling policy for a process is **LOS_SCHED_RR** (time slice round robin) and its priority is the same as that of another process in the Ready state, this process will change from the Running state to the Ready state after its time slices are used up, and the other process with the same priority will change from the Ready state to the Running state.
- Running→Zombies:
After the main thread or all threads of a process are stopped, the process changes from the **Running** state to the **Zombies** state and waits for the parent process to reclaim resources.
## Working Principles<a name="section174514474512"></a>
## Working Principles
The OpenHarmony process module is used to isolate user-mode processes and supports the following functions: creating and exiting user-mode processes, reclaiming process resources, setting and obtaining scheduling parameters and process group IDs, and obtaining process IDs.
...
...
@@ -66,105 +68,65 @@ A user-mode process is created by forking a parent process. During forking, the
A process is only a resource management unit, and the actual running is executed by threads in the process. When switching occurs between threads in different processes, the process space will be switched.
**Figure 2** Process management<aname="fig123709256334"></a>
<tdclass="cellrowborder"valign="top"width="33.33333333333333%"headers="mcps1.2.4.1.3 "><pid="p205724410813"><aname="p205724410813"></a><aname="p205724410813"></a>Obtains the scheduling policy of the specified process.</p>
<tdclass="cellrowborder"valign="top"headers="mcps1.2.4.1.2 "><pid="p18572443819"><aname="p18572443819"></a><aname="p18572443819"></a>Sets the scheduling parameters, including the priority and scheduling policy, for the specified process.</p>
<tdclass="cellrowborder"valign="top"headers="mcps1.2.4.1.2 "><pid="p95710448818"><aname="p95710448818"></a><aname="p95710448818"></a>Obtains the priority of the specified process.</p>
<tdclass="cellrowborder"valign="top"headers="mcps1.2.4.1.2 "><pid="p16573445819"><aname="p16573445819"></a><aname="p16573445819"></a>Sets the priority of the specified process.</p>
</td>
</tr>
<trid="row162882182816"><tdclass="cellrowborder"valign="top"width="33.33333333333333%"headers="mcps1.2.4.1.1 "><pid="p175734417814"><aname="p175734417814"></a><aname="p175734417814"></a>Waiting for reclaiming child processes</p>
<tdclass="cellrowborder"valign="top"width="33.33333333333333%"headers="mcps1.2.4.1.3 "><pid="p5578441687"><aname="p5578441687"></a><aname="p5578441687"></a>Waits for the specified child process to terminate, and reclaims its resources.</p>
<tdclass="cellrowborder"valign="top"width="33.33333333333333%"headers="mcps1.2.4.1.3 "><pid="p145704416818"><aname="p145704416818"></a><aname="p145704416818"></a>Obtains the process group ID of the specified process.</p>
<tdclass="cellrowborder"valign="top"headers="mcps1.2.4.1.2 "><pid="p165816445819"><aname="p165816445819"></a><aname="p165816445819"></a>Obtains the process group ID of the current process.</p>
</td>
</tr>
<trid="row1260011213718"><tdclass="cellrowborder"valign="top"width="33.33333333333333%"headers="mcps1.2.4.1.1 "><pid="p125818441781"><aname="p125818441781"></a><aname="p125818441781"></a>Obtaining the process ID.</p>
<tdclass="cellrowborder"valign="top"width="33.33333333333333%"headers="mcps1.2.4.1.3 "><pid="p1058644687"><aname="p1058644687"></a><aname="p1058644687"></a>Obtains the ID of the current process.</p>
</td>
</tr>
<trid="row060019121871"><tdclass="cellrowborder"rowspan="3"valign="top"width="33.33333333333333%"headers="mcps1.2.4.1.1 "><pid="p145810441285"><aname="p145810441285"></a><aname="p145810441285"></a>User and user group</p>
<tdclass="cellrowborder"valign="top"width="33.33333333333333%"headers="mcps1.2.4.1.3 "><pid="p7581944287"><aname="p7581944287"></a><aname="p7581944287"></a>Obtains the user ID of the current process.</p>
<tdclass="cellrowborder"valign="top"headers="mcps1.2.4.1.2 "><pid="p3581444382"><aname="p3581444382"></a><aname="p3581444382"></a>Obtains the user group ID of the current process.</p>
<tdclass="cellrowborder"valign="top"headers="mcps1.2.4.1.2 "><pid="p5581144689"><aname="p5581144689"></a><aname="p5581144689"></a>Checks whether the specified user group ID is in the user group of the current process.</p>
</td>
</tr>
<trid="row317461111812"><tdclass="cellrowborder"valign="top"width="33.33333333333333%"headers="mcps1.2.4.1.1 "><pid="p105814419818"><aname="p105814419818"></a><aname="p105814419818"></a>Maximum number of processes supported</p>
<tdclass="cellrowborder"valign="top"width="33.33333333333333%"headers="mcps1.2.4.1.3 "><pid="p115818441187"><aname="p115818441187"></a><aname="p115818441187"></a>Obtains the maximum number of processes supported by the system.</p>
</td>
</tr>
</tbody>
</table>
### How to Develop<a name="section1533674618526"></a>
>- The number of idle threads depends on the number of CPU cores. Each CPU has a corresponding idle thread.
> **NOTE**
>
> - The number of idle threads depends on the number of CPU cores. Each CPU has a corresponding idle thread.
>- Except KProcess and KIdle, other kernel-mode processes cannot be created.
>- If a thread is created after a user-mode process enters the kernel mode by a system call, the thread belongs to a KProcess not a user-mode process.
> - If a thread is created after a user-mode process enters the kernel mode by a system call, the thread belongs to a KProcess not a user-mode process.
The OpenHarmony LiteOS-A kernel uses the preemptive scheduling mechanism for tasks. The tasks with a higher priority are scheduled first, and the tasks with the same priority are scheduled using the time slice polling. The system runs based on the real-time timeline from the startup, which ensures good real-time performance of the scheduling algorithm.
The OpenHarmony scheduling algorithm is embedded with the tickless mechanism, which ensures lower power consumption and on-demand response to tick interrupts. This minimizes useless tick interrupt response time and further improves the real-time performance of the system.
The OpenHarmony process scheduling policy is **SCHED\_RR**, and the thread scheduling policy can be **SCHED\_RR** or **SCHED\_FIFO**.
OpenHarmony supports **SCHED_RR** (time slice round robin) for process scheduling and **SCHED_RR** and **SCHED_FIFO** (first in, first out) for thread scheduling .
Threads are the minimum scheduling units in the OpenHarmony.
Threads are the minimum scheduling units in OpenHarmony.
## Working Principles<a name="section143015396572"></a>
The OpenHarmony uses process priority queue and thread priority queue for scheduling. The process priority ranges from 0 to 31, and there are 32 process priority bucket queues. Each bucket queue corresponds to a thread priority bucket queue. The thread priority ranges from 0 to 31, and a thread priority bucket queue also has 32 priority queues.
## Working Principles
OpenHarmony uses process priority queue and thread priority queue for scheduling. The process priority ranges from 0 to 31, and there are 32 process priority bucket queues. Each bucket queue corresponds to a thread priority bucket queue. The thread priority ranges from 0 to 31, and a thread priority bucket queue also has 32 priority queues.
The OpenHarmony system starts scheduling after the kernel initialization is complete. The processes or threads created during running are added to the scheduling queues. The system selects the optimal thread for scheduling based on the priorities of the processes and threads and the time slice consumption of the threads. Once a thread is scheduled, it is deleted from the scheduling queue. If a thread is blocked during running, the thread is added to the corresponding blocking queue and triggers scheduling of another thread. If no thread in the scheduling queue can be scheduled, the system selects the thread of the KIdle process for scheduling.
<tdclass="cellrowborder"valign="top"width="33.33333333333333%"headers="mcps1.1.4.1.3 "><pid="p181303297387"><aname="p181303297387"></a><aname="p181303297387"></a>Triggers system scheduling.</p>
</td>
</tr>
</tbody>
</table>
### How to Develop<a name="section1015110331584"></a>
Tasks 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.
In the OpenHarmony kernel, a task represents a thread.
Tasks in the processes of the same priority in the OpenHarmony kernel are scheduled and run in a unified manner.
Tasks for the processes of the same priority in the OpenHarmony kernel are scheduled and run in a unified manner.
The tasks in the kernel use the preemptive scheduling mechanism, either round-robin \(RR\) scheduling or First In First Out \(FIFO\) scheduling.
The tasks in the kernel use the preemptive scheduling mechanism, either round-robin (RR) scheduling or First In First Out (FIFO) scheduling.
Tasks are assigned 32 priorities, ranging from **0**\(highest\) to **31**\(lowest\).
Tasks are assigned 32 priorities, ranging from **0** (highest) to **31** (lowest).
In the same process, a higher-priority task can preempt resources of a lower-priority task. The lower-priority task can be scheduled only after the higher-priority task is blocked or terminated.
**Task Status Description**
**Task States**
- Init: The task is being created.
- Ready: The task is in the Ready queue and waits for scheduling by the CPU.
- Running: The task is running.
- Blocked: The task 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\).
- Blocked: The task 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 task is complete and waits for the parent task to reclaim its control block resources.
**Figure 1** Task state transition<aname="fig5251243193113"></a>
When a task is created, the task obtains the control block and enters the Init state \(initialization\). After the initialization is complete, the task is inserted into the scheduling queue and enters the Ready state.
When a task is created, the task obtains the control block and enters the Init state (initialization). After the initialization is complete, the task is inserted into the scheduling queue and enters the Ready state.
- Ready→Running:
When a task switching is triggered, the task with the highest priority in the Ready queue is executed and enters the Running state. Then, this task is deleted from the Ready queue.
- Running→Blocked:
When a running task is blocked \(for example, is pended, delayed, or reading semaphores\), its state changes from Running to Blocked. Then, a task switching is triggered to run the task with the highest priority in the Ready queue.
When a running task is blocked (for example, is pended, delayed, or reading semaphores), its state changes from Running to Blocked. Then, a task switching is triggered to run the task with the highest priority in the Ready queue.
- Blocked→Ready:
After the blocked task is restored \(the task is restored, the delay times out, the semaphore reading times out, or the semaphore is read\), the task is added to the Ready queue and will change from the Blocked state to the Ready state.
After the blocked task is restored (the task is restored, the delay times out, the semaphore reading times out, or the semaphore is read), the task is added to the Ready queue and will change from the Blocked state to the Ready state.
- Ready→Blocked:
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.
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.
- Running→Ready:
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 is added to the Ready queue.
- Running→Exit:
When a running task is complete, it changes to the Exit state. If the task is set with a detach attribute \(**LOS\_TASK\_STATUS\_DETACHED**\), it will be directly destroyed after being terminated.
When a running task is complete, it changes to the Exit state. If the task has a detach attribute (set by **LOS_TASK_STATUS_DETACHED** in **los_task.h**), it will be destroyed directly.
## Working Principles<a name="section1381918945512"></a>
## Working Principles
The OpenHarmony task management module provides the following functions: creating, delaying, suspending, and restoring tasks, locking and unlocking task scheduling, and querying task control block information by ID.
When a task is created, the system initializes the task stack and presets the context. The system also 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.
## Development Guidelines<a name="section10649727135519"></a>
### Available APIs<a name="section78333315555"></a>
<tbody><trid="row431611256303"><tdclass="cellrowborder"rowspan="3"valign="top"width="33.33333333333333%"headers="mcps1.1.4.1.1 "><pid="p0297202573015"><aname="p0297202573015"></a><aname="p0297202573015"></a>Task creation and deletion</p>
<tdclass="cellrowborder"valign="top"width="33.33333333333333%"headers="mcps1.1.4.1.3 "><pid="p12297825123016"><aname="p12297825123016"></a><aname="p12297825123016"></a>Creates a task and places the task in the Init state without scheduling.</p>
<tdclass="cellrowborder"valign="top"headers="mcps1.1.4.1.2 "><pid="p19297122518303"><aname="p19297122518303"></a><aname="p19297122518303"></a>Creates a task and places it in the Init state for scheduling.</p>
<tdclass="cellrowborder"valign="top"headers="mcps1.1.4.1.2 "><pid="p3297162517308"><aname="p3297162517308"></a><aname="p3297162517308"></a>Deletes the specified task.</p>
</td>
</tr>
<trid="row13316112533020"><tdclass="cellrowborder"rowspan="6"valign="top"width="33.33333333333333%"headers="mcps1.1.4.1.1 "><pid="p172979255306"><aname="p172979255306"></a><aname="p172979255306"></a>Task status control</p>
<tdclass="cellrowborder"valign="top"width="33.33333333333333%"headers="mcps1.1.4.1.3 "><pid="p1929732593018"><aname="p1929732593018"></a><aname="p1929732593018"></a>Resumes a suspended task.</p>
<tdclass="cellrowborder"valign="top"headers="mcps1.1.4.1.2 "><pid="p8297182563015"><aname="p8297182563015"></a><aname="p8297182563015"></a>Suspends the specified task.</p>
<tdclass="cellrowborder"valign="top"headers="mcps1.1.4.1.2 "><pid="p28851313104213"><aname="p28851313104213"></a><aname="p28851313104213"></a>Suspends this task till the specified task is complete and the task control block resources are reclaimed.</p>
<tdclass="cellrowborder"valign="top"headers="mcps1.1.4.1.2 "><pid="p188851813184219"><aname="p188851813184219"></a><aname="p188851813184219"></a>Changes the task attribute from <strongid="b1986175411125"><aname="b1986175411125"></a><aname="b1986175411125"></a>joinable</strong> to <strongid="b18996959101215"><aname="b18996959101215"></a><aname="b18996959101215"></a>detach</strong>. After the task of the <strongid="b15851429171317"><aname="b15851429171317"></a><aname="b15851429171317"></a>detach</strong> attribute is complete, the task control block resources will be automatically reclaimed.</p>
<tdclass="cellrowborder"valign="top"headers="mcps1.1.4.1.2 "><pid="p1297182517306"><aname="p1297182517306"></a><aname="p1297182517306"></a>Delays a task.</p>
<tdclass="cellrowborder"valign="top"headers="mcps1.1.4.1.2 "><pid="p2297325163019"><aname="p2297325163019"></a><aname="p2297325163019"></a>Adjusts the scheduling sequence of tasks that call the task priority.</p>
<tdclass="cellrowborder"valign="top"width="33.33333333333333%"headers="mcps1.1.4.1.3 "><pid="p142981925183020"><aname="p142981925183020"></a><aname="p142981925183020"></a>Sets the priority for the current task.</p>
<tdclass="cellrowborder"valign="top"headers="mcps1.1.4.1.2 "><pid="p629822563014"><aname="p629822563014"></a><aname="p629822563014"></a>Sets the priority for a specified task.</p>
<tdclass="cellrowborder"valign="top"headers="mcps1.1.4.1.2 "><pid="p19298182563018"><aname="p19298182563018"></a><aname="p19298182563018"></a>Obtains the priority of a specified task.</p>
<tdclass="cellrowborder"valign="top"width="33.33333333333333%"headers="mcps1.1.4.1.3 "><pid="p1029842519303"><aname="p1029842519303"></a><aname="p1029842519303"></a>Obtains the ID of the current task.</p>
<tdclass="cellrowborder"valign="top"headers="mcps1.1.4.1.2 "><pid="p122988259303"><aname="p122988259303"></a><aname="p122988259303"></a>Obtains information about the specified task.</p>
</td>
</tr>
<trid="row93146250305"><tdclass="cellrowborder"rowspan="2"valign="top"width="33.33333333333333%"headers="mcps1.1.4.1.1 "><pid="p82986256300"><aname="p82986256300"></a><aname="p82986256300"></a>Binding tasks to CPU cores</p>
<tdclass="cellrowborder"valign="top"width="33.33333333333333%"headers="mcps1.1.4.1.3 "><pid="p82981925163013"><aname="p82981925163013"></a><aname="p82981925163013"></a>Binds a specified task to the specified CPU. It is used only in multi-core scenarios.</p>
<tdclass="cellrowborder"valign="top"headers="mcps1.1.4.1.2 "><pid="p1729822513017"><aname="p1729822513017"></a><aname="p1729822513017"></a>Obtains the core binding information of the specified task. It is used only in multi-core scenarios.</p>
<tdclass="cellrowborder"valign="top"width="33.33333333333333%"headers="mcps1.1.4.1.3 "><pid="p1298182513010"><aname="p1298182513010"></a><aname="p1298182513010"></a>Obtains the scheduling policy of the specified task.</p>
<tdclass="cellrowborder"valign="top"headers="mcps1.1.4.1.2 "><pid="p11298172553015"><aname="p11298172553015"></a><aname="p11298172553015"></a>Sets the scheduling parameters, including the priority and scheduling policy, for the specified task.</p>
</td>
</tr>
<trid="row831492514307"><tdclass="cellrowborder"valign="top"width="33.33333333333333%"headers="mcps1.1.4.1.1 "><pid="p12981250307"><aname="p12981250307"></a><aname="p12981250307"></a>Maximum number of tasks supported</p>
<tdclass="cellrowborder"valign="top"width="33.33333333333333%"headers="mcps1.1.4.1.3 "><pid="p6298525123017"><aname="p6298525123017"></a><aname="p6298525123017"></a>Obtains the maximum number of tasks supported by the system.</p>
</td>
</tr>
</tbody>
</table>
### How to Develop<a name="section16229657115514"></a>
When a user creates a task, 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.
| LOS_TaskCreate | Creates a task. If the priority of the created task is higher than that of the task in running and task scheduling is not locked, the task will be scheduled to run. |
| LOS_TaskCreateOnly | Creates a task and blocks it. The task will not be added to the Ready queue unless it is resumed. |
| LOS_TaskDelete | Deletes a task and reclaims the resources consumed by the task control block and task stack. |
| LOS_TaskSuspend | Suspends a task. The suspended task will be removed from the Ready queue. |
| LOS_TaskJoin | Blocks the current task until the specified task is complete, and reclaims its resources. |
| LOS_TaskDetach | Changes the task attribute from **joinable** to **detach**. When a task of the **detach** attribute is complete, the task control block resources will be automatically reclaimed.|
| LOS_TaskDelay | Delays the current task for the specified time (number of ticks). |
| LOS_TaskYield | Moves the current task from the queue of the tasks with the same priority to the end of the Ready queue.|
| LOS_TaskUnlock | Unlocks task scheduling. After that, the task lock count decrements by 1. If a task is locked multiple times, the task can be scheduled only when the number of locks is reduced to 0. |
| LOS_GetTaskScheduler | Obtains the scheduling policy of a task. |
| LOS_SetTaskScheduler | Sets the scheduling parameters, including the priority and scheduling policy, for a task. |
| LOS_Schedule | Triggers active task scheduling. |
| LOS_TaskCpuAffiSet | Binds a task to the specified CPU core. This API is used only in multi-core CPUs.|
| LOS_TaskCpuAffiGet | Obtains information about the core binding of a task. This API is used only in multi-core CPUs. |
### How to Develop
The typical task development process is as follows:
1. Call **LOS\_TaskCreate** to create a task.
1.Call **LOS_TaskCreate** to create a task.
- Specify the execution entry function for the task.
- Specifies the task name.
- Specify the task stack size.
- Specify the priority of the task.
- Specify the task attribute, which can be **LOS\_TASK\_ATTR\_JOINABLE** or **LOS\_TASK\_STATUS\_DETACHED**.
- Specify the task attribute, which can be **LOS_TASK_ATTR_JOINABLE** or **LOS_TASK_STATUS_DETACHED**.
- Specify the task-core binding attribute for multi-core environment.
2. Run the service code to implement task scheduling.
3. Reclaim resources when the task is complete. If the task attribute is **LOS\_TASK\_STATUS\_DETACHED**, the task resources are automatically reclaimed. If the task attribute is **LOS\_TASK\_ATTR\_JOINABLE**, call **LOS\_TaskJoin** to reclaim task resources. The default task attribute is **LOS\_TASK\_STATUS\_DETACHED**.
>- The kernel mode has the highest permission and can operate tasks in any process.
>- If a task is created after a user-mode process enters the kernel mode by a system call, the task belongs to a KProcess not a user-mode process.
3. Reclaim resources when the task is complete. If the task attribute is **LOS_TASK_STATUS_DETACHED**, the task resources are automatically reclaimed. If the task attribute is **LOS_TASK_ATTR_JOINABLE**, call **LOS_TaskJoin** to reclaim task resources. The default task attribute is **LOS_TASK_STATUS_DETACHED**.
### Development Example<a name="section2809723165612"></a>
> **NOTE**
>
> - The kernel mode has the highest permission and can operate tasks in any process.
>
> - If a task is created after a user-mode process enters the kernel mode by a system call, the task belongs to a KProcess not a user-mode process.
The sample code is as follows:
```
### Development Example
The sample code is as follows. You can add the test function of the sample code to **TestTaskEntry** in **kernel/liteos_a/testsuites/kernel/src /osTest.c** for testing
```c
UINT32g_taskLoID;
UINT32g_taskHiID;
#define TSK_PRIOR_HI 4
...
...
@@ -231,15 +158,15 @@ UINT32 ExampleTaskHi(VOID)
{
UINT32ret;
PRINTK("Enter TaskHi Handler.\n");
/* Delay the task for 2 ticks. The task is then suspended, and the remaining task with the highest priority (g_taskLoID) will be executed.*/
/* Delay the task for 2 ticks. The task is 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");
returnLOS_NOK;
}
/* After 2 ticks elapse, the task is resumed and executed.*/
/* After 2 ticks elapse, the task is resumed and executed.*/
PRINTK("TaskHi LOS_TaskDelay Done.\n");
/* Suspend the task.*/
/* Suspend the task.*/
ret=LOS_TaskSuspend(g_taskHiID);
if(ret!=LOS_OK){
PRINTK("Suspend TaskHi Failed.\n");
...
...
@@ -249,19 +176,19 @@ UINT32 ExampleTaskHi(VOID)
returnLOS_OK;
}
/* Entry function of the lower-priority task */
/* Entry function of the low-priority task. */
UINT32ExampleTaskLo(VOID)
{
UINT32ret;
PRINTK("Enter TaskLo Handler.\n");
/* Delay the task for 2 ticks. The task is then suspended, and the remaining task with the highest priority (background task) will be executed.*/
/* Delay the task for 2 ticks. The task is 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");
returnLOS_NOK;
}
PRINTK("TaskHi LOS_TaskSuspend Success.\n");
/* Resume the suspended task g_taskHiID.*/
/* Resume the suspended task g_taskHiID.*/
ret=LOS_TaskResume(g_taskHiID);
if(ret!=LOS_OK){
PRINTK("Resume TaskHi Failed.\n");
...
...
@@ -270,22 +197,23 @@ UINT32 ExampleTaskLo(VOID)
PRINTK("TaskHi LOS_TaskDelete Success.\n");
returnLOS_OK;
}
/* Task test entry function, which is used to create two tasks with different priorities.*/
/* Create two tasks with different priorities in the task test entry function. */
UINT32ExampleTaskCaseEntry(VOID)
{
UINT32ret;
TSK_INIT_PARAM_SinitParam={0};
/* Lock task scheduling.*/
/* Lock task scheduling.*/
LOS_TaskLock();
PRINTK("LOS_TaskLock() Success!\n");
/* Parameters used to initialize the high-priority task, the resources of which can be reclaimed by LOS_TaskJoin. */
The kernel startup process consists of the assembly startup and C language startup, as shown in the following figure.
The kernel startup process consists of the assembly startup and C language startup, as shown in **Figure 1**.
The assembly startup involves the following operations: initializing CPU settings, disabling dCache/iCache, enabling the FPU and NEON, setting the MMU to establish the virtual-physical address mapping, setting the system stack, clearing the BSS segment, and calling the main function of the C language.
The C language startup involves the following operations: starting the **OsMain** function and starting scheduling. As shown in the following figure, the **OsMain** function is used for basic kernel initialization and architecture- and board-level initialization. The kernel startup framework leads the initialization process. The right part of the figure shows the phase in which external modules can register with the kernel startup framework and starts. The table below describes each phase.
The C language startup involves the following operations: starting the **OsMain** function and starting scheduling.
**OsMain()** is used for basic kernel initialization and architecture- and board-level initialization. The kernel startup framework leads the initialization process. The right part of the figure shows the phase in which external modules can register with the kernel startup framework and starts. **Table 1** describes each phase.
| LOS_INIT_LEVEL_EARLIEST | Earliest initialization.<br>The initialization is architecture-independent. The board and subsequent modules initialize the pure software modules on which they depend.<br>Example: trace module|
| LOS_INIT_LEVEL_ARCH_EARLY | Early initialization of the architecture.<br>The initialization is architecture-dependent. Subsequent modules initialize the modules on which they depend. It is recommended that functions not required for startup be placed at **LOS_INIT_LEVEL_ARCH**.|
...
...
@@ -28,54 +30,52 @@ The C language startup involves the following operations: starting the **OsMain*
| LOS_INIT_LEVEL_KMOD_BASIC | Initialization of the kernel basic modules.<br>Initialize the basic modules that can be detached from the kernel.<br>Example: VFS initialization|
| LOS_INIT_LEVEL_KMOD_EXTENDED | Initialization of the kernel extended modules.<br>Initialize the extended modules that can be detached from the kernel.<br>Example: initialization of system call, ProcFS, Futex, HiLog, HiEvent, and LiteIPC|
| LOS_INIT_LEVEL_KMOD_TASK | Kernel task creation.<br>Create kernel tasks (kernel tasks and software timer tasks).<br>Example: creation of the resident resource reclaiming task, SystemInit task, and CPU usage statistics task|
| LOS_INIT_LEVEL_FINISH | Complete of the kernel initialization.|
## Programming Example
## Development Example
**Example Description**
Add a kernel module and register the initialization function of the module to the kernel startup process through the kernel startup framework, so as to complete the module initialization during the kernel initialization process.
You can compile and verify the sample code in **kernel/liteos_a/testsuites/kernel/src/osTest.c**.
**Sample Code**
```
```c
/* Header file of the kernel startup framework */
#include "los_init.h"
...
/* Initialization function of the new module */
unsignedintOsSampleModInit(void)
{
PRINTK("OsSampleModInit SUCCESS!\n");
......
}
...
/* Register the new module at the target level of the kernel startup framework. */
/* The print information may vary depending on the running environment. */
...
/* Print the initialization function of the new module in the test code. */
OsSampleModInit SUCCESS!
releasing 1 secondary cores
cpu 1 entering scheduler
cpu 0 entering scheduler
```
According to the information displayed during the system startup, the kernel has called the initialization function of the registered module during the startup to initialize the module.
According to the information displayed during the system startup, the kernel calls the initialization function of the registered module during the startup to initialize the module.
> Modules at the same level cannot depend on each other. It is recommended that a new module be split based on the preceding startup phase and be registered and started as required.
> Modules of the same level cannot depend on each other. It is recommended that a new module be split based on the preceding startup phase and be registered and started as required.
>
> You can view the symbol table in the **.rodata.init.kernel.*** segment of the **OHOS_Image.map** file generated after the build is complete, so as to learn about the initialization entry of each module that has been registered with the kernel startup framework and check whether the newly registered initialization entry has taken effect.
During system startup, **OsUserInitProcess** is called to start the **init** process. The procedure is as follows:
> **NOTE**
>
> The preceeding code is in **kernel/liteos_a/kernel/user/src/los_user_init.c**. The value of **g_initPath** can be **/dev/shm/init** or **/bin/init**, depending on the startup settings.
1. The kernel calls **OsLoadUserInit** to load the code.
2. A process space is created to start the **/bin/init** process.
Use **OsUserInitProcess** to start the **init** process. The procedure is as follows:
### Responsibilities of the Root Process<a name="section1590220321759"></a>
1. The kernel calls **OsLoadUserInit** to load the code for startup.
2. A process space is created to start the **/bin/init** process.
- Starts key system programs or services, such as shell.
>In OpenHarmony, the **init** process reads the **/etc/init.cfg** file and runs specified commands or starts specified processes based on configurations. For details, see [init Module](../subsystems/subsys-boot-init-cfg.md).
### Responsibilities of the Root Process
- The root process starts key system programs or services, such as shell.
> **NOTE**
> In OpenHarmony, the **init** process reads **/etc/init.cfg** and runs commands or starts processes based on the configuration. For details, see [init Configuration File](../subsystems/subsys-boot-init-cfg.md).
- Monitors the process for reclaiming the orphan process and clears the zombie processes in child processes.
-The root process monitors the process for reclaiming the orphan process and clears the zombie processes in child processes.
## Running Programs in User Mode<a name="section194576310611"></a>
## Running Programs in User Mode
A user-mode program can be started in either of the following ways:
- Run the shell command to start the process.
-Using shell commands
```
OHOS $ exec helloworld
...
...
@@ -52,9 +59,6 @@ A user-mode program can be started in either of the following ways:
OHOS $ /bin/helloworld
```
- Start a new process by calling the POSIX API.
Use the **Fork\(\)** method to create a process, and call the **exec\(\)** method to execute a new process.
- Using POSIX APIs
Use **Fork()** to create a process, and call **exec()** to execute a process.