@@ -643,6 +643,33 @@ static void _synchronize_rcu_expedited(void)
643
643
mutex_unlock (& rcu_state .exp_mutex );
644
644
}
645
645
646
+ /*
647
+ * During early boot, any blocking grace-period wait automatically
648
+ * implies a grace period. Later on, this is never the case for PREEMPT.
649
+ *
650
+ * Howevr, because a context switch is a grace period for !PREEMPT, any
651
+ * blocking grace-period wait automatically implies a grace period if
652
+ * there is only one CPU online at any point time during execution of
653
+ * either synchronize_rcu() or synchronize_rcu_expedited(). It is OK to
654
+ * occasionally incorrectly indicate that there are multiple CPUs online
655
+ * when there was in fact only one the whole time, as this just adds some
656
+ * overhead: RCU still operates correctly.
657
+ */
658
+ static int rcu_blocking_is_gp (void )
659
+ {
660
+ int ret ;
661
+
662
+ if (rcu_scheduler_active == RCU_SCHEDULER_INACTIVE )
663
+ return true;
664
+ if (IS_ENABLED (CONFIG_PREEMPT ))
665
+ return false;
666
+ might_sleep (); /* Check for RCU read-side critical section. */
667
+ preempt_disable ();
668
+ ret = num_online_cpus () <= 1 ;
669
+ preempt_enable ();
670
+ return ret ;
671
+ }
672
+
646
673
#ifdef CONFIG_PREEMPT_RCU
647
674
648
675
/*
@@ -729,39 +756,6 @@ static void sync_sched_exp_online_cleanup(int cpu)
729
756
{
730
757
}
731
758
732
- /**
733
- * synchronize_rcu_expedited - Brute-force RCU grace period
734
- *
735
- * Wait for an RCU-preempt grace period, but expedite it. The basic
736
- * idea is to IPI all non-idle non-nohz online CPUs. The IPI handler
737
- * checks whether the CPU is in an RCU-preempt critical section, and
738
- * if so, it sets a flag that causes the outermost rcu_read_unlock()
739
- * to report the quiescent state. On the other hand, if the CPU is
740
- * not in an RCU read-side critical section, the IPI handler reports
741
- * the quiescent state immediately.
742
- *
743
- * Although this is a greate improvement over previous expedited
744
- * implementations, it is still unfriendly to real-time workloads, so is
745
- * thus not recommended for any sort of common-case code. In fact, if
746
- * you are using synchronize_rcu_expedited() in a loop, please restructure
747
- * your code to batch your updates, and then Use a single synchronize_rcu()
748
- * instead.
749
- *
750
- * This has the same semantics as (but is more brutal than) synchronize_rcu().
751
- */
752
- void synchronize_rcu_expedited (void )
753
- {
754
- RCU_LOCKDEP_WARN (lock_is_held (& rcu_bh_lock_map ) ||
755
- lock_is_held (& rcu_lock_map ) ||
756
- lock_is_held (& rcu_sched_lock_map ),
757
- "Illegal synchronize_rcu_expedited() in RCU read-side critical section" );
758
-
759
- if (rcu_scheduler_active == RCU_SCHEDULER_INACTIVE )
760
- return ;
761
- _synchronize_rcu_expedited ();
762
- }
763
- EXPORT_SYMBOL_GPL (synchronize_rcu_expedited );
764
-
765
759
#else /* #ifdef CONFIG_PREEMPT_RCU */
766
760
767
761
/* Invoked on each online non-idle CPU for expedited quiescent state. */
@@ -801,40 +795,39 @@ static void sync_sched_exp_online_cleanup(int cpu)
801
795
WARN_ON_ONCE (ret );
802
796
}
803
797
804
- /*
805
- * Because a context switch is a grace period for !PREEMPT, any
806
- * blocking grace-period wait automatically implies a grace period if
807
- * there is only one CPU online at any point time during execution of
808
- * either synchronize_rcu() or synchronize_rcu_expedited(). It is OK to
809
- * occasionally incorrectly indicate that there are multiple CPUs online
810
- * when there was in fact only one the whole time, as this just adds some
811
- * overhead: RCU still operates correctly.
812
- */
813
- static int rcu_blocking_is_gp (void )
814
- {
815
- int ret ;
816
-
817
- might_sleep (); /* Check for RCU read-side critical section. */
818
- preempt_disable ();
819
- ret = num_online_cpus () <= 1 ;
820
- preempt_enable ();
821
- return ret ;
822
- }
798
+ #endif /* #else #ifdef CONFIG_PREEMPT_RCU */
823
799
824
- /* PREEMPT=n implementation of synchronize_rcu_expedited(). */
800
+ /**
801
+ * synchronize_rcu_expedited - Brute-force RCU grace period
802
+ *
803
+ * Wait for an RCU grace period, but expedite it. The basic idea is to
804
+ * IPI all non-idle non-nohz online CPUs. The IPI handler checks whether
805
+ * the CPU is in an RCU critical section, and if so, it sets a flag that
806
+ * causes the outermost rcu_read_unlock() to report the quiescent state
807
+ * for RCU-preempt or asks the scheduler for help for RCU-sched. On the
808
+ * other hand, if the CPU is not in an RCU read-side critical section,
809
+ * the IPI handler reports the quiescent state immediately.
810
+ *
811
+ * Although this is a greate improvement over previous expedited
812
+ * implementations, it is still unfriendly to real-time workloads, so is
813
+ * thus not recommended for any sort of common-case code. In fact, if
814
+ * you are using synchronize_rcu_expedited() in a loop, please restructure
815
+ * your code to batch your updates, and then Use a single synchronize_rcu()
816
+ * instead.
817
+ *
818
+ * This has the same semantics as (but is more brutal than) synchronize_rcu().
819
+ */
825
820
void synchronize_rcu_expedited (void )
826
821
{
827
822
RCU_LOCKDEP_WARN (lock_is_held (& rcu_bh_lock_map ) ||
828
823
lock_is_held (& rcu_lock_map ) ||
829
824
lock_is_held (& rcu_sched_lock_map ),
830
825
"Illegal synchronize_rcu_expedited() in RCU read-side critical section" );
831
826
832
- /* If only one CPU, this is automatically a grace period. */
827
+ /* Is the state is such that the call is a grace period? */
833
828
if (rcu_blocking_is_gp ())
834
829
return ;
835
830
836
831
_synchronize_rcu_expedited ();
837
832
}
838
833
EXPORT_SYMBOL_GPL (synchronize_rcu_expedited );
839
-
840
- #endif /* #else #ifdef CONFIG_PREEMPT_RCU */
0 commit comments