Android 休眠机制->wake_lock机制浅析

Android的休眠唤醒主要基于wake_lock机制,只要系统中存在任一有效的wake_lock,系统就不能进入深度休眠,但可以进行设备的浅度休眠操作。wake_lock一般在关闭lcd、tp,但系统仍然需要正常运行的情况下使用,比如听歌、传输很大的文件等。
-----------------------------------------------------------------------------
深度休眠:
深度休眠的机制主要是锁,只要系统中存在任一有效的wake_lock,系统就不能进入深度休眠。
当所有的锁都无效时,那么系统就会进入深度休眠状态。以下我对wake_lock锁机制的理解。可能有些偏差。

分析driver层wake_lock的实现,我的讲解流程是从锁到全局。

数据结构定义:linux-3.4\kernel\power\wakelock.h
enum {
WAKE_LOCK_SUSPEND,    // 阻止进入深度休眠模式
WAKE_LOCK_IDLE,       // 阻止进入空闲模式
WAKE_LOCK_TYPE_COUNT  // 锁的数量
};

#define WAKE_LOCK_TYPE_MASK              (0x0f)    // 标志掩码
#define WAKE_LOCK_INITIALIZED            (1U << 8)   // 锁已经初始化
#define WAKE_LOCK_ACTIVE                 (1U << 9)   // 锁有效标志
#define WAKE_LOCK_AUTO_EXPIRE            (1U << 10)   // 表示是超时锁
#define WAKE_LOCK_PREVENTING_SUSPEND     (1U << 11)   // 正在阻止休眠标志

锁的结构:
struct wake_lock {
#ifdef CONFIG_HAS_WAKELOCK
struct list_head    link;     // 链表节点
int                 flags;    // 标志
const char         *name;     // 名称
unsigned long       expires;  // 超时时间
#ifdef CONFIG_WAKELOCK_STAT
struct {        // 统计信息机构体
  int             count;         // 使用计数
  int             expire_count;  // 超时计数
  int             wakeup_count;  // 唤醒计数
  ktime_t         total_time;    // 锁使用时间
  ktime_t         prevent_suspend_time;  // 锁阻止休眠的时间
  ktime_t         max_time;      // 锁使用时间最长的一次
  ktime_t         last_time;     // 锁上次操作时间
} stat;
#endif
#endif
};

安卓提供了操作锁的接口:linux-3.4\kernel\power\wakelock.c

// 初始化新锁,type指定了锁的类型
void wake_lock_init(struct wake_lock *lock, int type, const char *name);

// 注销锁
void wake_lock_destroy(struct wake_lock *lock);

// 激活永久锁
void wake_lock(struct wake_lock *lock);

// 激活超时锁
void wake_lock_timeout(struct wake_lock *lock, long timeout);

// 解锁
void wake_unlock(struct wake_lock *lock); 

// 判断当前锁是否有效,有效返回非 0
int wake_lock_active(struct wake_lock *lock);

// 判断系统中是否还存在有效的type类型的锁,如果存在则返回最长的一个锁的超时时间,
// 如果存在永久锁则返回-1,如果系统中不存在有效锁则返回0
long has_wake_lock(int type); 

这些接口都被EXPORT_SYMBOL()导出,可以为其他模块所用。

它们都是通过维护两个锁链表(有效锁链表、无效锁链表)实现整套锁机制。
有效锁链表:
active_wake_locks[0]维护的是 WAKE_LOCK_SUSPEND.
active_wake_locks[1]维护的是 WAKE_LOCK_IDLE.
无效锁链表:
inactive_locks  

调试信息输出:(这个挺有意思的,可以指定输出调试类型的信息)
enum {
DEBUG_EXIT_SUSPEND = 1U << 0,
DEBUG_WAKEUP = 1U << 1,
DEBUG_SUSPEND = 1U << 2,
DEBUG_EXPIRE = 1U << 3,
DEBUG_WAKE_LOCK = 1U << 4,
};
static int debug_mask = DEBUG_EXIT_SUSPEND | DEBUG_WAKEUP | DEBUG_SUSPEND;

