学习一下kernel6.12中sugov_iowait_apply的函数逻辑
一.函数实现
/**
318 * sugov_iowait_apply() - Apply the IO boost to a CPU.
319 * @sg_cpu: the sugov data for the cpu to boost
320 * @time: the update time from the caller
321 * @max_cap: the max CPU capacity
322 *
323 * A CPU running a task which woken up after an IO operation can have its
324 * utilization boosted to speed up the completion of those IO operations.
325 * The IO boost value is increased each time a task wakes up from IO, in
326 * sugov_iowait_apply(), and it's instead decreased by this function,
327 * each time an increase has not been requested (!iowait_boost_pending).
328 *
329 * A CPU which also appears to have been idle for at least one tick has also
330 * its IO boost utilization reset.
331 *
332 * This mechanism is designed to boost high frequently IO waiting tasks, while
333 * being more conservative on tasks which does sporadic IO operations.
334 */
335 static unsigned long sugov_iowait_apply(struct sugov_cpu *sg_cpu, u64 time,
336 unsigned long max_cap)
337 {
338 /* No boost currently required */// 如果当前无 I/O boost 需求,返回 0
339 if (!sg_cpu->iowait_boost)
340 return 0;
341
342 /* Reset boost if the CPU appears to have been idle enough */// CPU 是否 空闲超过一个 tick(通常 4ms)// 如果是,说明 没有活跃的 I/O 任务,重置 boost
343 if (sugov_iowait_reset(sg_cpu, time, false))
344 return 0;
345 // iowait_boost_pending:由 sugov_update() 在检测到 I/O 唤醒任务 时置为 true// 如果本次调用 没有新 I/O 唤醒(pending == false),说明 I/O 活动减少,逐步衰减 boost// 衰减方式:每次减半(指数衰减),直到低于阈值(IOWAIT_BOOST_MIN)后清零。
346 if (!sg_cpu->iowait_boost_pending) {
347 /*
348 * No boost pending; reduce the boost value.
349 */
350 sg_cpu->iowait_boost >>= 1;
351 if (sg_cpu->iowait_boost < IOWAIT_BOOST_MIN) {
352 sg_cpu->iowait_boost = 0;
353 return 0;
354 }
355 }
356 // 本轮处理完成,重置 pending
357 sg_cpu->iowait_boost_pending = false;
358
359 /*
360 * sg_cpu->util is already in capacity scale; convert iowait_boost
361 * into the same scale so we can compare.
362 */// 此处将其 转换为与 util 相同的算力 scale(0~max_cap)
363 return (sg_cpu->iowait_boost * max_cap) >> SCHED_CAPACITY_SHIFT;
364 }
365 这段代码是 Linux schedutil(sugov)调频策略中的 I/O Wait Boost(I/O 等待加速)机制 的核心部分。它的目标是:
当任务因等待 I/O(如磁盘、网络)而阻塞后被唤醒时,临时提升 CPU 频率,加速后续处理,从而改善 I/O 延迟和系统响应性。
🎯 二、为什么需要 I/O Boost?
场景举例:
数据库写入:
- 应用线程写数据到磁盘 → 进入 D 状态(不可中断睡眠);
- I/O 完成后,线程被唤醒 → 需要快速处理回调、释放锁、响应客户端;
- 如果此时 CPU 频率很低(因之前睡眠被降频),处理延迟会很高。
UI 应用加载资源:
- 从磁盘加载图片 → 睡眠;
- 唤醒后解码、渲染;
- 若 CPU 频率未及时提升,用户会感到卡顿。
❌ 问题:
- 任务在 I/O 睡眠期间,CPU 利用率(util_avg)趋近于 0;
schedutil会因此 大幅降低 CPU 频率;- 但任务唤醒后 立刻需要高性能,频率爬升需要时间(几十~几百毫秒);
- 结果:I/O 延迟增加,用户体验下降。
✅ I/O Boost 的作用:
在任务因 I/O 唤醒时,强制 CPU 频率快速提升,避免“唤醒后性能饥饿”。
▶ 函数参数:
sg_cpu:当前 CPU 的 sugov 数据;time:当前时间(用于判断是否空闲);max_cap:该 CPU 的最大算力(如 1024)
🔄 二、I/O Boost 的完整工作流程
- 任务因 I/O 睡眠 →
util_avg下降 → CPU 降频; - I/O 完成,任务被唤醒 → 调度器调用
cpufreq_update_util(); - sugov 检测到
SCHED_CPUFREQ_IOWAIT标志 → 设置:
sg_cpu->iowait_boost = max(sg_cpu->iowait_boost << 1, IOWAIT_BOOST_MIN);
sg_cpu->iowait_boost_pending = true
- 下次频率更新时 →
sugov_iowait_apply()被调用:- 若有 pending → 保持或提升 boost;
- 若无 pending → 衰减 boost;
- boost 值参与最终频率计算:
target_util = max(util, iowait_boost_value);
📌 总结
sugov_iowait_apply()的作用:
管理 I/O wait boost 的 衰减与重置,返回当前应施加的 boost 值。为什么要 I/O boost:
解决 “I/O 唤醒后 CPU 频率滞后” 问题,提升交互响应性和 I/O 吞吐。关键机制:
- 唤醒时提升 boost;
- 无新 I/O 时指数衰减;
- 空闲时重置;
- 仅对高频 I/O 任务持续生效。
