History

workqueue: Introduce show_one_worker_pool and show_one_workqueue.

Currently show_workqueue_state shows the state of all workqueues and of all worker pools. In certain cases we may need to dump state of only a specific workqueue or worker pool. For example in destroy_workqueue we only need to show state of the workqueue which is getting destroyed. So rename show_workqueue_state to show_all_workqueues(to signify it dumps state of all busy workqueues) and divide it into more granular functions (show_one_workqueue and show_one_worker_pool), that would show states of individual workqueues and worker pools and can be used in cases such as the one mentioned above. Also, as mentioned earlier, make destroy_workqueue dump data pertaining to only the workqueue that is being destroyed and make user(s) of earlier interface(show_workqueue_state), use new interface (show_all_workqueues).

Imran Khan committed 5 years ago

Commit 55df0931 parent d25302e4 files · +100 −79Browse files

Showing the changes to kernel/workqueue.c (1 of 4 files). Show all

Unified · Split

kernel/workqueue.c+96−76
@@ -375,6 +375,7 @@ EXPORT_SYMBOL_GPL(system_freezable_power_efficient_wq); · 374 unmodified lines
375static int worker_thread(void *__worker);375static int worker_thread(void *__worker);
376static void workqueue_sysfs_unregister(struct workqueue_struct *wq);376static void workqueue_sysfs_unregister(struct workqueue_struct *wq);
377static void show_pwq(struct pool_workqueue *pwq);377static void show_pwq(struct pool_workqueue *pwq);
378static void show_one_worker_pool(struct worker_pool *pool);
378 379
379#define CREATE_TRACE_POINTS380#define CREATE_TRACE_POINTS
380#include <trace/events/workqueue.h>381#include <trace/events/workqueue.h>
@@ -4447,7 +4448,7 @@ void destroy_workqueue(struct workqueue_struct *wq) · 4066 unmodified lines
4447 raw_spin_unlock_irq(&pwq->pool->lock);4448 raw_spin_unlock_irq(&pwq->pool->lock);
4448 mutex_unlock(&wq->mutex);4449 mutex_unlock(&wq->mutex);
4449 mutex_unlock(&wq_pool_mutex);4450 mutex_unlock(&wq_pool_mutex);
4450 show_workqueue_state();4451 show_one_workqueue(wq);
4451 return;4452 return;
4452 }4453 }
4453 raw_spin_unlock_irq(&pwq->pool->lock);4454 raw_spin_unlock_irq(&pwq->pool->lock);
@@ -4797,97 +4798,116 @@ static void show_pwq(struct pool_workqueue *pwq) · 343 unmodified lines
4797}4798}
4798 4799
4799/**4800/**
4800 * show_workqueue_state - dump workqueue state4801 * show_one_workqueue - dump state of specified workqueue
4801 *4802 * @wq: workqueue whose state will be printed
4802 * Called from a sysrq handler or try_to_freeze_tasks() and prints out
4803 * all busy workqueues and pools.
4804 */4803 */
4805void show_workqueue_state(void)4804void show_one_workqueue(struct workqueue_struct *wq)
4806{4805{
4807 struct workqueue_struct *wq;4806 struct pool_workqueue *pwq;
4808 struct worker_pool *pool;4807 bool idle = true;
4809 unsigned long flags;4808 unsigned long flags;
4810 int pi;
4811
4812 rcu_read_lock();
4813 4809
4814 pr_info("Showing busy workqueues and worker pools:\n");4810 for_each_pwq(pwq, wq) {
4815 4811 if (pwq->nr_active || !list_empty(&pwq->inactive_works)) {
4816 list_for_each_entry_rcu(wq, &workqueues, list) {4812 idle = false;
4817 struct pool_workqueue *pwq;4813 break;
4818 bool idle = true;
4819
4820 for_each_pwq(pwq, wq) {
4821 if (pwq->nr_active || !list_empty(&pwq->inactive_works)) {
4822 idle = false;
4823 break;
4824 }
4825 }4814 }
4826 if (idle)4815 }
4827 continue;4816 if (idle) /* Nothing to print for idle workqueue */
4817 return;
4828 4818
4829 pr_info("workqueue %s: flags=0x%x\n", wq->name, wq->flags);4819 pr_info("workqueue %s: flags=0x%x\n", wq->name, wq->flags);
4830 4820
4831 for_each_pwq(pwq, wq) {4821 for_each_pwq(pwq, wq) {
4832 raw_spin_lock_irqsave(&pwq->pool->lock, flags);4822 raw_spin_lock_irqsave(&pwq->pool->lock, flags);
4833 if (pwq->nr_active || !list_empty(&pwq->inactive_works)) {4823 if (pwq->nr_active || !list_empty(&pwq->inactive_works)) {
4834 /*
4835 * Defer printing to avoid deadlocks in console
4836 * drivers that queue work while holding locks
4837 * also taken in their write paths.
4838 */
4839 printk_deferred_enter();
4840 show_pwq(pwq);
4841 printk_deferred_exit();
4842 }
4843 raw_spin_unlock_irqrestore(&pwq->pool->lock, flags);
4844 /*4824 /*
4845 * We could be printing a lot from atomic context, e.g.4825 * Defer printing to avoid deadlocks in console
4846 * sysrq-t -> show_workqueue_state(). Avoid triggering4826 * drivers that queue work while holding locks
4847 * hard lockup.4827 * also taken in their write paths.
4848 */4828 */
4849 touch_nmi_watchdog();4829 printk_deferred_enter();
4850 }4830 show_pwq(pwq);
4851 }4831 printk_deferred_exit();
4852
4853 for_each_pool(pool, pi) {
4854 struct worker *worker;
4855 bool first = true;
4856
4857 raw_spin_lock_irqsave(&pool->lock, flags);
4858 if (pool->nr_workers == pool->nr_idle)
4859 goto next_pool;
4860 /*
4861 * Defer printing to avoid deadlocks in console drivers that
4862 * queue work while holding locks also taken in their write
4863 * paths.
4864 */
4865 printk_deferred_enter();
4866 pr_info("pool %d:", pool->id);
4867 pr_cont_pool_info(pool);
4868 pr_cont(" hung=%us workers=%d",
4869 jiffies_to_msecs(jiffies - pool->watchdog_ts) / 1000,
4870 pool->nr_workers);
4871 if (pool->manager)
4872 pr_cont(" manager: %d",
4873 task_pid_nr(pool->manager->task));
4874 list_for_each_entry(worker, &pool->idle_list, entry) {
4875 pr_cont(" %s%d", first ? "idle: " : "",
4876 task_pid_nr(worker->task));
4877 first = false;
4878 }4832 }
4879 pr_cont("\n");4833 raw_spin_unlock_irqrestore(&pwq->pool->lock, flags);
4880 printk_deferred_exit();
4881 next_pool:
4882 raw_spin_unlock_irqrestore(&pool->lock, flags);
4883 /*4834 /*
4884 * We could be printing a lot from atomic context, e.g.4835 * We could be printing a lot from atomic context, e.g.
4885 * sysrq-t -> show_workqueue_state(). Avoid triggering4836 * sysrq-t -> show_all_workqueues(). Avoid triggering
4886 * hard lockup.4837 * hard lockup.
4887 */4838 */
4888 touch_nmi_watchdog();4839 touch_nmi_watchdog();
4889 }4840 }
4890 4841
4842}
4843
4844/**
4845 * show_one_worker_pool - dump state of specified worker pool
4846 * @pool: worker pool whose state will be printed
4847 */
4848static void show_one_worker_pool(struct worker_pool *pool)
4849{
4850 struct worker *worker;
4851 bool first = true;
4852 unsigned long flags;
4853
4854 raw_spin_lock_irqsave(&pool->lock, flags);
4855 if (pool->nr_workers == pool->nr_idle)
4856 goto next_pool;
4857 /*
4858 * Defer printing to avoid deadlocks in console drivers that
4859 * queue work while holding locks also taken in their write
4860 * paths.
4861 */
4862 printk_deferred_enter();
4863 pr_info("pool %d:", pool->id);
4864 pr_cont_pool_info(pool);
4865 pr_cont(" hung=%us workers=%d",
4866 jiffies_to_msecs(jiffies - pool->watchdog_ts) / 1000,
4867 pool->nr_workers);
4868 if (pool->manager)
4869 pr_cont(" manager: %d",
4870 task_pid_nr(pool->manager->task));
4871 list_for_each_entry(worker, &pool->idle_list, entry) {
4872 pr_cont(" %s%d", first ? "idle: " : "",
4873 task_pid_nr(worker->task));
4874 first = false;
4875 }
4876 pr_cont("\n");
4877 printk_deferred_exit();
4878next_pool:
4879 raw_spin_unlock_irqrestore(&pool->lock, flags);
4880 /*
4881 * We could be printing a lot from atomic context, e.g.
4882 * sysrq-t -> show_all_workqueues(). Avoid triggering
4883 * hard lockup.
4884 */
4885 touch_nmi_watchdog();
4886
4887}
4888
4889/**
4890 * show_all_workqueues - dump workqueue state
4891 *
4892 * Called from a sysrq handler or try_to_freeze_tasks() and prints out
4893 * all busy workqueues and pools.
4894 */
4895void show_all_workqueues(void)
4896{
4897 struct workqueue_struct *wq;
4898 struct worker_pool *pool;
4899 int pi;
4900
4901 rcu_read_lock();
4902
4903 pr_info("Showing busy workqueues and worker pools:\n");
4904
4905 list_for_each_entry_rcu(wq, &workqueues, list)
4906 show_one_workqueue(wq);
4907
4908 for_each_pool(pool, pi)
4909 show_one_worker_pool(pool);
4910
4891 rcu_read_unlock();4911 rcu_read_unlock();
4892}4912}
4893 4913
@@ -5876,7 +5896,7 @@ static void wq_watchdog_timer_fn(struct timer_list *unused) · 982 unmodified lines
5876 rcu_read_unlock();5896 rcu_read_unlock();
5877 5897
5878 if (lockup_detected)5898 if (lockup_detected)
5879 show_workqueue_state();5899 show_all_workqueues();
5880 5900
5881 wq_watchdog_reset_touched();5901 wq_watchdog_reset_touched();
5882 mod_timer(&wq_watchdog_timer, jiffies + thresh);5902 mod_timer(&wq_watchdog_timer, jiffies + thresh);