/* 初始化锁 参数: 锁对象,类型,名字
* 主要是初始化了锁的数据结构,并且将该节点加入到无效锁链表中 
* 在激活的时候就可以将该锁从无效锁链表中加到有效锁链表*/
void wake_lock_init(struct wake_lock *lock, int type, const char *name)
{
unsigned long irqflags = 0;

if (name)                               // 锁的名称
  lock->name = name;
BUG_ON(!lock->name);     // 断言 参数检查

if (debug_mask & DEBUG_WAKE_LOCK)
  pr_info("wake_lock_init name=%s\n", lock->name);
#ifdef CONFIG_WAKELOCK_STAT     // 初始化状态信息
lock->stat.count = 0;
lock->stat.expire_count = 0;
lock->stat.wakeup_count = 0;
lock->stat.total_time = ktime_set(0, 0);
lock->stat.prevent_suspend_time = ktime_set(0, 0);
lock->stat.max_time = ktime_set(0, 0);
lock->stat.last_time = ktime_set(0, 0);
#endif
    // 初始化 flag ,WAKE_LOCK_INITIALIZED 表示已经初始化过
lock->flags = (type & WAKE_LOCK_TYPE_MASK) | WAKE_LOCK_INITIALIZED;
    // 初始化链表节点
INIT_LIST_HEAD(&lock->link);
spin_lock_irqsave(&list_lock, irqflags);
    // 将锁加入无效锁链表
list_add(&lock->link, &inactive_locks);
spin_unlock_irqrestore(&list_lock, irqflags);
}
EXPORT_SYMBOL(wake_lock_init);

/* 注销锁,参数:锁对象
* 清除已经初始化的标志、将锁的状态信息放入 deleted_wake_locks 
* 不知道为什么要进去,网上有一份资料说是统计信息,但是我没有看到有哪些地方用上
*/
void wake_lock_destroy(struct wake_lock *lock)
{
unsigned long irqflags;
if (debug_mask & DEBUG_WAKE_LOCK)
  pr_info("wake_lock_destroy name=%s\n", lock->name);
spin_lock_irqsave(&list_lock, irqflags);
    // 清除已经初始化的标志
lock->flags &= ~WAKE_LOCK_INITIALIZED;
#ifdef CONFIG_WAKELOCK_STAT
if (lock->stat.count) {   //  将该锁的状态复制给 deleted_wake_locks
  deleted_wake_locks.stat.count += lock->stat.count;
  deleted_wake_locks.stat.expire_count += lock->stat.expire_count;
  deleted_wake_locks.stat.total_time =
   ktime_add(deleted_wake_locks.stat.total_time,
      lock->stat.total_time);
  deleted_wake_locks.stat.prevent_suspend_time =
   ktime_add(deleted_wake_locks.stat.prevent_suspend_time,
      lock->stat.prevent_suspend_time);
  deleted_wake_locks.stat.max_time =
   ktime_add(deleted_wake_locks.stat.max_time,
      lock->stat.max_time);
}
#endif
    // 从当前链表中删除
list_del(&lock->link);
spin_unlock_irqrestore(&list_lock, irqflags);
}
EXPORT_SYMBOL(wake_lock_destroy);

/* 激活永久锁 */
void wake_lock(struct wake_lock *lock)
{
    POWER_DEBUGOUT();
wake_lock_internal(lock, 0, 0);
}
EXPORT_SYMBOL(wake_lock);

/* 激活超时锁 */
void wake_lock_timeout(struct wake_lock *lock, long timeout)
{
    POWER_DEBUGOUT();
wake_lock_internal(lock, timeout, 1);
}
EXPORT_SYMBOL(wake_lock_timeout);

