当前位置:   article > 正文

wakelock锁_bluesleep占用wakelock锁

bluesleep占用wakelock锁

android的内核版本中,提供了一套阻止系统进入睡眠的wakelock接口,该套接口共有6个;


   
   
  1. struct wake_lock{
  2. struct wakeup_source ws;
  3. };
  4. static inline void wake_lock_init(struct wake_lock *lock,int type,const char* name)
  5. {
  6. wakeup_source_init(&lock->ws,name);
  7. }
  8. static inline void wake_lock_destroy(struct wake_lock* lock)
  9. {
  10. wakeup_source_trash(&lock->ws);
  11. }
  12. static inline void wake_lock(struct wake_lock* lock)
  13. {
  14. __pm_stay_awake(&lock->ws);
  15. }
  16. static inline void wake_lock_timeout(struct wake_lock* lock,long timeout)
  17. {
  18. __pm_stay_awake(&lock->ws);
  19. }
  20. static inline void wake_unlock(struct wake_lock* lock)
  21. {
  22. __pm_relax(&lock->ws);
  23. }
  24. static inline bool wake_lock_active(struct wake_lock* lock)
  25. {
  26. return lock->ws.active;
  27. }
  • 1
还有一个重要的数据结构需要亮一下,那就是wakeup_source,该数据结构完成wakelock锁的基本控制
   
   
  • 1

   
   
  1. /**
  2. * struct wakeup_source - Representation of wakeup sources
  3. *
  4. * @total_time: Total time this wakeup source has been active.
  5. * @max_time: Maximum time this wakeup source has been continuously active.
  6. * @last_time: Monotonic clock when the wakeup source's was touched last time.
  7. * @prevent_sleep_time: Total time this source has been preventing autosleep.
  8. * @event_count: Number of signaled wakeup events.
  9. * @active_count: Number of times the wakeup sorce was activated.
  10. * @relax_count: Number of times the wakeup sorce was deactivated.
  11. * @expire_count: Number of times the wakeup source's timeout has expired.
  12. * @wakeup_count: Number of times the wakeup source might abort suspend.
  13. * @active: Status of the wakeup source.
  14. * @has_timeout: The wakeup source has been activated with a timeout.
  15. */
  16. struct wakeup_source {
  17. const char *name;
  18. struct list_head entry;
  19. spinlock_t lock;
  20. struct timer_list timer;
  21. unsigned long timer_expires;
  22. ktime_t total_time;
  23. ktime_t max_time;
  24. ktime_t last_time;
  25. ktime_t start_prevent_time;
  26. ktime_t prevent_sleep_time;
  27. unsigned long event_count;
  28. unsigned long active_count;
  29. unsigned long relax_count;
  30. unsigned long expire_count;
  31. unsigned long wakeup_count;
  32. bool active: 1;
  33. bool autosleep_enabled: 1;
  34. };
  • 1

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


   
   
  1. static inline void wake_lock_init(struct wake_lock *lock,int type,const char* name)
  2. {
  3. wakeup_source_init(&lock->ws,name);
  4. }
  5. <pre class= "cpp" name= "code"> static inline void wakeup_source_init( struct wakeup_source *ws,
  6. const char *name)
  7. {
  8. wakeup_source_prepare(ws, name);
  9. wakeup_source_add(ws);
  10. }
  • 1

 
  

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


   
   
  1. /**
  2. * wakeup_source_prepare - Prepare a new wakeup source for initialization.
  3. * @ws: Wakeup source to prepare.
  4. * @name: Pointer to the name of the new wakeup source.
  5. *
  6. * Callers must ensure that the @name string won't be freed when @ws is still in
  7. * use.
  8. */
  9. void wakeup_source_prepare(struct wakeup_source *ws, const char *name)
  10. {
  11. if (ws) {
  12. memset(ws, 0, sizeof(*ws));
  13. ws->name = name;
  14. }
  15. }
  16. EXPORT_SYMBOL_GPL(wakeup_source_prepare);
  • 1


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


   
   
  1. /**
  2. * wakeup_source_add - Add given object to the list of wakeup sources.
  3. * @ws: Wakeup source object to add to the list.
  4. */
  5. void wakeup_source_add(struct wakeup_source *ws)
  6. {
  7. if ( WARN_ON(!ws))
  8. return;
  9. spin_lock_init(&ws->lock);
  10. setup_timer(&ws->timer, pm_wakeup_timer_fn, ( unsigned long)ws); //pm_wakeup_timer_fn设置为wakelock锁的超时回调,供超时锁使用
  11. ws->active = false;
  12. ws->last_time = ktime_get();
  13. spin_lock_irq(&events_lock);
  14. list_add_rcu(&ws->entry, &wakeup_sources); //此处添加到链表中,wakelock模块主要操作该链表来控制wakelock锁
  15. spin_unlock_irq(&events_lock);
  16. }
  17. EXPORT_SYMBOL_GPL(wakeup_source_add);
  • 1

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


   
   
  1. /**
  2. * pm_wakeup_timer_fn - Delayed finalization of a wakeup event.
  3. * @data: Address of the wakeup source object associated with the event source.
  4. *
  5. * Call wakeup_source_deactivate() for the wakeup source whose address is stored
  6. * in @data if it is currently active and its timer has not been canceled and
  7. * the expiration time of the timer is not in future.
  8. */
  9. static void pm_wakeup_timer_fn(unsigned long data)
  10. {
  11. struct wakeup_source *ws = ( struct wakeup_source *)data;
  12. unsigned long flags;
  13. spin_lock_irqsave(&ws->lock, flags);
  14. if (ws->active && ws->timer_expires
  15. && time_after_eq(jiffies, ws->timer_expires)) {
  16. wakeup_source_deactivate(ws);
  17. ws->expire_count++;
  18. }
  19. spin_unlock_irqrestore(&ws->lock, flags);
  20. }
  • 1

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


   
   
  1. static inline void wake_lock_destroy(struct wake_lock* lock)
  2. {
  3. wakeup_source_trash(&lock->ws);
  4. }
  5. static inline void wakeup_source_trash(struct wakeup_source *ws)
  6. {
  7. wakeup_source_remove(ws);
  8. wakeup_source_drop(ws);
  9. }
  • 1


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


   
   
  1. /**
  2. * wakeup_source_remove - Remove given object from the wakeup sources list.
  3. * @ws: Wakeup source object to remove from the list.
  4. */
  5. void wakeup_source_remove(struct wakeup_source *ws)
  6. {
  7. if ( WARN_ON(!ws))
  8. return;
  9. spin_lock_irq(&events_lock);
  10. list_del_rcu(&ws->entry);
  11. spin_unlock_irq(&events_lock);
  12. synchronize_rcu();
  13. }
  • 1


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


   
   
  1. /**
  2. * wakeup_source_drop - Prepare a struct wakeup_source object for destruction.
  3. * @ws: Wakeup source to prepare for destruction.
  4. *
  5. * Callers must ensure that __pm_stay_awake() or __pm_wakeup_event() will never
  6. * be run in parallel with this function for the same wakeup source object.
  7. */
  8. void wakeup_source_drop(struct wakeup_source *ws)
  9. {
  10. if (!ws)
  11. return;
  12. del_timer_sync(&ws->timer);
  13. __pm_relax(ws);
  14. }
  • 1

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


   
   
  1. static inline void wake_lock(struct wake_lock* lock)
  2. {
  3. __pm_stay_awake(&lock->ws);
  4. }
  • 1

