Linux内核Thermal框架详解四、Thermal Core(3)
创始人
2024-06-01 08:41:39
0

本文部分内容参考Linux Thermal 学习笔记 - 爱码网。特此致谢!

接前一篇文章Linux内核Thermal框架详解三、Thermal Core(2)

三、相关源码及分析

2. thermal_register_governors

原本thermal_register_governors属于下一级函数,在前篇文章已经介绍过了。但是由于其重要性,因此将它提升一级,并且在本篇文章中进行更详细解析。再次列出函数源码,位于drivers/thermal/thermal_core.c中,如下所示:

static void __init thermal_unregister_governors(void)
{struct thermal_governor **governor;for_each_governor_table(governor)thermal_unregister_governor(*governor);
}static int __init thermal_register_governors(void)
{int ret = 0;struct thermal_governor **governor;for_each_governor_table(governor) {ret = thermal_register_governor(*governor);if (ret) {pr_err("Failed to register governor: '%s'",(*governor)->name);break;}pr_info("Registered thermal governor '%s'",(*governor)->name);}if (ret) {struct thermal_governor **gov;for_each_governor_table(gov) {if (gov == governor)break;thermal_unregister_governor(*gov);}}return ret;
}

thermal_register_governor函数的总体功能是将所有的governor策略(step_wise、power_alloctor、user_space、fair_share等)默认都注册给kernel。

下边对于关键代码进行分析。

(1)for_each_governor_table

for_each_governor_table是一个宏定义,在drivers/thermal/thermal_core.h中,代码如下:

#define for_each_governor_table(__governor)		\for (__governor = __governor_thermal_table;	\__governor < __governor_thermal_table_end;	\__governor++)

__governor_thermal_table的定义直接搜索是找不到的,只是在同文件中有一个extern的引用。如下所示:

extern struct thermal_governor *__governor_thermal_table[];
extern struct thermal_governor *__governor_thermal_table_end[];

那么__governor_thermal_table的定义到底在什么地方?这得从THERMAL_TABLE宏说起。

THERMAL_TABLE宏在include/asm-generic/vmlinux.lds.h中,代码如下:

#ifdef CONFIG_THERMAL
#define THERMAL_TABLE(name)						\. = ALIGN(8);							\__##name##_thermal_table = .;					\KEEP(*(__##name##_thermal_table))				\__##name##_thermal_table_end = .;
#else
#define THERMAL_TABLE(name)
#endif

在配置了THERMAL选项的时候,才会有内容。假设有这样的定义THERMAL_TABLE(governor),那么实际展开来,代码为:

. = ALIGN(8);							\
__governor_thermal_table = .;			\
KEEP(*(__governor_thermal_table))		\
__governor_thermal_table_end = .;

看到我们要找的__governor_thermal_table了吧,就是在这里最终出现了。

到此,还有一个问题没有弄清楚:我们上边是假设有THERMAL_TABLE(governor)的代码,那么真正调用THERMAL_TABLE宏的代码在哪里?

其实是在同文件(include/asm-generic/vmlinux.lds.h)中,代码如下:

/* init and exit section handling */
#define INIT_DATA							\KEEP(*(SORT(___kentry+*)))					\*(.init.data init.data.*)					\MEM_DISCARD(init.data*)						\KERNEL_CTORS()							\MCOUNT_REC()							\*(.init.rodata .init.rodata.*)					\FTRACE_EVENTS()							\TRACE_SYSCALLS()						\KPROBE_BLACKLIST()						\ERROR_INJECT_WHITELIST()					\MEM_DISCARD(init.rodata)					\CLK_OF_TABLES()							\RESERVEDMEM_OF_TABLES()						\TIMER_OF_TABLES()						\CPU_METHOD_OF_TABLES()						\CPUIDLE_METHOD_OF_TABLES()					\KERNEL_DTB()							\IRQCHIP_OF_MATCH_TABLE()					\ACPI_PROBE_TABLE(irqchip)					\ACPI_PROBE_TABLE(timer)						\THERMAL_TABLE(governor)						\EARLYCON_TABLE()						\LSM_TABLE()							\EARLY_LSM_TABLE()						\KUNIT_TABLE()

看到代码中的THERMAL_TABLE(governer)了吧,就是在这里。至于在哪里调用的INIT_DATA宏,在此就不再刨根问底了,毕竟不是本文的重点。

回到for_each_governor_table代码中,在弄清楚了全部细节之后,接着往下看整个代码段:

for_each_governor_table(governor) {ret = thermal_register_governor(*governor);if (ret) {pr_err("Failed to register governor: '%s'",(*governor)->name);break;}pr_info("Registered thermal governor '%s'",(*governor)->name);
}

展开:

for (__governor = __governor_thermal_table;	\__governor < __governor_thermal_table_end;	\__governor++) {ret = thermal_register_governor(*governor);if (ret) {pr_err("Failed to register governor: '%s'",(*governor)->name);break;}pr_info("Registered thermal governor '%s'",(*governor)->name);
}

这段代码的意思就比较明显了,遍历__governor_thermal_table中的每一项,进行注册。那么__governor_thermal_table中都包括了哪些项?又是什么时候加入进去的?且听我慢慢道来……

实际上,各个governor是通过 __section() 属性配合链接器脚本链接到一起的。以step_wise为例进行说明。