/* 真正激活锁操作,参数:锁对象,若是超时锁则为超时值否则为0,是否超时锁 
* 将该锁从无效链表中删除,加入到有效链表,
* 如果是超时锁则设置其超时值,遍历并取有效链表中超时值最长的超时锁,将该超时值更新到定时器中
* (在遍历过程中,会将已经超时的超时锁移除 具体看 static long has_wake_lock_locked()的实现)
* 如果是永久锁就将其超时值设置为极限,并清除超时锁的标志
* 如果所有没有超时锁则删除定时器,如果也没有永久锁则启动深度休眠流程
* 注意,超时锁是用 list_add_tail() 加入有效锁链表,而永久锁是用 list_add() 加入有效锁链表
* 所以有效链表的结构是这样: --永久锁--链表头--超时锁-- 
* 这种方式是为了提高has_wake_lock_locked()遍历效率
*/
static void wake_lock_internal(struct wake_lock *lock, long timeout, int has_timeout)
{
int type;
unsigned long irqflags;
long expire_in;

spin_lock_irqsave(&list_lock, irqflags);
    // 获取锁的类型
type = lock->flags & WAKE_LOCK_TYPE_MASK;
BUG_ON(type >= WAKE_LOCK_TYPE_COUNT);
BUG_ON(!(lock->flags & WAKE_LOCK_INITIALIZED));
#ifdef CONFIG_WAKELOCK_STAT
if (type == WAKE_LOCK_SUSPEND && wait_for_wakeup) 
{
  if (debug_mask & DEBUG_WAKEUP)
   pr_info("wakeup wake lock: %s\n", lock->name);
  wait_for_wakeup = 0;
  lock->stat.wakeup_count++;
}
if ((lock->flags & WAKE_LOCK_AUTO_EXPIRE) && (long)(lock->expires - jiffies) <= 0) 
{
  wake_unlock_stat_locked(lock, 0);
  lock->stat.last_time = ktime_get();
}
#endif
    // 设置锁有效的标志位
if (!(lock->flags & WAKE_LOCK_ACTIVE)) 
{
  lock->flags |= WAKE_LOCK_ACTIVE;
#ifdef CONFIG_WAKELOCK_STAT
  lock->stat.last_time = ktime_get();
#endif
}
    // 将该锁从无效链表中删除
list_del(&lock->link);
    // 如果是超时锁
if (has_timeout) 
{
  if (debug_mask & DEBUG_WAKE_LOCK) 
   pr_info("wake_lock: %s, type %d, timeout %ld.%03lu\n", lock->name, type, timeout / HZ,
    (timeout % HZ) * MSEC_PER_SEC / HZ);
        // 设置锁超时时间,以当前jiffies为基准
        lock->expires = jiffies + timeout;
        // 设置锁的超时锁标志
  lock->flags |= WAKE_LOCK_AUTO_EXPIRE;
  // 将超时锁加入到 active_wake_locks[type] 链表头的后面 
  // 注意,超时锁在链表的后面,永久锁在链表的前面  --永久锁--链表头--超时锁--
  list_add_tail(&lock->link, &active_wake_locks[type]);

    else 
{  // 如果是永久锁
  if (debug_mask & DEBUG_WAKE_LOCK)
   pr_info("wake_lock: %s, type %d\n", lock->name, type);
        // 设置超时时间为极限
        lock->expires = LONG_MAX;
        // 清除超时锁的标志
  lock->flags &= ~WAKE_LOCK_AUTO_EXPIRE;
        // 将锁加入有效锁链表 active_wake_locks[type] 链表头的前面
  // 注意,超时锁在链表的后面,永久锁在链表的前面  --永久锁--链表头--超时锁--
  list_add(&lock->link, &active_wake_locks[type]);
}
    // 如果是休眠锁
if (type == WAKE_LOCK_SUSPEND) 
{
  current_event_num++;        // 休眠锁使用计数加1
  
#ifdef CONFIG_WAKELOCK_STAT
        // 如果是内核休眠锁
  if (lock == &main_wake_lock)
   update_sleep_wait_stats_locked(1);
        // 如果休眠锁无效
  else if (!wake_lock_active(&main_wake_lock))
   update_sleep_wait_stats_locked(0);
#endif
        // 如果是超时锁
  if (has_timeout)
   expire_in = has_wake_lock_locked(type);  // 遍历WAKE_LOCK_SUSPEND锁类型的有效锁链表
  else
   expire_in = -1;
        // 当前存在有效超时锁,并且最长的一个到期时间间隔为 expire_in
        if (expire_in > 0) 
  {
   if (debug_mask & DEBUG_EXPIRE)
    pr_info("wake_lock: %s, start expire timer, "
     "%ld\n", lock->name, expire_in);
   // 更新定时器的超时时间 为最长有效锁的超时时间 当时间到了,就会触发 expire_wake_locks()
   // 该函数会重新检查所有的超时锁,过期则从有效链表中移除过期的锁
   mod_timer(&expire_timer, jiffies + expire_in);
  } 
  else // 如果有永久锁或者无效锁
  {    
   // 删除该定时器
   if (del_timer(&expire_timer))
   {
    if (debug_mask & DEBUG_EXPIRE)
     pr_info("wake_lock: %s, stop expire timer\n",
      lock->name);
   }
            // 无有效锁 启动 suspend_work_queue队列 进入深度休眠流程
   if (expire_in == 0)
    queue_work(suspend_work_queue, &suspend_work);
  }
}
spin_unlock_irqrestore(&list_lock, irqflags);
}

/* 遍历指定类型的有效锁链表,参数指定类型的有效锁链表: WAKE_LOCK_SUSPEND、WAKE_LOCK_IDLE
* 遍历有效锁链表中断超时锁,并将已经过期的锁移除,取没有过期并且超时时间最长的锁时间
* 如果没有有效的超时锁则返回-1,如果有效链表没有锁则返回0
* 这个函数每次调用都会遍历锁链表就是因为要处理已经过期的锁,并取得最长的锁时间用于更新定时器
* 重点链表结构: --永久锁--链表头--超时锁-- 
* has_wake_lock_locked()是从链表头后面开始遍历的,即从超时锁遍历。
*/
static long has_wake_lock_locked(int type)
{
struct wake_lock *lock, *n;
long max_timeout = 0;     // 取默认值为 0 如果没有进入代码块

BUG_ON(type >= WAKE_LOCK_TYPE_COUNT);
    // 遍历指定锁类型有效锁链表 如果有效锁链表里面没有锁则不会执行下面的代码块
list_for_each_entry_safe(lock, n, &active_wake_locks[type], link) 
{       // <-- 进入了代码块说明有效链表上有锁
        // 如果是超时锁
        if (lock->flags & WAKE_LOCK_AUTO_EXPIRE) 
  {      // <-- 进入这个代码块说明有效链表上有超时锁
            // 计算超时剩余时间
   long timeout = lock->expires - jiffies;
            // 如果锁已经过期 则移除过期锁
   if (timeout <= 0)
    expire_wake_lock(lock);
            // 如果锁没有过期 则取最长的一个超时时间的锁
   else if (timeout > max_timeout)
    max_timeout = timeout;  
  } 
  else  // 如果不是超时锁说明超时锁已经遍历完,剩下的就是永久锁了,返回 -1 说明其是永久锁
   return -1;
}
return max_timeout;
}

/* 移除过期超时锁 */
static void expire_wake_lock(struct wake_lock *lock)
{
#ifdef CONFIG_WAKELOCK_STAT
wake_unlock_stat_locked(lock, 1);
#endif
    // 清除锁有效和超时锁标志
lock->flags &= ~(WAKE_LOCK_ACTIVE | WAKE_LOCK_AUTO_EXPIRE);
    // 从当前链表中删除
list_del(&lock->link);
    // 加入无效锁链表
list_add(&lock->link, &inactive_locks);
if (debug_mask & (DEBUG_WAKE_LOCK | DEBUG_EXPIRE))
  pr_info("expired wake lock %s\n", lock->name);
}
static DEFINE_TIMER(expire_timer, expire_wake_locks, 0, 0);

/* 判断锁是否有效 这个是直接判断标志位*/
int wake_lock_active(struct wake_lock *lock)
{
return !!(lock->flags & WAKE_LOCK_ACTIVE);
}
EXPORT_SYMBOL(wake_lock_active);

/*
* 定时器的回调函数,因为定时器的定时值一直会被 wake_lock_internal()\wake_unlock()
* 更新为当前有效链表中时间最长的超时锁的超时值,当最长的超时锁时间来到,这函数就会被执行
* 这个函数会调用 has_wake_lock_locked() 来清理过期锁,同时检测到没锁就会进入深度休眠模式
*/
static void expire_wake_locks(unsigned long data)
{
long has_lock;
unsigned long irqflags;
if (debug_mask & DEBUG_EXPIRE)
  pr_info("expire_wake_locks: start\n");
spin_lock_irqsave(&list_lock, irqflags);
    // 如果是调试模式则打印当前有效锁
if (debug_mask & DEBUG_SUSPEND)
  print_active_locks(WAKE_LOCK_SUSPEND);
    // 检测系统是否持有休眠锁 重点 -> 
has_lock = has_wake_lock_locked(WAKE_LOCK_SUSPEND);
if (debug_mask & DEBUG_EXPIRE)
  pr_info("expire_wake_locks: done, has_lock %ld\n", has_lock);
    // 如果系统当前没有持有有效的锁
    if (has_lock == 0)  // 则启动深度休眠工作队列
  queue_work(suspend_work_queue, &suspend_work);
spin_unlock_irqrestore(&list_lock, irqflags);
}
static DEFINE_TIMER(expire_timer, expire_wake_locks, 0, 0);


/* 该函数用于释放一个锁,首先将锁从有效锁链表中移除并加入无效锁链表,并判断系统是否
* 还持有有效锁,如果没有则删除定时器并进入深度休眠流程,如果有则取其中延时最长的超
* 时锁时间用于更新定时器的定时值,当时间到达时就会调用  expire_wake_locks()
*/
void wake_unlock(struct wake_lock *lock)
{
int type;
unsigned long irqflags;
spin_lock_irqsave(&list_lock, irqflags);
type = lock->flags & WAKE_LOCK_TYPE_MASK;
    
#ifdef CONFIG_WAKELOCK_STAT
    // 更新锁的状态
wake_unlock_stat_locked(lock, 0);
#endif

if (debug_mask & DEBUG_WAKE_LOCK)
  pr_info("wake_unlock: %s\n", lock->name);
  
    // 清除有效锁和超时锁标志
lock->flags &= ~(WAKE_LOCK_ACTIVE | WAKE_LOCK_AUTO_EXPIRE);
    // 将锁从有效锁链表中移除
list_del(&lock->link);
    //加入到无效锁链表
list_add(&lock->link, &inactive_locks);
    // 如果是休眠锁
if (type == WAKE_LOCK_SUSPEND) 
{
        // 判断系统当前是否还持有锁
  long has_lock = has_wake_lock_locked(type);
        // 如果还持有锁,设置timer到超时时间点触发
  if (has_lock > 0)  
  {
   if (debug_mask & DEBUG_EXPIRE)
    pr_info("wake_unlock: %s, start expire timer, "
     "%ld\n", lock->name, has_lock);
   mod_timer(&expire_timer, jiffies + has_lock);
  } 
  else 
  {
      // 删除 timer
   if (del_timer(&expire_timer))
    if (debug_mask & DEBUG_EXPIRE)
     pr_info("wake_unlock: %s, stop expire "
      "timer\n", lock->name);
   if (has_lock == 0)  // 启动深度休眠工作队列
    queue_work(suspend_work_queue, &suspend_work);
  }
        // 如果是内核锁 则打印当前有效锁信息
  if (lock == &main_wake_lock) 
  {
   if (debug_mask & DEBUG_SUSPEND)
    print_active_locks(WAKE_LOCK_SUSPEND);
#ifdef CONFIG_WAKELOCK_STAT
   update_sleep_wait_stats_locked(0);
#endif
  }
}
spin_unlock_irqrestore(&list_lock, irqflags);
}
EXPORT_SYMBOL(wake_unlock);

/* 判断系统是否还持有有效锁 */
long has_wake_lock(int type)
{
long ret;
unsigned long irqflags;
spin_lock_irqsave(&list_lock, irqflags);
    // 开始判断流程
ret = has_wake_lock_locked(type);
    // 如果还有休眠锁有效则打印状态信息
if (ret && (debug_mask & DEBUG_WAKEUP) && type == WAKE_LOCK_SUSPEND)
  print_active_locks(type);
spin_unlock_irqrestore(&list_lock, irqflags);
return ret;
}


从以上函数的解析来看,整个锁机制都已经呼之欲出了。

当系统已经没有锁的时候,就会启动 queue_work(suspend_work_queue, &suspend_work); 队列,从而进入深度休眠的流程。
当系统有一个锁,都不会启动深度休眠。所以安卓启动的时候会初始化并激活一把永久锁->main,在需要深度休眠的时候会移除这把锁。
我们初始化锁的时候,调用 wake_lock_init(); 它会初始化锁对象的名字、状态信息等,并将其加入无效锁链表中。

当激活时调用 wake_lock()\wake_lock_timeout()->wake_lock_internal() 会将锁加入到有效链表中,如果是超时锁会调用list_add_tail()
将该锁加入到链表头的后面,如果是永久锁则调用list_add()将该锁加入链表头的前面,有效链表的结构是这样:--永久锁--链表头--超时锁-- ,
这种方式是为了提高has_wake_lock_locked()遍历效率。如果激活的是超时锁,会调用has_wake_lock_locked() 函数遍历 active_wake_locks[0]
->WAKE_LOCK_SUSPEND 类型的有效链表,移除过期锁并取该链表中超时锁中超时值最长的值,将该值作为定时器的值更新到定时器中。如果没有锁
则进入深度休眠流程:queue_work(suspend_work_queue, &suspend_work);

当超时最长的锁的时间到了,那么定时器函数expire_wake_locks()自然也就被回调,定时器函数被回调后就会再次调用 has_wake_lock_locked(WAKE_LOCK_SUSPEND), 将过期的锁移除,定时器根据其返回值知道链表上还有没有锁,如果没有锁则进入深度休眠流程:queue_work(suspend_work_queue, &suspend_work);

当我们要释放锁的时候,调用wake_unlock() 将该锁从有效链表中移到无效链表中,并调用 has_wake_lock_locked(),该函数的功能不再复述,
当有效链表中没有锁时,则进入深度休眠流程:queue_work(suspend_work_queue, &suspend_work);

当我们要销毁一个锁的时候则调用wake_lock_destroy(),就会将锁从链表中删除。

由此可见,android 进入深度休眠时的入口出现在:expire_wake_locks()、wake_lock_internal()、wake_unlock(),这三个地方。每个地方都一定会
调用has_wake_lock_locked()去清除过期锁并得到有效锁链表是否还有锁,如果没有都会启动休眠队列queue_work(suspend_work_queue, &suspend_work);进入深度休眠流程。

我不太明白为什么要大费周章实现这个锁机制,如果有一个APK注册了锁而又忘记了释放锁,那岂不是系统一直都会无法进入深度休眠状态?
可能只进入了浅度休眠状态,而我们以为进入了深度休眠状态导致电池的电量浪费。

不过这锁机制有一个地方很有意思,就是有效锁链表的组织上很巧妙,一点小小的改动就很好的将超时锁和永久锁分好,很大的优化了遍历的性能。
这点表现在wake_lock_internal()函数中,将超时锁加在链表头的后面,而将永久锁加在链表头的前面。
这个链表是双向循环链表,当遍历的时候,就从链表头的后面开始,也就是遍历超时锁,当遍历到的节点不是超时锁,这就意味着是永久锁,
就不需要再继续无谓的遍历了。

--------------------------------------------------- 零散记录 ------------------------------------------------------
驱动代码:linux-3.5\kernel\power\wakelock.c

core_initcall(wakelocks_init);  // 驱动入口 最高优先级 最先加载的驱动
module_exit(wakelocks_exit);

驱动入口函数主要做了如下的事情 static int __init wakelocks_init(void):
1、初始化两个有效锁链表:用于阻止进入深度休眠模式的锁和用于阻止进入浅度休眠模式的锁
当初始化好并被激活的锁都会被加入到相应的有效链表锁里。
2、如果定义了 CONFIG_WAKELOCK_STAT 初始化 deleted_wake_locks 用于处理统计信息
3、初始化内核休眠锁 main_wake_lock ,并激活这个锁,深度休眠时需要释放这个锁
4、初始化同步锁 sync_wake_lock 用于浅度休眠阶段同步缓存时阻止内核进入深度休眠
5、初始化未知锁 用于唤醒时延迟0.5s进入下一次可能的深度休眠
6、如果定义了 CONFIG_EARLYSUSPEND_DELAY 则初始化并激活 ealysuspend_delay_work 浅度休眠锁
7、 注册 power_device power_driver 用于深度休眠阶段检测是否存在有效锁
8、创建 suspend内核工作队列 用于进行浅度休眠和深度休眠
9、创建 同步系统锁内核队列
10、在proc下创建wakelocks文件  节点用于提供节点显示wake_lock的统计信息

static int __init wakelocks_init(void)
{
int ret;
int i;

    // 初始化有效锁链表,内核维护了2个有效锁链表
    // WAKE_LOCK_SUSPEND 用于阻止进入深度休眠模式
    // WAKE_LOCK_IDLE    用于阻止进入空闲模式
for (i = 0; i < ARRAY_SIZE(active_wake_locks); i++)
  INIT_LIST_HEAD(&active_wake_locks[ i]);

#ifdef CONFIG_WAKELOCK_STAT
    // 初始化 deleted_wake_locks 用于处理统计信息
wake_lock_init(&deleted_wake_locks, WAKE_LOCK_SUSPEND, "deleted_wake_locks");
#endif
    // 初始化内核休眠锁
wake_lock_init(&main_wake_lock, WAKE_LOCK_SUSPEND, "main");
    // 初始化同步锁 用于浅度休眠阶段同步缓存时阻止内核进入深度休眠
wake_lock_init(&sync_wake_lock, WAKE_LOCK_SUSPEND, "sync_system");
    // 激活内核休眠锁 系统启动时会激活这个锁,深度休眠时需要释放这个锁
wake_lock(&main_wake_lock);
    // 初始化未知锁 用于唤醒时延迟0.5s进入下一次可能的深度休眠
wake_lock_init(&unknown_wakeup, WAKE_LOCK_SUSPEND, "unknown_wakeups");

wake_lock_init(&suspend_backoff_lock, WAKE_LOCK_SUSPEND, "suspend_backoff");
#ifdef CONFIG_EARLYSUSPEND_DELAY
wake_lock_init(&ealysuspend_delay_work, WAKE_LOCK_SUSPEND, "suspend_delay");
    // 激活 浅度休眠锁
    wake_lock(&ealysuspend_delay_work);
#endif

    // 注册 power_device power_driver 用于深度休眠阶段检测是否存在有效锁
ret = platform_device_register(&power_device);
if (ret) {
  pr_err("wakelocks_init: platform_device_register failed\n");
  goto err_platform_device_register;
}
ret = platform_driver_register(&power_driver);
if (ret) {
  pr_err("wakelocks_init: platform_driver_register failed\n");
  goto err_platform_driver_register;
}
    // 创建 suspend内核工作队列 用于进行浅度休眠和深度休眠
suspend_work_queue = create_singlethread_workqueue("suspend");
if (suspend_work_queue == NULL) {
  ret = -ENOMEM;
  goto err_suspend_work_queue;
}
    // 创建 同步系统锁内核队列
sync_work_queue = create_singlethread_workqueue("sync_system_work");
if (sync_work_queue == NULL) {
  ret = -ENOMEM;
  goto err_sync_work_queue;
}

#ifdef CONFIG_WAKELOCK_STAT
    // 在proc下创建wakelocks文件  节点用于显示wake_lock的统计信息
proc_create("wakelocks", S_IRUGO, NULL, &wakelock_stats_fops);
#endif

return 0;
// 出错处理
err_sync_work_queue:
destroy_workqueue(suspend_work_queue);
err_suspend_work_queue:
platform_driver_unregister(&power_driver);
err_platform_driver_register:
platform_device_unregister(&power_device);
err_platform_device_register:
#ifdef CONFIG_EARLYSUSPEND_DELAY
wake_lock_destroy(&ealysuspend_delay_work);
#endif
wake_lock_destroy(&suspend_backoff_lock);
wake_lock_destroy(&unknown_wakeup);
wake_lock_destroy(&sync_wake_lock);
wake_lock_destroy(&main_wake_lock);
#ifdef CONFIG_WAKELOCK_STAT
wake_lock_destroy(&deleted_wake_locks);
#endif
return ret;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值