码迷,mamicode.com
首页 > 其他好文 > 详细

wakelock锁

时间:2015-03-15 00:53:17      阅读:402      评论:0      收藏:0      [点我收藏+]

标签:

linaro 发布的内核版本中,提供了一套wakelock接口与google的wakelock接口实现了无缝对接,该套接口共有6个;

struct wake_lock{
	struct wakeup_source ws;
};
static inline void wake_lock_init(struct wake_lock *lock,int type,const char* name)
{
	wakeup_source_init(&lock->ws,name);
}
static inline void wake_lock_destroy(struct wake_lock* lock)
{
	wakeup_source_trash(&lock->ws);
}
static inline void wake_lock(struct wake_lock* lock)
{
	__pm_stay_awake(&lock->ws);
}
static inline void wake_lock_timeout(struct wake_lock* lock,long timeout)
{
	__pm_stay_awake(&lock->ws);
}
static inline void wake_unlock(struct wake_lock* lock)
{
	__pm_relax(&lock->ws);
}
static inline bool wake_lock_active(struct wake_lock* lock)
{
	return lock->ws.active;
}
还有一个重要的数据结构需要亮一下,那就是wakeup_source,该数据结构完成wakelock锁的基本控制
/**
 * struct wakeup_source - Representation of wakeup sources
 *
 * @total_time: Total time this wakeup source has been active.
 * @max_time: Maximum time this wakeup source has been continuously active.
 * @last_time: Monotonic clock when the wakeup source's was touched last time.
 * @prevent_sleep_time: Total time this source has been preventing autosleep.
 * @event_count: Number of signaled wakeup events.
 * @active_count: Number of times the wakeup sorce was activated.
 * @relax_count: Number of times the wakeup sorce was deactivated.
 * @expire_count: Number of times the wakeup source's timeout has expired.
 * @wakeup_count: Number of times the wakeup source might abort suspend.
 * @active: Status of the wakeup source.
 * @has_timeout: The wakeup source has been activated with a timeout.
 */
struct wakeup_source {
	const char 		*name;
	struct list_head	entry;
	spinlock_t		lock;
	struct timer_list	timer;
	unsigned long		timer_expires;
	ktime_t total_time;
	ktime_t max_time;
	ktime_t last_time;
	ktime_t start_prevent_time;
	ktime_t prevent_sleep_time;
	unsigned long		event_count;
	unsigned long		active_count;
	unsigned long		relax_count;
	unsigned long		expire_count;
	unsigned long		wakeup_count;
	bool			active:1;
	bool			autosleep_enabled:1;
};

1)wake_lock_init:实现wakelock锁的初始化,包括名字初始化,添加到wakelock锁的统一控制链表wakeup_sources中;

static inline void wake_lock_init(struct wake_lock *lock,int type,const char* name)
{
	wakeup_source_init(&lock->ws,name);
}
<pre class="cpp" name="code">static inline void wakeup_source_init(struct wakeup_source *ws,
				      const char *name)
{
	wakeup_source_prepare(ws, name);
	wakeup_source_add(ws);
}


其中wakelock_source_prepare主要完成的是锁的名字的初始化

/**
 * wakeup_source_prepare - Prepare a new wakeup source for initialization.
 * @ws: Wakeup source to prepare.
 * @name: Pointer to the name of the new wakeup source.
 *
 * Callers must ensure that the @name string won't be freed when @ws is still in
 * use.
 */
void wakeup_source_prepare(struct wakeup_source *ws, const char *name)
{
	if (ws) {
		memset(ws, 0, sizeof(*ws));
		ws->name = name;
	}
}
EXPORT_SYMBOL_GPL(wakeup_source_prepare);


而wakeup_source_add则完成的工作比较多,包括自旋锁的初始化,添加到wakelock锁的全局控制链表中,超时timer的初始化等

/**
 * wakeup_source_add - Add given object to the list of wakeup sources.
 * @ws: Wakeup source object to add to the list.
 */
