5757/* Low-order bit definition for polled grace-period APIs. */
5858#define RCU_GET_STATE_COMPLETED 0x1
5959
60+ /* A complete grace period count */
61+ #define RCU_SEQ_GP (RCU_SEQ_STATE_MASK + 1)
62+
6063extern int sysctl_sched_rt_runtime ;
6164
6265/*
@@ -157,12 +160,21 @@ static inline bool rcu_seq_done(unsigned long *sp, unsigned long s)
157160 * Given a snapshot from rcu_seq_snap(), determine whether or not a
158161 * full update-side operation has occurred, but do not allow the
159162 * (ULONG_MAX / 2) safety-factor/guard-band.
163+ *
164+ * The token returned by get_state_synchronize_rcu_full() is based on
165+ * rcu_state.gp_seq but it is tested in poll_state_synchronize_rcu_full()
166+ * against the root rnp->gp_seq. Since rcu_seq_start() is first called
167+ * on rcu_state.gp_seq and only later reflected on the root rnp->gp_seq,
168+ * it is possible that rcu_seq_snap(rcu_state.gp_seq) returns 2 full grace
169+ * periods ahead of the root rnp->gp_seq. To prevent false-positives with the
170+ * full polling API that a wrap around instantly completed the GP, when nothing
171+ * like that happened, adjust for the 2 GPs in the ULONG_CMP_LT().
160172 */
161173static inline bool rcu_seq_done_exact (unsigned long * sp , unsigned long s )
162174{
163175 unsigned long cur_s = READ_ONCE (* sp );
164176
165- return ULONG_CMP_GE (cur_s , s ) || ULONG_CMP_LT (cur_s , s - (3 * RCU_SEQ_STATE_MASK + 1 ));
177+ return ULONG_CMP_GE (cur_s , s ) || ULONG_CMP_LT (cur_s , s - (2 * RCU_SEQ_GP ));
166178}
167179
168180/*
@@ -572,6 +584,8 @@ void do_trace_rcu_torture_read(const char *rcutorturename,
572584 unsigned long c_old ,
573585 unsigned long c );
574586void rcu_gp_set_torture_wait (int duration );
587+ void rcu_set_gpwrap_lag (unsigned long lag );
588+ int rcu_get_gpwrap_count (int cpu );
575589#else
576590static inline void rcutorture_get_gp_data (int * flags , unsigned long * gp_seq )
577591{
@@ -589,6 +603,8 @@ void do_trace_rcu_torture_read(const char *rcutorturename,
589603 do { } while (0)
590604#endif
591605static inline void rcu_gp_set_torture_wait (int duration ) { }
606+ static inline void rcu_set_gpwrap_lag (unsigned long lag ) { }
607+ static inline int rcu_get_gpwrap_count (int cpu ) { return 0 ; }
592608#endif
593609unsigned long long rcutorture_gather_gp_seqs (void );
594610void rcutorture_format_gp_seqs (unsigned long long seqs , char * cp , size_t len );
0 commit comments