안드로이드에서 wake lock이란 기능이 있습니다. 그런데 대부분 wake lock을 어떤 모듈이 잡고 있어서 슬립에 못 들어가는 문제가 생기죠. 이럴 때 프로파일링하면 좋은 디버그 패치를 소개합니다.
diff --git a/drivers/base/power/wakeup.c b/drivers/base/power/wakeup.c
old mode 100644
new mode 100755
index 7dbfe1a..2ca0964
--- a/drivers/base/power/wakeup.c
+++ b/drivers/base/power/wakeup.c
@@ -54,6 +54,7 @@ static DEFINE_SPINLOCK(events_lock);
static void pm_wakeup_timer_fn(unsigned long data);
static LIST_HEAD(wakeup_sources);
+static LIST_HEAD(wakeup_sources_shadow);
static DECLARE_WAIT_QUEUE_HEAD(wakeup_count_wait_queue);
@@ -134,6 +135,17 @@ static void wakeup_source_destroy_cb(struct rcu_head *head)
wakeup_source_destroy(container_of(head, struct wakeup_source, rcu));
}
+struct wakeup_source_shadow {
+ struct list_head entry;
+ const char *name;
+ struct task_struct *p;
+ struct wakeup_source *ws;
+ ktime_t add_ts;
+ ktime_t rmv_ts;
+ int ws_event; /* 1 for add, 2 for remove */
+};
+
+
/**
* wakeup_source_add - Add given object to the list of wakeup sources.
* @ws: Wakeup source object to add to the list.
@@ -141,7 +153,8 @@ static void wakeup_source_destroy_cb(struct rcu_head *head)
void wakeup_source_add(struct wakeup_source *ws)
{
unsigned long flags;
-
+ struct wakeup_source_shadow *ws_sh;
+
if (WARN_ON(!ws))
return;
@@ -152,6 +165,19 @@ void wakeup_source_add(struct wakeup_source *ws)
spin_lock_irqsave(&events_lock, flags);
list_add_rcu(&ws->entry, &wakeup_sources);
+ if (!strncmp(ws->name, "wlan", strlen("wlan"))) {
+ pr_err("[%s] add hit : %p, %s\n", __func__, ws, ws->name);
+ ws_sh = kmalloc(sizeof(*ws_sh), GFP_ATOMIC);
+ if (ws_sh) {
+ ws_sh->ws = ws;
+ ws_sh->p = current;
+ ws_sh->name = ws->name;
+ ws_sh->add_ts = ws_sh->rmv_ts = ws->last_time;
+ ws_sh->ws_event = 1;
+ list_add_rcu(&ws_sh->entry, &wakeup_sources_shadow);
+ dump_stack();
+ }
+ }
spin_unlock_irqrestore(&events_lock, flags);
}
EXPORT_SYMBOL_GPL(wakeup_source_add);
@@ -163,12 +189,25 @@ EXPORT_SYMBOL_GPL(wakeup_source_add);
void wakeup_source_remove(struct wakeup_source *ws)
{
unsigned long flags;
-
+ struct wakeup_source_shadow *ws_sh;
+
if (WARN_ON(!ws))
return;
spin_lock_irqsave(&events_lock, flags);
list_del_rcu(&ws->entry);
+ if (!strncmp(ws->name, "wlan", strlen("wlan"))) {
+ pr_err("[%s] rmv hit : %p, %s\n", __func__, ws, ws->name);
+ list_for_each_entry(ws_sh, &wakeup_sources_shadow, entry) {
+ if (ws_sh->ws == ws) {
+ ws_sh->rmv_ts = ktime_get();
+ ws_sh->ws_event = 2;
+ ws_sh->p = current;
+ dump_stack();
+ break;
+ }
+ }
+ }
spin_unlock_irqrestore(&events_lock, flags);
synchronize_rcu();
}
'[Debugging] Tips' 카테고리의 다른 글
[crash-utility] wakelock 디버깅(rbtree: wakelocks_tree) (0) | 2023.05.04 |
---|---|
[Best][Kernel][Stability] 스택 오염(Stack Corruption) 디버깅 (0) | 2023.05.04 |
[Kernel][Debug] 런큐에서 CFS 스케쥴러에 큐잉된 프로세스 찾기 (0) | 2023.05.04 |
[Trace32] 폰트 색상 변경 - setup.color (0) | 2023.05.04 |
[리눅스커널][Trace32] wakelock 디버깅 - container_of (0) | 2023.05.04 |