void wakeup_source_add(struct wakeup_source *ws)
{
	if (WARN_ON(!ws))
		return;

	spin_lock_init(&ws->lock);
	setup_timer(&ws->timer, pm_wakeup_timer_fn, (unsigned long)ws);//pm_wakeup_timer_fn设置为wakelock锁的超时回调,供超时锁使用
	ws->active = false;
	ws->last_time = ktime_get();

	spin_lock_irq(&events_lock);
	list_add_rcu(&ws->entry, &wakeup_sources);//此处添加到链表中,wakelock模块主要操作该链表来控制wakelock锁
	spin_unlock_irq(&events_lock);
}
EXPORT_SYMBOL_GPL(wakeup_source_add);

其中pm_wakeup_timer_fn的实现如下,主要完成wakelock锁的释放,以及相关debug信息的记录

/**
 * pm_wakeup_timer_fn - Delayed finalization of a wakeup event.
 * @data: Address of the wakeup source object associated with the event source.
 *
 * Call wakeup_source_deactivate() for the wakeup source whose address is stored
 * in @data if it is currently active and its timer has not been canceled and
 * the expiration time of the timer is not in future.
 */
static void pm_wakeup_timer_fn(unsigned long data)
{
	struct wakeup_source *ws = (struct wakeup_source *)data;
	unsigned long flags;

	spin_lock_irqsave(&ws->lock, flags);

	if (ws->active && ws->timer_expires
	    && time_after_eq(jiffies, ws->timer_expires)) {
		wakeup_source_deactivate(ws);
		ws->expire_count++;
	}

	spin_unlock_irqrestore(&ws->lock, flags);
}

2)wake_lock_destroy:该接口完成wakelock锁的销毁操作,其实使用上的地方不多,一般创建完一个wakelock锁都会一直使用的

static inline void wake_lock_destroy(struct wake_lock* lock)
{
	wakeup_source_trash(&lock->ws);
}
static inline void wakeup_source_trash(struct wakeup_source *ws)
{
	wakeup_source_remove(ws);
	wakeup_source_drop(ws);
}


其中wakeup_source_remove负责把wakelocks锁从控制链表中删除

/**
 * wakeup_source_remove - Remove given object from the wakeup sources list.
 * @ws: Wakeup source object to remove from the list.
 */
void wakeup_source_remove(struct wakeup_source *ws)
{
	if (WARN_ON(!ws))
		return;

	spin_lock_irq(&events_lock);
	list_del_rcu(&ws->entry);
	spin_unlock_irq(&events_lock);
	synchronize_rcu();
}


而wakeup_source_drop则主要负责把对应timer从激活链表中删除(如果是出于激活状态),以及释放wakelock锁,而且该函数注释也提醒了,调用该函数时,一定要确保__pm_stay_awake() or __pm_wakeup_event()两个函数没有并行被调用,否则删除状态未知。

/**
 * wakeup_source_drop - Prepare a struct wakeup_source object for destruction.
 * @ws: Wakeup source to prepare for destruction.
 *
 * Callers must ensure that __pm_stay_awake() or __pm_wakeup_event() will never
 * be run in parallel with this function for the same wakeup source object.
 */
void wakeup_source_drop(struct wakeup_source *ws)
{
	if (!ws)
		return;

	del_timer_sync(&ws->timer);
	__pm_relax(ws);
}

3)wake_lock:投票反对睡眠(待完善)

static inline void wake_lock(struct wake_lock* lock)
{
	__pm_stay_awake(&lock->ws);
}

4)wake_lock_timeout:投超时锁,超时后释放锁(待完善)

5)wake_unlock:投票同意睡眠,释放wakelock锁(待完善)

6)wake_lock_active:返回锁的激活状态(待完善)





 

wakelock锁

标签:

原文地址:http://blog.csdn.net/lixiaojie1012/article/details/44264583

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!