__pm_stay_awake完成相关超时timer的删除,相关debug信息更新,以及持锁信息的+1操作


   
   
  1. void __pm_stay_awake( struct wakeup_source *ws)
  2. {
  3. unsigned long flags;
  4. if (!ws)
  5. return;
  6. spin_lock_irqsave(&ws->lock, flags);
  7. wakeup_source_report_event(ws);
  8. del_timer(&ws->timer);
  9. ws->timer_expires = 0;
  10. spin_unlock_irqrestore(&ws->lock, flags);
  11. }
  12. static void wakeup_source_report_event(struct wakeup_source *ws)
  13. {
  14. ws->event_count++;
  15. /* This is racy, but the counter is approximate anyway. */
  16. if (events_check_enabled)
  17. ws->wakeup_count++;
  18. if (!ws->active)
  19. wakeup_source_activate(ws);
  20. }
  21. static void wakeup_source_activate(struct wakeup_source *ws)
  22. {
  23. unsigned int cec;
  24. ws->active = true;
  25. ws->active_count++;
  26. ws->last_time = ktime_get();
  27. if (ws->autosleep_enabled)
  28. ws->start_prevent_time = ws->last_time;
  29. /* Increment the counter of events in progress. */
  30. cec = atomic_inc_return(&combined_event_count);
  31. trace_wakeup_source_activate(ws->name, cec);
  32. }
  • 1

