Linux内核Thermal框架详解五、Thermal Core(4)
创始人
2024-06-01 10:21:39
0

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

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

三、相关源码及分析

2. thermal_register_governors

上一回说到这一段代码:

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这个变量了。

__governor这个变量在之前代码中出现过,如下:

struct thermal_governor **governor;

这是一个二重指针,即指向指针的指针。在上述代码中,它一开始指向了__governor_thermal_table,还记得__governor_thermal_table是怎样定义的吗?

在drivers/thermal/thermal_core.h中:

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

虽然这里是extern,但是这比include/asm-generic/vmlinux.lds.h中真正定义__governor_thermal_table的地方好理解。__governor_thermal_table实际上是一个指针数组。所以使用二重指针governor指向它也就合情合理了。

再来回顾一下各种governor策略:

  • step_wise

drivers/thermal/gov_step_wise.c中:

static struct thermal_governor thermal_gov_step_wise = {.name		= "step_wise",.throttle	= step_wise_throttle,
};static struct thermal_governor *__thermal_table_entry_thermal_gov_step_wise    \__used __section("__governor_thermal_table") = &thermal_gov_step_wise
  • 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,
};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,
};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,
};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,
};static struct thermal_governor *__thermal_table_entry_thermal_gov_bang_bang    \__used __section("__governor_thermal_table") = &thermal_gov_bang_bang

弄清楚了以上细节后就能知道,本文开头的代码的意义是:遍历所有的governor策略并进行注册。注册具体都完成了哪些工作?下边接着来看。

(2)thermal_register_governor

thermal_register_governor函数同样在drivers/thermal/thermal_core.c中实现,代码如下:

int thermal_register_governor(struct thermal_governor *governor)
{int err;const char *name;struct thermal_zone_device *pos;if (!governor)return -EINVAL;mutex_lock(&thermal_governor_lock);err = -EBUSY;if (!__find_governor(governor->name)) {bool match_default;err = 0;list_add(&governor->governor_list, &thermal_governor_list);match_default = !strncmp(governor->name,DEFAULT_THERMAL_GOVERNOR,THERMAL_NAME_LENGTH);if (!def_governor && match_default)def_governor = governor;}mutex_lock(&thermal_list_lock);list_for_each_entry(pos, &thermal_tz_list, node) {/** only thermal zones with specified tz->tzp->governor_name* may run with tz->govenor unset*/if (pos->governor)continue;name = pos->tzp->governor_name;if (!strncasecmp(name, governor->name, THERMAL_NAME_LENGTH)) {int ret;ret = thermal_set_governor(pos, governor);if (ret)dev_err(&pos->device,"Failed to set governor %s for thermal zone %s: %d\n",governor->name, pos->type, ret);}}mutex_unlock(&thermal_list_lock);mutex_unlock(&thermal_governor_lock);return err;
}

函数虽然不算太长,但也不算太短,还是有一些内容的。逐段来看:

一开始是判断并确保入参governor不为空。

接下来加锁mutex_lock(&thermal_governor_lock)。thermal_governor_lock在同文件(drivers/thermal/thermal_core.c)中定义并初始化,代码如下:

static DEFINE_MUTEX(thermal_governor_lock);

接下来是一个判断if (!__find_governor(governor->name))。__find_governor函数同样在drivers/thermal/thermal_core.c中,代码如下:

/** Governor section: set of functions to handle thermal governors** Functions to help in the life cycle of thermal governors within* the thermal core and by the thermal governor code.*/static struct thermal_governor *__find_governor(const char *name)
{struct thermal_governor *pos;if (!name || !name[0])return def_governor;list_for_each_entry(pos, &thermal_governor_list, governor_list)if (!strncasecmp(name, pos->name, THERMAL_NAME_LENGTH))return pos;return NULL;
}

要弄清楚这个函数的功能,就必须弄清楚list_for_each_entry的含义。list_for_each_entry是一个宏,在include/linux/list.h中,代码如下:

/*** list_for_each_entry	-	iterate over list of given type* @pos:	the type * to use as a loop cursor.* @head:	the head for your list.* @member:	the name of the list_head within the struct.*/
#define list_for_each_entry(pos, head, member)				\for (pos = list_first_entry(head, typeof(*pos), member);	\!list_entry_is_head(pos, head, member);			\pos = list_next_entry(pos, member))

list_first_entry当然也在include/linux/list.h中,代码如下:

/*** list_first_entry - get the first element from a list* @ptr:	the list head to take the element from.* @type:	the type of the struct this is embedded in.* @member:	the name of the list_head within the struct.** Note, that list is expected to be not empty.*/
#define list_first_entry(ptr, type, member) \list_entry((ptr)->next, type, member)

