When diagnosing workqueue stalls, knowing how long each in-flight work item has been executing is valuable. Add a current_start timestamp (jiffies) to struct worker, set it when a work item begins execution in process_one_work(), and print the elapsed wall-clock time in show_pwq(). Unlike current_at (which tracks CPU runtime and resets on wakeup for CPU-intensive detection), current_start is never reset because the diagnostic cares about total wall-clock time including sleeps. Before: in-flight: 165:stall_work_fn [wq_stall] After: in-flight: 165:stall_work_fn [wq_stall] for 100s
Showing the changes to kernel/workqueue.c (1 of 2 files). Show all
Unified · Split
| @@ -3204,6 +3204,7 @@ __acquires(&pool->lock) · 3203 unmodified lines | |||
| 3204 | worker->current_pwq = pwq; | 3204 | worker->current_pwq = pwq; |
| 3205 | if (worker->task) | 3205 | if (worker->task) |
| 3206 | worker->current_at = worker->task->se.sum_exec_runtime; | 3206 | worker->current_at = worker->task->se.sum_exec_runtime; |
| 3207 | worker->current_start = jiffies; | ||
| 3207 | work_data = *work_data_bits(work); | 3208 | work_data = *work_data_bits(work); |
| 3208 | worker->current_color = get_work_color(work_data); | 3209 | worker->current_color = get_work_color(work_data); |
| 3209 | 3210 | ||
| @@ -6359,6 +6360,8 @@ static void show_pwq(struct pool_workqueue *pwq) · 3149 unmodified lines | |||
| 6359 | pr_cont(" %s", comma ? "," : ""); | 6360 | pr_cont(" %s", comma ? "," : ""); |
| 6360 | pr_cont_worker_id(worker); | 6361 | pr_cont_worker_id(worker); |
| 6361 | pr_cont(":%ps", worker->current_func); | 6362 | pr_cont(":%ps", worker->current_func); |
| 6363 | pr_cont(" for %us", | ||
| 6364 | jiffies_to_msecs(jiffies - worker->current_start) / 1000); | ||
| 6362 | list_for_each_entry(work, &worker->scheduled, entry) | 6365 | list_for_each_entry(work, &worker->scheduled, entry) |
| 6363 | pr_cont_work(false, work, &pcws); | 6366 | pr_cont_work(false, work, &pcws); |
| 6364 | pr_cont_work_flush(comma, (work_func_t)-1L, &pcws); | 6367 | pr_cont_work_flush(comma, (work_func_t)-1L, &pcws); |