mirror of
https://github.com/torvalds/linux.git
synced 2026-11-06 21:58:01 +01:00
srcutree: Disable preemption across synchronize_srcu_atomic()
Because synchronize_srcu_atomic() cannot sleep, if a pair of them run concurrently pinned to the same CPU, it is possible that one will spin uselessly waiting for the other while at the same time preventing that other from running. This commit therefore disables preemption to prevent this failure mode. Signed-off-by: Paul E. McKenney <paulmck@kernel.org>
This commit is contained in:
parent
7fb2388e0d
commit
18c55d888b
|
|
@ -2123,11 +2123,14 @@ void synchronize_srcu_atomic(struct srcu_struct *ssp)
|
|||
|
||||
// Perhaps others will do our work for us.
|
||||
srcu_state = get_state_synchronize_srcu(ssp);
|
||||
preempt_disable();
|
||||
while (atomic_read(&sup->srcu_atomic_gp_flag) ||
|
||||
atomic_xchg(&sup->srcu_atomic_gp_flag, 1)) {
|
||||
preempt_enable();
|
||||
if (poll_state_synchronize_srcu(ssp, srcu_state))
|
||||
return;
|
||||
cpu_relax();
|
||||
preempt_disable();
|
||||
}
|
||||
|
||||
// One last check for others doing our work for us under the lock.
|
||||
|
|
@ -2135,6 +2138,7 @@ void synchronize_srcu_atomic(struct srcu_struct *ssp)
|
|||
if (poll_state_synchronize_srcu(ssp, srcu_state)) {
|
||||
raw_spin_unlock_irq_rcu_node(sup);
|
||||
atomic_set(&sup->srcu_atomic_gp_flag, 0);
|
||||
preempt_enable();
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -2152,6 +2156,7 @@ void synchronize_srcu_atomic(struct srcu_struct *ssp)
|
|||
}
|
||||
ASSERT_EXCLUSIVE_WRITER(sup->srcu_atomic_gp_flag);
|
||||
atomic_set_release(&sup->srcu_atomic_gp_flag, 0);
|
||||
preempt_enable();
|
||||
non_block_end();
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(synchronize_srcu_atomic);
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user