OSDN Git Service

rcutorture: Record grace periods in forward-progress histogram
authorPaul E. McKenney <paulmck@linux.ibm.com>
Tue, 8 Jan 2019 21:41:26 +0000 (13:41 -0800)
committerPaul E. McKenney <paulmck@linux.ibm.com>
Fri, 25 Jan 2019 23:37:09 +0000 (15:37 -0800)
This commit records grace periods in rcutorture's n_launders_hist[]
histogram, thus allowing rcu_torture_fwd_cb_hist() to print out the
elapsed number of grace periods between buckets.  This information
helps to determine whether a lack of forward progress is due to stalled
grace periods on the one hand or due to sluggish callback invocation on
the other.

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

index f6e85fa..0955f3a 100644 (file)
@@ -1630,21 +1630,34 @@ static bool rcu_fwd_emergency_stop;
 #define MIN_FWD_CB_LAUNDERS    3       /* This many CB invocations to count. */
 #define MIN_FWD_CBS_LAUNDERED  100     /* Number of counted CBs. */
 #define FWD_CBS_HIST_DIV       10      /* Histogram buckets/second. */
-static long n_launders_hist[2 * MAX_FWD_CB_JIFFIES / (HZ / FWD_CBS_HIST_DIV)];
+struct rcu_launder_hist {
+       long n_launders;
+       unsigned long launder_gp_seq;
+};
+#define N_LAUNDERS_HIST (2 * MAX_FWD_CB_JIFFIES / (HZ / FWD_CBS_HIST_DIV))
+static struct rcu_launder_hist n_launders_hist[N_LAUNDERS_HIST];
+static unsigned long rcu_launder_gp_seq_start;
 
 static void rcu_torture_fwd_cb_hist(void)
 {
+       unsigned long gps;
+       unsigned long gps_old;
        int i;
        int j;
 
        for (i = ARRAY_SIZE(n_launders_hist) - 1; i > 0; i--)
-               if (n_launders_hist[i] > 0)
+               if (n_launders_hist[i].n_launders > 0)
                        break;
        pr_alert("%s: Callback-invocation histogram (duration %lu jiffies):",
                 __func__, jiffies - rcu_fwd_startat);
-       for (j = 0; j <= i; j++)
-               pr_cont(" %ds/%d: %ld",
-                       j + 1, FWD_CBS_HIST_DIV, n_launders_hist[j]);
+       gps_old = rcu_launder_gp_seq_start;
+       for (j = 0; j <= i; j++) {
+               gps = n_launders_hist[j].launder_gp_seq;
+               pr_cont(" %ds/%d: %ld:%ld",
+                       j + 1, FWD_CBS_HIST_DIV, n_launders_hist[j].n_launders,
+                       rcutorture_seq_diff(gps, gps_old));
+               gps_old = gps;
+       }
        pr_cont("\n");
 }
 
@@ -1666,7 +1679,8 @@ static void rcu_torture_fwd_cb_cr(struct rcu_head *rhp)
        i = ((jiffies - rcu_fwd_startat) / (HZ / FWD_CBS_HIST_DIV));
        if (i >= ARRAY_SIZE(n_launders_hist))
                i = ARRAY_SIZE(n_launders_hist) - 1;
-       n_launders_hist[i]++;
+       n_launders_hist[i].n_launders++;
+       n_launders_hist[i].launder_gp_seq = cur_ops->get_gp_seq();
        spin_unlock_irqrestore(&rcu_fwd_lock, flags);
 }
 
@@ -1786,9 +1800,10 @@ static void rcu_torture_fwd_prog_cr(void)
        n_max_cbs = 0;
        n_max_gps = 0;
        for (i = 0; i < ARRAY_SIZE(n_launders_hist); i++)
-               n_launders_hist[i] = 0;
+               n_launders_hist[i].n_launders = 0;
        cver = READ_ONCE(rcu_torture_current_version);
        gps = cur_ops->get_gp_seq();
+       rcu_launder_gp_seq_start = gps;
        while (time_before(jiffies, stopat) &&
               !READ_ONCE(rcu_fwd_emergency_stop) && !torture_must_stop()) {
                rfcp = READ_ONCE(rcu_fwd_cb_head);