diff options
| -rw-r--r-- | kernel/rcu/tree.c | 51 |
1 files changed, 32 insertions, 19 deletions
diff --git a/kernel/rcu/tree.c b/kernel/rcu/tree.c index 0aeddc908181..5643c135fb06 100644 --- a/kernel/rcu/tree.c +++ b/kernel/rcu/tree.c | |||
| @@ -1702,6 +1702,34 @@ static bool rcu_accelerate_cbs(struct rcu_state *rsp, struct rcu_node *rnp, | |||
| 1702 | } | 1702 | } |
| 1703 | 1703 | ||
| 1704 | /* | 1704 | /* |
| 1705 | * Similar to rcu_accelerate_cbs(), but does not require that the leaf | ||
| 1706 | * rcu_node structure's ->lock be held. It consults the cached value | ||
| 1707 | * of ->gp_seq_needed in the rcu_data structure, and if that indicates | ||
| 1708 | * that a new grace-period request be made, invokes rcu_accelerate_cbs() | ||
| 1709 | * while holding the leaf rcu_node structure's ->lock. | ||
| 1710 | */ | ||
| 1711 | static void rcu_accelerate_cbs_unlocked(struct rcu_state *rsp, | ||
| 1712 | struct rcu_node *rnp, | ||
| 1713 | struct rcu_data *rdp) | ||
| 1714 | { | ||
| 1715 | unsigned long c; | ||
| 1716 | bool needwake; | ||
| 1717 | |||
| 1718 | lockdep_assert_irqs_disabled(); | ||
| 1719 | c = rcu_seq_snap(&rsp->gp_seq); | ||
| 1720 | if (!rdp->gpwrap && ULONG_CMP_GE(rdp->gp_seq_needed, c)) { | ||
| 1721 | /* Old request still live, so mark recent callbacks. */ | ||
| 1722 | (void)rcu_segcblist_accelerate(&rdp->cblist, c); | ||
| 1723 | return; | ||
| 1724 | } | ||
| 1725 | raw_spin_lock_rcu_node(rnp); /* irqs already disabled. */ | ||
| 1726 | needwake = rcu_accelerate_cbs(rsp, rnp, rdp); | ||
| 1727 | raw_spin_unlock_rcu_node(rnp); /* irqs remain disabled. */ | ||
| 1728 | if (needwake) | ||
| 1729 | rcu_gp_kthread_wake(rsp); | ||
| 1730 | } | ||
| 1731 | |||
| 1732 | /* | ||
| 1705 | * Move any callbacks whose grace period has completed to the | 1733 | * Move any callbacks whose grace period has completed to the |
| 1706 | * RCU_DONE_TAIL sublist, then compact the remaining sublists and | 1734 | * RCU_DONE_TAIL sublist, then compact the remaining sublists and |
| 1707 | * assign ->gp_seq numbers to any callbacks in the RCU_NEXT_TAIL | 1735 | * assign ->gp_seq numbers to any callbacks in the RCU_NEXT_TAIL |
| @@ -2739,7 +2767,6 @@ static void | |||
| 2739 | __rcu_process_callbacks(struct rcu_state *rsp) | 2767 | __rcu_process_callbacks(struct rcu_state *rsp) |
| 2740 | { | 2768 | { |
| 2741 | unsigned long flags; | 2769 | unsigned long flags; |
| 2742 | bool needwake; | ||
| 2743 | struct rcu_data *rdp = raw_cpu_ptr(rsp->rda); | 2770 | struct rcu_data *rdp = raw_cpu_ptr(rsp->rda); |
| 2744 | struct rcu_node *rnp = rdp->mynode; | 2771 | struct rcu_node *rnp = rdp->mynode; |
| 2745 | 2772 | ||
| @@ -2752,15 +2779,9 @@ __rcu_process_callbacks(struct rcu_state *rsp) | |||
| 2752 | if (!rcu_gp_in_progress(rsp) && | 2779 | if (!rcu_gp_in_progress(rsp) && |
| 2753 | rcu_segcblist_is_enabled(&rdp->cblist)) { | 2780 | rcu_segcblist_is_enabled(&rdp->cblist)) { |
| 2754 | local_irq_save(flags); | 2781 | local_irq_save(flags); |
| 2755 | if (rcu_segcblist_restempty(&rdp->cblist, RCU_NEXT_READY_TAIL)) { | 2782 | if (!rcu_segcblist_restempty(&rdp->cblist, RCU_NEXT_READY_TAIL)) |
| 2756 | local_irq_restore(flags); | 2783 | rcu_accelerate_cbs_unlocked(rsp, rnp, rdp); |
| 2757 | } else { | 2784 | local_irq_restore(flags); |
| 2758 | raw_spin_lock_rcu_node(rnp); /* irqs disabled. */ | ||
| 2759 | needwake = rcu_accelerate_cbs(rsp, rnp, rdp); | ||
| 2760 | raw_spin_unlock_irqrestore_rcu_node(rnp, flags); | ||
| 2761 | if (needwake) | ||
| 2762 | rcu_gp_kthread_wake(rsp); | ||
| 2763 | } | ||
| 2764 | } | 2785 | } |
| 2765 | 2786 | ||
| 2766 | rcu_check_gp_start_stall(rsp, rnp, rdp); | 2787 | rcu_check_gp_start_stall(rsp, rnp, rdp); |
| @@ -2818,8 +2839,6 @@ static void invoke_rcu_core(void) | |||
| 2818 | static void __call_rcu_core(struct rcu_state *rsp, struct rcu_data *rdp, | 2839 | static void __call_rcu_core(struct rcu_state *rsp, struct rcu_data *rdp, |
| 2819 | struct rcu_head *head, unsigned long flags) | 2840 | struct rcu_head *head, unsigned long flags) |
| 2820 | { | 2841 | { |
| 2821 | bool needwake; | ||
| 2822 | |||
| 2823 | /* | 2842 | /* |
| 2824 | * If called from an extended quiescent state, invoke the RCU | 2843 | * If called from an extended quiescent state, invoke the RCU |
| 2825 | * core in order to force a re-evaluation of RCU's idleness. | 2844 | * core in order to force a re-evaluation of RCU's idleness. |
| @@ -2846,13 +2865,7 @@ static void __call_rcu_core(struct rcu_state *rsp, struct rcu_data *rdp, | |||
| 2846 | 2865 | ||
| 2847 | /* Start a new grace period if one not already started. */ | 2866 | /* Start a new grace period if one not already started. */ |
| 2848 | if (!rcu_gp_in_progress(rsp)) { | 2867 | if (!rcu_gp_in_progress(rsp)) { |
| 2849 | struct rcu_node *rnp = rdp->mynode; | 2868 | rcu_accelerate_cbs_unlocked(rsp, rdp->mynode, rdp); |
| 2850 | |||
| 2851 | raw_spin_lock_rcu_node(rnp); | ||
| 2852 | needwake = rcu_accelerate_cbs(rsp, rnp, rdp); | ||
| 2853 | raw_spin_unlock_rcu_node(rnp); | ||
| 2854 | if (needwake) | ||
| 2855 | rcu_gp_kthread_wake(rsp); | ||
| 2856 | } else { | 2869 | } else { |
| 2857 | /* Give the grace period a kick. */ | 2870 | /* Give the grace period a kick. */ |
| 2858 | rdp->blimit = LONG_MAX; | 2871 | rdp->blimit = LONG_MAX; |
