从这篇开始我就开始对android下的wakelock和suspend是如何结合做些自己的分析,长话短说吧,我们首先看看个函数:
路径如下:
kernel/kernel/power/main.c
这个函数就是Native曾调用的接口程序,比如:state, wakelock , unwakelock,这里都有具体实现,下面我们先分析下wake_lock相关函数,上锁过程:
(注意我只分析store函数 show函数我就不分析了)
456 static ssize_t wake_lock_store(struct kobject *kobj,
457 struct kobj_attribute *attr,
458 const char *buf, size_t n)
459 {
460 int error = pm_wake_lock(buf);
461 return error ? error : n;
462 }
这端函数没有什么可说的,就是直接把上层申请的锁名称传到pm_wake_lock中,比如 mWakeLockSuspendBlocker = createSuspendBlockerLocked("PowerManagerService"); 中的PowerManagerService。我们继续看下pm_wake_lock函数,
183 int pm_wake_lock(const char *buf)
184 {
185 const char *str = buf;
186 struct wakelock *wl;
187 u64 timeout_ns = 0;
188 size_t len;
189 int ret = 0;
190
191 while (*str && !isspace(*str))
192 str++;
193
194 len = str - buf;
195 if (!len)
196 return -EINVAL;
197
198 if (*str && *str != '\n') {
199 /* Find out if there's a valid timeout string appended. */
200 ret = kstrtou64(skip_spaces(str), 10, &timeout_ns);
201 if (ret)
202 return -EINVAL;
203 }
204
205 mutex_lock(&wakelocks_lock);
206
207 wl = wakelock_lookup_add(buf, len, true);
208 if (IS_ERR(wl)) {
209 ret = PTR_ERR(wl);
210 goto out;
211 }
212 if (timeout_ns) {
213 u64 timeout_ms = timeout_ns + NSEC_PER_MSEC - 1;
214
215 do_div(timeout_ms, NSEC_PER_MSEC);
216 __pm_wakeup_event(&wl->ws, timeout_ms);
217 } else {
218 __pm_stay_awake(&wl->ws);
219 }
220
221 wakelocks_lru_most_recent(wl);
222
223 out:
224 mutex_unlock(&wakelocks_lock);
225 return ret;
226 }
这端函数主要功能在于检查这个wakelock是否存在红黑二叉树上,把名字短的放在左叉,名字长的放在右叉,这里是不是跟进程调度的二叉树很像?^_^,然后调用__pm_wakeup_event或者__pm_stay_awake函数,这里的timeout_ms我没有看明白怎么取得的,烦人,以后慢慢看看再。继续跟踪没有timeout_ms的函数吧,另外的函数进入也干了同样的事情,还对timeout进行了一些处理,可能和两种锁有关系哦?一种是带timeout时间的锁,到时会注销,一种是不带时间锁,如果没有显示的unlock就不会放弃锁。
418 void __pm_stay_awake(struct wakeup_source *ws)
419 {
420 unsigned long flags;
421
422 if (!ws)
423 return;
424
425 spin_lock_irqsave(&ws->lock, flags);
426
427 wakeup_source_report_event(ws);
428 del_timer(&ws->timer);
429 ws->timer_expires = 0;
430
431 spin_unlock_irqrestore(&ws->lock, flags);
432 }
这个函数主要干的就是调用wakeup_source_report_evet这个函数
01 static void wakeup_source_report_event(struct wakeup_source *ws)
402 {
403 ws->event_count++;
404 /* This is racy, but the counter is approximate anyway. */
405 if (events_check_enabled)
406 ws->wakeup_count++;
407
408 if (!ws->active)
409 wakeup_source_activate(ws);
381 static void wakeup_source_activate(struct wakeup_source *ws)
382 {
383 unsigned int cec;
384
385 ws->active = true;
386 ws->active_count++;
387 ws->last_time = ktime_get();
388 if (ws->autosleep_enabled)
389 ws->start_prevent_time = ws->last_time;
390
391 /* Increment the counter of events in progress. */
392 cec = atomic_inc_return(&combined_event_count);
393
394 trace_wakeup_source_activate(ws->name, cec);
395 }
这两段函数连续看,会发现,对与一些count进行的++,设置了下wake_lock中的wake_source的一些变量,主要是 对于combined_event_count这个变量进行的原子操作++,(这个变量暂时理解胃是记录有多少个wakelock吧),然后就完活了啊,这样就对一个wakelock进行。
我们再分析下wake_unlock_store这个函数,
473 static ssize_t wake_unlock_store(struct kobject *kobj,
474 struct kobj_attribute *attr,
475 const char *buf, size_t n)
476 {
477 int error = pm_wake_unlock(buf);
478 return error ? error : n;
479 }
操作一样,把写到节点的字符串传到pm_wake_unlock(buf)函数中
228 int pm_wake_unlock(const char *buf)
229 {
230 struct wakelock *wl;
231 size_t len;
232 int ret = 0;
233
234 len = strlen(buf);
235 if (!len)
236 return -EINVAL;
237
238 if (buf[len-1] == '\n')
239 len--;
240
241 if (!len)
242 return -EINVAL;
243
244 mutex_lock(&wakelocks_lock);
245
246 wl = wakelock_lookup_add(buf, len, false);
247 if (IS_ERR(wl)) {
248 ret = PTR_ERR(wl);
249 goto out;
250 }
251 __pm_relax(&wl->ws);
252
253 wakelocks_lru_most_recent(wl);
254 wakelocks_gc();
255
256 out:
257 mutex_unlock(&wakelocks_lock);
258 return ret;
259 }
这里也是在wake_lock二叉树查找wake_lock,然后调用__pm_relax(&wl->ws);这个函数,精髓都在这里,我们跟踪下去
535 void __pm_relax(struct wakeup_source *ws)
536 {
537 unsigned long flags;
538
539 if (!ws)
540 return;
541
542 spin_lock_irqsave(&ws->lock, flags);
543 if (ws->active)
544 wakeup_source_deactivate(ws);
545 spin_unlock_irqrestore(&ws->lock, flags);
546 }
547 EXPORT_SYMBOL_GPL(__pm_relax);
看到ws->active了吗?这个在之前上锁的时候我们定义过true哦,然后调用wakeup_source_deactivate这个函数,
478 static void wakeup_source_deactivate(struct wakeup_source *ws)
479 {
480 unsigned int cnt, inpr, cec;
481 ktime_t duration;
482 ktime_t now;
483
484 ws->relax_count++;
485 /*
486 * __pm_relax() may be called directly or from a timer function.
487 * If it is called directly right after the timer function has been
488 * started, but before the timer function calls __pm_relax(), it is
489 * possible that __pm_stay_awake() will be called in the meantime and
490 * will set ws->active. Then, ws->active may be cleared immediately
491 * by the __pm_relax() called from the timer function, but in such a
492 * case ws->relax_count will be different from ws->active_count.
493 */
494 if (ws->relax_count != ws->active_count) {
495 ws->relax_count--;
496 return;
497 }
498
499 ws->active = false;
500
501 now = ktime_get();
502 duration = ktime_sub(now, ws->last_time);
503 ws->total_time = ktime_add(ws->total_time, duration);
504 if (ktime_to_ns(duration) > ktime_to_ns(ws->max_time))
505 ws->max_time = duration;
506
507 ws->last_time = now;
508 del_timer(&ws->timer);
509 ws->timer_expires = 0;
510
511 if (ws->autosleep_enabled)
512 update_prevent_sleep_time(ws, now);
513
514 /*
515 * Increment the counter of registered wakeup events and decrement the
516 * couter of wakeup events in progress simultaneously.
517 */
518 cec = atomic_add_return(MAX_IN_PROGRESS, &combined_event_count);
519 trace_wakeup_source_deactivate(ws->name, cec);
520
521 split_counters(&cnt, &inpr);
522 if (!inpr && waitqueue_active(&wakeup_count_wait_queue))
523 wake_up(&wakeup_count_wait_queue);
524 }
这个函数前面我们就不看了,主要看下 521行到523行,这里split_counters实现如下
32 static atomic_t combined_event_count = ATOMIC_INIT(0);
33
34 #define IN_PROGRESS_BITS (sizeof(int) * 4)
35 #define MAX_IN_PROGRESS ((1 << IN_PROGRESS_BITS) - 1)
36
37 static void split_counters(unsigned int *cnt, unsigned int *inpr)
38 {
39 unsigned int comb = atomic_read(&combined_event_count);
40
41 *cnt = (comb >> IN_PROGRESS_BITS);
42 *inpr = comb & MAX_IN_PROGRESS;
43 }
这个原子操作不就是得到了刚才我们++combined_event_count记录的wake_lock数量的变量吗?取得32位数上的高16位数啊,这样的话难道每次都是高16位存的都是新值,而后16位都是旧值吗?这个还需要研究研究!然后我们看下后两行
522 if (!inpr && waitqueue_active(&wakeup_count_wait_queue))
523 wake_up(&wakeup_count_wait_queue);
这个就是判断wake_locks数,等待队列是否活动,然后唤醒等待队列,这个等待队列到底在哪里了?我们往后再说,这里先卖个关子 哇哈哈!
好了 现在我们wake_lock和unwake_lock都已经说了,但是他们和suspend有毛关系呢?我们继续分析state这个函数。
如果我们执行echo mem > /sys/power/state 会发生什么? 没错,手机屏幕会灭,手机会进入了earlysuspend状态,呵呵,这就是我分析第二片文章为什么要特意说下farmework 到 native 怎么把值写到这个节点的必要性了。下面我们看看函数
301 static ssize_t state_store(struct kobject *kobj, struct kobj_attribute *attr,
302 const char *buf, size_t n)
303 {
304 suspend_state_t state;
305 int error;
306
307 error = pm_autosleep_lock();
308 if (error)
309 return error;
310
311 if (pm_autosleep_state() > PM_SUSPEND_ON) {
312 error = -EBUSY;
313 goto out;
314 }
315
316 state = decode_state(buf, n);
317 if (state < PM_SUSPEND_MAX) {
318 #ifdef CONFIG_EARLYSUSPEND
319 if (state == PM_SUSPEND_ON || valid_state(state)) {
320 error = 0;
321 request_suspend_state(state);
322 }
323 #else
324 error = pm_suspend(state);
325 #endif
326
327 }
328 else if (state == PM_SUSPEND_MAX)
329 error = hibernate();
330 else
331 error = -EINVAL;
332
333 out:
334 pm_autosleep_unlock();
335 return error ? error : n;
336 }
首先判断系统是不是正在suspend的状态,然后检查写入的值是否有效,如果有效这里分支就是为了支持earlysuspend过能和不带earlysuspend功能,然后调用request_suspend_state(state);这个函数。移动设备默认都带earlysuspend功能
208 void request_suspend_state(suspend_state_t new_state)
209 {
210 unsigned long irqflags;
211 int old_sleep;
212 suspend_state_t prev_state;
213
214 mutex_lock(&suspend_lock);
215 prev_state = suspend_state;
216 spin_lock_irqsave(&state_lock, irqflags);
217 old_sleep = state & SUSPEND_REQUESTED;
218 if (debug_mask & DEBUG_USER_STATE) {
219 struct timespec ts;
220 struct rtc_time tm;
221 getnstimeofday(&ts);
222 rtc_time_to_tm(ts.tv_sec, &tm);
223 pr_info("request_suspend_state: %s (%d->%d) at %lld "
224 "(%d-%02d-%02d %02d:%02d:%02d.%09lu UTC)\n",
225 new_state != PM_SUSPEND_ON ? "sleep" : "wakeup",
226 prev_state, new_state,
227 ktime_to_ns(ktime_get()),
228 tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
229 tm.tm_hour, tm.tm_min, tm.tm_sec, ts.tv_nsec);
230 }
231 if (!old_sleep && new_state != PM_SUSPEND_ON) {
232 state |= SUSPEND_REQUESTED;
233 queue_up_early_suspend_work(&early_suspend_work);
234 } else if (old_sleep && new_state == PM_SUSPEND_ON) {
235 state &= ~SUSPEND_REQUESTED;
236 __pm_stay_awake(early_suspend_ws);
237 queue_up_early_suspend_work(&late_resume_work);
238 }
239 suspend_state = new_state;
240 spin_unlock_irqrestore(&state_lock, irqflags);
241 mutex_unlock(&suspend_lock);
242 }
这个函数主要就是区分是要走earlysuspend 还是lateresume,然后调用&early_suspend_work)这个工作队列,其实就是调用early_suspend函数
136 static void early_suspend(struct work_struct *work)
137 {
138 struct early_suspend *pos;
139 unsigned long irqflags;
140 int abort = 0;
141
142 mutex_lock(&early_suspend_lock);
143 spin_lock_irqsave(&state_lock, irqflags);
144 if (state == SUSPEND_REQUESTED)
145 state |= SUSPENDED;
146 else
147 abort = 1;
148 spin_unlock_irqrestore(&state_lock, irqflags);
149
150 if (abort) {
151 if (debug_mask & DEBUG_SUSPEND)
152 pr_info("early_suspend: abort, state %d\n", state);
153 mutex_unlock(&early_suspend_lock);
154 goto abort;
155 }
156
157 if (debug_mask & DEBUG_SUSPEND)
158 pr_info("early_suspend: call handlers\n");
159 list_for_each_entry(pos, &early_suspend_handlers, link) {
160 if (pos->suspend != NULL)
161 pos->suspend(pos);
162 }
163 mutex_unlock(&early_suspend_lock);
164
165 if (debug_mask & DEBUG_SUSPEND)
166 pr_info("early_suspend: after call handlers\n");
167 /* just wake up flusher to start write back and don't wait it finished*/
168 wakeup_flusher_threads(0, WB_REASON_SYNC);
169 abort:
170 spin_lock_irqsave(&state_lock, irqflags);
171 if (state == SUSPEND_REQUESTED_AND_SUSPENDED)
172 __pm_relax(early_suspend_ws);
173 spin_unlock_irqrestore(&state_lock, irqflags);
174 mod_timer(&monitor_timer, jiffies + monitor_period*HZ);
175 queue_work(suspend_wq, &suspend_work);
176 }
这里就是逐个调用平台注册过得earlysuspend函数,按照leave来调用哦,注册时候会定义,然后系统会调用 queue_work(suspend_wq, &suspend_work);这个工作队列,这个其实就是try_to_suspend,
68 static void try_to_suspend(struct work_struct *work)
69 {
70 unsigned int initial_count, final_count;
71
72 if (!pm_get_wakeup_count(&initial_count, true) ||
73 !alarm_pm_wake_check())
74 goto queue_again;
75
76 mutex_lock(&suspend_lock);
77
78 if (!pm_save_wakeup_count(initial_count)) {
79 mutex_unlock(&suspend_lock);
80 goto queue_again;
81 }
82 del_timer_sync(&monitor_timer);
83
84 if (suspend_state == PM_SUSPEND_ON) {
85 mutex_unlock(&suspend_lock);
86 return;
87 }
88
89 if (suspend_state >= PM_SUSPEND_MAX)
90 hibernate();
91 else
92 pm_suspend(suspend_state);
93
94 mutex_unlock(&suspend_lock);
95
96 if (!pm_get_wakeup_count(&final_count, false))
97 goto queue_again;
98
99 /*
100 * If the wakeup occured for an unknown reason, wait to prevent the
101 * system from trying to suspend and waking up in a tight loop.
102 */
103 if (final_count == initial_count)
104 schedule_timeout_uninterruptible(HZ / 2);
105
106 queue_again:
107 queue_work(suspend_wq, &suspend_work);
108 }
函数嘴开始就执行了 pm_get_wakeup_count()这个函数,这个函数:
722 bool pm_get_wakeup_count(unsigned int *count, bool block)
723 {
724 unsigned int cnt, inpr;
725
726 if (block) {
727 DEFINE_WAIT(wait);
728
729 for (;;) {
730 prepare_to_wait(&wakeup_count_wait_queue, &wait,
731 TASK_INTERRUPTIBLE);
732 split_counters(&cnt, &inpr);
733 if (inpr == 0 || signal_pending(current))
734 break;
735
736 schedule();
737 }
738 finish_wait(&wakeup_count_wait_queue, &wait);
739 }
740
741 split_counters(&cnt, &inpr);
742 *count = cnt;
743 return !inpr;
744 }
看到了刚才我们介绍unwake_lock函数的时候碰见的wakeup_count_wait_queue等待队列了吧,没错,这里就循环等待是不是有应用或者driver拿着锁,如果拿着就调度出去做别的事情,等待unwake_lock的显示唤醒队列,然后再去检查split_counters(&cnt, &inpr);锁数量,如果没有锁了,OK,我们跳出循环,准备进入下面的suspend流程,到这里是不是就算解释清楚,wakelock和suspend的关系了呢?上层 中层 底层调用基本上已经联系一起了,我会在下篇文章继续分析suspend的流程!
还是一样,本人小菜鸟一名,如果不对,请指出,谢谢!
阅读(6857) | 评论(2) | 转发(4) |