The current freezer traverses all user tasks in a single pass, without distinguishing between tasks that are easier or harder to freeze. This uniform treatment may cause suboptimal behavior when certain newly created tasks, service daemons, or system threads block the progress of freeze due to dependency ordering issues. This patch introduces a simple multi-pass traversal model in try_to_freeze_tasks(), where user tasks are grouped and frozen by their freeze_priority in descending order. Tasks marked with higher priority are attempted earlier, which can help break dependency cycles earlier and reduce retry iterations. Specifically: - A new loop iterates over priority levels. - In each round, only tasks with freeze_priority < current priority are visited. - The behavior applies only to user task freezing (when user_only == true). This approach preserves compatibility with the current logic, while enabling fine-grained control via future enhancements (e.g., dynamic priority tuning). Signed-off-by: Zihuan Zhang --- kernel/power/process.c | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/kernel/power/process.c b/kernel/power/process.c index dc0dfc349f22..06eafdb32abb 100644 --- a/kernel/power/process.c +++ b/kernel/power/process.c @@ -32,10 +32,12 @@ static int try_to_freeze_tasks(bool user_only) struct task_struct *g, *p; unsigned long end_time; unsigned int todo; + unsigned int round = 0; bool wq_busy = false; ktime_t start, end, elapsed; unsigned int elapsed_msecs; bool wakeup = false; + bool has_freezable_task; int sleep_usecs = USEC_PER_MSEC; pr_info("Freezing %s\n", what); @@ -47,13 +49,18 @@ static int try_to_freeze_tasks(bool user_only) if (!user_only) freeze_workqueues_begin(); - while (true) { + while (round < FREEZE_PRIORITY_NEVER) { todo = 0; + has_freezable_task = false; read_lock(&tasklist_lock); for_each_process_thread(g, p) { + if (user_only && !(p->flags & PF_KTHREAD) && round < p->freeze_priority) + continue; + if (p == current || !freeze_task(p)) continue; + has_freezable_task = true; todo++; } read_unlock(&tasklist_lock); @@ -63,6 +70,12 @@ static int try_to_freeze_tasks(bool user_only) todo += wq_busy; } + round++; + + /* sleep only if need to freeze tasks */ + if (user_only && !has_freezable_task) + continue; + if (!todo || time_after(jiffies, end_time)) break; -- 2.25.1