@@ -772,20 +772,10 @@ EXPORT_SYMBOL_GPL(__srcu_read_unlock_nmisafe);
772772 */
773773static void srcu_gp_start (struct srcu_struct * ssp )
774774{
775- struct srcu_data * sdp ;
776775 int state ;
777776
778- if (smp_load_acquire (& ssp -> srcu_sup -> srcu_size_state ) < SRCU_SIZE_WAIT_BARRIER )
779- sdp = per_cpu_ptr (ssp -> sda , get_boot_cpu_id ());
780- else
781- sdp = this_cpu_ptr (ssp -> sda );
782777 lockdep_assert_held (& ACCESS_PRIVATE (ssp -> srcu_sup , lock ));
783778 WARN_ON_ONCE (ULONG_CMP_GE (ssp -> srcu_sup -> srcu_gp_seq , ssp -> srcu_sup -> srcu_gp_seq_needed ));
784- spin_lock_rcu_node (sdp ); /* Interrupts already disabled. */
785- rcu_segcblist_advance (& sdp -> srcu_cblist ,
786- rcu_seq_current (& ssp -> srcu_sup -> srcu_gp_seq ));
787- WARN_ON_ONCE (!rcu_segcblist_segempty (& sdp -> srcu_cblist , RCU_NEXT_TAIL ));
788- spin_unlock_rcu_node (sdp ); /* Interrupts remain disabled. */
789779 WRITE_ONCE (ssp -> srcu_sup -> srcu_gp_start , jiffies );
790780 WRITE_ONCE (ssp -> srcu_sup -> srcu_n_exp_nodelay , 0 );
791781 smp_mb (); /* Order prior store to ->srcu_gp_seq_needed vs. GP start. */
@@ -1271,9 +1261,11 @@ static unsigned long srcu_gp_start_if_needed(struct srcu_struct *ssp,
12711261 * period (gp_num = X + 8). So acceleration fails.
12721262 */
12731263 s = rcu_seq_snap (& ssp -> srcu_sup -> srcu_gp_seq );
1274- rcu_segcblist_advance (& sdp -> srcu_cblist ,
1275- rcu_seq_current (& ssp -> srcu_sup -> srcu_gp_seq ));
1276- WARN_ON_ONCE (!rcu_segcblist_accelerate (& sdp -> srcu_cblist , s ) && rhp );
1264+ if (rhp ) {
1265+ rcu_segcblist_advance (& sdp -> srcu_cblist ,
1266+ rcu_seq_current (& ssp -> srcu_sup -> srcu_gp_seq ));
1267+ WARN_ON_ONCE (!rcu_segcblist_accelerate (& sdp -> srcu_cblist , s ));
1268+ }
12771269 if (ULONG_CMP_LT (sdp -> srcu_gp_seq_needed , s )) {
12781270 sdp -> srcu_gp_seq_needed = s ;
12791271 needgp = true;
@@ -1723,6 +1715,11 @@ static void srcu_invoke_callbacks(struct work_struct *work)
17231715 WARN_ON_ONCE (!rcu_segcblist_segempty (& sdp -> srcu_cblist , RCU_NEXT_TAIL ));
17241716 rcu_segcblist_advance (& sdp -> srcu_cblist ,
17251717 rcu_seq_current (& ssp -> srcu_sup -> srcu_gp_seq ));
1718+ /*
1719+ * Although this function is theoretically re-entrant, concurrent
1720+ * callbacks invocation is disallowed to avoid executing an SRCU barrier
1721+ * too early.
1722+ */
17261723 if (sdp -> srcu_cblist_invoking ||
17271724 !rcu_segcblist_ready_cbs (& sdp -> srcu_cblist )) {
17281725 spin_unlock_irq_rcu_node (sdp );
@@ -1753,6 +1750,7 @@ static void srcu_invoke_callbacks(struct work_struct *work)
17531750 sdp -> srcu_cblist_invoking = false;
17541751 more = rcu_segcblist_ready_cbs (& sdp -> srcu_cblist );
17551752 spin_unlock_irq_rcu_node (sdp );
1753+ /* An SRCU barrier or callbacks from previous nesting work pending */
17561754 if (more )
17571755 srcu_schedule_cbs_sdp (sdp , 0 );
17581756}
0 commit comments