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);

Reply via email to