diff options
Diffstat (limited to 'kernel/rcu/tree.c')
| -rw-r--r-- | kernel/rcu/tree.c | 100 |
1 files changed, 81 insertions, 19 deletions
diff --git a/kernel/rcu/tree.c b/kernel/rcu/tree.c index aa7cade1b9f3..a9a4a260ea7d 100644 --- a/kernel/rcu/tree.c +++ b/kernel/rcu/tree.c | |||
| @@ -1368,7 +1368,6 @@ static inline void panic_on_rcu_stall(void) | |||
| 1368 | static void print_other_cpu_stall(struct rcu_state *rsp, unsigned long gpnum) | 1368 | static void print_other_cpu_stall(struct rcu_state *rsp, unsigned long gpnum) |
| 1369 | { | 1369 | { |
| 1370 | int cpu; | 1370 | int cpu; |
| 1371 | long delta; | ||
| 1372 | unsigned long flags; | 1371 | unsigned long flags; |
| 1373 | unsigned long gpa; | 1372 | unsigned long gpa; |
| 1374 | unsigned long j; | 1373 | unsigned long j; |
| @@ -1381,18 +1380,6 @@ static void print_other_cpu_stall(struct rcu_state *rsp, unsigned long gpnum) | |||
| 1381 | if (rcu_cpu_stall_suppress) | 1380 | if (rcu_cpu_stall_suppress) |
| 1382 | return; | 1381 | return; |
| 1383 | 1382 | ||
| 1384 | /* Only let one CPU complain about others per time interval. */ | ||
| 1385 | |||
| 1386 | raw_spin_lock_irqsave_rcu_node(rnp, flags); | ||
| 1387 | delta = jiffies - READ_ONCE(rsp->jiffies_stall); | ||
| 1388 | if (delta < RCU_STALL_RAT_DELAY || !rcu_gp_in_progress(rsp)) { | ||
| 1389 | raw_spin_unlock_irqrestore_rcu_node(rnp, flags); | ||
| 1390 | return; | ||
| 1391 | } | ||
| 1392 | WRITE_ONCE(rsp->jiffies_stall, | ||
| 1393 | jiffies + 3 * rcu_jiffies_till_stall_check() + 3); | ||
| 1394 | raw_spin_unlock_irqrestore_rcu_node(rnp, flags); | ||
| 1395 | |||
| 1396 | /* | 1383 | /* |
| 1397 | * OK, time to rat on our buddy... | 1384 | * OK, time to rat on our buddy... |
| 1398 | * See Documentation/RCU/stallwarn.txt for info on how to debug | 1385 | * See Documentation/RCU/stallwarn.txt for info on how to debug |
| @@ -1441,6 +1428,10 @@ static void print_other_cpu_stall(struct rcu_state *rsp, unsigned long gpnum) | |||
| 1441 | sched_show_task(current); | 1428 | sched_show_task(current); |
| 1442 | } | 1429 | } |
| 1443 | } | 1430 | } |
| 1431 | /* Rewrite if needed in case of slow consoles. */ | ||
| 1432 | if (ULONG_CMP_GE(jiffies, READ_ONCE(rsp->jiffies_stall))) | ||
| 1433 | WRITE_ONCE(rsp->jiffies_stall, | ||
| 1434 | jiffies + 3 * rcu_jiffies_till_stall_check() + 3); | ||
| 1444 | 1435 | ||
| 1445 | rcu_check_gp_kthread_starvation(rsp); | 1436 | rcu_check_gp_kthread_starvation(rsp); |
| 1446 | 1437 | ||
| @@ -1485,6 +1476,7 @@ static void print_cpu_stall(struct rcu_state *rsp) | |||
| 1485 | rcu_dump_cpu_stacks(rsp); | 1476 | rcu_dump_cpu_stacks(rsp); |
| 1486 | 1477 | ||
| 1487 | raw_spin_lock_irqsave_rcu_node(rnp, flags); | 1478 | raw_spin_lock_irqsave_rcu_node(rnp, flags); |
| 1479 | /* Rewrite if needed in case of slow consoles. */ | ||
| 1488 | if (ULONG_CMP_GE(jiffies, READ_ONCE(rsp->jiffies_stall))) | 1480 | if (ULONG_CMP_GE(jiffies, READ_ONCE(rsp->jiffies_stall))) |
| 1489 | WRITE_ONCE(rsp->jiffies_stall, | 1481 | WRITE_ONCE(rsp->jiffies_stall, |
| 1490 | jiffies + 3 * rcu_jiffies_till_stall_check() + 3); | 1482 | jiffies + 3 * rcu_jiffies_till_stall_check() + 3); |
| @@ -1508,6 +1500,7 @@ static void check_cpu_stall(struct rcu_state *rsp, struct rcu_data *rdp) | |||
| 1508 | unsigned long gpnum; | 1500 | unsigned long gpnum; |
| 1509 | unsigned long gps; | 1501 | unsigned long gps; |
| 1510 | unsigned long j; | 1502 | unsigned long j; |
| 1503 | unsigned long jn; | ||
| 1511 | unsigned long js; | 1504 | unsigned long js; |
| 1512 | struct rcu_node *rnp; | 1505 | struct rcu_node *rnp; |
| 1513 | 1506 | ||
| @@ -1546,14 +1539,17 @@ static void check_cpu_stall(struct rcu_state *rsp, struct rcu_data *rdp) | |||
| 1546 | ULONG_CMP_GE(gps, js)) | 1539 | ULONG_CMP_GE(gps, js)) |
| 1547 | return; /* No stall or GP completed since entering function. */ | 1540 | return; /* No stall or GP completed since entering function. */ |
| 1548 | rnp = rdp->mynode; | 1541 | rnp = rdp->mynode; |
| 1542 | jn = jiffies + 3 * rcu_jiffies_till_stall_check() + 3; | ||
| 1549 | if (rcu_gp_in_progress(rsp) && | 1543 | if (rcu_gp_in_progress(rsp) && |
| 1550 | (READ_ONCE(rnp->qsmask) & rdp->grpmask)) { | 1544 | (READ_ONCE(rnp->qsmask) & rdp->grpmask) && |
| 1545 | cmpxchg(&rsp->jiffies_stall, js, jn) == js) { | ||
| 1551 | 1546 | ||
| 1552 | /* We haven't checked in, so go dump stack. */ | 1547 | /* We haven't checked in, so go dump stack. */ |
| 1553 | print_cpu_stall(rsp); | 1548 | print_cpu_stall(rsp); |
| 1554 | 1549 | ||
| 1555 | } else if (rcu_gp_in_progress(rsp) && | 1550 | } else if (rcu_gp_in_progress(rsp) && |
| 1556 | ULONG_CMP_GE(j, js + RCU_STALL_RAT_DELAY)) { | 1551 | ULONG_CMP_GE(j, js + RCU_STALL_RAT_DELAY) && |
| 1552 | cmpxchg(&rsp->jiffies_stall, js, jn) == js) { | ||
| 1557 | 1553 | ||
| 1558 | /* They had a few time units to dump stack, so complain. */ | 1554 | /* They had a few time units to dump stack, so complain. */ |
| 1559 | print_other_cpu_stall(rsp, gpnum); | 1555 | print_other_cpu_stall(rsp, gpnum); |
| @@ -1685,6 +1681,7 @@ static bool rcu_start_this_gp(struct rcu_node *rnp, struct rcu_data *rdp, | |||
| 1685 | } | 1681 | } |
| 1686 | trace_rcu_this_gp(rnp_root, rdp, c, TPS("Startedroot")); | 1682 | trace_rcu_this_gp(rnp_root, rdp, c, TPS("Startedroot")); |
| 1687 | WRITE_ONCE(rsp->gp_flags, rsp->gp_flags | RCU_GP_FLAG_INIT); | 1683 | WRITE_ONCE(rsp->gp_flags, rsp->gp_flags | RCU_GP_FLAG_INIT); |
| 1684 | rsp->gp_req_activity = jiffies; | ||
| 1688 | if (!rsp->gp_kthread) { | 1685 | if (!rsp->gp_kthread) { |
| 1689 | trace_rcu_this_gp(rnp_root, rdp, c, TPS("NoGPkthread")); | 1686 | trace_rcu_this_gp(rnp_root, rdp, c, TPS("NoGPkthread")); |
| 1690 | goto unlock_out; | 1687 | goto unlock_out; |
| @@ -2084,7 +2081,8 @@ static void rcu_gp_cleanup(struct rcu_state *rsp) | |||
| 2084 | */ | 2081 | */ |
| 2085 | rcu_for_each_node_breadth_first(rsp, rnp) { | 2082 | rcu_for_each_node_breadth_first(rsp, rnp) { |
| 2086 | raw_spin_lock_irq_rcu_node(rnp); | 2083 | raw_spin_lock_irq_rcu_node(rnp); |
| 2087 | WARN_ON_ONCE(rcu_preempt_blocked_readers_cgp(rnp)); | 2084 | if (WARN_ON_ONCE(rcu_preempt_blocked_readers_cgp(rnp))) |
| 2085 | dump_blkd_tasks(rnp, 10); | ||
| 2088 | WARN_ON_ONCE(rnp->qsmask); | 2086 | WARN_ON_ONCE(rnp->qsmask); |
| 2089 | WRITE_ONCE(rnp->completed, rsp->gpnum); | 2087 | WRITE_ONCE(rnp->completed, rsp->gpnum); |
| 2090 | rdp = this_cpu_ptr(rsp->rda); | 2088 | rdp = this_cpu_ptr(rsp->rda); |
| @@ -2116,10 +2114,12 @@ static void rcu_gp_cleanup(struct rcu_state *rsp) | |||
| 2116 | /* Advance CBs to reduce false positives below. */ | 2114 | /* Advance CBs to reduce false positives below. */ |
| 2117 | if (!rcu_accelerate_cbs(rsp, rnp, rdp) && needgp) { | 2115 | if (!rcu_accelerate_cbs(rsp, rnp, rdp) && needgp) { |
| 2118 | WRITE_ONCE(rsp->gp_flags, RCU_GP_FLAG_INIT); | 2116 | WRITE_ONCE(rsp->gp_flags, RCU_GP_FLAG_INIT); |
| 2117 | rsp->gp_req_activity = jiffies; | ||
| 2119 | trace_rcu_grace_period(rsp->name, READ_ONCE(rsp->gpnum), | 2118 | trace_rcu_grace_period(rsp->name, READ_ONCE(rsp->gpnum), |
| 2120 | TPS("newreq")); | 2119 | TPS("newreq")); |
| 2120 | } else { | ||
| 2121 | WRITE_ONCE(rsp->gp_flags, rsp->gp_flags & RCU_GP_FLAG_INIT); | ||
| 2121 | } | 2122 | } |
| 2122 | WRITE_ONCE(rsp->gp_flags, rsp->gp_flags & RCU_GP_FLAG_INIT); | ||
| 2123 | raw_spin_unlock_irq_rcu_node(rnp); | 2123 | raw_spin_unlock_irq_rcu_node(rnp); |
| 2124 | } | 2124 | } |
| 2125 | 2125 | ||
| @@ -2294,6 +2294,7 @@ rcu_report_qs_rnp(unsigned long mask, struct rcu_state *rsp, | |||
| 2294 | raw_spin_unlock_irqrestore_rcu_node(rnp, flags); | 2294 | raw_spin_unlock_irqrestore_rcu_node(rnp, flags); |
| 2295 | return; | 2295 | return; |
| 2296 | } | 2296 | } |
| 2297 | rnp->completedqs = rnp->gpnum; | ||
| 2297 | mask = rnp->grpmask; | 2298 | mask = rnp->grpmask; |
| 2298 | if (rnp->parent == NULL) { | 2299 | if (rnp->parent == NULL) { |
| 2299 | 2300 | ||
| @@ -2747,6 +2748,65 @@ static void force_quiescent_state(struct rcu_state *rsp) | |||
| 2747 | } | 2748 | } |
| 2748 | 2749 | ||
| 2749 | /* | 2750 | /* |
| 2751 | * This function checks for grace-period requests that fail to motivate | ||
| 2752 | * RCU to come out of its idle mode. | ||
| 2753 | */ | ||
| 2754 | static void | ||
| 2755 | rcu_check_gp_start_stall(struct rcu_state *rsp, struct rcu_node *rnp, | ||
| 2756 | struct rcu_data *rdp) | ||
| 2757 | { | ||
| 2758 | unsigned long flags; | ||
| 2759 | unsigned long j; | ||
| 2760 | struct rcu_node *rnp_root = rcu_get_root(rsp); | ||
| 2761 | static atomic_t warned = ATOMIC_INIT(0); | ||
| 2762 | |||
| 2763 | if (!IS_ENABLED(CONFIG_PROVE_RCU) || | ||
| 2764 | rcu_gp_in_progress(rsp) || !need_any_future_gp(rcu_get_root(rsp))) | ||
| 2765 | return; | ||
| 2766 | j = jiffies; /* Expensive access, and in common case don't get here. */ | ||
| 2767 | if (time_before(j, READ_ONCE(rsp->gp_req_activity) + HZ) || | ||
| 2768 | time_before(j, READ_ONCE(rsp->gp_activity) + HZ) || | ||
| 2769 | atomic_read(&warned)) | ||
| 2770 | return; | ||
| 2771 | |||
| 2772 | raw_spin_lock_irqsave_rcu_node(rnp, flags); | ||
| 2773 | j = jiffies; | ||
| 2774 | if (rcu_gp_in_progress(rsp) || !need_any_future_gp(rcu_get_root(rsp)) || | ||
| 2775 | time_before(j, READ_ONCE(rsp->gp_req_activity) + HZ) || | ||
| 2776 | time_before(j, READ_ONCE(rsp->gp_activity) + HZ) || | ||
| 2777 | atomic_read(&warned)) { | ||
| 2778 | raw_spin_unlock_irqrestore_rcu_node(rnp, flags); | ||
| 2779 | return; | ||
| 2780 | } | ||
| 2781 | /* Hold onto the leaf lock to make others see warned==1. */ | ||
| 2782 | |||
| 2783 | if (rnp_root != rnp) | ||
| 2784 | raw_spin_lock_rcu_node(rnp_root); /* irqs already disabled. */ | ||
| 2785 | j = jiffies; | ||
| 2786 | if (rcu_gp_in_progress(rsp) || !need_any_future_gp(rcu_get_root(rsp)) || | ||
| 2787 | time_before(j, rsp->gp_req_activity + HZ) || | ||
| 2788 | time_before(j, rsp->gp_activity + HZ) || | ||
| 2789 | atomic_xchg(&warned, 1)) { | ||
| 2790 | raw_spin_unlock_rcu_node(rnp_root); /* irqs remain disabled. */ | ||
| 2791 | raw_spin_unlock_irqrestore_rcu_node(rnp, flags); | ||
| 2792 | return; | ||
| 2793 | } | ||
| 2794 | pr_alert("%s: g%lu %d%d%d%d gar:%lu ga:%lu f%#x %s->state:%#lx\n", | ||
| 2795 | __func__, READ_ONCE(rsp->gpnum), | ||
| 2796 | need_future_gp_element(rcu_get_root(rsp), 0), | ||
| 2797 | need_future_gp_element(rcu_get_root(rsp), 1), | ||
| 2798 | need_future_gp_element(rcu_get_root(rsp), 2), | ||
| 2799 | need_future_gp_element(rcu_get_root(rsp), 3), | ||
| 2800 | j - rsp->gp_req_activity, j - rsp->gp_activity, | ||
| 2801 | rsp->gp_flags, rsp->name, | ||
| 2802 | rsp->gp_kthread ? rsp->gp_kthread->state : 0x1ffffL); | ||
| 2803 | WARN_ON(1); | ||
| 2804 | if (rnp_root != rnp) | ||
| 2805 | raw_spin_unlock_rcu_node(rnp_root); | ||
| 2806 | raw_spin_unlock_irqrestore_rcu_node(rnp, flags); | ||
| 2807 | } | ||
| 2808 | |||
| 2809 | /* | ||
| 2750 | * This does the RCU core processing work for the specified rcu_state | 2810 | * This does the RCU core processing work for the specified rcu_state |
| 2751 | * and rcu_data structures. This may be called only from the CPU to | 2811 | * and rcu_data structures. This may be called only from the CPU to |
| 2752 | * whom the rdp belongs. | 2812 | * whom the rdp belongs. |
| @@ -2757,7 +2817,7 @@ __rcu_process_callbacks(struct rcu_state *rsp) | |||
| 2757 | unsigned long flags; | 2817 | unsigned long flags; |
| 2758 | bool needwake; | 2818 | bool needwake; |
| 2759 | struct rcu_data *rdp = raw_cpu_ptr(rsp->rda); | 2819 | struct rcu_data *rdp = raw_cpu_ptr(rsp->rda); |
| 2760 | struct rcu_node *rnp; | 2820 | struct rcu_node *rnp = rdp->mynode; |
| 2761 | 2821 | ||
| 2762 | WARN_ON_ONCE(!rdp->beenonline); | 2822 | WARN_ON_ONCE(!rdp->beenonline); |
| 2763 | 2823 | ||
| @@ -2771,7 +2831,6 @@ __rcu_process_callbacks(struct rcu_state *rsp) | |||
| 2771 | if (rcu_segcblist_restempty(&rdp->cblist, RCU_NEXT_READY_TAIL)) { | 2831 | if (rcu_segcblist_restempty(&rdp->cblist, RCU_NEXT_READY_TAIL)) { |
| 2772 | local_irq_restore(flags); | 2832 | local_irq_restore(flags); |
| 2773 | } else { | 2833 | } else { |
| 2774 | rnp = rdp->mynode; | ||
| 2775 | raw_spin_lock_rcu_node(rnp); /* irqs disabled. */ | 2834 | raw_spin_lock_rcu_node(rnp); /* irqs disabled. */ |
| 2776 | needwake = rcu_accelerate_cbs(rsp, rnp, rdp); | 2835 | needwake = rcu_accelerate_cbs(rsp, rnp, rdp); |
| 2777 | raw_spin_unlock_irqrestore_rcu_node(rnp, flags); | 2836 | raw_spin_unlock_irqrestore_rcu_node(rnp, flags); |
| @@ -2780,6 +2839,8 @@ __rcu_process_callbacks(struct rcu_state *rsp) | |||
| 2780 | } | 2839 | } |
| 2781 | } | 2840 | } |
| 2782 | 2841 | ||
| 2842 | rcu_check_gp_start_stall(rsp, rnp, rdp); | ||
| 2843 | |||
| 2783 | /* If there are callbacks ready, invoke them. */ | 2844 | /* If there are callbacks ready, invoke them. */ |
| 2784 | if (rcu_segcblist_ready_cbs(&rdp->cblist)) | 2845 | if (rcu_segcblist_ready_cbs(&rdp->cblist)) |
| 2785 | invoke_rcu_callbacks(rsp, rdp); | 2846 | invoke_rcu_callbacks(rsp, rdp); |
| @@ -3930,6 +3991,7 @@ static void __init rcu_init_one(struct rcu_state *rsp) | |||
| 3930 | &rcu_fqs_class[i], fqs[i]); | 3991 | &rcu_fqs_class[i], fqs[i]); |
| 3931 | rnp->gpnum = rsp->gpnum; | 3992 | rnp->gpnum = rsp->gpnum; |
| 3932 | rnp->completed = rsp->completed; | 3993 | rnp->completed = rsp->completed; |
| 3994 | rnp->completedqs = rsp->completed; | ||
| 3933 | rnp->qsmask = 0; | 3995 | rnp->qsmask = 0; |
| 3934 | rnp->qsmaskinit = 0; | 3996 | rnp->qsmaskinit = 0; |
| 3935 | rnp->grplo = j * cpustride; | 3997 | rnp->grplo = j * cpustride; |
