diff options
| author | Paul E. McKenney <paulmck@linux.vnet.ibm.com> | 2018-04-30 16:09:17 -0400 | 
|---|---|---|
| committer | Paul E. McKenney <paulmck@linux.vnet.ibm.com> | 2018-07-12 17:27:56 -0400 | 
| commit | 471f87c3d91bd0884451c0e3071473476c165630 (patch) | |
| tree | 98f4f3f50c68d24e2949a7f719b645610296f607 /kernel/rcu/tree.c | |
| parent | 29365e563b1e4e5bfde211280d37dc6127c019ed (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.c | 51 | 
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 | ||
| 1343 | static void print_other_cpu_stall(struct rcu_state *rsp, unsigned long gpnum) | 1343 | static 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 | ||
| 1472 | static void check_cpu_stall(struct rcu_state *rsp, struct rcu_data *rdp) | 1473 | static 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 | ||
