History

workqueue: don't clear cwq->thread until it exits

Pointed out by Srivatsa Vaddagiri. cleanup_workqueue_thread() sets cwq->thread = NULL and does kthread_stop(). This breaks the "if (cwq->thread == current)" logic in flush_cpu_workqueue() and leads to deadlock. Kill the thead first, then clear cwq->thread. workqueue_mutex protects us from create_workqueue_thread() so we don't need cwq->lock.

Oleg Nesterov committed 19 years ago

Commit 36aa9df1 parent d7213041 file · +5 −10Browse files

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

Unified · Split

kernel/workqueue.c+5−10
@@ -625,17 +625,12 @@ EXPORT_SYMBOL_GPL(__create_workqueue); · 624 unmodified lines
625 625
626static void cleanup_workqueue_thread(struct workqueue_struct *wq, int cpu)626static void cleanup_workqueue_thread(struct workqueue_struct *wq, int cpu)
627{627{
628 struct cpu_workqueue_struct *cwq;628 struct cpu_workqueue_struct *cwq = per_cpu_ptr(wq->cpu_wq, cpu);
629 unsigned long flags;
630 struct task_struct *p;
631 629
632 cwq = per_cpu_ptr(wq->cpu_wq, cpu);630 if (cwq->thread) {
633 spin_lock_irqsave(&cwq->lock, flags);631 kthread_stop(cwq->thread);
634 p = cwq->thread;632 cwq->thread = NULL;
635 cwq->thread = NULL;633 }
636 spin_unlock_irqrestore(&cwq->lock, flags);
637 if (p)
638 kthread_stop(p);
639}634}
640 635
641/**636/**