본문 바로가기

[Debugging] Tips

[crash-utility]wakelock - rbtree debugging(디버깅)

 
코어 덤프에서 wakelock 정보를 CrashTool(red hat crash-utility)로 확인할 수 있는 팁을 공유하고자 해요.
 
CrashTool "rbtree"에 대해 강력한 명령어를 제공하거든요.
wakelocks_tree란 전역 변수에서 rb_node를 확인하고요. 0xffffffc0e397b108
아래 오프셋으로 명령어를 주면 되요.
crash64> tree -t rbtree -o wakelock.node -N 0xffffffc0e397b108
ffffffc0e397b100
ffffffc0d4262200
ffffffc0c9e8e100
ffffffc066355400
ffffffc06a0a0900
ffffffc0c5cd8600
ffffffc04fddcb00
ffffffc0e397bb00
ffffffc06c55b800
ffffffc06c7c3e00
ffffffc0eb6b5100
ffffffc0d6dc2b00
ffffffc06a124500
ffffffc0c5d35300
(where)
crash64> p wakelocks_tree
wakelocks_tree = $1 = {
  rb_node = 0xffffffc0e397b108
}
 
자 하나 하나 씩 점검 좀 해볼께요. 
"PowerManagerService.Display" wakelock 소스는 active가 true이니 wakelock을 잡고 있네요.
crash64> struct wakelock   ffffffc0d4262200
struct wakelock {
  name = 0xffffffc063479080 "PowerManagerService.Display",
  node = {
    __rb_parent_color = 18446743802650013961,
    rb_right = 0xffffffc0c5cd8608,
    rb_left = 0xffffffc0c9e8e108
  },
// .. 생략...
    expire_count = 0,
    wakeup_count = 14,
    pending_count = 6,
    active = true,
    autosleep_enabled = false
 
"KeyEvents"는 안 잡고 있고요.
crash64> struct wakelock   ffffffc0c9e8e100
struct wakelock {
  name = 0xffffffc066213900 "KeyEvents",
  node = {
    __rb_parent_color = 18446743802390913545,
    rb_right = 0xffffffc06a0a0908,
    rb_left = 0xffffffc066355408
  },
// .. 생략...
    wakeup_count = 258,
    pending_count = 1,
    active = false,
    autosleep_enabled = false
 
이런 식으로 wakelock을 누가 잡고 있는 지 확인할 수 있어요.
그럼 wakelock을 잡는 코드는 어디일까요? 아래 패치를 잠깐 보면 알 수 있어요.
diff --git a/drivers/base/power/wakeup.c b/drivers/base/power/wakeup.c
index 7af116e..18b8b2e 100644
--- a/drivers/base/power/wakeup.c
+++ b/drivers/base/power/wakeup.c
@@ -177,6 +177,9 @@ void wakeup_source_add(struct wakeup_source *ws)
                return;
 
        spin_lock_init(&ws->lock);
+
+       trace_printk("+ wakelock add - process(%s), from(%pF)\n", current->comm, __builtin_return_address(0));
+
        setup_timer(&ws->timer, pm_wakeup_timer_fn, (unsigned long)ws);
        ws->active = false;
        ws->last_time = ktime_get();
@@ -547,6 +550,8 @@ static void wakeup_source_activate(struct wakeup_source *ws)
        /* Increment the counter of events in progress. */
        cec = atomic_inc_return(&combined_event_count);
 
+       trace_printk("+ wakelock activate process(%s), from(%pF)\n", current->comm, __builtin_return_address(0));
+
        trace_wakeup_source_activate(ws->name, cec);
 }
 
위 패치를 적용하고 나면 아래 ftrace log로 언제 wakelock을 잡았는 지 확인할 수 있어요
<...>-4480  [000] ....    32.668732: wakeup_source_activate: + wakelock activate process(rild),  from(pm_wake_lock+0xa4/0x174) source[radio-interface]
 
상세 wakelock 동작에 대해서는 나중에 다뤄보도록 할께요.