diff options
Diffstat (limited to 'kernel/rcu')
-rw-r--r-- | kernel/rcu/torture.c | 8 | ||||
-rw-r--r-- | kernel/rcu/tree.c | 3 | ||||
-rw-r--r-- | kernel/rcu/tree_plugin.h | 6 |
3 files changed, 13 insertions, 4 deletions
diff --git a/kernel/rcu/torture.c b/kernel/rcu/torture.c index 3929cd451511..69a4ec80a788 100644 --- a/kernel/rcu/torture.c +++ b/kernel/rcu/torture.c | |||
@@ -1578,6 +1578,7 @@ static int rcu_torture_barrier_cbs(void *arg) | |||
1578 | { | 1578 | { |
1579 | long myid = (long)arg; | 1579 | long myid = (long)arg; |
1580 | bool lastphase = 0; | 1580 | bool lastphase = 0; |
1581 | bool newphase; | ||
1581 | struct rcu_head rcu; | 1582 | struct rcu_head rcu; |
1582 | 1583 | ||
1583 | init_rcu_head_on_stack(&rcu); | 1584 | init_rcu_head_on_stack(&rcu); |
@@ -1585,10 +1586,11 @@ static int rcu_torture_barrier_cbs(void *arg) | |||
1585 | set_user_nice(current, 19); | 1586 | set_user_nice(current, 19); |
1586 | do { | 1587 | do { |
1587 | wait_event(barrier_cbs_wq[myid], | 1588 | wait_event(barrier_cbs_wq[myid], |
1588 | barrier_phase != lastphase || | 1589 | (newphase = |
1590 | ACCESS_ONCE(barrier_phase)) != lastphase || | ||
1589 | kthread_should_stop() || | 1591 | kthread_should_stop() || |
1590 | fullstop != FULLSTOP_DONTSTOP); | 1592 | fullstop != FULLSTOP_DONTSTOP); |
1591 | lastphase = barrier_phase; | 1593 | lastphase = newphase; |
1592 | smp_mb(); /* ensure barrier_phase load before ->call(). */ | 1594 | smp_mb(); /* ensure barrier_phase load before ->call(). */ |
1593 | if (kthread_should_stop() || fullstop != FULLSTOP_DONTSTOP) | 1595 | if (kthread_should_stop() || fullstop != FULLSTOP_DONTSTOP) |
1594 | break; | 1596 | break; |
@@ -1625,7 +1627,7 @@ static int rcu_torture_barrier(void *arg) | |||
1625 | if (kthread_should_stop() || fullstop != FULLSTOP_DONTSTOP) | 1627 | if (kthread_should_stop() || fullstop != FULLSTOP_DONTSTOP) |
1626 | break; | 1628 | break; |
1627 | n_barrier_attempts++; | 1629 | n_barrier_attempts++; |
1628 | cur_ops->cb_barrier(); | 1630 | cur_ops->cb_barrier(); /* Implies smp_mb() for wait_event(). */ |
1629 | if (atomic_read(&barrier_cbs_invoked) != n_barrier_cbs) { | 1631 | if (atomic_read(&barrier_cbs_invoked) != n_barrier_cbs) { |
1630 | n_rcu_torture_barrier_error++; | 1632 | n_rcu_torture_barrier_error++; |
1631 | WARN_ON_ONCE(1); | 1633 | WARN_ON_ONCE(1); |
diff --git a/kernel/rcu/tree.c b/kernel/rcu/tree.c index 5243ebea0fc1..abef9c358d47 100644 --- a/kernel/rcu/tree.c +++ b/kernel/rcu/tree.c | |||
@@ -1533,6 +1533,7 @@ static void rcu_gp_cleanup(struct rcu_state *rsp) | |||
1533 | rdp = this_cpu_ptr(rsp->rda); | 1533 | rdp = this_cpu_ptr(rsp->rda); |
1534 | if (rnp == rdp->mynode) | 1534 | if (rnp == rdp->mynode) |
1535 | __note_gp_changes(rsp, rnp, rdp); | 1535 | __note_gp_changes(rsp, rnp, rdp); |
1536 | /* smp_mb() provided by prior unlock-lock pair. */ | ||
1536 | nocb += rcu_future_gp_cleanup(rsp, rnp); | 1537 | nocb += rcu_future_gp_cleanup(rsp, rnp); |
1537 | raw_spin_unlock_irq(&rnp->lock); | 1538 | raw_spin_unlock_irq(&rnp->lock); |
1538 | cond_resched(); | 1539 | cond_resched(); |
@@ -1577,6 +1578,7 @@ static int __noreturn rcu_gp_kthread(void *arg) | |||
1577 | wait_event_interruptible(rsp->gp_wq, | 1578 | wait_event_interruptible(rsp->gp_wq, |
1578 | ACCESS_ONCE(rsp->gp_flags) & | 1579 | ACCESS_ONCE(rsp->gp_flags) & |
1579 | RCU_GP_FLAG_INIT); | 1580 | RCU_GP_FLAG_INIT); |
1581 | /* Locking provides needed memory barrier. */ | ||
1580 | if (rcu_gp_init(rsp)) | 1582 | if (rcu_gp_init(rsp)) |
1581 | break; | 1583 | break; |
1582 | cond_resched(); | 1584 | cond_resched(); |
@@ -1606,6 +1608,7 @@ static int __noreturn rcu_gp_kthread(void *arg) | |||
1606 | (!ACCESS_ONCE(rnp->qsmask) && | 1608 | (!ACCESS_ONCE(rnp->qsmask) && |
1607 | !rcu_preempt_blocked_readers_cgp(rnp)), | 1609 | !rcu_preempt_blocked_readers_cgp(rnp)), |
1608 | j); | 1610 | j); |
1611 | /* Locking provides needed memory barriers. */ | ||
1609 | /* If grace period done, leave loop. */ | 1612 | /* If grace period done, leave loop. */ |
1610 | if (!ACCESS_ONCE(rnp->qsmask) && | 1613 | if (!ACCESS_ONCE(rnp->qsmask) && |
1611 | !rcu_preempt_blocked_readers_cgp(rnp)) | 1614 | !rcu_preempt_blocked_readers_cgp(rnp)) |
diff --git a/kernel/rcu/tree_plugin.h b/kernel/rcu/tree_plugin.h index 6abb03dff5c0..b023e5407111 100644 --- a/kernel/rcu/tree_plugin.h +++ b/kernel/rcu/tree_plugin.h | |||
@@ -779,8 +779,10 @@ static void rcu_report_exp_rnp(struct rcu_state *rsp, struct rcu_node *rnp, | |||
779 | } | 779 | } |
780 | if (rnp->parent == NULL) { | 780 | if (rnp->parent == NULL) { |
781 | raw_spin_unlock_irqrestore(&rnp->lock, flags); | 781 | raw_spin_unlock_irqrestore(&rnp->lock, flags); |
782 | if (wake) | 782 | if (wake) { |
783 | smp_mb(); /* EGP done before wake_up(). */ | ||
783 | wake_up(&sync_rcu_preempt_exp_wq); | 784 | wake_up(&sync_rcu_preempt_exp_wq); |
785 | } | ||
784 | break; | 786 | break; |
785 | } | 787 | } |
786 | mask = rnp->grpmask; | 788 | mask = rnp->grpmask; |
@@ -1852,6 +1854,7 @@ static int rcu_oom_notify(struct notifier_block *self, | |||
1852 | 1854 | ||
1853 | /* Wait for callbacks from earlier instance to complete. */ | 1855 | /* Wait for callbacks from earlier instance to complete. */ |
1854 | wait_event(oom_callback_wq, atomic_read(&oom_callback_count) == 0); | 1856 | wait_event(oom_callback_wq, atomic_read(&oom_callback_count) == 0); |
1857 | smp_mb(); /* Ensure callback reuse happens after callback invocation. */ | ||
1855 | 1858 | ||
1856 | /* | 1859 | /* |
1857 | * Prevent premature wakeup: ensure that all increments happen | 1860 | * Prevent premature wakeup: ensure that all increments happen |
@@ -2250,6 +2253,7 @@ static int rcu_nocb_kthread(void *arg) | |||
2250 | trace_rcu_nocb_wake(rdp->rsp->name, rdp->cpu, | 2253 | trace_rcu_nocb_wake(rdp->rsp->name, rdp->cpu, |
2251 | TPS("Sleep")); | 2254 | TPS("Sleep")); |
2252 | wait_event_interruptible(rdp->nocb_wq, rdp->nocb_head); | 2255 | wait_event_interruptible(rdp->nocb_wq, rdp->nocb_head); |
2256 | /* Memory barrier provide by xchg() below. */ | ||
2253 | } else if (firsttime) { | 2257 | } else if (firsttime) { |
2254 | firsttime = 0; | 2258 | firsttime = 0; |
2255 | trace_rcu_nocb_wake(rdp->rsp->name, rdp->cpu, | 2259 | trace_rcu_nocb_wake(rdp->rsp->name, rdp->cpu, |