Preemption
抢占时机
1、主动让出cpu(不管用户态还是内核态):yield() or schedule()
2、用户态抢占:用户态运行的程序,通过syscall、exception、interrupt事件,进入内核态;当返回用户态时,是一个抢占触发点;调度器会根据具体情况,判断是否抢占当前进程。
3、内核态抢占:
- CONFIG_PREEMPT_NONE:内核线程如果不主动yield或sleep,就不会被抢占!
- CONFIG_PREEMPT_VOLUNTRY:如果内核线程不主动让出cpu,也不会被抢占;不过使能该配置后,内核会在其API中增加很多抢占点,在这些抢占点内核会主动判断是否需要reschedule,并执行切换。
- CONFIG_PREEMPT & CONFIG_PREEMPT_RT:使能内核抢占;不过当处理中断或执行disable_preempt()区域代码时,会出现一些latency。
下面是针对几个内核配置,抢占执行情况示例图:
Linux的几种抢占模型
PREEMPT_NONE:
- No Forced Preemption (Server)
- This model is suitable for servers as it optimizes performance by prioritizing batch tasks while minimizing latency .
- Uses low timer cycles of 100hz to 250hz.
- Minimize context switching
PREEMPT_VOLUNTARY:
- Voluntary Kernel Preemption (Desktop)
- In APIs or drivers that are expected to take a long time, preemption points can be placed in between to allow tasks that have requested rescheduling to be preempted first. (Change the schedule at necessary preemption points in between.)
- This model is suitable for desktops as it allows for keyboard, mouse, and multimedia operations by increasing the response speed (latency) to a certain degree and also guarantees a certain level of performance .
- preemption points
- We reduced preemption latency by adding explicit preemption points to several codes running in kernel mode, checking if a reschedule is needed often and increasing the frequency at which preemption should be used.
- With the help of these preemption points, we were able to reduce the latency required to start urgent tasks to less than 100us.
- A preemption point is usually added to routines that take more than 1ms (100us).
- There are currently close to a thousand preemption points in the kernel(内核里有接近1000抢占点!)
PREEMPT:
- Preemptible Kernel (Low-Latency Desktop)
- Even in kernel mode, preemption is always allowed except in a few cases (also PREEMPT_RT), so that higher priority tasks are scheduled first most of the time. Therefore, when this option is used, preemption points are unnecessary and are replaced by empty codes.
- This model is suitable for embedded systems such as network devices that require a latency of approximately milliseconds and a fast response speed (latency).
PREEMPT_RT:
- Fully Preemptible Kernel (Real-Time)
- Recently, it was officially registered in the mainline starting with kernel v5.3-rc1.
- sched/rt, Kconfig: Introduce CONFIG_PREEMPT_RT (2019, v5.3-rc1)
- Meanwhile, kernel mainliners have been concerned about the full preempt kernel. It is because of the performance degradation, which is also the reason why it has not been included in the mainline. (Reference: Optimizing preemption | LWN.net)
- Since most timers and various devices' interrupt processing is done in the bottom-half by default, the time blocked due to hardirq processing is shortened. Therefore, this model is suitable for systems that require real-time interrupt processing .
- Added hard mode and soft mode flags to hrtimer, and it operates in soft mode by default. Soft mode processes bottom-half so that the timer function runs on the rt thread, and hard mode processes hardirq.
- Only systems with architecture support can use it.
Preemption Point
might_sleep()
# define might_sleep() do { might_resched(); } while (0)
might_resched()
#ifdef CONFIG_PREEMPT_VOLUNTARY
# define might_resched() _cond_resched()
#else
# define might_resched() do { } while (0)
#endif
cond_resched()
#define cond_resched() ({ \
___might_sleep(__FILE__, __LINE__, 0); \
_cond_resched(); \
})
preempt_count
ARM64架构下,preempt_count的定义:
跟preempt_count相关的操作类函数:
跟preempt_count相关的查询类函数:
跟preempt_count相关的判断类函数: