srcu: Make rcutorture writer stalls print SRCU GP state
authorPaul E. McKenney <paulmck@linux.vnet.ibm.com>
Wed, 19 Apr 2017 00:17:35 +0000 (17:17 -0700)
committerPaul E. McKenney <paulmck@linux.vnet.ibm.com>
Wed, 26 Apr 2017 18:23:28 +0000 (11:23 -0700)
In the past, SRCU was simple enough that there was little point in
making the rcutorture writer stall messages print the SRCU grace-period
number state.  With the advent of Tree SRCU, this has changed.  This
commit therefore makes Classic, Tiny, and Tree SRCU report this state
to rcutorture as needed.

Signed-off-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
Tested-by: Mike Galbraith <efault@gmx.de>
include/linux/srcuclassic.h
include/linux/srcutiny.h
include/linux/srcutree.h
kernel/rcu/rcutorture.c
kernel/rcu/srcutree.c
kernel/rcu/tree.c

index 41cf99930f342fbf622ac6dd133f0bd5cc74a216..5753f73222629c1340d363eba4e50510e437c575 100644 (file)
@@ -98,4 +98,18 @@ void synchronize_srcu_expedited(struct srcu_struct *sp);
 void srcu_barrier(struct srcu_struct *sp);
 unsigned long srcu_batches_completed(struct srcu_struct *sp);
 
+static inline void srcutorture_get_gp_data(enum rcutorture_type test_type,
+                                          struct srcu_struct *sp, int *flags,
+                                          unsigned long *gpnum,
+                                          unsigned long *completed)
+{
+       if (test_type != SRCU_FLAVOR)
+               return;
+       *flags = 0;
+       *completed = sp->completed;
+       *gpnum = *completed;
+       if (sp->batch_queue.head || sp->batch_check0.head || sp->batch_check0.head)
+               (*gpnum)++;
+}
+
 #endif
index 4f284e4f4d8c5d7003e2ef308e03ab277829922d..42311ee0334fde629280f6b92cdc065853e3ba14 100644 (file)
@@ -78,4 +78,16 @@ static inline unsigned long srcu_batches_completed(struct srcu_struct *sp)
        return 0;
 }
 
+static inline void srcutorture_get_gp_data(enum rcutorture_type test_type,
+                                          struct srcu_struct *sp, int *flags,
+                                          unsigned long *gpnum,
+                                          unsigned long *completed)
+{
+       if (test_type != SRCU_FLAVOR)
+               return;
+       *flags = 0;
+       *completed = sp->srcu_gp_seq;
+       *gpnum = *completed;
+}
+
 #endif
index 94515ff226fb17a02bfcc7b0143e0157b84c4881..3865717df1244f1b10c7e9aa504021c2ea1c56ea 100644 (file)
@@ -140,4 +140,8 @@ void synchronize_srcu_expedited(struct srcu_struct *sp);
 void srcu_barrier(struct srcu_struct *sp);
 unsigned long srcu_batches_completed(struct srcu_struct *sp);
 
+void srcutorture_get_gp_data(enum rcutorture_type test_type,
+                            struct srcu_struct *sp, int *flags,
+                            unsigned long *gpnum, unsigned long *completed);
+
 #endif
index e9d4527cdd43dfcd2993f48c18094ac2ccf2cdd6..ae6e574d4cf5c3fbdd8ab9a56009981cec9935a1 100644 (file)
@@ -1360,12 +1360,14 @@ rcu_torture_stats_print(void)
                cur_ops->stats();
        if (rtcv_snap == rcu_torture_current_version &&
            rcu_torture_current != NULL) {
-               int __maybe_unused flags;
-               unsigned long __maybe_unused gpnum;
-               unsigned long __maybe_unused completed;
+               int __maybe_unused flags = 0;
+               unsigned long __maybe_unused gpnum = 0;
+               unsigned long __maybe_unused completed = 0;
 
                rcutorture_get_gp_data(cur_ops->ttype,
                                       &flags, &gpnum, &completed);
+               srcutorture_get_gp_data(cur_ops->ttype, srcu_ctlp,
+                                       &flags, &gpnum, &completed);
                wtp = READ_ONCE(writer_task);
                pr_alert("??? Writer stall state %s(%d) g%lu c%lu f%#x ->state %#lx\n",
                         rcu_torture_writer_state_getname(),
index 1c2c1004b3b19756c85d06fc122ca385d68215e6..72b6cce5f59151c581455db2d255fd1f51a75977 100644 (file)
@@ -1011,3 +1011,16 @@ void process_srcu(struct work_struct *work)
        srcu_reschedule(sp, atomic_read(&sp->srcu_exp_cnt) ? 0 : SRCU_INTERVAL);
 }
 EXPORT_SYMBOL_GPL(process_srcu);
+
+void srcutorture_get_gp_data(enum rcutorture_type test_type,
+                                          struct srcu_struct *sp, int *flags,
+                                          unsigned long *gpnum,
+                                          unsigned long *completed)
+{
+       if (test_type != SRCU_FLAVOR)
+               return;
+       *flags = 0;
+       *completed = rcu_seq_ctr(sp->srcu_gp_seq);
+       *gpnum = rcu_seq_ctr(sp->srcu_gp_seq_needed);
+}
+EXPORT_SYMBOL_GPL(srcutorture_get_gp_data);
index 23aa02587d0fd245919ce26d26225d49f06a8a6b..91fff49d5869826a25039e8a47a2b14fe6cb7be6 100644 (file)
@@ -704,15 +704,11 @@ void rcutorture_get_gp_data(enum rcutorture_type test_type, int *flags,
        default:
                break;
        }
-       if (rsp != NULL) {
-               *flags = READ_ONCE(rsp->gp_flags);
-               *gpnum = READ_ONCE(rsp->gpnum);
-               *completed = READ_ONCE(rsp->completed);
+       if (rsp == NULL)
                return;
-       }
-       *flags = 0;
-       *gpnum = 0;
-       *completed = 0;
+       *flags = READ_ONCE(rsp->gp_flags);
+       *gpnum = READ_ONCE(rsp->gpnum);
+       *completed = READ_ONCE(rsp->completed);
 }
 EXPORT_SYMBOL_GPL(rcutorture_get_gp_data);