当前位置:网站首页>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);
-
}
边栏推荐
- 准确率(Accuracy)、精度(Precision)、召回率(Recall)和 mAP 的图解
- LeetCode 1161.最大层内元素和:层序遍历
- MySQL limit paging query and performance issues
- Is the working process of the belt you know the story - actionreducerstore
- CoCube群机器人预览→资讯剧透←
- MySql模糊查询大全
- Use ODBC in Excel to read data from CDS view on SAP BTP platform
- MySQL 行级锁(行锁、临键锁、间隙锁)
- If the value of the enum map does not exist, deserialization is not performed
- 一文吃透接口调用神器RestTemplate
猜你喜欢

Different lower_case_table_names settings for server ('1') and data dictionary ('0') solution

Initial JDBC programming

“带薪划水”偷刷阿里老哥的面经宝典,三次挑战字节,终成正果

ESP8266-Arduino编程实例-HDC1008温度湿度传感器驱动
502 bad gateway原因、解决方法

Docker build Mysql master-slave replication

最全phpmyadmin漏洞汇总

mysql 索引使用与优化

MySQL日志中“binlog”的三种格式玩起来真爽

无法将“node.exe”项识别为 cmdlet、函数、脚本文件或可运行程序的名称。
随机推荐
xmind使用指南(XMind具有下列哪些功能)
三层架构service、dao、controller层
结构化查询语言SQL-关系数据库标准语言
Docker build Mysql master-slave replication
【虚拟化生态平台】平台架构图&思路和实现细节
JVS设置不同应用的登录时效时间
R语言做面板panelvar例子
Experience innovation and iteration through the development of lucky draw mini-programs
Different lower_case_table_names settings for server (‘1‘) and data dictionary (‘0‘) 解决方案
最近两个月谷歌 ad 掉的厉害
VBA输出日志到工作簿demo
订song餐系统
Acwing第 62 场周赛【未完结】
ApiPost is really fragrant and powerful, it's time to throw away Postman and Swagger
DCM middleware family welcomes a new member
多线程学习笔记-2.final关键字和不变性
Use Excel to read data exposed by SAP ABAP CDS View through ODBC
学习爬虫之Scrapy框架学习(1)---Scrapy框架初学习及豆瓣top250电影信息获取的实战!
科学论文和学术论文写作
一周精彩内容分享(第14期)