list_entry也在include/linux/linux.h中,就在list_first_entry宏定义的上边,代码如下:

/*** list_entry - get the struct for this entry* @ptr:	the &struct list_head pointer.* @type:	the type of the struct this is embedded in.* @member:	the name of the list_head within the struct.*/
#define list_entry(ptr, type, member) \container_of(ptr, type, member)

由上,list_first_entry展开为:

#define list_first_entry    container_of((ptr)->next, type, member)

list_entry_is_head同样在include/linux/linux.h中,代码如下:

/*** list_entry_is_head - test if the entry points to the head of the list* @pos:	the type * to cursor* @head:	the head for your list.* @member:	the name of the list_head within the struct.*/
#define list_entry_is_head(pos, head, member)				\(&pos->member == (head))

list_next_entry同样在include/linux/linux.h中,代码如下:

/*** list_next_entry - get the next element in list* @pos:	the type * to cursor* @member:	the name of the list_head within the struct.*/
#define list_next_entry(pos, member) \list_entry((pos)->member.next, typeof(*(pos)), member)

相关内容

热门资讯

《墨竹梅》 《墨竹梅》 曾几 宋代 曾几 的皪江梅竹外枝,能将幻法转生机。凭君莫作风垂绿,便恐飘零学雪飞...
《中秋夜月》 《中秋夜月》 钱钟书 当代 钱钟书 赢得儿童尽笑欢,盈盈露洗挂云端。一生几见当头满,四野哀嗷...
《人欲》 《人欲》 李商隐 唐代 李商隐 人欲天从竟不疑,莫言圆盖便无私。秦中已久乌头白,却是君王未备...
《饭客》 《饭客》 艾性夫 宋代 艾性夫 菜剪尧时韭,羹羞晋代莼。家寒多食淡,客好不嫌贫。一夜小窗雨,...
《齐威王》 《齐威王》 徐钧 宋代 徐钧 赏罚严明国富强,独能仗义一朝王。周网此日微如发,独有人心理未亡...
《和惠思波上鸥》 《和惠思波上鸥》 王安石 宋代 王安石 翩翩白凫鸥,泛泛水中游。西来久不见,梦想在沧洲。 作...
《采桑子》 《采桑子》 欧阳修 宋代 欧阳修 天容水色西湖好,云物俱鲜。鸥鹭闲眠,应惯寻常听管弦。风清月...
《观刈麦》 《观刈麦》 白居易 唐代 白居易 田家少闲月,五月人倍忙。夜来南风起,小麦覆陇黄。妇姑荷箪食...
《春光》 《春光》 李商隐 唐代 李商隐 九十春光斗日光,山城斜路杏花香。几时心绪浑无事,得及游丝百尺...
《读东湖集二首》 《读东湖集二首》 赵蕃 宋代 赵蕃 世竞江西派,人吟老杜诗。五言真有律,徐稚是吾师。不但时相...
《寄黄晞》 《寄黄晞》 李覯 宋代 李覯 长忆黄夫子,才高行亦淳。世情轻近事,见惯即常人。何力康时务,将...
《虞美人草》 《虞美人草》 姜夔 宋代 姜夔 夜阑浩歌起,玉帐生悲风。江东可千里,弃妾蓬蒿中。化石那解语,...
《狂歌》 《狂歌》 陆游 宋代 陆游 少年虽狂犹有限,遇酒时能傲忧患;即今狂处不待酒,混混长歌老岩涧。...
《咏华山》 《咏华山》 寇准 宋代 寇准 只有天在上,更无山与齐。举头红日近,回首白云低。 作者简介(寇...
《长安少年行》 《长安少年行》 皎然 唐代 皎然 翠楼春酒虾蟆陵,长安少年皆共矜。纷纷半醉绿槐道,躞蹀花骢骄...
《月儿弯弯照九州》 《月儿弯弯照九州》 佚名 宋代 佚名 月儿弯弯照九州,几家欢乐几家愁。几家夫妇同罗帐,几个飘...
《双髻山》 《双髻山》 胡仲弓 宋代 胡仲弓 千古丫鬟高插天,淡妆浓抹傅雪烟。眼前不见峨眉老,独有青山长...
《山中呈聂心远诸客》 《山中呈聂心远诸客》 文天祥 宋代 文天祥 谁入山来问野舟,一篙花外渡深流。小颦风树蹁跹鹤,...
《千丈岩瀑布》 《千丈岩瀑布》 曾巩 宋代 曾巩 玉虬垂处雪花翻,四季雷声六月寒。凭槛未穷千丈势,请从岩下举...
《盖延》 《盖延》 徐钧 宋代 徐钧 力挽强弓数百斤,兵锋到处策奇勋。可怜轻敌多深入,不似君王善料军。...