【policy】【driver】【governor】
之前看过interactive调度器,对应的还有ondemand、performance等调度器,调度器是上层策略,而调度器的实现则是通过policy来实现的。
policy
Governor是调频的上层策略, policy是一次调频操作的实体 (句柄), 一个policy可以与多个cpu对应.
struct cpufreq_policy {/* CPUs sharing clock, require sw coordination(协调) */cpumask_var_t cpus; /* Online CPUs only */cpumask_var_t related_cpus; /* Online + Offline CPUs */cpumask_var_t real_cpus; /* Related and present */unsigned int shared_type; /* ACPI: ANY or ALL affected CPUsshould set cpufreq */// policy的managed cpu号. 一般为注册policy的cpu; 当该cpu offline时, // 会选取cpus的下一cpu作为新的managed cpu. 此时前面的cpu称为last_cpu.unsigned int cpu; /* cpu managing this policy, must be online */struct clk *clk;// 硬件特性struct cpufreq_cpuinfo cpuinfo;/* see above */// 软件特性unsigned int min; /* in kHz */unsigned int max; /* in kHz */unsigned int cur; /* in kHz, only needed if cpufreq* governors are used */// 类似变频之前的freq和目标frequnsigned int restore_freq; /* = policy->cur before transition */unsigned int target_freq; /* freq that the policy wants to set */unsigned int suspend_freq; /* freq to set during suspend */unsigned int policy; /* see above */unsigned int last_policy; /* policy before unplug(拔核) */// 当前使用的governor,governor_data是tuables,governor_enabled是witch开关struct cpufreq_governor *governor; /* see below */void *governor_data;bool governor_enabled; /* governor start/stop flag */// 因为governor是可以切换的char last_governor[CPUFREQ_NAME_LEN]; /* last governor used */struct work_struct update; /* if update_policy() needs to be* called, but you're in IRQ context */// user_policy一般用于保存原始参数,因为温度过高的时候最大频率可能会发生变化struct cpufreq_user_policy user_policy;struct cpufreq_frequency_table *freq_table;struct list_head policy_list;struct kobject kobj;struct completion kobj_unregister;struct notifier_block pm_qos_freq_nb;/** The rules for this semaphore:* - Any routine that wants to read from the policy structure will* do a down_read on this semaphore.* - Any routine that will write to the policy structure and/or may take away* the policy altogether (eg. CPU hotplug), will hold this lock in write* mode before doing so.** Additional rules:* - Lock should not be held across* __cpufreq_governor(data, CPUFREQ_GOV_POLICY_EXIT);*/struct rw_semaphore rwsem;(信号量)/** Fast switch flags:* - fast_switch_possible should be set by the driver if it can* guarantee that frequency can be changed on any CPU sharing the* policy and that the change will affect all of the policy CPUs then.* - fast_switch_enabled is to be set by governors that support fast* freqnency switching with the help of cpufreq_enable_fast_switch().*/bool fast_switch_possible;bool fast_switch_enabled;/** Preferred average time interval between consecutive invocations of* the driver to set the frequency for this policy. To be set by the* scaling driver (0, which is the default, means no preference).*/unsigned int up_transition_delay_us;unsigned int down_transition_delay_us;/* Cached frequency lookup from cpufreq_driver_resolve_freq. */unsigned int cached_target_freq;int cached_resolved_idx;/* Synchronization for frequency transitions */bool transition_ongoing; /* Tracks transition status */spinlock_t transition_lock;wait_queue_head_t transition_wait;struct task_struct *transition_task; /* Task which is doing the transition *//* cpufreq-stats */// 对应的是stat这个节点struct cpufreq_stats *stats;/* For cpufreq driver's internal use */void *driver_data;
};
其中
struct cpufreq_cpuinfo {// 硬件特性unsigned int max_freq;unsigned int min_freq;/* in 10^(-9) s = nanoseconds */纳秒为单位unsigned int transition_latency;
};
struct cpufreq_user_policy {unsigned int min; /* in kHz */unsigned int max; /* in kHz */
};
不管具体的驱动如何变化,核心层都提供了节点,而不是每家驱动各自添加的,这就解释了为什么不同芯片厂商,只要架构是相同的,他们的节点就都相同
/*** show_cpuinfo_cur_freq - current CPU frequency as detected by hardware*/
static ssize_t show_cpuinfo_cur_freq(struct cpufreq_policy *policy,char *buf)
{unsigned int cur_freq = __cpufreq_get(policy);if (cur_freq)return sprintf(buf, "%u\n", cur_freq);return sprintf(buf, "<unknown>\n");
}
/*** show_scaling_driver - show the cpufreq driver currently loaded*/
static ssize_t show_scaling_driver(struct cpufreq_policy *policy, char *buf)
{return scnprintf(buf, CPUFREQ_NAME_PLEN, "%s\n", cpufreq_driver->name);
}
/*** show_scaling_governor - show the current policy for the specified CPU*/static ssize_t show_scaling_governor(struct cpufreq_policy *policy, char *buf)
{// 也就是说policy里面的powersave和performance,和governor里面的是不一样的嘛!if (policy->policy == CPUFREQ_POLICY_POWERSAVE)return sprintf(buf, "powersave\n");else if (policy->policy == CPUFREQ_POLICY_PERFORMANCE)return sprintf(buf, "performance\n");else if (policy->governor)return scnprintf(buf, CPUFREQ_NAME_PLEN, "%s\n", policy->governor->name);return -EINVAL;
}
static ssize_t show_scaling_cur_freq(struct cpufreq_policy *policy, char *buf)
{ssize_t ret;if (cpufreq_driver && cpufreq_driver->setpolicy && cpufreq_driver->get)ret = sprintf(buf, "%u\n", cpufreq_driver->get(policy->cpu));elseret = sprintf(buf, "%u\n", policy->cur);return ret;
}
static ssize_t show_scaling_cur_freq(struct cpufreq_policy *policy, char *buf)
{ssize_t ret;// 一般都是没有设置setpolicy函数的if (cpufreq_driver && cpufreq_driver->setpolicy && cpufreq_driver->get)ret = sprintf(buf, "%u\n", cpufreq_driver->get(policy->cpu));elseret = sprintf(buf, "%u\n", policy->cur);return ret;
}
driver
struct cpufreq_driver {char name[CPUFREQ_NAME_LEN];u8 flags;void *driver_data;/* needed by all drivers */int (*init)(struct cpufreq_policy *policy);int (*verify)(struct cpufreq_policy *policy);//检查policy的参数是否被支持// 定义下面两个中的一个/* define one out of two *///如果不支持通过governor选择合适的运行频率,则实现setpolicy回调函数,//这样系统只能支持CPUFREQ_POLICY_POWERSAVE和CPUFREQ_POLICY_PERFORMANCE这两种工作策略 int (*setpolicy)(struct cpufreq_policy *policy);/** On failure, should always restore frequency to policy->restore_freq* (i.e. old freq).*///实现target回调函数,通过target回调设定governor所需要的频率//target或者target_index设定目标频率int (*target)(struct cpufreq_policy *policy,unsigned int target_freq,unsigned int relation); /* Deprecated */int (*target_index)(struct cpufreq_policy *policy,unsigned int index);/** Only for drivers with target_index() and CPUFREQ_ASYNC_NOTIFICATION* unset.** get_intermediate should return a stable intermediate frequency* platform wants to switch to and target_intermediate() should set CPU* to to that frequency, before jumping to the frequency corresponding* to 'index'. Core will take care of sending notifications and driver* doesn't have to handle them in target_intermediate() or* target_index().** Drivers can return '0' from get_intermediate() in case they don't* wish to switch to intermediate frequency for some target frequency.* In that case core will directly call ->target_index().*/unsigned int (*get_intermediate)(struct cpufreq_policy *policy,unsigned int index);int (*target_intermediate)(struct cpufreq_policy *policy,unsigned int index);/* should be defined, if possible */// 从硬件获取当前frequnsigned int (*get)(unsigned int cpu);/* optional */int (*bios_limit)(int cpu, unsigned int *limit);// 与init对应int (*exit)(struct cpufreq_policy *policy);void (*stop_cpu)(struct cpufreq_policy *policy);// 针对boot cpu, 因为其他cpu已经在suspend前offline了int (*suspend)(struct cpufreq_policy *policy);int (*resume)(struct cpufreq_policy *policy);/* Will be called after the driver is fully initialized */void (*ready)(struct cpufreq_policy *policy);struct freq_attr **attr;/* platform specific boost support code */bool boost_supported;bool boost_enabled;int (*set_boost)(int state);
};
governor
struct cpufreq_governor {char name[CPUFREQ_NAME_LEN];int initialized;//指向一个回调函数,CPUFreq Core会在不同的阶段调用该回调函数,用于该governor的启动、停止、初始化、退出动作int (*governor) (struct cpufreq_policy *policy,unsigned int event);ssize_t (*show_setspeed) (struct cpufreq_policy *policy,char *buf);int (*store_setspeed) (struct cpufreq_policy *policy,unsigned int freq);unsigned int max_transition_latency; /* HW must be able to switch tonext freq faster than this value in nano secs or wewill fallback to performance governor *///所有注册的governor都会利用该字段链接在一个全局链表中,以供系统查询和使用struct list_head governor_list;struct module *owner;
};
【policy】【driver】【governor】相关推荐
- MyBatis-学习笔记01【01.Mybatis课程介绍及环境搭建】
Java后端 学习路线 笔记汇总表[黑马程序员] MyBatis-学习笔记01[01.Mybatis课程介绍及环境搭建][day01] MyBatis-学习笔记02[02.Mybatis入门案例] M ...
- 【复杂系统迁移 .NET Core平台系列】之调度服务改造
源宝导读:微软跨平台技术框架-.NET Core已经日趋成熟,已经具备了支撑大型系统稳定运行的条件.本文将介绍明源云ERP平台从.NET Framework向.NET Core迁移过程中的实践经验. ...
- 【复杂系统迁移 .NET Core平台系列】之认证和授权
源宝导读:微软跨平台技术框架-.NET Core已经日趋成熟,已经具备了支撑大型系统稳定运行的条件.本文将介绍明源云ERP平台从.NET Framework向.NET Core迁移过程中的实践经验. ...
- jdbc mysql分页_JDBC【数据库连接池、DbUtils框架、分页】
1.数据库连接池 什么是数据库连接池 简单来说:数据库连接池就是提供连接的... 为什么我们要使用数据库连接池 数据库的连接的建立和关闭是非常消耗资源的 频繁地打开.关闭连接造成系统性能低下 编写连接 ...
- dbcp连接池配置详解_JDBC第四篇【数据库连接池、DbUtils框架、分页】(修订版)
前言 只有光头才能变强. 文本已收录至我的GitHub仓库,欢迎Star:https://github.com/ZhongFuCheng3y/3y 1.数据库连接池 什么是数据库连接池 简单来说:数据 ...
- CCNP13:QOS【分类、队列、标记、丢弃】技术
文章目录 CCNP13:QOS[分类.队列.标记.丢弃]技术 一.浅谈网络通讯: 二.QOS的工具概述: 1.分类: 2.队列: 3.标记: 4.丢弃机制: 三.分类: 四.标记: 1.优先级: 2. ...
- 【北邮国院大三上】电子商务法(e-commerce law)知识点整理——Banking Lawe-Payment
北邮国院大三电商在读,随课程进行整理知识点.仅整理PPT和相关法条中相对重要的知识点,个人认为相对不重要的细小的知识点不列在其中.如有错误请指出.转载请注明出处,祝您学习愉快. Why are leg ...
- JDBC第四篇【数据库连接池、DbUtils框架、分页】(修订版)
前言 只有光头才能变强. 文本已收录至我的GitHub仓库,欢迎Star:https://github.com/ZhongFuCheng3y/3y 1.数据库连接池 什么是数据库连接池 简单来说:数据 ...
- JDBC【数据库连接池、DbUtils框架、分页】
1.数据库连接池 什么是数据库连接池 简单来说:数据库连接池就是提供连接的... 为什么我们要使用数据库连接池 数据库的连接的建立和关闭是非常消耗资源的 频繁地打开.关闭连接造成系统性能低下 编写连接 ...
- 【梅哥的Ring0湿润插入教程】第一课Windows内核/驱动编程概述及应用、商业驱动保护软件原理分析...
[梅哥的Ring0湿润插入教程] Email:mlkui@163.com 转载请注明出处,谢绝喷子记者等,如引起各类不适请自觉滚J8蛋! 第一课Windows内核/驱动编程概述及应用. 商业驱动保护软 ...
最新文章
- 互联网协议 — RTSP 实时流传输协议
- C++11 正则表达式——实例1
- 树莓派4B装载ROS系统启动摄像头
- python tk 当输入数值错误是报错_Python的异常处理
- gulp+babel实现es6压缩,并替换es6语法,压缩html,css
- from mysql_MySQL的FROM
- apktoolkit apk反编译没有文件_[工具] Mac下一键APK逆向环境
- linux命令取数字前两位,linux中head命令使用详解(显示开头数量的文字块)
- 华为云UGO正式公测:4大核心优势破解异构数据库迁移难题
- 微服务2.0时代,论其痛点与触点
- HDU1760 A New Tetris Game NP态
- 关于U盘物理读写锁失效解决(只读状态):工具解锁或U盘量产
- html万花筒相册旋转效果,jquery css3 3D万花筒图片相册展示特效
- 【SDCC讲师专访】Swoole开源项目创始人韩天峰:PHP是最好的编程语言
- Mysql orchestrator高可用
- 孕育独角兽独立融资上市,互联网巨头都藏着什么“阳谋“?
- 敖丙带你设计【秒杀系统】
- hdu 5145 NPY and girls (莫队算法)
- mac 终端 创建java文件_第一个 终端Java程序 (Mac)
- 二次规划问题(qp)和序列二次规划问题(sqp)的简单理解