Linux内核Thermal框架详解七、Thermal Core(6)

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

三、相关源码及分析

2. thermal_register_governors

前一(几)篇文章分析完了thermal_register_governor函数,回到thermal_register_governors函数中来。为了更好地回忆并加深印象,再次贴出thermal_register_governors函数的源码(drivers/thermal/thermal_core.c中):

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 governor(温度控制管理)过程中有任何一个出现了错误,则跳出遍历循环,而后将已经注册的thermal governor去注册。核心函数是thermal_unregister_governor,该函数同样位于drivers/thermal/thermal_core.c中,代码如下:

void thermal_unregister_governor(struct thermal_governor *governor)
{struct thermal_zone_device *pos;if (!governor)return;mutex_lock(&thermal_governor_lock);if (!__find_governor(governor->name))goto exit;mutex_lock(&thermal_list_lock);list_for_each_entry(pos, &thermal_tz_list, node) {if (!strncasecmp(pos->governor->name, governor->name,THERMAL_NAME_LENGTH))thermal_set_governor(pos, NULL);}mutex_unlock(&thermal_list_lock);list_del(&governor->governor_list);
exit:mutex_unlock(&thermal_governor_lock);
}

仔细看不难发现,这个函数其实就是thermal_unregister_governor函数的反函数。如果thermal_governor_list链表上还没有governor加入,则无须做任何动作,直接退出。如果已有governor加入,则遍历thermal_tz_list链表,将此thermal governor与其绑定的thermal zone解绑。解绑后将该thermal governor从thermal_governor_list中删除。

再贴一下struct thermal_governor的代码:

/*** struct thermal_governor - structure that holds thermal governor information* @name:	name of the governor* @bind_to_tz: callback called when binding to a thermal zone.  If it*		returns 0, the governor is bound to the thermal zone,*		otherwise it fails.* @unbind_from_tz:	callback called when a governor is unbound from a*			thermal zone.* @throttle:	callback called for every trip point even if temperature is*		below the trip point temperature* @governor_list:	node in thermal_governor_list (in thermal_core.c)*/
struct thermal_governor {char name[THERMAL_NAME_LENGTH];int (*bind_to_tz)(struct thermal_zone_device *tz);void (*unbind_from_tz)(struct thermal_zone_device *tz);int (*throttle)(struct thermal_zone_device *tz, int trip);struct list_head	governor_list;
};

list_del函数在include/linux/list.h中定义,代码如下:

/** Delete a list entry by making the prev/next entries* point to each other.** This is only for internal list manipulation where we know* the prev/next entries already!*/
static inline void __list_del(struct list_head * prev, struct list_head * next)
{next->prev = prev;WRITE_ONCE(prev->next, next);
}/** Delete a list entry and clear the 'prev' pointer.** This is a special-purpose list clearing method used in the networking code* for lists allocated as per-cpu, where we don't want to incur the extra* WRITE_ONCE() overhead of a regular list_del_init(). The code that uses this* needs to check the node 'prev' pointer instead of calling list_empty().*/
static inline void __list_del_clearprev(struct list_head *entry)
{__list_del(entry->prev, entry->next);entry->prev = NULL;
}static inline void __list_del_entry(struct list_head *entry)
{if (!__list_del_entry_valid(entry))return;__list_del(entry->prev, entry->next);
}/*** list_del - deletes entry from list.* @entry: the element to delete from the list.* Note: list_empty() on entry does not return true after this, the entry is* in an undefined state.*/
static inline void list_del(struct list_head *entry)
{__list_del_entry(entry);entry->next = LIST_POISON1;entry->prev = LIST_POISON2;
}

至此,thermal_register_governors函数就全部分析完了。


本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!

相关文章

立即
投稿

微信公众账号

微信扫一扫加关注

返回
顶部