Commit cd618d10 authored by Paul E. McKenney's avatar Paul E. McKenney
Browse files

rcutorture: Record grace periods in forward-progress histogram



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: default avatarPaul E. McKenney <paulmck@linux.ibm.com>
parent 7a968bb2
Loading
Loading
Loading
Loading
+22 −7
Original line number Diff line number Diff line
@@ -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);