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
625625
626626 static void cleanup_workqueue_thread(struct workqueue_struct *wq, int cpu)
627627 {
628− struct cpu_workqueue_struct *cwq;
629− unsigned long flags;
630− struct task_struct *p;
628+ struct cpu_workqueue_struct *cwq = per_cpu_ptr(wq->cpu_wq, cpu);
631629
632− cwq = per_cpu_ptr(wq->cpu_wq, cpu);
633− spin_lock_irqsave(&cwq->lock, flags);
634− p = cwq->thread;
635− cwq->thread = NULL;
636− spin_unlock_irqrestore(&cwq->lock, flags);
637− if (p)
638− kthread_stop(p);
630+ if (cwq->thread) {
631+ kthread_stop(cwq->thread);
632+ cwq->thread = NULL;
633+ }
639634 }
640635
641636 /**