【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内核/驱动编程概述及应用. 商业驱动保护软 ...
最新文章
- Java集合7 (NavigableSet)
- matlab 直方图_MATLAB作图实例:19:用二元直方图分析图片颜色
- web前端-移动端HTML5微商城项目实战分享案例
- 【转】最流行的编程语言JavaScript能做什么?
- pytorch 训练过程acc_Pytorch之Softmax多分类任务
- Spring Spring MVC Hibernate 整合备忘
- lua——alien库实现lua调用C动态链接库(dll、so)
- matlab seed函数_如何用matlab生成随机数函数_matlab随机数生成函数
- OpenCV-腐蚀cv::erode
- 计算机信息数据集通信的概念,南京信息工程大学数据通信与计算机网络复习题库.doc...
- css 固定列头,表格头部固定和表格列固定
- Java HashSet和LinkedHashSet的用法
- 五、瞰景Smart3D空三解算
- 做个合格的吃货~利用Python爬取美食网站3032个菜谱并分析
- cython使用说明
- 修改 ubnt 路由器固件
- 十一、mysql连接查询
- 单片机控制LED灯长亮
- 实现抢拍竞答——多线程
- Unity无缝大世界实现调研