aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/linux/rcutree.h7
-rw-r--r--kernel/rcutree.c32
2 files changed, 32 insertions, 7 deletions
diff --git a/include/linux/rcutree.h b/include/linux/rcutree.h
index e8ee5dd0854c..b06363055ef8 100644
--- a/include/linux/rcutree.h
+++ b/include/linux/rcutree.h
@@ -98,13 +98,6 @@ extern void rcu_force_quiescent_state(void);
98extern void rcu_bh_force_quiescent_state(void); 98extern void rcu_bh_force_quiescent_state(void);
99extern void rcu_sched_force_quiescent_state(void); 99extern void rcu_sched_force_quiescent_state(void);
100 100
101/* A context switch is a grace period for RCU-sched and RCU-bh. */
102static inline int rcu_blocking_is_gp(void)
103{
104 might_sleep(); /* Check for RCU read-side critical section. */
105 return num_online_cpus() == 1;
106}
107
108extern void rcu_scheduler_starting(void); 101extern void rcu_scheduler_starting(void);
109extern int rcu_scheduler_active __read_mostly; 102extern int rcu_scheduler_active __read_mostly;
110 103
diff --git a/kernel/rcutree.c b/kernel/rcutree.c
index 780acf8e15e9..8f6a344306e6 100644
--- a/kernel/rcutree.c
+++ b/kernel/rcutree.c
@@ -1894,6 +1894,38 @@ void call_rcu_bh(struct rcu_head *head, void (*func)(struct rcu_head *rcu))
1894} 1894}
1895EXPORT_SYMBOL_GPL(call_rcu_bh); 1895EXPORT_SYMBOL_GPL(call_rcu_bh);
1896 1896
1897/*
1898 * Because a context switch is a grace period for RCU-sched and RCU-bh,
1899 * any blocking grace-period wait automatically implies a grace period
1900 * if there is only one CPU online at any point time during execution
1901 * of either synchronize_sched() or synchronize_rcu_bh(). It is OK to
1902 * occasionally incorrectly indicate that there are multiple CPUs online
1903 * when there was in fact only one the whole time, as this just adds
1904 * some overhead: RCU still operates correctly.
1905 *
1906 * Of course, sampling num_online_cpus() with preemption enabled can
1907 * give erroneous results if there are concurrent CPU-hotplug operations.
1908 * For example, given a demonic sequence of preemptions in num_online_cpus()
1909 * and CPU-hotplug operations, there could be two or more CPUs online at
1910 * all times, but num_online_cpus() might well return one (or even zero).
1911 *
1912 * However, all such demonic sequences require at least one CPU-offline
1913 * operation. Furthermore, rcu_blocking_is_gp() giving the wrong answer
1914 * is only a problem if there is an RCU read-side critical section executing
1915 * throughout. But RCU-sched and RCU-bh read-side critical sections
1916 * disable either preemption or bh, which prevents a CPU from going offline.
1917 * Therefore, the only way that rcu_blocking_is_gp() can incorrectly return
1918 * that there is only one CPU when in fact there was more than one throughout
1919 * is when there were no RCU readers in the system. If there are no
1920 * RCU readers, the grace period by definition can be of zero length,
1921 * regardless of the number of online CPUs.
1922 */
1923static inline int rcu_blocking_is_gp(void)
1924{
1925 might_sleep(); /* Check for RCU read-side critical section. */
1926 return num_online_cpus() <= 1;
1927}
1928
1897/** 1929/**
1898 * synchronize_sched - wait until an rcu-sched grace period has elapsed. 1930 * synchronize_sched - wait until an rcu-sched grace period has elapsed.
1899 * 1931 *