4)wake_lock_timeout:投超时锁,超时后释放锁


   
   
  1. static inline void wake_lock_timeout(struct wake_lock* lock,long timeout)
  2. {
  3. __pm_wakeup_event(&lock->ws, jiffies_to_msecs(timeout));
  4. }
  • 1

   
   
  1. void __pm_wakeup_event( struct wakeup_source *ws, unsigned int msec)
  2. {
  3. unsigned long flags;
  4. unsigned long expires;
  5. if (!ws)
  6. return;
  7. spin_lock_irqsave(&ws->lock, flags);
  8. wakeup_source_report_event(ws); //先上锁
  9. if (!msec) { //如果超时时间为0,则立刻释放锁
  10. wakeup_source_deactivate(ws);
  11. goto unlock;
  12. }
  13. expires = jiffies + msecs_to_jiffies(msec);
  14. if (!expires)
  15. expires = 1;
  16. if (!ws->timer_expires || time_after(expires, ws->timer_expires)) {
  17. mod_timer(&ws->timer, expires); //更新timer超时时间,超时后调用 pm_wakeup_timer_fn释放锁
  18. ws->timer_expires = expires;
  19. }
  20. unlock:
  21. spin_unlock_irqrestore(&ws->lock, flags);
  22. }
  • 1

5)wake_unlock:投票同意睡眠,释放wakelock锁


   
   
  1. static inline void wake_unlock(struct wake_lock* lock)
  2. {
  3. __pm_relax(&lock->ws);
  4. }
  • 1

   
   
  1. void __pm_relax( struct wakeup_source *ws)
  2. {
  3. unsigned long flags;
  4. if (!ws)
  5. return;
  6. spin_lock_irqsave(&ws->lock, flags);
  7. if (ws->active)
  8. wakeup_source_deactivate(ws); //释放锁
  9. spin_unlock_irqrestore(&ws->lock, flags);
  10. }
  11. static void wakeup_source_deactivate(struct wakeup_source *ws)
  12. {
  13. unsigned int cnt, inpr, cec;
  14. ktime_t duration;
  15. ktime_t now;
  16. ws->relax_count++;
  17. /*
  18. * __pm_relax() may be called directly or from a timer function.
  19. * If it is called directly right after the timer function has been
  20. * started, but before the timer function calls __pm_relax(), it is
  21. * possible that __pm_stay_awake() will be called in the meantime and
  22. * will set ws->active. Then, ws->active may be cleared immediately
  23. * by the __pm_relax() called from the timer function, but in such a
  24. * case ws->relax_count will be different from ws->active_count.
  25. */
  26. if (ws->relax_count != ws->active_count) {
  27. ws->relax_count--;
  28. return;
  29. }
  30. ws->active = false;
  31. now = ktime_get();
  32. duration = ktime_sub(now, ws->last_time);
  33. ws->total_time = ktime_add(ws->total_time, duration);
  34. if ( ktime_to_ns(duration) > ktime_to_ns(ws->max_time))
  35. ws->max_time = duration;
  36. ws->last_time = now;
  37. del_timer(&ws->timer);
  38. ws->timer_expires = 0;
  39. if (ws->autosleep_enabled)
  40. update_prevent_sleep_time(ws, now);
  41. /*
  42. * Increment the counter of registered wakeup events and decrement the
  43. * couter of wakeup events in progress simultaneously.
  44. */
  45. cec = atomic_add_return(MAX_IN_PROGRESS, &combined_event_count);
  46. trace_wakeup_source_deactivate(ws->name, cec);
  47. split_counters(&cnt, &inpr);
  48. if (!inpr && waitqueue_active(&wakeup_count_wait_queue)) //如果满足睡眠条件,则唤醒等待队列
  49. wake_up(&wakeup_count_wait_queue); //此处需要配合前边讲的autosleep来看了}
  • 1

6)wake_lock_active:返回锁的激活状态,主要是查询功能


   
   
  1. static inline bool wake_lock_active(struct wake_lock* lock)
  2. {
  3. return lock->ws.active;
  4. }
  • 1





 


 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/喵喵爱编程/article/detail/818027
推荐阅读
相关标签
  

闽ICP备14008679号