Operations 10 min read

Linux Real-Time Thread CPU Selection Process

The article details Linux’s real‑time thread CPU‑selection process, explaining how priorities (0‑99 for rt, 100‑139 for CFS) set the sched_class, how functions like select_task_rq_rt, find_lowest_rq, cpupri_find_fitness and __cpupri_find build a candidate CPU mask, and how the final CPU is chosen by previous affinity, domain order, wake‑up CPU or random selection, while warning that excessive rt tasks can increase power use and cause scheduling delays.

OPPO Kernel Craftsman
OPPO Kernel Craftsman
OPPO Kernel Craftsman
Linux Real-Time Thread CPU Selection Process

In Linux, some threads need to be scheduled fairly so that each thread gets CPU time, which is handled by the CFS (Completely Fair Scheduler) class. However, certain critical threads (e.g., display refresh threads) must be scheduled promptly. For light workloads, normal scheduling is sufficient, but as background tasks increase—especially on Android devices—real-time processes become necessary to guarantee timely execution.

Linux distinguishes non‑real‑time and real‑time threads by priority. The system defines 140 priority levels (0‑139); a smaller number means higher priority. Real‑time (rt) threads occupy priorities 0‑99, while non‑real‑time (CFS) threads use 100‑139. The default priority for a CFS thread is 120, derived from its nice value (range -20 to 19), which can be viewed in the NI column of ps .

This article mainly explains the CPU‑selection flow for rt threads.

rt CPU‑selection flow introduction

When a task is woken up, it starts from try_to_wake_up . The function select_task_rq chooses an appropriate CPU based on the task's sched_class . The sched_class is set when the system changes or sets the task's priority.

If a thread is rt, its sched_class is rt_sched_class . The structure definition is shown below:

The CPU‑selection function for rt threads is select_task_rq_rt . Its basic execution logic is illustrated in Figure 1.

Figure 1

The rt selection flow is relatively simple; its core logic resides in the find_lowest_rq function, which searches for CPUs suitable for the current rt thread. The main logic is shown in Figure 2.

Figure 2

The function cpupri_find_fitness extracts all CPUs that satisfy the task's conditions and stores them in lowest_mask . Afterwards, find_lowest_rq selects a suitable CPU from this mask using the following logic:

If lowest_mask contains the task's previous CPU, choose that CPU directly.

Otherwise, pick the first CPU within the task's scheduling domain that appears in lowest_mask .

If still not found, and lowest_mask contains the wake‑up CPU, return the wake‑up CPU.

If none of the above succeed and lowest_mask is not empty, select a random CPU from the mask.

Below is a deeper look at how cpupri_find_fitness determines the suitable CPUs. The process consists of three parts, illustrated in Figure 3.

Figure 3

First, the task's priority is transformed into 0‑102 levels, classified as invalid, idle, normal, and rt. Invalid priority is 0, idle is 1, all CFS threads belong to level 2, and each rt priority occupies its own level.

Because rt threads are preemptive, a for‑loop iterates from the lowest priority upward (now expressed as 103 levels). The selection prefers idle CPUs, then CPUs running CFS tasks, and finally CPUs that can preempt lower‑priority rt tasks. The function __cpupri_find checks the status of each priority on each CPU. The cpupri_vec structure has two members: count (the number of CPUs where a given priority is the highest) and mask (the CPU mask where that priority is highest). For example, if CPUs 0‑5 have no CFS tasks, the count for normal tasks is 6 and the mask is 0x3f.

The basic logic of __cpupri_find is:

Determine on which CPUs the current priority is the highest. If none, the priority either has no tasks or is not the highest on any CPU.

From those CPUs, remove those that are not allowed for the task and those that are isolated. If lowest_mask still contains CPUs, it becomes the basis for the next selection step.

After obtaining lowest_mask , CPUs that cannot satisfy the task's capacity are filtered out. The remaining mask represents CPUs that can run the task. If the mask becomes empty, the algorithm proceeds to the next higher priority level and repeats the search.

If the current loop fails to find a suitable CPU, another iteration is performed to try again.

In summary, the rt CPU‑selection process involves converting task priority, locating candidate CPUs with cpupri_find_fitness , refining the candidate set with __cpupri_find , and finally choosing a CPU based on the rules described above.

Conclusion

This article explains the Linux rt thread CPU‑selection flow from a code perspective, helping readers understand how rt threads are scheduled and how they can mitigate latency‑related performance issues. While rt threads are simpler than CFS threads (they ignore energy considerations), an excess of rt tasks can increase power consumption and, in heavily loaded scenarios, may cause scheduling delays for other important workloads. Therefore, the number of rt tasks should be kept reasonable.

References

[1] https://mirrors.edge.kernel.org/pub/linux/

[2] "Understanding the Linux Kernel" (3rd Edition), B. Bovey & C. Sistern, translated by Chen Lijun, Feng Rui, Niu Xinyuan.

[3] http://www.wowotech.net/process_management/process-priority.html (Linux scheduler – process priority)

Long‑press to follow the "Kernel Artisan" WeChat account.

Linux Kernel Black Tech | Technical Articles | Curated Tutorials

LinuxKernelCPU Selectionreal-time schedulingRT-Thread
OPPO Kernel Craftsman
Written by

OPPO Kernel Craftsman

Sharing Linux kernel-related cutting-edge technology, technical articles, technical news, and curated tutorials

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.