赞
踩
android的内核版本中,提供了一套阻止系统进入睡眠的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);
-
}
__pm_stay_awake完成相关超时timer的删除,相关debug信息更新,以及持锁信息的+1操作
-
void __pm_stay_awake(
struct wakeup_source *ws)
-
{
-
unsigned
long flags;
-
-
if (!ws)
-
return;
-
-
spin_lock_irqsave(&ws->lock, flags);
-
-
wakeup_source_report_event(ws);
-
del_timer(&ws->timer);
-
ws->timer_expires =
0;
-
-
spin_unlock_irqrestore(&ws->lock, flags);
-
}
-
static void wakeup_source_report_event(struct wakeup_source *ws)
-
{
-
ws->event_count++;
-
/* This is racy, but the counter is approximate anyway. */
-
if (events_check_enabled)
-
ws->wakeup_count++;
-
-
if (!ws->active)
-
wakeup_source_activate(ws);
-
}
-
static void wakeup_source_activate(struct wakeup_source *ws)
-
{
-
unsigned
int cec;
-
-
ws->active =
true;
-
ws->active_count++;
-
ws->last_time =
ktime_get();
-
if (ws->autosleep_enabled)
-
ws->start_prevent_time = ws->last_time;
-
-
/* Increment the counter of events in progress. */
-
cec =
atomic_inc_return(&combined_event_count);
-
-
trace_wakeup_source_activate(ws->name, cec);
-
}
4)wake_lock_timeout:投超时锁,超时后释放锁
-
static inline void wake_lock_timeout(struct wake_lock* lock,long timeout)
-
{
-
__pm_wakeup_event(&lock->ws,
jiffies_to_msecs(timeout));
-
}
-
void __pm_wakeup_event(
struct wakeup_source *ws,
unsigned
int msec)
-
{
-
unsigned
long flags;
-
unsigned
long expires;
-
-
if (!ws)
-
return;
-
-
spin_lock_irqsave(&ws->lock, flags);
-
-
wakeup_source_report_event(ws);
//先上锁
-
-
if (!msec) {
//如果超时时间为0,则立刻释放锁
-
wakeup_source_deactivate(ws);
-
goto unlock;
-
}
-
-
expires = jiffies +
msecs_to_jiffies(msec);
-
if (!expires)
-
expires =
1;
-
-
if (!ws->timer_expires ||
time_after(expires, ws->timer_expires)) {
-
mod_timer(&ws->timer, expires);
//更新timer超时时间,超时后调用 pm_wakeup_timer_fn释放锁
-
ws->timer_expires = expires;
-
}
-
-
unlock:
-
spin_unlock_irqrestore(&ws->lock, flags);
-
}
5)wake_unlock:投票同意睡眠,释放wakelock锁
-
static inline void wake_unlock(struct wake_lock* lock)
-
{
-
__pm_relax(&lock->ws);
-
}
-
void __pm_relax(
struct wakeup_source *ws)
-
{
-
unsigned
long flags;
-
-
if (!ws)
-
return;
-
-
spin_lock_irqsave(&ws->lock, flags);
-
if (ws->active)
-
wakeup_source_deactivate(ws);
//释放锁
-
spin_unlock_irqrestore(&ws->lock, flags);
-
}
-
static void wakeup_source_deactivate(struct wakeup_source *ws)
-
{
-
unsigned
int cnt, inpr, cec;
-
ktime_t duration;
-
ktime_t now;
-
-
ws->relax_count++;
-
/*
-
* __pm_relax() may be called directly or from a timer function.
-
* If it is called directly right after the timer function has been
-
* started, but before the timer function calls __pm_relax(), it is
-
* possible that __pm_stay_awake() will be called in the meantime and
-
* will set ws->active. Then, ws->active may be cleared immediately
-
* by the __pm_relax() called from the timer function, but in such a
-
* case ws->relax_count will be different from ws->active_count.
-
*/
-
if (ws->relax_count != ws->active_count) {
-
ws->relax_count--;
-
return;
-
}
-
-
ws->active =
false;
-
-
now =
ktime_get();
-
duration =
ktime_sub(now, ws->last_time);
-
ws->total_time =
ktime_add(ws->total_time, duration);
-
if (
ktime_to_ns(duration) >
ktime_to_ns(ws->max_time))
-
ws->max_time = duration;
-
-
ws->last_time = now;
-
del_timer(&ws->timer);
-
ws->timer_expires =
0;
-
-
if (ws->autosleep_enabled)
-
update_prevent_sleep_time(ws, now);
-
-
/*
-
* Increment the counter of registered wakeup events and decrement the
-
* couter of wakeup events in progress simultaneously.
-
*/
-
cec =
atomic_add_return(MAX_IN_PROGRESS, &combined_event_count);
-
trace_wakeup_source_deactivate(ws->name, cec);
-
-
split_counters(&cnt, &inpr);
-
if (!inpr &&
waitqueue_active(&wakeup_count_wait_queue))
//如果满足睡眠条件,则唤醒等待队列
-
wake_up(&wakeup_count_wait_queue);
//此处需要配合前边讲的autosleep来看了}
6)wake_lock_active:返回锁的激活状态,主要是查询功能
-
static inline bool wake_lock_active(struct wake_lock* lock)
-
{
-
return lock->ws.active;
-
}
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。