57
57
/* Low-order bit definition for polled grace-period APIs. */
58
58
#define RCU_GET_STATE_COMPLETED 0x1
59
59
60
+ /* A complete grace period count */
61
+ #define RCU_SEQ_GP (RCU_SEQ_STATE_MASK + 1)
62
+
60
63
extern int sysctl_sched_rt_runtime ;
61
64
62
65
/*
@@ -157,12 +160,21 @@ static inline bool rcu_seq_done(unsigned long *sp, unsigned long s)
157
160
* Given a snapshot from rcu_seq_snap(), determine whether or not a
158
161
* full update-side operation has occurred, but do not allow the
159
162
* (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().
160
172
*/
161
173
static inline bool rcu_seq_done_exact (unsigned long * sp , unsigned long s )
162
174
{
163
175
unsigned long cur_s = READ_ONCE (* sp );
164
176
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 ));
166
178
}
167
179
168
180
/*
@@ -572,6 +584,8 @@ void do_trace_rcu_torture_read(const char *rcutorturename,
572
584
unsigned long c_old ,
573
585
unsigned long c );
574
586
void rcu_gp_set_torture_wait (int duration );
587
+ void rcu_set_gpwrap_lag (unsigned long lag );
588
+ int rcu_get_gpwrap_count (int cpu );
575
589
#else
576
590
static inline void rcutorture_get_gp_data (int * flags , unsigned long * gp_seq )
577
591
{
@@ -589,6 +603,8 @@ void do_trace_rcu_torture_read(const char *rcutorturename,
589
603
do { } while (0)
590
604
#endif
591
605
static 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 ; }
592
608
#endif
593
609
unsigned long long rcutorture_gather_gp_seqs (void );
594
610
void rcutorture_format_gp_seqs (unsigned long long seqs , char * cp , size_t len );
0 commit comments