标签:
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:返回锁的激活状态(待完善)
标签:
原文地址:http://blog.csdn.net/lixiaojie1012/article/details/44264583