在drivers/thermal/gov_step_wise.c中有这样一行代码:

static struct thermal_governor thermal_gov_step_wise = {.name		= "step_wise",.throttle	= step_wise_throttle,
};
THERMAL_GOVERNOR_DECLARE(thermal_gov_step_wise);

THERMAL_GOVERNOR_DECLARE同样是宏,也是在drivers/thermal/thermal_core.h中,如下所示:

#define THERMAL_TABLE_ENTRY(table, name)			\static typeof(name) *__thermal_table_entry_##name	\__used __section("__" #table "_thermal_table") = &name#define THERMAL_GOVERNOR_DECLARE(name)	THERMAL_TABLE_ENTRY(governor, name)

上边代码连同进一步的宏定义一起写出了。因此,完全展开来就是:

static typeof(thermal_gov_step_wise) *__thermal_table_entry_thermal_gov_step_wise __used __section("__governor_thermal_table") = &thermal_gov_step_wise

由于thermal_gov_step_wise的类型为struct thermal_governor,因此,最终展开为:

static struct thermal_governor *__thermal_table_entry_thermal_gov_step_wise    \__used __section("__governor_thermal_table") = &thermal_gov_step_wise

这样,就完成了在__governor_thermal_table中添加一项thermal_gov_step_wise。

对于其它几种governor来说,都是同样的方法。在此,为了能够解析得更清晰、更彻底,列出全部的governor。

power_allocator在drivers/thermal/gov_power_allocator.c中:

static struct thermal_governor thermal_gov_power_allocator = {.name		= "power_allocator",.bind_to_tz	= power_allocator_bind,.unbind_from_tz	= power_allocator_unbind,.throttle	= power_allocator_throttle,
};
THERMAL_GOVERNOR_DECLARE(thermal_gov_power_allocator);

展开为:

static struct thermal_governor *__thermal_table_entry_thermal_gov_power_allocator    \__used __section("__governor_thermal_table") = &thermal_gov_power_allocator

fair_share在drivers/thermal/gov_fair_share.c中:

static struct thermal_governor thermal_gov_fair_share = {.name		= "fair_share",.throttle	= fair_share_throttle,
};
THERMAL_GOVERNOR_DECLARE(thermal_gov_fair_share);

展开为:

static struct thermal_governor *__thermal_table_entry_thermal_gov_fair_share    \__used __section("__governor_thermal_table") = &thermal_gov_fair_share

user_space在drivers/thermal/gov_user_space.c中:

static struct thermal_governor thermal_gov_user_space = {.name		= "user_space",.throttle	= notify_user_space,.bind_to_tz	= user_space_bind,
};
THERMAL_GOVERNOR_DECLARE(thermal_gov_user_space);

展开为:

static struct thermal_governor *__thermal_table_entry_thermal_gov_user_space    \__used __section("__governor_thermal_table") = &thermal_gov_user_space

bang_bang在drivers/thermal/gov_bang_bang.c中:

static struct thermal_governor thermal_gov_bang_bang = {.name		= "bang_bang",.throttle	= bang_bang_control,
};
THERMAL_GOVERNOR_DECLARE(thermal_gov_bang_bang);

展开为:

static struct thermal_governor *__thermal_table_entry_thermal_gov_bang_bang    \__used __section("__governor_thermal_table") = &thermal_gov_bang_bang

欲知后事如何,且听下回分解。

相关内容

热门资讯

喜欢穿一身黑的男生性格(喜欢穿... 今天百科达人给各位分享喜欢穿一身黑的男生性格的知识,其中也会对喜欢穿一身黑衣服的男人人好相处吗进行解...
发春是什么意思(思春和发春是什... 本篇文章极速百科给大家谈谈发春是什么意思,以及思春和发春是什么意思对应的知识点,希望对各位有所帮助,...
网络用语zl是什么意思(zl是... 今天给各位分享网络用语zl是什么意思的知识,其中也会对zl是啥意思是什么网络用语进行解释,如果能碰巧...
为什么酷狗音乐自己唱的歌不能下... 本篇文章极速百科小编给大家谈谈为什么酷狗音乐自己唱的歌不能下载到本地?,以及为什么酷狗下载的歌曲不是...
华为下载未安装的文件去哪找(华... 今天百科达人给各位分享华为下载未安装的文件去哪找的知识,其中也会对华为下载未安装的文件去哪找到进行解...
怎么往应用助手里添加应用(应用... 今天百科达人给各位分享怎么往应用助手里添加应用的知识,其中也会对应用助手怎么添加微信进行解释,如果能...
家里可以做假山养金鱼吗(假山能... 今天百科达人给各位分享家里可以做假山养金鱼吗的知识,其中也会对假山能放鱼缸里吗进行解释,如果能碰巧解...
一帆风顺二龙腾飞三阳开泰祝福语... 本篇文章极速百科给大家谈谈一帆风顺二龙腾飞三阳开泰祝福语,以及一帆风顺二龙腾飞三阳开泰祝福语结婚对应...
四分五裂是什么生肖什么动物(四... 本篇文章极速百科小编给大家谈谈四分五裂是什么生肖什么动物,以及四分五裂打一生肖是什么对应的知识点,希...
美团联名卡审核成功待激活(美团... 今天百科达人给各位分享美团联名卡审核成功待激活的知识,其中也会对美团联名卡审核未通过进行解释,如果能...