|
@@ -1894,6 +1894,38 @@ void call_rcu_bh(struct rcu_head *head, void (*func)(struct rcu_head *rcu))
|
|
|
}
|
|
|
EXPORT_SYMBOL_GPL(call_rcu_bh);
|
|
|
|
|
|
+/*
|
|
|
+ * Because a context switch is a grace period for RCU-sched and RCU-bh,
|
|
|
+ * 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_sched() or synchronize_rcu_bh(). 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.
|
|
|
+ *
|
|
|
+ * Of course, sampling num_online_cpus() with preemption enabled can
|
|
|
+ * give erroneous results if there are concurrent CPU-hotplug operations.
|
|
|
+ * For example, given a demonic sequence of preemptions in num_online_cpus()
|
|
|
+ * and CPU-hotplug operations, there could be two or more CPUs online at
|
|
|
+ * all times, but num_online_cpus() might well return one (or even zero).
|
|
|
+ *
|
|
|
+ * However, all such demonic sequences require at least one CPU-offline
|
|
|
+ * operation. Furthermore, rcu_blocking_is_gp() giving the wrong answer
|
|
|
+ * is only a problem if there is an RCU read-side critical section executing
|
|
|
+ * throughout. But RCU-sched and RCU-bh read-side critical sections
|
|
|
+ * disable either preemption or bh, which prevents a CPU from going offline.
|
|
|
+ * Therefore, the only way that rcu_blocking_is_gp() can incorrectly return
|
|
|
+ * that there is only one CPU when in fact there was more than one throughout
|
|
|
+ * is when there were no RCU readers in the system. If there are no
|
|
|
+ * RCU readers, the grace period by definition can be of zero length,
|
|
|
+ * regardless of the number of online CPUs.
|
|
|
+ */
|
|
|
+static inline int rcu_blocking_is_gp(void)
|
|
|
+{
|
|
|
+ might_sleep(); /* Check for RCU read-side critical section. */
|
|
|
+ return num_online_cpus() <= 1;
|
|
|
+}
|
|
|
+
|
|
|
/**
|
|
|
* synchronize_sched - wait until an rcu-sched grace period has elapsed.
|
|
|
*
|