rcu: Add synchronize_sched_expedited() primitive
[linux-2.6.git] / kernel / rcupdate.c
index a967c9f..eae29c2 100644 (file)
@@ -98,6 +98,30 @@ void synchronize_rcu(void)
 }
 EXPORT_SYMBOL_GPL(synchronize_rcu);
 
+/**
+ * synchronize_rcu_bh - wait until an rcu_bh grace period has elapsed.
+ *
+ * Control will return to the caller some time after a full rcu_bh grace
+ * period has elapsed, in other words after all currently executing rcu_bh
+ * read-side critical sections have completed.  RCU read-side critical
+ * sections are delimited by rcu_read_lock_bh() and rcu_read_unlock_bh(),
+ * and may be nested.
+ */
+void synchronize_rcu_bh(void)
+{
+       struct rcu_synchronize rcu;
+
+       if (rcu_blocking_is_gp())
+               return;
+
+       init_completion(&rcu.completion);
+       /* Will wake me after RCU finished. */
+       call_rcu_bh(&rcu.head, wakeme_after_rcu);
+       /* Wait for it. */
+       wait_for_completion(&rcu.completion);
+}
+EXPORT_SYMBOL_GPL(synchronize_rcu_bh);
+
 static void rcu_barrier_callback(struct rcu_head *notused)
 {
        if (atomic_dec_and_test(&rcu_barrier_cpu_count))
@@ -129,6 +153,7 @@ static void rcu_barrier_func(void *type)
 static inline void wait_migrated_callbacks(void)
 {
        wait_event(rcu_migrate_wq, !atomic_read(&rcu_migrate_type_count));
+       smp_mb(); /* In case we didn't sleep. */
 }
 
 /*