rcu: Consolidate PREEMPT and !PREEMPT synchronize_rcu_expedited()
The CONFIG_PREEMPT=n and CONFIG_PREEMPT=y implementations of synchronize_rcu_expedited() are quite similar, and with small modifications to rcu_blocking_is_gp() can be made identical. This commit therefore makes this change in order to save a few lines of code and to reduce the amount of duplicate code. Signed-off-by: Paul E. McKenney <paulmck@linux.ibm.com>hifive-unleashed-5.1
parent
142d106d5e
commit
3cd4ca47aa
|
@ -643,6 +643,33 @@ static void _synchronize_rcu_expedited(void)
|
||||||
mutex_unlock(&rcu_state.exp_mutex);
|
mutex_unlock(&rcu_state.exp_mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* During early boot, any blocking grace-period wait automatically
|
||||||
|
* implies a grace period. Later on, this is never the case for PREEMPT.
|
||||||
|
*
|
||||||
|
* Howevr, because a context switch is a grace period for !PREEMPT, any
|
||||||
|
* blocking grace-period wait automatically implies a grace period if
|
||||||
|
* there is only one CPU online at any point time during execution of
|
||||||
|
* either synchronize_rcu() or synchronize_rcu_expedited(). It is OK to
|
||||||
|
* occasionally incorrectly indicate that there are multiple CPUs online
|
||||||
|
* when there was in fact only one the whole time, as this just adds some
|
||||||
|
* overhead: RCU still operates correctly.
|
||||||
|
*/
|
||||||
|
static int rcu_blocking_is_gp(void)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if (rcu_scheduler_active == RCU_SCHEDULER_INACTIVE)
|
||||||
|
return true;
|
||||||
|
if (IS_ENABLED(CONFIG_PREEMPT))
|
||||||
|
return false;
|
||||||
|
might_sleep(); /* Check for RCU read-side critical section. */
|
||||||
|
preempt_disable();
|
||||||
|
ret = num_online_cpus() <= 1;
|
||||||
|
preempt_enable();
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_PREEMPT_RCU
|
#ifdef CONFIG_PREEMPT_RCU
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -729,39 +756,6 @@ static void sync_sched_exp_online_cleanup(int cpu)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* synchronize_rcu_expedited - Brute-force RCU grace period
|
|
||||||
*
|
|
||||||
* Wait for an RCU-preempt grace period, but expedite it. The basic
|
|
||||||
* idea is to IPI all non-idle non-nohz online CPUs. The IPI handler
|
|
||||||
* checks whether the CPU is in an RCU-preempt critical section, and
|
|
||||||
* if so, it sets a flag that causes the outermost rcu_read_unlock()
|
|
||||||
* to report the quiescent state. On the other hand, if the CPU is
|
|
||||||
* not in an RCU read-side critical section, the IPI handler reports
|
|
||||||
* the quiescent state immediately.
|
|
||||||
*
|
|
||||||
* Although this is a greate improvement over previous expedited
|
|
||||||
* implementations, it is still unfriendly to real-time workloads, so is
|
|
||||||
* thus not recommended for any sort of common-case code. In fact, if
|
|
||||||
* you are using synchronize_rcu_expedited() in a loop, please restructure
|
|
||||||
* your code to batch your updates, and then Use a single synchronize_rcu()
|
|
||||||
* instead.
|
|
||||||
*
|
|
||||||
* This has the same semantics as (but is more brutal than) synchronize_rcu().
|
|
||||||
*/
|
|
||||||
void synchronize_rcu_expedited(void)
|
|
||||||
{
|
|
||||||
RCU_LOCKDEP_WARN(lock_is_held(&rcu_bh_lock_map) ||
|
|
||||||
lock_is_held(&rcu_lock_map) ||
|
|
||||||
lock_is_held(&rcu_sched_lock_map),
|
|
||||||
"Illegal synchronize_rcu_expedited() in RCU read-side critical section");
|
|
||||||
|
|
||||||
if (rcu_scheduler_active == RCU_SCHEDULER_INACTIVE)
|
|
||||||
return;
|
|
||||||
_synchronize_rcu_expedited();
|
|
||||||
}
|
|
||||||
EXPORT_SYMBOL_GPL(synchronize_rcu_expedited);
|
|
||||||
|
|
||||||
#else /* #ifdef CONFIG_PREEMPT_RCU */
|
#else /* #ifdef CONFIG_PREEMPT_RCU */
|
||||||
|
|
||||||
/* Invoked on each online non-idle CPU for expedited quiescent state. */
|
/* Invoked on each online non-idle CPU for expedited quiescent state. */
|
||||||
|
@ -801,27 +795,28 @@ static void sync_sched_exp_online_cleanup(int cpu)
|
||||||
WARN_ON_ONCE(ret);
|
WARN_ON_ONCE(ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
#endif /* #else #ifdef CONFIG_PREEMPT_RCU */
|
||||||
* Because a context switch is a grace period for !PREEMPT, any
|
|
||||||
* blocking grace-period wait automatically implies a grace period if
|
/**
|
||||||
* there is only one CPU online at any point time during execution of
|
* synchronize_rcu_expedited - Brute-force RCU grace period
|
||||||
* either synchronize_rcu() or synchronize_rcu_expedited(). It is OK to
|
*
|
||||||
* occasionally incorrectly indicate that there are multiple CPUs online
|
* Wait for an RCU grace period, but expedite it. The basic idea is to
|
||||||
* when there was in fact only one the whole time, as this just adds some
|
* IPI all non-idle non-nohz online CPUs. The IPI handler checks whether
|
||||||
* overhead: RCU still operates correctly.
|
* the CPU is in an RCU critical section, and if so, it sets a flag that
|
||||||
|
* causes the outermost rcu_read_unlock() to report the quiescent state
|
||||||
|
* for RCU-preempt or asks the scheduler for help for RCU-sched. On the
|
||||||
|
* other hand, if the CPU is not in an RCU read-side critical section,
|
||||||
|
* the IPI handler reports the quiescent state immediately.
|
||||||
|
*
|
||||||
|
* Although this is a greate improvement over previous expedited
|
||||||
|
* implementations, it is still unfriendly to real-time workloads, so is
|
||||||
|
* thus not recommended for any sort of common-case code. In fact, if
|
||||||
|
* you are using synchronize_rcu_expedited() in a loop, please restructure
|
||||||
|
* your code to batch your updates, and then Use a single synchronize_rcu()
|
||||||
|
* instead.
|
||||||
|
*
|
||||||
|
* This has the same semantics as (but is more brutal than) synchronize_rcu().
|
||||||
*/
|
*/
|
||||||
static int rcu_blocking_is_gp(void)
|
|
||||||
{
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
might_sleep(); /* Check for RCU read-side critical section. */
|
|
||||||
preempt_disable();
|
|
||||||
ret = num_online_cpus() <= 1;
|
|
||||||
preempt_enable();
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* PREEMPT=n implementation of synchronize_rcu_expedited(). */
|
|
||||||
void synchronize_rcu_expedited(void)
|
void synchronize_rcu_expedited(void)
|
||||||
{
|
{
|
||||||
RCU_LOCKDEP_WARN(lock_is_held(&rcu_bh_lock_map) ||
|
RCU_LOCKDEP_WARN(lock_is_held(&rcu_bh_lock_map) ||
|
||||||
|
@ -829,12 +824,10 @@ void synchronize_rcu_expedited(void)
|
||||||
lock_is_held(&rcu_sched_lock_map),
|
lock_is_held(&rcu_sched_lock_map),
|
||||||
"Illegal synchronize_rcu_expedited() in RCU read-side critical section");
|
"Illegal synchronize_rcu_expedited() in RCU read-side critical section");
|
||||||
|
|
||||||
/* If only one CPU, this is automatically a grace period. */
|
/* Is the state is such that the call is a grace period? */
|
||||||
if (rcu_blocking_is_gp())
|
if (rcu_blocking_is_gp())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
_synchronize_rcu_expedited();
|
_synchronize_rcu_expedited();
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(synchronize_rcu_expedited);
|
EXPORT_SYMBOL_GPL(synchronize_rcu_expedited);
|
||||||
|
|
||||||
#endif /* #else #ifdef CONFIG_PREEMPT_RCU */
|
|
||||||
|
|
Loading…
Reference in New Issue