当前位置:网站首页>kernel syscore
kernel syscore
2022-07-31 11:52:00 【szembed】
syscore作为低功耗流程的一部分,其涉及的文件主要有syscore_ops.h和syscore.c,这一级别的回调函数是在完全屏蔽中断的场景下进行的。
1、主要结构体struct syscore_ops,该结构体是syscore操作的对象类型。
-
struct
syscore_ops {
-
struct
list_head node;
//用于链表控制,注册和删除syscore对象时操作此链表完成
-
int (*suspend)(
void);
//睡眠流程时回调函数
-
void (*resume)(
void);
//唤醒流程时回调函数
-
void (*shutdown)(
void);
//这一级别的回调函数主要用于系统级的重启、停止或者掉电时才会使用
-
};
2、主要接口:
-
extern void register_syscore_ops(struct syscore_ops *ops);
//注册syscore回调函数
-
extern void unregister_syscore_ops(struct syscore_ops *ops);
//取消注册的回调函数
-
#ifdef CONFIG_PM_SLEEP
-
extern int syscore_suspend(void);
//回调注册的syscore对象的suspend回调函数
-
extern void syscore_resume(void);
//回调注册的syscore对象的resume回调函数
-
#endif
-
extern void syscore_shutdown(void);
//回调注册的syscore对象的shutdown回调函数
3、具体实现,syscore.c
1)全局变量
-
static LIST_HEAD(syscore_ops_list);
//初始化控制链表头结点,统一管理注册的syscore对象
-
static DEFINE_MUTEX(syscore_ops_lock);
//访问上述链表时,通过此互斥信号量来互斥访问
2)register_syscore_ops:其他组件主要通过此接口来注册回调函数,我们可以看到,把注册的对象存放在了syscore_ops_list链表中。
-
/**
-
* register_syscore_ops - Register a set of system core operations.
-
* @ops: System core operations to register.
-
*/
-
void register_syscore_ops(struct syscore_ops *ops)
-
{
-
mutex_lock(&syscore_ops_lock);
-
list_add_tail(&ops->node, &syscore_ops_list);
-
mutex_unlock(&syscore_ops_lock);
-
}
3)unregister_syscore_ops:与register_syscore_ops功能相反,取消注册,从控制链表中删除。
-
/**
-
* unregister_syscore_ops - Unregister a set of system core operations.
-
* @ops: System core operations to unregister.
-
*/
-
void unregister_syscore_ops(struct syscore_ops *ops)
-
{
-
mutex_lock(&syscore_ops_lock);
-
list_del(&ops->node);
-
mutex_unlock(&syscore_ops_lock);
-
}
4)syscore_suspend:该接口回调所有注册对象的suspend接口,该接口在suspend.c的suspend_enter函数中被调用,执行cpu掉电前的最后阶段操作。
-
/**
-
* syscore_suspend - Execute all the registered system core suspend callbacks.
-
*
-
* This function is executed with one CPU on-line and disabled interrupts.
-
*/
-
int syscore_suspend(void)
-
{
-
struct
syscore_ops *ops;
-
int ret =
0;
-
-
pr_debug(
"Checking wakeup interrupts\n");
-
-
/* Return error code if there are any wakeup interrupts pending. */
-
ret =
check_wakeup_irqs();
-
if (ret)
-
return ret;
-
-
WARN_ONCE(!
irqs_disabled(),
-
"Interrupts enabled before system core suspend.\n");
//我们可以看到,如果此时中断没有屏蔽掉,会有警告产生
-
-
list_for_each_entry_reverse(ops, &syscore_ops_list, node)
//按照链表逆序执行各个注册对象的suspend回调函数
-
if (ops->suspend) {
-
if (initcall_debug)
-
pr_info(
"PM: Calling %pF\n", ops->suspend);
-
ret = ops->
suspend();
-
if (ret)
-
goto err_out;
-
WARN_ONCE(!
irqs_disabled(),
-
"Interrupts enabled after %pF\n", ops->suspend);
-
}
-
-
return
0;
-
-
err_out:
-
pr_err(
"PM: System core suspend callback %pF failed.\n", ops->suspend);
-
-
list_for_each_entry_continue(ops, &syscore_ops_list, node)
//如果有失败的,则执行已经执行过suspend回调的对象的resume回调
-
if (ops->resume)
-
ops->
resume();
-
-
return ret;
-
}
-
EXPORT_SYMBOL_GPL(syscore_suspend);
-
5)syscore_resume:执行注册对象的resume回调,在suspend.c的唤醒流程中被调用
-
/**
-
* syscore_resume - Execute all the registered system core resume callbacks.
-
*
-
* This function is executed with one CPU on-line and disabled interrupts.
-
*/
-
void syscore_resume(void)
-
{
-
struct
syscore_ops *ops;
-
-
WARN_ONCE(!
irqs_disabled(),
-
"Interrupts enabled before system core resume.\n");
-
-
list_for_each_entry(ops, &syscore_ops_list, node)
-
if (ops->resume) {
-
if (initcall_debug)
-
pr_info(
"PM: Calling %pF\n", ops->resume);
-
ops->
resume();
-
WARN_ONCE(!
irqs_disabled(),
-
"Interrupts enabled after %pF\n", ops->resume);
-
}
-
}
6)syscore_shutdown:该接口正常睡眠流程中不涉及调用,主要在sys.c中调用,涉及系统重启、halt等流程。
-
/**
-
* syscore_shutdown - Execute all the registered system core shutdown callbacks.
-
*/
-
void syscore_shutdown(void)
-
{
-
struct
syscore_ops *ops;
-
-
mutex_lock(&syscore_ops_lock);
-
-
list_for_each_entry_reverse(ops, &syscore_ops_list, node)
-
if (ops->shutdown) {
-
if (initcall_debug)
-
pr_info(
"PM: Calling %pF\n", ops->shutdown);
-
ops->
shutdown();
-
}
-
-
mutex_unlock(&syscore_ops_lock);
-
}
边栏推荐
猜你喜欢

