aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/rcu/tree.c
diff options
context:
space:
mode:
authorPaul E. McKenney <paulmck@linux.vnet.ibm.com>2018-04-30 16:09:17 -0400
committerPaul E. McKenney <paulmck@linux.vnet.ibm.com>2018-07-12 17:27:56 -0400
commit471f87c3d91bd0884451c0e3071473476c165630 (patch)
tree98f4f3f50c68d24e2949a7f719b645610296f607 /kernel/rcu/tree.c
parent29365e563b1e4e5bfde211280d37dc6127c019ed (diff)
rcu: Make RCU CPU stall warnings use ->gp_seq
This commit makes the RCU CPU stall-warning code in print_other_cpu_stall(), print_cpu_stall(), and check_cpu_stall() use ->gp_seq instead of ->gpnum and ->completed. Signed-off-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
Diffstat (limited to 'kernel/rcu/tree.c')
-rw-r--r--kernel/rcu/tree.c51
1 files changed, 26 insertions, 25 deletions
diff --git a/kernel/rcu/tree.c b/kernel/rcu/tree.c
index ffa45b6175d9..9e619c4878d3 100644
--- a/kernel/rcu/tree.c
+++ b/kernel/rcu/tree.c
@@ -1340,7 +1340,7 @@ static inline void panic_on_rcu_stall(void)
1340 panic("RCU Stall\n"); 1340 panic("RCU Stall\n");
1341} 1341}
1342 1342
1343static void print_other_cpu_stall(struct rcu_state *rsp, unsigned long gpnum) 1343static void print_other_cpu_stall(struct rcu_state *rsp, unsigned long gp_seq)
1344{ 1344{
1345 int cpu; 1345 int cpu;
1346 unsigned long flags; 1346 unsigned long flags;
@@ -1350,6 +1350,8 @@ static void print_other_cpu_stall(struct rcu_state *rsp, unsigned long gpnum)
1350 struct rcu_node *rnp = rcu_get_root(rsp); 1350 struct rcu_node *rnp = rcu_get_root(rsp);
1351 long totqlen = 0; 1351 long totqlen = 0;
1352 1352
1353 WARN_ON_ONCE(gp_seq & 0x2); /* Remove when ->gpnum removed. */
1354
1353 /* Kick and suppress, if so configured. */ 1355 /* Kick and suppress, if so configured. */
1354 rcu_stall_kick_kthreads(rsp); 1356 rcu_stall_kick_kthreads(rsp);
1355 if (rcu_cpu_stall_suppress) 1357 if (rcu_cpu_stall_suppress)
@@ -1380,17 +1382,16 @@ static void print_other_cpu_stall(struct rcu_state *rsp, unsigned long gpnum)
1380 for_each_possible_cpu(cpu) 1382 for_each_possible_cpu(cpu)
1381 totqlen += rcu_segcblist_n_cbs(&per_cpu_ptr(rsp->rda, 1383 totqlen += rcu_segcblist_n_cbs(&per_cpu_ptr(rsp->rda,
1382 cpu)->cblist); 1384 cpu)->cblist);
1383 pr_cont("(detected by %d, t=%ld jiffies, g=%ld, c=%ld, q=%lu)\n", 1385 pr_cont("(detected by %d, t=%ld jiffies, g=%ld, q=%lu)\n",
1384 smp_processor_id(), (long)(jiffies - rsp->gp_start), 1386 smp_processor_id(), (long)(jiffies - rsp->gp_start),
1385 (long)rsp->gpnum, (long)rsp->completed, totqlen); 1387 (long)rcu_seq_current(&rsp->gp_seq), totqlen);
1386 if (ndetected) { 1388 if (ndetected) {
1387 rcu_dump_cpu_stacks(rsp); 1389 rcu_dump_cpu_stacks(rsp);
1388 1390
1389 /* Complain about tasks blocking the grace period. */ 1391 /* Complain about tasks blocking the grace period. */
1390 rcu_print_detail_task_stall(rsp); 1392 rcu_print_detail_task_stall(rsp);
1391 } else { 1393 } else {
1392 if (READ_ONCE(rsp->gpnum) != gpnum || 1394 if (rcu_seq_current(&rsp->gp_seq) != gp_seq) {
1393 READ_ONCE(rsp->completed) == gpnum) {
1394 pr_err("INFO: Stall ended before state dump start\n"); 1395 pr_err("INFO: Stall ended before state dump start\n");
1395 } else { 1396 } else {
1396 j = jiffies; 1397 j = jiffies;
@@ -1442,9 +1443,9 @@ static void print_cpu_stall(struct rcu_state *rsp)
1442 for_each_possible_cpu(cpu) 1443 for_each_possible_cpu(cpu)
1443 totqlen += rcu_segcblist_n_cbs(&per_cpu_ptr(rsp->rda, 1444 totqlen += rcu_segcblist_n_cbs(&per_cpu_ptr(rsp->rda,
1444 cpu)->cblist); 1445 cpu)->cblist);
1445 pr_cont(" (t=%lu jiffies g=%ld c=%ld q=%lu)\n", 1446 pr_cont(" (t=%lu jiffies g=%ld q=%lu)\n",
1446 jiffies - rsp->gp_start, 1447 jiffies - rsp->gp_start,
1447 (long)rsp->gpnum, (long)rsp->completed, totqlen); 1448 (long)rcu_seq_current(&rsp->gp_seq), totqlen);
1448 1449
1449 rcu_check_gp_kthread_starvation(rsp); 1450 rcu_check_gp_kthread_starvation(rsp);
1450 1451
@@ -1471,8 +1472,8 @@ static void print_cpu_stall(struct rcu_state *rsp)
1471 1472
1472static void check_cpu_stall(struct rcu_state *rsp, struct rcu_data *rdp) 1473static void check_cpu_stall(struct rcu_state *rsp, struct rcu_data *rdp)
1473{ 1474{
1474 unsigned long completed; 1475 unsigned long gs1;
1475 unsigned long gpnum; 1476 unsigned long gs2;
1476 unsigned long gps; 1477 unsigned long gps;
1477 unsigned long j; 1478 unsigned long j;
1478 unsigned long jn; 1479 unsigned long jn;
@@ -1488,28 +1489,28 @@ static void check_cpu_stall(struct rcu_state *rsp, struct rcu_data *rdp)
1488 /* 1489 /*
1489 * Lots of memory barriers to reject false positives. 1490 * Lots of memory barriers to reject false positives.
1490 * 1491 *
1491 * The idea is to pick up rsp->gpnum, then rsp->jiffies_stall, 1492 * The idea is to pick up rsp->gp_seq, then rsp->jiffies_stall,
1492 * then rsp->gp_start, and finally rsp->completed. These values 1493 * then rsp->gp_start, and finally another copy of rsp->gp_seq.
1493 * are updated in the opposite order with memory barriers (or 1494 * These values are updated in the opposite order with memory
1494 * equivalent) during grace-period initialization and cleanup. 1495 * barriers (or equivalent) during grace-period initialization
1495 * Now, a false positive can occur if we get an new value of 1496 * and cleanup. Now, a false positive can occur if we get an new
1496 * rsp->gp_start and a old value of rsp->jiffies_stall. But given 1497 * value of rsp->gp_start and a old value of rsp->jiffies_stall.
1497 * the memory barriers, the only way that this can happen is if one 1498 * But given the memory barriers, the only way that this can happen
1498 * grace period ends and another starts between these two fetches. 1499 * is if one grace period ends and another starts between these
1499 * Detect this by comparing rsp->completed with the previous fetch 1500 * two fetches. This is detected by comparing the second fetch
1500 * from rsp->gpnum. 1501 * of rsp->gp_seq with the previous fetch from rsp->gp_seq.
1501 * 1502 *
1502 * Given this check, comparisons of jiffies, rsp->jiffies_stall, 1503 * Given this check, comparisons of jiffies, rsp->jiffies_stall,
1503 * and rsp->gp_start suffice to forestall false positives. 1504 * and rsp->gp_start suffice to forestall false positives.
1504 */ 1505 */
1505 gpnum = READ_ONCE(rsp->gpnum); 1506 gs1 = READ_ONCE(rsp->gp_seq);
1506 smp_rmb(); /* Pick up ->gpnum first... */ 1507 smp_rmb(); /* Pick up ->gp_seq first... */
1507 js = READ_ONCE(rsp->jiffies_stall); 1508 js = READ_ONCE(rsp->jiffies_stall);
1508 smp_rmb(); /* ...then ->jiffies_stall before the rest... */ 1509 smp_rmb(); /* ...then ->jiffies_stall before the rest... */
1509 gps = READ_ONCE(rsp->gp_start); 1510 gps = READ_ONCE(rsp->gp_start);
1510 smp_rmb(); /* ...and finally ->gp_start before ->completed. */ 1511 smp_rmb(); /* ...and finally ->gp_start before ->gp_seq again. */
1511 completed = READ_ONCE(rsp->completed); 1512 gs2 = READ_ONCE(rsp->gp_seq);
1512 if (ULONG_CMP_GE(completed, gpnum) || 1513 if (gs1 != gs2 ||
1513 ULONG_CMP_LT(j, js) || 1514 ULONG_CMP_LT(j, js) ||
1514 ULONG_CMP_GE(gps, js)) 1515 ULONG_CMP_GE(gps, js))
1515 return; /* No stall or GP completed since entering function. */ 1516 return; /* No stall or GP completed since entering function. */
@@ -1527,7 +1528,7 @@ static void check_cpu_stall(struct rcu_state *rsp, struct rcu_data *rdp)
1527 cmpxchg(&rsp->jiffies_stall, js, jn) == js) { 1528 cmpxchg(&rsp->jiffies_stall, js, jn) == js) {
1528 1529
1529 /* They had a few time units to dump stack, so complain. */ 1530 /* They had a few time units to dump stack, so complain. */
1530 print_other_cpu_stall(rsp, gpnum); 1531 print_other_cpu_stall(rsp, gs2);
1531 } 1532 }
1532} 1533}
1533 1534