aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--kernel/workqueue.c19
1 files changed, 12 insertions, 7 deletions
diff --git a/kernel/workqueue.c b/kernel/workqueue.c
index 11723c5b2b20..4fef9527a620 100644
--- a/kernel/workqueue.c
+++ b/kernel/workqueue.c
@@ -570,11 +570,19 @@ static void set_work_cwq(struct work_struct *work,
570static void set_work_cpu_and_clear_pending(struct work_struct *work, 570static void set_work_cpu_and_clear_pending(struct work_struct *work,
571 unsigned int cpu) 571 unsigned int cpu)
572{ 572{
573 /*
574 * The following wmb is paired with the implied mb in
575 * test_and_set_bit(PENDING) and ensures all updates to @work made
576 * here are visible to and precede any updates by the next PENDING
577 * owner.
578 */
579 smp_wmb();
573 set_work_data(work, (unsigned long)cpu << WORK_OFFQ_CPU_SHIFT, 0); 580 set_work_data(work, (unsigned long)cpu << WORK_OFFQ_CPU_SHIFT, 0);
574} 581}
575 582
576static void clear_work_data(struct work_struct *work) 583static void clear_work_data(struct work_struct *work)
577{ 584{
585 smp_wmb(); /* see set_work_cpu_and_clear_pending() */
578 set_work_data(work, WORK_STRUCT_NO_CPU, 0); 586 set_work_data(work, WORK_STRUCT_NO_CPU, 0);
579} 587}
580 588
@@ -2182,14 +2190,11 @@ __acquires(&gcwq->lock)
2182 wake_up_worker(pool); 2190 wake_up_worker(pool);
2183 2191
2184 /* 2192 /*
2185 * Record the last CPU and clear PENDING. The following wmb is 2193 * Record the last CPU and clear PENDING which should be the last
2186 * paired with the implied mb in test_and_set_bit(PENDING) and 2194 * update to @work. Also, do this inside @gcwq->lock so that
2187 * ensures all updates to @work made here are visible to and 2195 * PENDING and queued state changes happen together while IRQ is
2188 * precede any updates by the next PENDING owner. Also, clear 2196 * disabled.
2189 * PENDING inside @gcwq->lock so that PENDING and queued state
2190 * changes happen together while IRQ is disabled.
2191 */ 2197 */
2192 smp_wmb();
2193 set_work_cpu_and_clear_pending(work, gcwq->cpu); 2198 set_work_cpu_and_clear_pending(work, gcwq->cpu);
2194 2199
2195 spin_unlock_irq(&gcwq->lock); 2200 spin_unlock_irq(&gcwq->lock);