当前位置:网站首页>一点点读懂cpufreq(二)
一点点读懂cpufreq(二)
2022-08-04 22:50:00 【szembed】
目录
4.1 对cpufreq_transition_notifier_list的处理
4.2 对cpufreq_policy_notifier_list的处理
本章节主要介绍cpufreq中的通知链实现,在调频策略以及频率变化时来通知对该事件敏感的模块,各个模块可以通过注册和去注册接口来加入到通知链中。
1、注册接口:
-
/**
-
-
* cpufreq_register_notifier - Register a notifier with cpufreq.
-
-
* @nb: notifier function to register.
-
-
* @list: CPUFREQ_TRANSITION_NOTIFIER or CPUFREQ_POLICY_NOTIFIER.
-
-
* Add a notifier to one of two lists: either a list of notifiers that run on
-
-
* clock rate changes (once before and once after every transition), or a list
-
-
* of notifiers that ron on cpufreq policy changes.
-
-
* This function may sleep and it has the same return values as
-
-
* blocking_notifier_chain_register().
-
-
*/
-
-
int cpufreq_register_notifier(struct notifier_block *nb, unsigned int list)
-
-
{
-
-
int ret;
-
-
if (
cpufreq_disabled())
-
-
return -EINVAL;
-
-
switch (list) {
-
-
case CPUFREQ_TRANSITION_NOTIFIER:
-
-
mutex_lock(&cpufreq_fast_switch_lock);
-
-
if (cpufreq_fast_switch_count >
0) {
-
-
mutex_unlock(&cpufreq_fast_switch_lock);
-
-
return -EBUSY;
-
-
}
-
-
ret =
srcu_notifier_chain_register(
-
-
&cpufreq_transition_notifier_list, nb);
-
-
if (!ret)
-
-
cpufreq_fast_switch_count--;
-
-
mutex_unlock(&cpufreq_fast_switch_lock);
-
-
break;
-
-
case CPUFREQ_POLICY_NOTIFIER:
-
-
ret =
blocking_notifier_chain_register(
-
-
&cpufreq_policy_notifier_list, nb);
-
-
break;
-
-
default:
-
-
ret = -EINVAL;
-
-
}
-
-
return ret;
-
-
}
-
-
EXPORT_SYMBOL(cpufreq_register_notifier);
-
-
-
CPUFREQ_TRANSITION_NOTIFIER:对频率变化敏感,注册进来的模块添加到cpufreq_transition_notifier_list链表中进行维护及后续操作,模块在回调中进行处理时,可以通过CPUFREQ_PRECHANGE和CPUFREQ_POSTCHANGE来区分是在频率变化前做动作还是在变化后做动作。
CPUFREQ_POLICY_NOTIFIER:对策略变化敏感,注册进来的模块,添加到cpufreq_policy_notifier_list链表中进行维护及后续操作,模块在回调中进行处理时,可以通过CPUFREQ_CREATE_POLICY和CPUFREQ_REMOVE_POLICY来区分是在策略变化前做动作还是在变化后做动作。
2、去注册接口:
-
/**
-
-
* cpufreq_unregister_notifier - Unregister a notifier from cpufreq.
-
-
* @nb: notifier block to be unregistered.
-
-
* @list: CPUFREQ_TRANSITION_NOTIFIER or CPUFREQ_POLICY_NOTIFIER.
-
-
* Remove a notifier from one of the cpufreq notifier lists.
-
-
* This function may sleep and it has the same return values as
-
-
* blocking_notifier_chain_unregister().
-
-
*/
-
-
int cpufreq_unregister_notifier(struct notifier_block *nb, unsigned int list)
-
-
{
-
-
int ret;
-
-
if (
cpufreq_disabled())
-
-
return -EINVAL;
-
-
switch (list) {
-
-
case CPUFREQ_TRANSITION_NOTIFIER:
-
-
mutex_lock(&cpufreq_fast_switch_lock);
-
-
ret =
srcu_notifier_chain_unregister(
-
-
&cpufreq_transition_notifier_list, nb);
-
-
if (!ret && !
WARN_ON(cpufreq_fast_switch_count >=
0))
-
-
cpufreq_fast_switch_count++;
-
-
mutex_unlock(&cpufreq_fast_switch_lock);
-
-
break;
-
-
case CPUFREQ_POLICY_NOTIFIER:
-
-
ret =
blocking_notifier_chain_unregister(
-
-
&cpufreq_policy_notifier_list, nb);
-
-
break;
-
-
default:
-
-
ret = -EINVAL;
-
-
}
-
-
return ret;
-
-
}
-
-
EXPORT_SYMBOL(cpufreq_unregister_notifier);
去注册接口为注册接口的逆向操作,不再做过多解析。
3、使用样例
我们以loongson1-cpufreq.c作为样例
-
static int ls1x_cpufreq_notifier(struct notifier_block *nb,
-
unsigned
long val,
void *data)
-
{
-
if (val == CPUFREQ_POSTCHANGE)
-
current_cpu_data.udelay_val = loops_per_jiffy;
-
-
return NOTIFY_OK;
-
}
-
-
static
struct
notifier_block ls1x_cpufreq_notifier_block = {
-
.notifier_call = ls1x_cpufreq_notifier
-
};
该模块需要感知到频率的变化,需要在频率变化后来做一些事务处理,于是该模块就在回调中通过判断阶段为CPUFREQ_POSTCHANGE时做对应动作,并在初始化时通过调用cpufreq_register_notifier来注册。
4、软件处理
4.1 对cpufreq_transition_notifier_list的处理
现在该注册的模块已经注册进来了,那么cpufreq.c是如何回调注册的回调函数呢?cpufreq对cpufreq_transition_notifier_list链表的处理,统一封装到了函数cpufreq_notify_transition中来实现。
实际代码以cppc_cpufreq.c为例:
其中核心函数cpufreq_notify_transition的实现也是正常的逻辑实现,根据入参的不同分别处理
cpufreq_notify_transition函数会分别被cpufreq_freq_transition_begin和cpufreq_freq_transition_end来调用,而这2个函数则分别嵌入在了频率调换前和调换后调用,如此以来用户注册的回调会被最终调用到。
4.2 对cpufreq_policy_notifier_list的处理
对cpufreq_policy_notifier_list的调用,分别在cpufreq_policy_free和cpufreq_online中调用,分别针对policy移除和生效
边栏推荐
- Pytest learning - fixtures
- 2022年全网最全接口自动化测试框架搭建,没有之一
- 后排乘客不系安全带?事故瞬间被甩出
- Detailed usage of LocalDateTime
- The Controller layer code is written like this, concise and elegant!
- Pytest学习-Fixture
- 2022精选最新金融银行面试真题——附带答案
- CS8416国产替代DP8416 数字音频接收器
- 【游戏建模模型制作全流程】在ZBrush中雕刻恶魔城男性角色模型
- synchronized和ReentrantLock都很丝滑,因为他们都是可重入锁,一个线程多次拿锁也不会死锁,我们需要可重入
猜你喜欢
随机推荐
【云原生 · Kubernetes】Kubernetes运维
Detailed usage of LocalDateTime
剑指 Offer | 03. 数组中重复的数字
Redisson
【3D建模制作技巧分享】ZBrush纹理贴图怎么导入
PHP(3)
基于内容的图像检索系统设计与实现--颜色信息--纹理信息--形状信息--PHASH--SHFT特征点的综合检测项目,包含简易版与完整版的源码及数据!
【3D建模制作技巧分享】在zbrush中如何雕刻头发 ZBrush头发雕刻小技巧
正则表达式绕过
Use ngrok to optimize web pages on raspberry pi (1)
MQTT[一]基础知识介绍
Rt-thread [三] link.lds链接脚本详解
历史上的今天:PHP公开发布;iPhone 4 问世;万维网之父诞生
3D激光SLAM:LeGO-LOAM---两步优化的帧间里程计及代码分析
SSM整合完整流程讲解
Since a new byte of 20K came out, I have seen what the ceiling is
DREAMWEAVER8 part of the problem solution
Redisson
基于事实的结果
Based on the results of the facts