Merge branches 'cpuinfo.2020.11.06a', 'doc.2020.11.06a', 'fixes.2020.11.19b', 'lockde...
[linux-2.6-microblaze.git] / kernel / rcu / rcutorture.c
index 916ea4f..528ed10 100644 (file)
@@ -317,6 +317,7 @@ struct rcu_torture_ops {
        void (*cb_barrier)(void);
        void (*fqs)(void);
        void (*stats)(void);
+       void (*gp_kthread_dbg)(void);
        int (*stall_dur)(void);
        int irq_capable;
        int can_boost;
@@ -466,6 +467,7 @@ static struct rcu_torture_ops rcu_ops = {
        .cb_barrier     = rcu_barrier,
        .fqs            = rcu_force_quiescent_state,
        .stats          = NULL,
+       .gp_kthread_dbg = show_rcu_gp_kthreads,
        .stall_dur      = rcu_jiffies_till_stall_check,
        .irq_capable    = 1,
        .can_boost      = rcu_can_boost(),
@@ -693,6 +695,7 @@ static struct rcu_torture_ops tasks_ops = {
        .exp_sync       = synchronize_rcu_mult_test,
        .call           = call_rcu_tasks,
        .cb_barrier     = rcu_barrier_tasks,
+       .gp_kthread_dbg = show_rcu_tasks_classic_gp_kthread,
        .fqs            = NULL,
        .stats          = NULL,
        .irq_capable    = 1,
@@ -762,6 +765,7 @@ static struct rcu_torture_ops tasks_rude_ops = {
        .exp_sync       = synchronize_rcu_tasks_rude,
        .call           = call_rcu_tasks_rude,
        .cb_barrier     = rcu_barrier_tasks_rude,
+       .gp_kthread_dbg = show_rcu_tasks_rude_gp_kthread,
        .fqs            = NULL,
        .stats          = NULL,
        .irq_capable    = 1,
@@ -800,6 +804,7 @@ static struct rcu_torture_ops tasks_tracing_ops = {
        .exp_sync       = synchronize_rcu_tasks_trace,
        .call           = call_rcu_tasks_trace,
        .cb_barrier     = rcu_barrier_tasks_trace,
+       .gp_kthread_dbg = show_rcu_tasks_trace_gp_kthread,
        .fqs            = NULL,
        .stats          = NULL,
        .irq_capable    = 1,
@@ -912,7 +917,8 @@ static int rcu_torture_boost(void *arg)
                oldstarttime = boost_starttime;
                while (time_before(jiffies, oldstarttime)) {
                        schedule_timeout_interruptible(oldstarttime - jiffies);
-                       stutter_wait("rcu_torture_boost");
+                       if (stutter_wait("rcu_torture_boost"))
+                               sched_set_fifo_low(current);
                        if (torture_must_stop())
                                goto checkwait;
                }
@@ -932,7 +938,8 @@ static int rcu_torture_boost(void *arg)
                                                                 jiffies);
                                call_rcu_time = jiffies;
                        }
-                       stutter_wait("rcu_torture_boost");
+                       if (stutter_wait("rcu_torture_boost"))
+                               sched_set_fifo_low(current);
                        if (torture_must_stop())
                                goto checkwait;
                }
@@ -964,7 +971,8 @@ static int rcu_torture_boost(void *arg)
                }
 
                /* Go do the stutter. */
-checkwait:     stutter_wait("rcu_torture_boost");
+checkwait:     if (stutter_wait("rcu_torture_boost"))
+                       sched_set_fifo_low(current);
        } while (!torture_must_stop());
 
        /* Clean up and exit. */
@@ -987,6 +995,7 @@ rcu_torture_fqs(void *arg)
 {
        unsigned long fqs_resume_time;
        int fqs_burst_remaining;
+       int oldnice = task_nice(current);
 
        VERBOSE_TOROUT_STRING("rcu_torture_fqs task started");
        do {
@@ -1002,7 +1011,8 @@ rcu_torture_fqs(void *arg)
                        udelay(fqs_holdoff);
                        fqs_burst_remaining -= fqs_holdoff;
                }
-               stutter_wait("rcu_torture_fqs");
+               if (stutter_wait("rcu_torture_fqs"))
+                       sched_set_normal(current, oldnice);
        } while (!torture_must_stop());
        torture_kthread_stopping("rcu_torture_fqs");
        return 0;
@@ -1022,9 +1032,11 @@ rcu_torture_writer(void *arg)
        bool gp_cond1 = gp_cond, gp_exp1 = gp_exp, gp_normal1 = gp_normal;
        bool gp_sync1 = gp_sync;
        int i;
+       int oldnice = task_nice(current);
        struct rcu_torture *rp;
        struct rcu_torture *old_rp;
        static DEFINE_TORTURE_RANDOM(rand);
+       bool stutter_waited;
        int synctype[] = { RTWS_DEF_FREE, RTWS_EXP_SYNC,
                           RTWS_COND_GET, RTWS_SYNC };
        int nsynctypes = 0;
@@ -1143,7 +1155,8 @@ rcu_torture_writer(void *arg)
                                       !rcu_gp_is_normal();
                }
                rcu_torture_writer_state = RTWS_STUTTER;
