rcutorture: Make rcu_torture_fakewriter() use blocking wait primitives
authorPaul E. McKenney <paulmck@kernel.org>
Tue, 17 Nov 2020 01:10:39 +0000 (17:10 -0800)
committerPaul E. McKenney <paulmck@kernel.org>
Thu, 7 Jan 2021 01:17:18 +0000 (17:17 -0800)
Full testing of the new SRCU polling API requires that the fake
writers also use it in order to test concurrent calls to all of the API
members, especially start_poll_synchronize_srcu().  This commit makes
rcu_torture_fakewriter() use all available blocking grace-period-wait
primitives available from the RCU flavor under test.

Link: https://lore.kernel.org/rcu/20201112201547.GF3365678@moria.home.lan/
Reported-by: Kent Overstreet <kent.overstreet@gmail.com>
Signed-off-by: Paul E. McKenney <paulmck@kernel.org>
kernel/rcu/rcutorture.c

index 0d257e2dc9c6a8c623b4d7c271d0b34524987a39..03bdf6752fe47b3f7c200c8b7c5bf2b08b6bc33a 100644 (file)
@@ -1289,6 +1289,8 @@ rcu_torture_writer(void *arg)
 static int
 rcu_torture_fakewriter(void *arg)
 {
+       unsigned long gp_snap;
+       int i;
        DEFINE_TORTURE_RANDOM(rand);
 
        VERBOSE_TOROUT_STRING("rcu_torture_fakewriter task started");
@@ -1300,15 +1302,37 @@ rcu_torture_fakewriter(void *arg)
                if (cur_ops->cb_barrier != NULL &&
                    torture_random(&rand) % (nfakewriters * 8) == 0) {
                        cur_ops->cb_barrier();
-               } else if (gp_normal == gp_exp) {
-                       if (cur_ops->sync && torture_random(&rand) & 0x80)
-                               cur_ops->sync();
-                       else if (cur_ops->exp_sync)
+               } else {
+                       switch (synctype[torture_random(&rand) % nsynctypes]) {
+                       case RTWS_DEF_FREE:
+                               break;
+                       case RTWS_EXP_SYNC:
                                cur_ops->exp_sync();
-               } else if (gp_normal && cur_ops->sync) {
-                       cur_ops->sync();
-               } else if (cur_ops->exp_sync) {
-                       cur_ops->exp_sync();
+                               break;
+                       case RTWS_COND_GET:
+                               gp_snap = cur_ops->get_gp_state();
+                               i = torture_random(&rand) % 16;
+                               if (i != 0)
+                                       schedule_timeout_interruptible(i);
+                               udelay(torture_random(&rand) % 1000);
+                               cur_ops->cond_sync(gp_snap);
+                               break;
+                       case RTWS_POLL_GET:
+                               gp_snap = cur_ops->start_gp_poll();
+                               while (!cur_ops->poll_gp_state(gp_snap)) {
+                                       i = torture_random(&rand) % 16;
+                                       if (i != 0)
+                                               schedule_timeout_interruptible(i);
+                                       udelay(torture_random(&rand) % 1000);
+                               }
+                               break;
+                       case RTWS_SYNC:
+                               cur_ops->sync();
+                               break;
+                       default:
+                               WARN_ON_ONCE(1);
+                               break;
+                       }
                }
                stutter_wait("rcu_torture_fakewriter");
        } while (!torture_must_stop());