| @@ -375,6 +375,7 @@ EXPORT_SYMBOL_GPL(system_freezable_power_efficient_wq); · 374 unmodified lines |
| 375 | static int worker_thread(void *__worker); | 375 | static int worker_thread(void *__worker); |
| 376 | static void workqueue_sysfs_unregister(struct workqueue_struct *wq); | 376 | static void workqueue_sysfs_unregister(struct workqueue_struct *wq); |
| 377 | static void show_pwq(struct pool_workqueue *pwq); | 377 | static void show_pwq(struct pool_workqueue *pwq); |
| | 378 | static void show_one_worker_pool(struct worker_pool *pool); |
| 378 | | 379 | |
| 379 | #define CREATE_TRACE_POINTS | 380 | #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 state | 4801 | * 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 | */ |
| 4805 | void show_workqueue_state(void) | 4804 | void 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 triggering | 4826 | * 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 triggering | 4836 | * 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 | */ |
| | 4848 | static 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(); |
| | 4878 | next_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 | */ |
| | 4895 | void 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); |