-               if (stutter_wait("rcu_torture_writer") &&
+               stutter_waited = stutter_wait("rcu_torture_writer");
+               if (stutter_waited &&
                    !READ_ONCE(rcu_fwd_cb_nodelay) &&
                    !cur_ops->slow_gps &&
                    !torture_must_stop() &&
@@ -1155,6 +1168,8 @@ rcu_torture_writer(void *arg)
                                        rcu_ftrace_dump(DUMP_ALL);
                                        WARN(1, "%s: rtort_pipe_count: %d\n", __func__, rcu_tortures[i].rtort_pipe_count);
                                }
+               if (stutter_waited)
+                       sched_set_normal(current, oldnice);
        } while (!torture_must_stop());
        rcu_torture_current = NULL;  // Let stats task know that we are done.
        /* Reset expediting back to unexpedited. */
@@ -1594,7 +1609,8 @@ rcu_torture_stats_print(void)
                        sched_show_task(wtp);
                        splatted = true;
                }
-               show_rcu_gp_kthreads();
+               if (cur_ops->gp_kthread_dbg)
+                       cur_ops->gp_kthread_dbg();
                rcu_ftrace_dump(DUMP_ALL);
        }
        rtcv_snap = rcu_torture_current_version;
@@ -1913,7 +1929,9 @@ static void rcu_torture_fwd_prog_nr(struct rcu_fwd *rfp,
        unsigned long stopat;
        static DEFINE_TORTURE_RANDOM(trs);
 
-       if  (cur_ops->call && cur_ops->sync && cur_ops->cb_barrier) {
+       if (!cur_ops->sync)
+               return; // Cannot do need_resched() forward progress testing without ->sync.
+       if (cur_ops->call && cur_ops->cb_barrier) {
                init_rcu_head_on_stack(&fcs.rh);
                selfpropcb = true;
        }
@@ -2103,6 +2121,7 @@ static struct notifier_block rcutorture_oom_nb = {
 /* Carry out grace-period forward-progress testing. */
 static int rcu_torture_fwd_prog(void *args)
 {
+       int oldnice = task_nice(current);
        struct rcu_fwd *rfp = args;
        int tested = 0;
        int tested_tries = 0;
@@ -2121,7 +2140,8 @@ static int rcu_torture_fwd_prog(void *args)
                        rcu_torture_fwd_prog_cr(rfp);
 
                /* Avoid slow periods, better to test when busy. */
-               stutter_wait("rcu_torture_fwd_prog");
+               if (stutter_wait("rcu_torture_fwd_prog"))
+                       sched_set_normal(current, oldnice);
        } while (!torture_must_stop());
        /* Short runs might not contain a valid forward-progress attempt. */
        WARN_ON(!tested && tested_tries >= 5);
@@ -2137,8 +2157,8 @@ static int __init rcu_torture_fwd_prog_init(void)
 
        if (!fwd_progress)
                return 0; /* Not requested, so don't do it. */
-       if (!cur_ops->stall_dur || cur_ops->stall_dur() <= 0 ||
-           cur_ops == &rcu_busted_ops) {
+       if ((!cur_ops->sync && !cur_ops->call) ||
+           !cur_ops->stall_dur || cur_ops->stall_dur() <= 0 || cur_ops == &rcu_busted_ops) {
                VERBOSE_TOROUT_STRING("rcu_torture_fwd_prog_init: Disabled, unsupported by RCU flavor under test");
                return 0;
        }
@@ -2472,7 +2492,8 @@ rcu_torture_cleanup(void)
                return;
        }
 
-       show_rcu_gp_kthreads();
+       if (cur_ops->gp_kthread_dbg)
+               cur_ops->gp_kthread_dbg();
        rcu_torture_read_exit_cleanup();
        rcu_torture_barrier_cleanup();
        rcu_torture_fwd_prog_cleanup();
@@ -2484,13 +2505,13 @@ rcu_torture_cleanup(void)
                        torture_stop_kthread(rcu_torture_reader,
                                             reader_tasks[i]);
                kfree(reader_tasks);
+               reader_tasks = NULL;
        }
 
        if (fakewriter_tasks) {
-               for (i = 0; i < nfakewriters; i++) {
+               for (i = 0; i < nfakewriters; i++)
                        torture_stop_kthread(rcu_torture_fakewriter,
                                             fakewriter_tasks[i]);
-               }
                kfree(fakewriter_tasks);
                fakewriter_tasks = NULL;
        }
@@ -2647,7 +2668,6 @@ rcu_torture_init(void)
                for (i = 0; i < ARRAY_SIZE(torture_ops); i++)
                        pr_cont(" %s", torture_ops[i]->name);
                pr_cont("\n");
-               WARN_ON(!IS_MODULE(CONFIG_RCU_TORTURE_TEST));
                firsterr = -EINVAL;
                cur_ops = NULL;
                goto unwind;
@@ -2815,6 +2835,10 @@ rcu_torture_init(void)
 unwind:
        torture_init_end();
        rcu_torture_cleanup();
+       if (shutdown_secs) {
+               WARN_ON(!IS_MODULE(CONFIG_RCU_TORTURE_TEST));
+               kernel_power_off();
+       }
        return firsterr;
 }