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: Paul E. McKenney <paulmck@linux.ibm.com>
This commit is contained in:
Paul E. McKenney 2019-01-08 13:41:26 -08:00
Родитель 7a968bb26a
Коммит cd618d102b
1 изменённых файлов: 22 добавлений и 7 удалений

Просмотреть файл

@ -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_CB_LAUNDERS 3 /* This many CB invocations to count. */
#define MIN_FWD_CBS_LAUNDERED 100 /* Number of counted CBs. */ #define MIN_FWD_CBS_LAUNDERED 100 /* Number of counted CBs. */
#define FWD_CBS_HIST_DIV 10 /* Histogram buckets/second. */ #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) static void rcu_torture_fwd_cb_hist(void)
{ {
unsigned long gps;
unsigned long gps_old;
int i; int i;
int j; int j;
for (i = ARRAY_SIZE(n_launders_hist) - 1; i > 0; i--) 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; break;
pr_alert("%s: Callback-invocation histogram (duration %lu jiffies):", pr_alert("%s: Callback-invocation histogram (duration %lu jiffies):",
__func__, jiffies - rcu_fwd_startat); __func__, jiffies - rcu_fwd_startat);
for (j = 0; j <= i; j++) gps_old = rcu_launder_gp_seq_start;
pr_cont(" %ds/%d: %ld", for (j = 0; j <= i; j++) {
j + 1, FWD_CBS_HIST_DIV, n_launders_hist[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"); 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)); i = ((jiffies - rcu_fwd_startat) / (HZ / FWD_CBS_HIST_DIV));
if (i >= ARRAY_SIZE(n_launders_hist)) if (i >= ARRAY_SIZE(n_launders_hist))
i = ARRAY_SIZE(n_launders_hist) - 1; 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); 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_cbs = 0;
n_max_gps = 0; n_max_gps = 0;
for (i = 0; i < ARRAY_SIZE(n_launders_hist); i++) 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); cver = READ_ONCE(rcu_torture_current_version);
gps = cur_ops->get_gp_seq(); gps = cur_ops->get_gp_seq();
rcu_launder_gp_seq_start = gps;
while (time_before(jiffies, stopat) && while (time_before(jiffies, stopat) &&
!READ_ONCE(rcu_fwd_emergency_stop) && !torture_must_stop()) { !READ_ONCE(rcu_fwd_emergency_stop) && !torture_must_stop()) {
rfcp = READ_ONCE(rcu_fwd_cb_head); rfcp = READ_ONCE(rcu_fwd_cb_head);