栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 系统运维 > 运维 > Linux

linux电源管理--wakesource

Linux 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

linux电源管理--wakesource

1、框架介绍

实现所在文件:driversbasepowerwakeup.c

函数所在文件:includelinuxpm_wakeup.h

该文件函数较多,主要实现了wakesource的功能,用于系统判断当前是否有事件阻止睡眠。整套框架基本上是围绕着combined_event_count这个变量在处理逻辑,在此变量中,高16位记录系统所有的wakeup event总数,低16位记录是否有wakeup events在处理中。在每次调用wakeup_source_activate时,wakeup events会加1,;每次调用wakeup_source_deactivate时,wakeup events会减1,同步wakeup event会加1.对于每次系统是否能够进入睡眠,通过判定是否有wakeup events在处理来判断。接口pm_wakeup_pending就实现了该功能。

 

2、接口实现

对外提供的接口主要有以下几个,本文也主要介绍以下主要函数接口:

2.1 操作直接操作wakeup_source来达到持锁和释放锁的功能

0、struct wakeup_source *wakeup_source_create(const char *name)

负责create一个struct wakeup_source类型的变量,注意该函数中有申请内存操作,不能在中断上下文中调用,通常在系统初始化时调用创建所需wakesource。

struct wakeup_source *wakeup_source_create(const char *name)
{
	struct wakeup_source *ws;
	const char *ws_name;
	int id;

	ws = kzalloc(sizeof(*ws), GFP_KERNEL);
	if (!ws)
		goto err_ws;

	ws_name = kstrdup_const(name, GFP_KERNEL);
	if (!ws_name)
		goto err_name;
	ws->name = ws_name;

	id = ida_alloc(&wakeup_ida, GFP_KERNEL);
	if (id < 0)
		goto err_id;
	ws->id = id;

	return ws;

err_id:
	kfree_const(ws->name);
err_name:
	kfree(ws);
err_ws:
	return NULL;
}
EXPORT_SYMBOL_GPL(wakeup_source_create);

1、void wakeup_source_destroy(struct wakeup_source *ws)

负责释放create创建的变量所占用的资源,通常不会被调用,一般一个wakesource创建后会一直使用。

void wakeup_source_destroy(struct wakeup_source *ws)
{
	if (!ws)
		return;

	__pm_relax(ws);
	wakeup_source_record(ws);
	wakeup_source_free(ws);
}

2、void wakeup_source_add(struct wakeup_source *ws) 

该函数负责把create创建的wakesource变量添加到wakeup_sources全局链表中统一维护记录。

void wakeup_source_add(struct wakeup_source *ws)
{
	unsigned long flags;

	if (WARN_ON(!ws))
		return;

	spin_lock_init(&ws->lock);
	timer_setup(&ws->timer, pm_wakeup_timer_fn, 0);
	ws->active = false;

	raw_spin_lock_irqsave(&events_lock, flags);
	list_add_rcu(&ws->entry, &wakeup_sources);
	raw_spin_unlock_irqrestore(&events_lock, flags);
}
EXPORT_SYMBOL_GPL(wakeup_source_add);

3、void wakeup_source_remove(struct wakeup_source *ws)

该函数负责把对应wakesource从wakeup_sources中删除掉。

4、void __pm_stay_awake(struct wakeup_source *ws)

可以理解为持锁,阻止系统进入睡眠,通过调用wakeup_source_activate来达到增加wakeup events。

5、void __pm_relax(struct wakeup_source *ws)

释放锁,该wakesource同意系统进入睡眠,最终通过调用wakeup_source_deactivate来达到wakeup events减一的效果。

6、void pm_wakeup_ws_event(struct wakeup_source *ws, unsigned int msec, bool hard)

可以理解为带超时时间的锁,在msec内,该锁会释放,超时回调机制通过定时器模块来实现。

2.2 通过dev来间接操作wakeup_source达到持锁和释放锁的功能

0、struct wakeup_source *wakeup_source_register(struct device *dev,const char *name)

对create和add接口的封装,通常在系统初始化时调用注册wakesource,使用上要比单独调用create和add方便些,约束之处也可以看到,必须与一个dev相关联。在一个与dev无关的相关实现中,dev传参可以为NULL。

1、void wakeup_source_unregister(struct wakeup_source *ws)

register的逆操作,释放占用的资源

2、void pm_stay_awake(struct device *dev)

作用等同__pm_stay_awake,是对__pm_stay_awake进行了一次封装,取值为dev->power.wakeup。

3、void pm_relax(struct device *dev)

作用等同__pm_relax(struct wakeup_source *ws),是对__pm_relax(struct wakeup_source *ws)进行了一层封装,取值同样为dev->power.wakeup

4、void pm_wakeup_dev_event(struct device *dev, unsigned int msec, bool hard)

作用等同pm_wakeup_ws_event(struct wakeup_source *ws, unsigned int msec, bool hard),是对pm_wakeup_ws_event(struct wakeup_source *ws, unsigned int msec, bool hard)进行了一层封装,取值同样为dev->power.wakeup

2.3 提供获取相关wakesource值的接口

0、bool pm_wakeup_pending(void)

确定当前是否还有event事件正在处理,以判定是否可以睡眠。在此多介绍一个函数:split_counters,该函数返回当前正在或者需要处理的wakeup_event个数和wakeup event总数。

1、bool pm_get_wakeup_count(unsigned int *count, bool block)

获取当前wakeup event总数,存储在count变量的地址中。同时,如果当前有event正在处理中,返回false,否则返回true.

2、bool pm_save_wakeup_count(unsigned int count)

保存当前wakeup event总数在saved_count变量中,该函数被autosleep的try_to_suspend函数调用,用于判断是否有wakeup event事件发生

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/642474.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号