This to-be-squashed commit avoids false-positive complaint of excessive ->up_read() delays. These false positives could arise by task-level delays in the rcu_torture_updown() and rcu_torture_updown_one() functions, or due to delays in softirq scheduling of the HRTIMER_MODE_SOFT rcu_torture_updown_hrt() handler. Avoid the task-level delays by sampling the time after queuing the hrtimer on the one hand and by sampling the time before reading the ->rtorsu_inuse flag on the other. Avoid the softirq scheduling delays through use of HRTIMER_MODE_HARD.
[ paulmck: Apply kernel test robot feedback. ] Tested-by: kernel test robot <[email protected]> Signed-off-by: Paul E. McKenney <[email protected]> diff --git a/kernel/rcu/rcutorture.c b/kernel/rcu/rcutorture.c index bb9a8e7185334..0e044afa98d32 100644 --- a/kernel/rcu/rcutorture.c +++ b/kernel/rcu/rcutorture.c @@ -2446,6 +2446,7 @@ rcu_torture_reader(void *arg) struct rcu_torture_one_read_state_updown { struct hrtimer rtorsu_hrt; bool rtorsu_inuse; + ktime_t rtorsu_kt; unsigned long rtorsu_j; unsigned long rtorsu_ndowns; unsigned long rtorsu_nups; @@ -2489,7 +2490,7 @@ static int rcu_torture_updown_init(void) for (i = 0; i < n_up_down; i++) { init_rcu_torture_one_read_state(&updownreaders[i].rtorsu_rtors, rand); hrtimer_setup(&updownreaders[i].rtorsu_hrt, rcu_torture_updown_hrt, CLOCK_MONOTONIC, - HRTIMER_MODE_REL | HRTIMER_MODE_SOFT); + HRTIMER_MODE_REL | HRTIMER_MODE_HARD); torture_random_init(&updownreaders[i].rtorsu_trs); init_rcu_torture_one_read_state(&updownreaders[i].rtorsu_rtors, &updownreaders[i].rtorsu_trs); @@ -2540,12 +2541,14 @@ static void rcu_torture_updown_one(struct rcu_torture_one_read_state_updown *rto schedule_timeout_idle(HZ); return; } - rtorsup->rtorsu_j = jiffies; smp_store_release(&rtorsup->rtorsu_inuse, true); t = torture_random(&rtorsup->rtorsu_trs) & 0xfffff; // One per million. if (t < 10 * 1000) t = 200 * 1000 * 1000; - hrtimer_start(&rtorsup->rtorsu_hrt, t, HRTIMER_MODE_REL | HRTIMER_MODE_SOFT); + hrtimer_start(&rtorsup->rtorsu_hrt, t, HRTIMER_MODE_REL | HRTIMER_MODE_HARD); + smp_mb(); // Sample jiffies after posting hrtimer. + rtorsup->rtorsu_j = jiffies; // Not used by hrtimer handler. + rtorsup->rtorsu_kt = t; } /* @@ -2556,6 +2559,7 @@ static void rcu_torture_updown_one(struct rcu_torture_one_read_state_updown *rto static int rcu_torture_updown(void *arg) { + unsigned long j; struct rcu_torture_one_read_state_updown *rtorsup; VERBOSE_TOROUT_STRING("rcu_torture_updown task started"); @@ -2563,8 +2567,10 @@ rcu_torture_updown(void *arg) for (rtorsup = updownreaders; rtorsup < &updownreaders[n_up_down]; rtorsup++) { if (torture_must_stop()) break; + j = smp_load_acquire(&jiffies); // Time before ->rtorsu_inuse. if (smp_load_acquire(&rtorsup->rtorsu_inuse)) { - WARN_ON_ONCE(time_after(jiffies, rtorsup->rtorsu_j + 10 * HZ)); + WARN_ONCE(time_after(j, rtorsup->rtorsu_j + 1 + HZ * 10), + "hrtimer queued at jiffies %lu for %lld ns took %lu jiffies\n", rtorsup->rtorsu_j, rtorsup->rtorsu_kt, j - rtorsup->rtorsu_j); continue; } rcu_torture_updown_one(rtorsup);