MySQL index usage and optimization

Service discovery of kubernetes

【虚拟化生态平台】树莓派安装虚拟化平台操作流程

After Effects 教程,如何在 After Effects 中修复曝光不足的镜头?

CoCube群机器人预览→资讯剧透←

Cloudera Manager —— 端到端的企业数据中心管理工具

PyQt5快速开发与实战 9.5 PyQtGraph在PyQt中的应用 && 9.6 Plotly在PyQt中的应用

Different lower_case_table_names settings for server (‘1‘) and data dictionary (‘0‘) 解决方案

Docker安装canal、mysql进行简单测试与实现redis和mysql缓存一致性
![[ 图 论 ]二分图判定及其匹配(基础+提高)](/img/79/56f750e71f558debe3d99404e296e3.png)
[ 图 论 ]二分图判定及其匹配(基础+提高)
随机推荐
拥抱趋势!阿里这套微服务开源框架权威手册,实战到底层细致清晰
连续变量离散化教程
MySQL index usage and optimization
准确率(Accuracy)、精度(Precision)、召回率(Recall)和 mAP 的图解
多线程学习笔记-2.final关键字和不变性
VBA实现双击单元格自动输出对号再次双击取消对号
线程池 ThreadPoolExecutor 详解
oracle优化:instr做join条件很慢「建议收藏」
R语言:文本(字符串)处理与正则表达式
瑞吉外卖项目:文件的上传与下载
JVS开发套件产品定位
WebGL给Unity传递参数问题1: Cannot read properties of undefined (reading ‘SendMessage‘)
ApiPost is really fragrant and powerful, it's time to throw away Postman and Swagger
数据湖(十九):SQL API 读取Kafka数据实时写入Iceberg表
Candence学习篇(11) allegro中设置规则,布局,走线,铺铜
给你一个大厂面试的机会,你能面试上吗?进来看看!
keras自带数据集(横线生成器)
关于==和equals的区别和联系,面试这么回答就可以
How MySQL's allowMultiQueries flag relates to JDBC and jOOQ
5 个开源的 Rust Web 开发框架,你选择哪个?
