mirror of
https://github.com/edk2-porting/linux-next.git
synced 2024-12-17 01:34:00 +08:00
rcu/nocb: Avoid confusing double write of rdp->nocb_cb_sleep
The nocb_cb_wait() function first sets the rdp->nocb_cb_sleep flag to true by after invoking the callbacks, and then sets it back to false if it finds more callbacks that are ready to invoke. This is confusing and will become unsafe if this flag is ever read locklessly. This commit therefore writes it only once, based on the state after both callback invocation and checking. Reported-by: Paul E. McKenney <paulmck@kernel.org> Cc: Josh Triplett <josh@joshtriplett.org> Cc: Lai Jiangshan <jiangshanlai@gmail.com> Cc: Joel Fernandes <joel@joelfernandes.org> Cc: Neeraj Upadhyay <neeraju@codeaurora.org> Cc: Boqun Feng <boqun.feng@gmail.com> Signed-off-by: Frederic Weisbecker <frederic@kernel.org> Signed-off-by: Paul E. McKenney <paulmck@kernel.org>
This commit is contained in:
parent
64305db285
commit
8a682b3974
@ -2230,6 +2230,7 @@ static void nocb_cb_wait(struct rcu_data *rdp)
|
||||
unsigned long flags;
|
||||
bool needwake_state = false;
|
||||
bool needwake_gp = false;
|
||||
bool can_sleep = true;
|
||||
struct rcu_node *rnp = rdp->mynode;
|
||||
|
||||
local_irq_save(flags);
|
||||
@ -2253,8 +2254,6 @@ static void nocb_cb_wait(struct rcu_data *rdp)
|
||||
raw_spin_unlock_rcu_node(rnp); /* irqs remain disabled. */
|
||||
}
|
||||
|
||||
WRITE_ONCE(rdp->nocb_cb_sleep, true);
|
||||
|
||||
if (rcu_segcblist_test_flags(cblist, SEGCBLIST_OFFLOADED)) {
|
||||
if (!rcu_segcblist_test_flags(cblist, SEGCBLIST_KTHREAD_CB)) {
|
||||
rcu_segcblist_set_flags(cblist, SEGCBLIST_KTHREAD_CB);
|
||||
@ -2262,7 +2261,7 @@ static void nocb_cb_wait(struct rcu_data *rdp)
|
||||
needwake_state = true;
|
||||
}
|
||||
if (rcu_segcblist_ready_cbs(cblist))
|
||||
WRITE_ONCE(rdp->nocb_cb_sleep, false);
|
||||
can_sleep = false;
|
||||
} else {
|
||||
/*
|
||||
* De-offloading. Clear our flag and notify the de-offload worker.
|
||||
@ -2275,6 +2274,8 @@ static void nocb_cb_wait(struct rcu_data *rdp)
|
||||
needwake_state = true;
|
||||
}
|
||||
|
||||
WRITE_ONCE(rdp->nocb_cb_sleep, can_sleep);
|
||||
|
||||
if (rdp->nocb_cb_sleep)
|
||||
trace_rcu_nocb_wake(rcu_state.name, rdp->cpu, TPS("CBSleep"));
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user