rcutorture: Abstract synchronous and polled API testing
authorPaul E. McKenney <paulmck@kernel.org>
Sat, 30 Jul 2022 05:05:17 +0000 (22:05 -0700)
committerPaul E. McKenney <paulmck@kernel.org>
Wed, 31 Aug 2022 12:08:07 +0000 (05:08 -0700)
This commit abstracts a do_rtws_sync() function that does synchronous
grace-period testing, but also testing the polled API 25% of the time
each for the normal and full-state variants of the polled API.

Signed-off-by: Paul E. McKenney <paulmck@kernel.org>
kernel/rcu/rcutorture.c

index 4f196ebce7f29c3715ab0b01e6b5c2a919bd88a8..c3c94e343eb28576f1c6baaf39d6cdcb18cc2f72 100644 (file)
@@ -1207,6 +1207,40 @@ static void rcu_torture_write_types(void)
        }
 }
 
+/*
+ * Do the specified rcu_torture_writer() synchronous grace period,
+ * while also testing out the polled APIs.  Note well that the single-CPU
+ * grace-period optimizations must be accounted for.
+ */
+static void do_rtws_sync(struct torture_random_state *trsp, void (*sync)(void))
+{
+       unsigned long cookie;
+       struct rcu_gp_oldstate cookie_full;
+       bool dopoll;
+       bool dopoll_full;
+       unsigned long r = torture_random(trsp);
+
+       dopoll = cur_ops->get_gp_state && cur_ops->poll_gp_state && !(r & 0x300);
+       dopoll_full = cur_ops->get_gp_state_full && cur_ops->poll_gp_state_full && !(r & 0xc00);
+       if (dopoll || dopoll_full)
+               cpus_read_lock();
+       if (dopoll)
+               cookie = cur_ops->get_gp_state();
+       if (dopoll_full)
+               cur_ops->get_gp_state_full(&cookie_full);
+       if (dopoll || (!IS_ENABLED(CONFIG_TINY_RCU) && dopoll_full && num_online_cpus() <= 1))
+               sync();
+       sync();
+       WARN_ONCE(dopoll && !cur_ops->poll_gp_state(cookie),
+                 "%s: Cookie check 3 failed %pS() online %*pbl.",
+                 __func__, sync, cpumask_pr_args(cpu_online_mask));
+       WARN_ONCE(dopoll_full && !cur_ops->poll_gp_state_full(&cookie_full),
+                 "%s: Cookie check 4 failed %pS() online %*pbl",
+                 __func__, sync, cpumask_pr_args(cpu_online_mask));
+       if (dopoll || dopoll_full)
+               cpus_read_unlock();
+}
+
 /*
  * RCU torture writer kthread.  Repeatedly substitutes a new structure
  * for that pointed to by rcu_torture_current, freeing the old structure
@@ -1295,12 +1329,7 @@ rcu_torture_writer(void *arg)
                                break;
                        case RTWS_EXP_SYNC:
                                rcu_torture_writer_state = RTWS_EXP_SYNC;
-                               if (cur_ops->get_gp_state_full && cur_ops->poll_gp_state_full)
-                                       cur_ops->get_gp_state_full(&cookie_full);
-                               cur_ops->exp_sync();
-                               cur_ops->exp_sync();
-                               if (cur_ops->get_gp_state_full && cur_ops->poll_gp_state_full)
-                                       WARN_ON_ONCE(!cur_ops->poll_gp_state_full(&cookie_full));
+                               do_rtws_sync(&rand, cur_ops->exp_sync);
                                rcu_torture_pipe_update(old_rp);
                                break;
                        case RTWS_COND_GET:
@@ -1339,12 +1368,7 @@ rcu_torture_writer(void *arg)
                                break;
                        case RTWS_SYNC:
                                rcu_torture_writer_state = RTWS_SYNC;
-                               if (cur_ops->get_gp_state && cur_ops->poll_gp_state)
-                                       cookie = cur_ops->get_gp_state();
-                               cur_ops->sync();
-                               cur_ops->sync();
-                               if (cur_ops->get_gp_state && cur_ops->poll_gp_state)
-                                       WARN_ON_ONCE(!cur_ops->poll_gp_state(cookie));
+                               do_rtws_sync(&rand, cur_ops->sync);
                                rcu_torture_pipe_update(old_rp);
                                break;
                        default: