diff options
Diffstat (limited to 'kernel/rcutree.c')
-rw-r--r-- | kernel/rcutree.c | 105 |
1 files changed, 38 insertions, 67 deletions
diff --git a/kernel/rcutree.c b/kernel/rcutree.c index 6b11b07cfe7f..52b06f6e158c 100644 --- a/kernel/rcutree.c +++ b/kernel/rcutree.c | |||
@@ -25,7 +25,7 @@ | |||
25 | * and inputs from Rusty Russell, Andrea Arcangeli and Andi Kleen. | 25 | * and inputs from Rusty Russell, Andrea Arcangeli and Andi Kleen. |
26 | * | 26 | * |
27 | * For detailed explanation of Read-Copy Update mechanism see - | 27 | * For detailed explanation of Read-Copy Update mechanism see - |
28 | * Documentation/RCU | 28 | * Documentation/RCU |
29 | */ | 29 | */ |
30 | #include <linux/types.h> | 30 | #include <linux/types.h> |
31 | #include <linux/kernel.h> | 31 | #include <linux/kernel.h> |
@@ -107,27 +107,23 @@ static void __cpuinit rcu_init_percpu_data(int cpu, struct rcu_state *rsp, | |||
107 | */ | 107 | */ |
108 | void rcu_sched_qs(int cpu) | 108 | void rcu_sched_qs(int cpu) |
109 | { | 109 | { |
110 | unsigned long flags; | ||
111 | struct rcu_data *rdp; | 110 | struct rcu_data *rdp; |
112 | 111 | ||
113 | local_irq_save(flags); | ||
114 | rdp = &per_cpu(rcu_sched_data, cpu); | 112 | rdp = &per_cpu(rcu_sched_data, cpu); |
115 | rdp->passed_quiesc = 1; | ||
116 | rdp->passed_quiesc_completed = rdp->completed; | 113 | rdp->passed_quiesc_completed = rdp->completed; |
117 | rcu_preempt_qs(cpu); | 114 | barrier(); |
118 | local_irq_restore(flags); | 115 | rdp->passed_quiesc = 1; |
116 | rcu_preempt_note_context_switch(cpu); | ||
119 | } | 117 | } |
120 | 118 | ||
121 | void rcu_bh_qs(int cpu) | 119 | void rcu_bh_qs(int cpu) |
122 | { | 120 | { |
123 | unsigned long flags; | ||
124 | struct rcu_data *rdp; | 121 | struct rcu_data *rdp; |
125 | 122 | ||
126 | local_irq_save(flags); | ||
127 | rdp = &per_cpu(rcu_bh_data, cpu); | 123 | rdp = &per_cpu(rcu_bh_data, cpu); |
128 | rdp->passed_quiesc = 1; | ||
129 | rdp->passed_quiesc_completed = rdp->completed; | 124 | rdp->passed_quiesc_completed = rdp->completed; |
130 | local_irq_restore(flags); | 125 | barrier(); |
126 | rdp->passed_quiesc = 1; | ||
131 | } | 127 | } |
132 | 128 | ||
133 | #ifdef CONFIG_NO_HZ | 129 | #ifdef CONFIG_NO_HZ |
@@ -605,8 +601,6 @@ rcu_start_gp(struct rcu_state *rsp, unsigned long flags) | |||
605 | { | 601 | { |
606 | struct rcu_data *rdp = rsp->rda[smp_processor_id()]; | 602 | struct rcu_data *rdp = rsp->rda[smp_processor_id()]; |
607 | struct rcu_node *rnp = rcu_get_root(rsp); | 603 | struct rcu_node *rnp = rcu_get_root(rsp); |
608 | struct rcu_node *rnp_cur; | ||
609 | struct rcu_node *rnp_end; | ||
610 | 604 | ||
611 | if (!cpu_needs_another_gp(rsp, rdp)) { | 605 | if (!cpu_needs_another_gp(rsp, rdp)) { |
612 | spin_unlock_irqrestore(&rnp->lock, flags); | 606 | spin_unlock_irqrestore(&rnp->lock, flags); |
@@ -615,6 +609,7 @@ rcu_start_gp(struct rcu_state *rsp, unsigned long flags) | |||
615 | 609 | ||
616 | /* Advance to a new grace period and initialize state. */ | 610 | /* Advance to a new grace period and initialize state. */ |
617 | rsp->gpnum++; | 611 | rsp->gpnum++; |
612 | WARN_ON_ONCE(rsp->signaled == RCU_GP_INIT); | ||
618 | rsp->signaled = RCU_GP_INIT; /* Hold off force_quiescent_state. */ | 613 | rsp->signaled = RCU_GP_INIT; /* Hold off force_quiescent_state. */ |
619 | rsp->jiffies_force_qs = jiffies + RCU_JIFFIES_TILL_FORCE_QS; | 614 | rsp->jiffies_force_qs = jiffies + RCU_JIFFIES_TILL_FORCE_QS; |
620 | record_gp_stall_check_time(rsp); | 615 | record_gp_stall_check_time(rsp); |
@@ -631,7 +626,9 @@ rcu_start_gp(struct rcu_state *rsp, unsigned long flags) | |||
631 | 626 | ||
632 | /* Special-case the common single-level case. */ | 627 | /* Special-case the common single-level case. */ |
633 | if (NUM_RCU_NODES == 1) { | 628 | if (NUM_RCU_NODES == 1) { |
629 | rcu_preempt_check_blocked_tasks(rnp); | ||
634 | rnp->qsmask = rnp->qsmaskinit; | 630 | rnp->qsmask = rnp->qsmaskinit; |
631 | rnp->gpnum = rsp->gpnum; | ||
635 | rsp->signaled = RCU_SIGNAL_INIT; /* force_quiescent_state OK. */ | 632 | rsp->signaled = RCU_SIGNAL_INIT; /* force_quiescent_state OK. */ |
636 | spin_unlock_irqrestore(&rnp->lock, flags); | 633 | spin_unlock_irqrestore(&rnp->lock, flags); |
637 | return; | 634 | return; |
@@ -644,42 +641,28 @@ rcu_start_gp(struct rcu_state *rsp, unsigned long flags) | |||
644 | spin_lock(&rsp->onofflock); /* irqs already disabled. */ | 641 | spin_lock(&rsp->onofflock); /* irqs already disabled. */ |
645 | 642 | ||
646 | /* | 643 | /* |
647 | * Set the quiescent-state-needed bits in all the non-leaf RCU | 644 | * Set the quiescent-state-needed bits in all the rcu_node |
648 | * nodes for all currently online CPUs. This operation relies | 645 | * structures for all currently online CPUs in breadth-first |
649 | * on the layout of the hierarchy within the rsp->node[] array. | 646 | * order, starting from the root rcu_node structure. This |
650 | * Note that other CPUs will access only the leaves of the | 647 | * operation relies on the layout of the hierarchy within the |
651 | * hierarchy, which still indicate that no grace period is in | 648 | * rsp->node[] array. Note that other CPUs will access only |
652 | * progress. In addition, we have excluded CPU-hotplug operations. | 649 | * the leaves of the hierarchy, which still indicate that no |
653 | * | 650 | * grace period is in progress, at least until the corresponding |
654 | * We therefore do not need to hold any locks. Any required | 651 | * leaf node has been initialized. In addition, we have excluded |
655 | * memory barriers will be supplied by the locks guarding the | 652 | * CPU-hotplug operations. |
656 | * leaf rcu_nodes in the hierarchy. | ||
657 | */ | ||
658 | |||
659 | rnp_end = rsp->level[NUM_RCU_LVLS - 1]; | ||
660 | for (rnp_cur = &rsp->node[0]; rnp_cur < rnp_end; rnp_cur++) | ||
661 | rnp_cur->qsmask = rnp_cur->qsmaskinit; | ||
662 | |||
663 | /* | ||
664 | * Now set up the leaf nodes. Here we must be careful. First, | ||
665 | * we need to hold the lock in order to exclude other CPUs, which | ||
666 | * might be contending for the leaf nodes' locks. Second, as | ||
667 | * soon as we initialize a given leaf node, its CPUs might run | ||
668 | * up the rest of the hierarchy. We must therefore acquire locks | ||
669 | * for each node that we touch during this stage. (But we still | ||
670 | * are excluding CPU-hotplug operations.) | ||
671 | * | 653 | * |
672 | * Note that the grace period cannot complete until we finish | 654 | * Note that the grace period cannot complete until we finish |
673 | * the initialization process, as there will be at least one | 655 | * the initialization process, as there will be at least one |
674 | * qsmask bit set in the root node until that time, namely the | 656 | * qsmask bit set in the root node until that time, namely the |
675 | * one corresponding to this CPU. | 657 | * one corresponding to this CPU, due to the fact that we have |
658 | * irqs disabled. | ||
676 | */ | 659 | */ |
677 | rnp_end = &rsp->node[NUM_RCU_NODES]; | 660 | for (rnp = &rsp->node[0]; rnp < &rsp->node[NUM_RCU_NODES]; rnp++) { |
678 | rnp_cur = rsp->level[NUM_RCU_LVLS - 1]; | 661 | spin_lock(&rnp->lock); /* irqs already disabled. */ |
679 | for (; rnp_cur < rnp_end; rnp_cur++) { | 662 | rcu_preempt_check_blocked_tasks(rnp); |
680 | spin_lock(&rnp_cur->lock); /* irqs already disabled. */ | 663 | rnp->qsmask = rnp->qsmaskinit; |
681 | rnp_cur->qsmask = rnp_cur->qsmaskinit; | 664 | rnp->gpnum = rsp->gpnum; |
682 | spin_unlock(&rnp_cur->lock); /* irqs already disabled. */ | 665 | spin_unlock(&rnp->lock); /* irqs already disabled. */ |
683 | } | 666 | } |
684 | 667 | ||
685 | rsp->signaled = RCU_SIGNAL_INIT; /* force_quiescent_state now OK. */ | 668 | rsp->signaled = RCU_SIGNAL_INIT; /* force_quiescent_state now OK. */ |
@@ -722,6 +705,7 @@ rcu_process_gp_end(struct rcu_state *rsp, struct rcu_data *rdp) | |||
722 | static void cpu_quiet_msk_finish(struct rcu_state *rsp, unsigned long flags) | 705 | static void cpu_quiet_msk_finish(struct rcu_state *rsp, unsigned long flags) |
723 | __releases(rnp->lock) | 706 | __releases(rnp->lock) |
724 | { | 707 | { |
708 | WARN_ON_ONCE(rsp->completed == rsp->gpnum); | ||
725 | rsp->completed = rsp->gpnum; | 709 | rsp->completed = rsp->gpnum; |
726 | rcu_process_gp_end(rsp, rsp->rda[smp_processor_id()]); | 710 | rcu_process_gp_end(rsp, rsp->rda[smp_processor_id()]); |
727 | rcu_start_gp(rsp, flags); /* releases root node's rnp->lock. */ | 711 | rcu_start_gp(rsp, flags); /* releases root node's rnp->lock. */ |
@@ -739,6 +723,8 @@ cpu_quiet_msk(unsigned long mask, struct rcu_state *rsp, struct rcu_node *rnp, | |||
739 | unsigned long flags) | 723 | unsigned long flags) |
740 | __releases(rnp->lock) | 724 | __releases(rnp->lock) |
741 | { | 725 | { |
726 | struct rcu_node *rnp_c; | ||
727 | |||
742 | /* Walk up the rcu_node hierarchy. */ | 728 | /* Walk up the rcu_node hierarchy. */ |
743 | for (;;) { | 729 | for (;;) { |
744 | if (!(rnp->qsmask & mask)) { | 730 | if (!(rnp->qsmask & mask)) { |
@@ -762,8 +748,10 @@ cpu_quiet_msk(unsigned long mask, struct rcu_state *rsp, struct rcu_node *rnp, | |||
762 | break; | 748 | break; |
763 | } | 749 | } |
764 | spin_unlock_irqrestore(&rnp->lock, flags); | 750 | spin_unlock_irqrestore(&rnp->lock, flags); |
751 | rnp_c = rnp; | ||
765 | rnp = rnp->parent; | 752 | rnp = rnp->parent; |
766 | spin_lock_irqsave(&rnp->lock, flags); | 753 | spin_lock_irqsave(&rnp->lock, flags); |
754 | WARN_ON_ONCE(rnp_c->qsmask); | ||
767 | } | 755 | } |
768 | 756 | ||
769 | /* | 757 | /* |
@@ -776,10 +764,10 @@ cpu_quiet_msk(unsigned long mask, struct rcu_state *rsp, struct rcu_node *rnp, | |||
776 | 764 | ||
777 | /* | 765 | /* |
778 | * Record a quiescent state for the specified CPU, which must either be | 766 | * Record a quiescent state for the specified CPU, which must either be |
779 | * the current CPU or an offline CPU. The lastcomp argument is used to | 767 | * the current CPU. The lastcomp argument is used to make sure we are |
780 | * make sure we are still in the grace period of interest. We don't want | 768 | * still in the grace period of interest. We don't want to end the current |
781 | * to end the current grace period based on quiescent states detected in | 769 | * grace period based on quiescent states detected in an earlier grace |
782 | * an earlier grace period! | 770 | * period! |
783 | */ | 771 | */ |
784 | static void | 772 | static void |
785 | cpu_quiet(int cpu, struct rcu_state *rsp, struct rcu_data *rdp, long lastcomp) | 773 | cpu_quiet(int cpu, struct rcu_state *rsp, struct rcu_data *rdp, long lastcomp) |
@@ -814,7 +802,6 @@ cpu_quiet(int cpu, struct rcu_state *rsp, struct rcu_data *rdp, long lastcomp) | |||
814 | * This GP can't end until cpu checks in, so all of our | 802 | * This GP can't end until cpu checks in, so all of our |
815 | * callbacks can be processed during the next GP. | 803 | * callbacks can be processed during the next GP. |
816 | */ | 804 | */ |
817 | rdp = rsp->rda[smp_processor_id()]; | ||
818 | rdp->nxttail[RCU_NEXT_READY_TAIL] = rdp->nxttail[RCU_NEXT_TAIL]; | 805 | rdp->nxttail[RCU_NEXT_READY_TAIL] = rdp->nxttail[RCU_NEXT_TAIL]; |
819 | 806 | ||
820 | cpu_quiet_msk(mask, rsp, rnp, flags); /* releases rnp->lock */ | 807 | cpu_quiet_msk(mask, rsp, rnp, flags); /* releases rnp->lock */ |
@@ -872,7 +859,7 @@ static void __rcu_offline_cpu(int cpu, struct rcu_state *rsp) | |||
872 | spin_lock_irqsave(&rsp->onofflock, flags); | 859 | spin_lock_irqsave(&rsp->onofflock, flags); |
873 | 860 | ||
874 | /* Remove the outgoing CPU from the masks in the rcu_node hierarchy. */ | 861 | /* Remove the outgoing CPU from the masks in the rcu_node hierarchy. */ |
875 | rnp = rdp->mynode; | 862 | rnp = rdp->mynode; /* this is the outgoing CPU's rnp. */ |
876 | mask = rdp->grpmask; /* rnp->grplo is constant. */ | 863 | mask = rdp->grpmask; /* rnp->grplo is constant. */ |
877 | do { | 864 | do { |
878 | spin_lock(&rnp->lock); /* irqs already disabled. */ | 865 | spin_lock(&rnp->lock); /* irqs already disabled. */ |
@@ -881,7 +868,7 @@ static void __rcu_offline_cpu(int cpu, struct rcu_state *rsp) | |||
881 | spin_unlock(&rnp->lock); /* irqs remain disabled. */ | 868 | spin_unlock(&rnp->lock); /* irqs remain disabled. */ |
882 | break; | 869 | break; |
883 | } | 870 | } |
884 | rcu_preempt_offline_tasks(rsp, rnp); | 871 | rcu_preempt_offline_tasks(rsp, rnp, rdp); |
885 | mask = rnp->grpmask; | 872 | mask = rnp->grpmask; |
886 | spin_unlock(&rnp->lock); /* irqs remain disabled. */ | 873 | spin_unlock(&rnp->lock); /* irqs remain disabled. */ |
887 | rnp = rnp->parent; | 874 | rnp = rnp->parent; |
@@ -890,9 +877,6 @@ static void __rcu_offline_cpu(int cpu, struct rcu_state *rsp) | |||
890 | 877 | ||
891 | spin_unlock(&rsp->onofflock); /* irqs remain disabled. */ | 878 | spin_unlock(&rsp->onofflock); /* irqs remain disabled. */ |
892 | 879 | ||
893 | /* Being offline is a quiescent state, so go record it. */ | ||
894 | cpu_quiet(cpu, rsp, rdp, lastcomp); | ||
895 | |||
896 | /* | 880 | /* |
897 | * Move callbacks from the outgoing CPU to the running CPU. | 881 | * Move callbacks from the outgoing CPU to the running CPU. |
898 | * Note that the outgoing CPU is now quiscent, so it is now | 882 | * Note that the outgoing CPU is now quiscent, so it is now |
@@ -1457,20 +1441,7 @@ rcu_init_percpu_data(int cpu, struct rcu_state *rsp, int preemptable) | |||
1457 | rnp = rnp->parent; | 1441 | rnp = rnp->parent; |
1458 | } while (rnp != NULL && !(rnp->qsmaskinit & mask)); | 1442 | } while (rnp != NULL && !(rnp->qsmaskinit & mask)); |
1459 | 1443 | ||
1460 | spin_unlock(&rsp->onofflock); /* irqs remain disabled. */ | 1444 | spin_unlock_irqrestore(&rsp->onofflock, flags); |
1461 | |||
1462 | /* | ||
1463 | * A new grace period might start here. If so, we will be part of | ||
1464 | * it, and its gpnum will be greater than ours, so we will | ||
1465 | * participate. It is also possible for the gpnum to have been | ||
1466 | * incremented before this function was called, and the bitmasks | ||
1467 | * to not be filled out until now, in which case we will also | ||
1468 | * participate due to our gpnum being behind. | ||
1469 | */ | ||
1470 | |||
1471 | /* Since it is coming online, the CPU is in a quiescent state. */ | ||
1472 | cpu_quiet(cpu, rsp, rdp, lastcomp); | ||
1473 | local_irq_restore(flags); | ||
1474 | } | 1445 | } |
1475 | 1446 | ||
1476 | static void __cpuinit rcu_online_cpu(int cpu) | 1447 | static void __cpuinit rcu_online_cpu(int cpu) |