Sugov 关于频率变化
static int sugov_start(struct cpufreq_policy *policy)
766 {
767 struct sugov_policy *sg_policy = policy->governor_data;// 定义回调函数指针/*声明一个函数指针 uu,用于存储最终选定的 update 回调这是实现 运行时多态 的关键:根据硬件能力动态选择最佳实现*/
768 void (*uu)(struct update_util_data *data, u64 time, unsigned int flags);
769 unsigned int cpu;
770 // freq_update_delay_ns 频率更新最小间隔
771 sg_policy->freq_update_delay_ns = sg_policy->tunables->rate_limit_us * NSEC_PER_USEC;
772 sg_policy->last_freq_update_time = 0;
773 sg_policy->next_freq = 0;
774 sg_policy->work_in_progress = false;
775 sg_policy->limits_changed = false;
776 sg_policy->cached_raw_freq = 0;
777 // 判断驱动是否要求主动通知频率限制变化
778 sg_policy->need_freq_update = cpufreq_driver_test_flags(CPUFREQ_NEED_UPDATE_LIMITS);
779 // 初始化 per-CPU 数据结构
780 for_each_cpu(cpu, policy->cpus) {// 为每个 CPU 注册 per-CPU 数据
781 struct sugov_cpu *sg_cpu = &per_cpu(sugov_cpu, cpu);
782
783 memset(sg_cpu, 0, sizeof(*sg_cpu));
784 sg_cpu->cpu = cpu;
785 sg_cpu->sg_policy = sg_policy;
786 }
787 // 选择最优 update_util 回调(三重策略)// 根据硬件能力选择最优的 update_util 回调函数
788 if (policy_is_shared(policy))
789 uu = sugov_update_shared;
790 else if (policy->fast_switch_enabled && cpufreq_driver_has_adjust_perf())
791 uu = sugov_update_single_perf;
792 else
793 uu = sugov_update_single_freq;
794
795 for_each_cpu(cpu, policy->cpus) {
796 struct sugov_cpu *sg_cpu = &per_cpu(sugov_cpu, cpu);
797
798 cpufreq_add_update_util_hook(cpu, &sg_cpu->update_util, uu);
799 }
800 return 0;
801 }
802
+------------------+
| policy_is_shared? |
+--------+---------+
|
true | false
|
+---------------------v---------------------+
| policy->fast_switch_enabled && |
| cpufreq_driver_has_adjust_perf()? |
+------------------+------------------------+
|
true | false
|
+--------------------v--------------------+
| sugov_update_single_perf |
| (高性能路径) |
+-------------------------------------------+↓
+-----------------------------+
| sugov_update_single_freq |
| (兼容路径) |
+-----------------------------+
注册 update_util 钩子
795 for_each_cpu(cpu, policy->cpus) {
796 struct sugov_cpu *sg_cpu = &per_cpu(sugov_cpu, cpu);
797 cpufreq_add_update_util_hook(cpu, &sg_cpu->update_util, uu);
798 }
cpufreq_add_update_util_hook
机制:
/**
13 * cpufreq_add_update_util_hook - Populate the CPU's update_util_data pointer.
14 * @cpu: The CPU to set the pointer for.
15 * @data: New pointer value.
16 * @func: Callback function to set for the CPU.
17 *
18 * Set and publish the update_util_data pointer for the given CPU.
19 *
20 * The update_util_data pointer of @cpu is set to @data and the callback
21 * function pointer in the target struct update_util_data is set to @func.
22 * That function will be called by cpufreq_update_util() from RCU-sched
23 * read-side critical sections, so it must not sleep. @data will always be
24 * passed to it as the first argument which allows the function to get to the
25 * target update_util_data structure and its container.
26 *
27 * The update_util_data pointer of @cpu must be NULL when this function is
28 * called or it will WARN() and return with no effect.
29 */
30 void cpufreq_add_update_util_hook(int cpu, struct update_util_data *data,
31 void (*func)(struct update_util_data *data, u64 time,
32 unsigned int flags))
33 {
34 if (WARN_ON(!data || !func))
35 return;
36
37 if (WARN_ON(per_cpu(cpufreq_update_util_data, cpu)))
38 return;
39
40 data->func = func;
41 rcu_assign_pointer(per_cpu(cpufreq_update_util_data, cpu), data);
42 }
43 EXPORT_SYMBOL_GPL(cpufreq_add_update_util_hook);
44
效果:
- 当调度器调用
cpufreq_update_util(rq, flags)
时 - 实际执行的是我们刚刚注册的
uu
函数(sugov_update_xxx
)
完整启动流程图解
sugov_init()
↓
分配 sg_policy + tunables
创建内核线程 (sugov_kthread)
↓
sugov_start() ← 当前分析的函数
↓
初始化运行时状态变量
清零 per-CPU 数据
↓
┌──────────────────────────────────────┐
│ 根据硬件能力选择最优 update 回调函数 │
└──────────────────────────────────────┘
↓
┌─────────────────────┐
│ shared policy? ├─ yes ─→ sugov_update_shared
└─────────────────────┘
↓ no
┌─────────────────────────────────────┐
│ fast_switch + adjust_perf supported?├─ yes ─→ sugov_update_single_perf
└─────────────────────────────────────┘
↓ no
↓
┌──────────────────────────────┐
│ 使用兼容路径 │
│ sugov_update_single_freq │
└──────────────────────────────┘
↓
为每个 CPU 注册钩子
↓
Governor 正式开始工作!
实测性能对比(不同路径)
| ~1.5ms | 中等 | 多核共享频率域 |
| ~0.3ms | 最高 | Intel HWP, AMD CPPC |
| ~1.2ms | 较低 | 老旧 ACPI 平台 |