diff options
| author | Dmitry Torokhov <dmitry.torokhov@gmail.com> | 2015-02-10 14:35:36 -0500 |
|---|---|---|
| committer | Dmitry Torokhov <dmitry.torokhov@gmail.com> | 2015-02-10 14:35:36 -0500 |
| commit | 4ba24fef3eb3b142197135223b90ced2f319cd53 (patch) | |
| tree | a20c125b27740ec7b4c761b11d801108e1b316b2 /kernel/rcu/tree.c | |
| parent | 47c1ffb2b6b630894e9a16442611c056ab21c057 (diff) | |
| parent | 98a4a59ee31a12105a2b84f5b8b515ac2cb208ef (diff) | |
Merge branch 'next' into for-linus
Prepare first round of input updates for 3.20.
Diffstat (limited to 'kernel/rcu/tree.c')
| -rw-r--r-- | kernel/rcu/tree.c | 227 |
1 files changed, 136 insertions, 91 deletions
diff --git a/kernel/rcu/tree.c b/kernel/rcu/tree.c index 1b70cb6fbe3c..7680fc275036 100644 --- a/kernel/rcu/tree.c +++ b/kernel/rcu/tree.c | |||
| @@ -79,9 +79,18 @@ static struct lock_class_key rcu_fqs_class[RCU_NUM_LVLS]; | |||
| 79 | * the tracing userspace tools to be able to decipher the string | 79 | * the tracing userspace tools to be able to decipher the string |
| 80 | * address to the matching string. | 80 | * address to the matching string. |
| 81 | */ | 81 | */ |
| 82 | #define RCU_STATE_INITIALIZER(sname, sabbr, cr) \ | 82 | #ifdef CONFIG_TRACING |
| 83 | # define DEFINE_RCU_TPS(sname) \ | ||
| 83 | static char sname##_varname[] = #sname; \ | 84 | static char sname##_varname[] = #sname; \ |
| 84 | static const char *tp_##sname##_varname __used __tracepoint_string = sname##_varname; \ | 85 | static const char *tp_##sname##_varname __used __tracepoint_string = sname##_varname; |
| 86 | # define RCU_STATE_NAME(sname) sname##_varname | ||
| 87 | #else | ||
| 88 | # define DEFINE_RCU_TPS(sname) | ||
| 89 | # define RCU_STATE_NAME(sname) __stringify(sname) | ||
| 90 | #endif | ||
| 91 | |||
| 92 | #define RCU_STATE_INITIALIZER(sname, sabbr, cr) \ | ||
| 93 | DEFINE_RCU_TPS(sname) \ | ||
| 85 | struct rcu_state sname##_state = { \ | 94 | struct rcu_state sname##_state = { \ |
| 86 | .level = { &sname##_state.node[0] }, \ | 95 | .level = { &sname##_state.node[0] }, \ |
| 87 | .call = cr, \ | 96 | .call = cr, \ |
| @@ -93,10 +102,10 @@ struct rcu_state sname##_state = { \ | |||
| 93 | .orphan_donetail = &sname##_state.orphan_donelist, \ | 102 | .orphan_donetail = &sname##_state.orphan_donelist, \ |
| 94 | .barrier_mutex = __MUTEX_INITIALIZER(sname##_state.barrier_mutex), \ | 103 | .barrier_mutex = __MUTEX_INITIALIZER(sname##_state.barrier_mutex), \ |
| 95 | .onoff_mutex = __MUTEX_INITIALIZER(sname##_state.onoff_mutex), \ | 104 | .onoff_mutex = __MUTEX_INITIALIZER(sname##_state.onoff_mutex), \ |
| 96 | .name = sname##_varname, \ | 105 | .name = RCU_STATE_NAME(sname), \ |
| 97 | .abbr = sabbr, \ | 106 | .abbr = sabbr, \ |
| 98 | }; \ | 107 | }; \ |
| 99 | DEFINE_PER_CPU(struct rcu_data, sname##_data) | 108 | DEFINE_PER_CPU_SHARED_ALIGNED(struct rcu_data, sname##_data) |
| 100 | 109 | ||
| 101 | RCU_STATE_INITIALIZER(rcu_sched, 's', call_rcu_sched); | 110 | RCU_STATE_INITIALIZER(rcu_sched, 's', call_rcu_sched); |
| 102 | RCU_STATE_INITIALIZER(rcu_bh, 'b', call_rcu_bh); | 111 | RCU_STATE_INITIALIZER(rcu_bh, 'b', call_rcu_bh); |
| @@ -143,19 +152,6 @@ EXPORT_SYMBOL_GPL(rcu_scheduler_active); | |||
| 143 | */ | 152 | */ |
| 144 | static int rcu_scheduler_fully_active __read_mostly; | 153 | static int rcu_scheduler_fully_active __read_mostly; |
| 145 | 154 | ||
| 146 | #ifdef CONFIG_RCU_BOOST | ||
| 147 | |||
| 148 | /* | ||
| 149 | * Control variables for per-CPU and per-rcu_node kthreads. These | ||
| 150 | * handle all flavors of RCU. | ||
| 151 | */ | ||
| 152 | static DEFINE_PER_CPU(struct task_struct *, rcu_cpu_kthread_task); | ||
| 153 | DEFINE_PER_CPU(unsigned int, rcu_cpu_kthread_status); | ||
| 154 | DEFINE_PER_CPU(unsigned int, rcu_cpu_kthread_loops); | ||
| 155 | DEFINE_PER_CPU(char, rcu_cpu_has_work); | ||
| 156 | |||
| 157 | #endif /* #ifdef CONFIG_RCU_BOOST */ | ||
| 158 | |||
| 159 | static void rcu_boost_kthread_setaffinity(struct rcu_node *rnp, int outgoingcpu); | 155 | static void rcu_boost_kthread_setaffinity(struct rcu_node *rnp, int outgoingcpu); |
| 160 | static void invoke_rcu_core(void); | 156 | static void invoke_rcu_core(void); |
| 161 | static void invoke_rcu_callbacks(struct rcu_state *rsp, struct rcu_data *rdp); | 157 | static void invoke_rcu_callbacks(struct rcu_state *rsp, struct rcu_data *rdp); |
| @@ -188,22 +184,24 @@ static int rcu_gp_in_progress(struct rcu_state *rsp) | |||
| 188 | * one since the start of the grace period, this just sets a flag. | 184 | * one since the start of the grace period, this just sets a flag. |
| 189 | * The caller must have disabled preemption. | 185 | * The caller must have disabled preemption. |
| 190 | */ | 186 | */ |
| 191 | void rcu_sched_qs(int cpu) | 187 | void rcu_sched_qs(void) |
| 192 | { | 188 | { |
| 193 | struct rcu_data *rdp = &per_cpu(rcu_sched_data, cpu); | 189 | if (!__this_cpu_read(rcu_sched_data.passed_quiesce)) { |
| 194 | 190 | trace_rcu_grace_period(TPS("rcu_sched"), | |
| 195 | if (rdp->passed_quiesce == 0) | 191 | __this_cpu_read(rcu_sched_data.gpnum), |
| 196 | trace_rcu_grace_period(TPS("rcu_sched"), rdp->gpnum, TPS("cpuqs")); | 192 | TPS("cpuqs")); |
| 197 | rdp->passed_quiesce = 1; | 193 | __this_cpu_write(rcu_sched_data.passed_quiesce, 1); |
| 194 | } | ||
| 198 | } | 195 | } |
| 199 | 196 | ||
| 200 | void rcu_bh_qs(int cpu) | 197 | void rcu_bh_qs(void) |
| 201 | { | 198 | { |
| 202 | struct rcu_data *rdp = &per_cpu(rcu_bh_data, cpu); | 199 | if (!__this_cpu_read(rcu_bh_data.passed_quiesce)) { |
| 203 | 200 | trace_rcu_grace_period(TPS("rcu_bh"), | |
| 204 | if (rdp->passed_quiesce == 0) | 201 | __this_cpu_read(rcu_bh_data.gpnum), |
| 205 | trace_rcu_grace_period(TPS("rcu_bh"), rdp->gpnum, TPS("cpuqs")); | 202 | TPS("cpuqs")); |
| 206 | rdp->passed_quiesce = 1; | 203 | __this_cpu_write(rcu_bh_data.passed_quiesce, 1); |
| 204 | } | ||
| 207 | } | 205 | } |
| 208 | 206 | ||
| 209 | static DEFINE_PER_CPU(int, rcu_sched_qs_mask); | 207 | static DEFINE_PER_CPU(int, rcu_sched_qs_mask); |
| @@ -275,11 +273,11 @@ static void rcu_momentary_dyntick_idle(void) | |||
| 275 | * and requires special handling for preemptible RCU. | 273 | * and requires special handling for preemptible RCU. |
| 276 | * The caller must have disabled preemption. | 274 | * The caller must have disabled preemption. |
| 277 | */ | 275 | */ |
| 278 | void rcu_note_context_switch(int cpu) | 276 | void rcu_note_context_switch(void) |
| 279 | { | 277 | { |
| 280 | trace_rcu_utilization(TPS("Start context switch")); | 278 | trace_rcu_utilization(TPS("Start context switch")); |
| 281 | rcu_sched_qs(cpu); | 279 | rcu_sched_qs(); |
| 282 | rcu_preempt_note_context_switch(cpu); | 280 | rcu_preempt_note_context_switch(); |
| 283 | if (unlikely(raw_cpu_read(rcu_sched_qs_mask))) | 281 | if (unlikely(raw_cpu_read(rcu_sched_qs_mask))) |
| 284 | rcu_momentary_dyntick_idle(); | 282 | rcu_momentary_dyntick_idle(); |
| 285 | trace_rcu_utilization(TPS("End context switch")); | 283 | trace_rcu_utilization(TPS("End context switch")); |
| @@ -314,7 +312,7 @@ static void force_qs_rnp(struct rcu_state *rsp, | |||
| 314 | unsigned long *maxj), | 312 | unsigned long *maxj), |
| 315 | bool *isidle, unsigned long *maxj); | 313 | bool *isidle, unsigned long *maxj); |
| 316 | static void force_quiescent_state(struct rcu_state *rsp); | 314 | static void force_quiescent_state(struct rcu_state *rsp); |
| 317 | static int rcu_pending(int cpu); | 315 | static int rcu_pending(void); |
| 318 | 316 | ||
| 319 | /* | 317 | /* |
| 320 | * Return the number of RCU-sched batches processed thus far for debug & stats. | 318 | * Return the number of RCU-sched batches processed thus far for debug & stats. |
| @@ -499,11 +497,11 @@ cpu_needs_another_gp(struct rcu_state *rsp, struct rcu_data *rdp) | |||
| 499 | * we really have entered idle, and must do the appropriate accounting. | 497 | * we really have entered idle, and must do the appropriate accounting. |
| 500 | * The caller must have disabled interrupts. | 498 | * The caller must have disabled interrupts. |
| 501 | */ | 499 | */ |
| 502 | static void rcu_eqs_enter_common(struct rcu_dynticks *rdtp, long long oldval, | 500 | static void rcu_eqs_enter_common(long long oldval, bool user) |
| 503 | bool user) | ||
| 504 | { | 501 | { |
| 505 | struct rcu_state *rsp; | 502 | struct rcu_state *rsp; |
| 506 | struct rcu_data *rdp; | 503 | struct rcu_data *rdp; |
| 504 | struct rcu_dynticks *rdtp = this_cpu_ptr(&rcu_dynticks); | ||
| 507 | 505 | ||
| 508 | trace_rcu_dyntick(TPS("Start"), oldval, rdtp->dynticks_nesting); | 506 | trace_rcu_dyntick(TPS("Start"), oldval, rdtp->dynticks_nesting); |
| 509 | if (!user && !is_idle_task(current)) { | 507 | if (!user && !is_idle_task(current)) { |
| @@ -520,12 +518,13 @@ static void rcu_eqs_enter_common(struct rcu_dynticks *rdtp, long long oldval, | |||
| 520 | rdp = this_cpu_ptr(rsp->rda); | 518 | rdp = this_cpu_ptr(rsp->rda); |
| 521 | do_nocb_deferred_wakeup(rdp); | 519 | do_nocb_deferred_wakeup(rdp); |
| 522 | } | 520 | } |
| 523 | rcu_prepare_for_idle(smp_processor_id()); | 521 | rcu_prepare_for_idle(); |
| 524 | /* CPUs seeing atomic_inc() must see prior RCU read-side crit sects */ | 522 | /* CPUs seeing atomic_inc() must see prior RCU read-side crit sects */ |
| 525 | smp_mb__before_atomic(); /* See above. */ | 523 | smp_mb__before_atomic(); /* See above. */ |
| 526 | atomic_inc(&rdtp->dynticks); | 524 | atomic_inc(&rdtp->dynticks); |
| 527 | smp_mb__after_atomic(); /* Force ordering with next sojourn. */ | 525 | smp_mb__after_atomic(); /* Force ordering with next sojourn. */ |
| 528 | WARN_ON_ONCE(atomic_read(&rdtp->dynticks) & 0x1); | 526 | WARN_ON_ONCE(atomic_read(&rdtp->dynticks) & 0x1); |
| 527 | rcu_dynticks_task_enter(); | ||
| 529 | 528 | ||
| 530 | /* | 529 | /* |
| 531 | * It is illegal to enter an extended quiescent state while | 530 | * It is illegal to enter an extended quiescent state while |
| @@ -553,7 +552,7 @@ static void rcu_eqs_enter(bool user) | |||
| 553 | WARN_ON_ONCE((oldval & DYNTICK_TASK_NEST_MASK) == 0); | 552 | WARN_ON_ONCE((oldval & DYNTICK_TASK_NEST_MASK) == 0); |
| 554 | if ((oldval & DYNTICK_TASK_NEST_MASK) == DYNTICK_TASK_NEST_VALUE) { | 553 | if ((oldval & DYNTICK_TASK_NEST_MASK) == DYNTICK_TASK_NEST_VALUE) { |
| 555 | rdtp->dynticks_nesting = 0; | 554 | rdtp->dynticks_nesting = 0; |
| 556 | rcu_eqs_enter_common(rdtp, oldval, user); | 555 | rcu_eqs_enter_common(oldval, user); |
| 557 | } else { | 556 | } else { |
| 558 | rdtp->dynticks_nesting -= DYNTICK_TASK_NEST_VALUE; | 557 | rdtp->dynticks_nesting -= DYNTICK_TASK_NEST_VALUE; |
| 559 | } | 558 | } |
| @@ -577,7 +576,7 @@ void rcu_idle_enter(void) | |||
| 577 | 576 | ||
| 578 | local_irq_save(flags); | 577 | local_irq_save(flags); |
| 579 | rcu_eqs_enter(false); | 578 | rcu_eqs_enter(false); |
| 580 | rcu_sysidle_enter(this_cpu_ptr(&rcu_dynticks), 0); | 579 | rcu_sysidle_enter(0); |
| 581 | local_irq_restore(flags); | 580 | local_irq_restore(flags); |
| 582 | } | 581 | } |
| 583 | EXPORT_SYMBOL_GPL(rcu_idle_enter); | 582 | EXPORT_SYMBOL_GPL(rcu_idle_enter); |
| @@ -627,8 +626,8 @@ void rcu_irq_exit(void) | |||
| 627 | if (rdtp->dynticks_nesting) | 626 | if (rdtp->dynticks_nesting) |
| 628 | trace_rcu_dyntick(TPS("--="), oldval, rdtp->dynticks_nesting); | 627 | trace_rcu_dyntick(TPS("--="), oldval, rdtp->dynticks_nesting); |
| 629 | else | 628 | else |
| 630 | rcu_eqs_enter_common(rdtp, oldval, true); | 629 | rcu_eqs_enter_common(oldval, true); |
| 631 | rcu_sysidle_enter(rdtp, 1); | 630 | rcu_sysidle_enter(1); |
| 632 | local_irq_restore(flags); | 631 | local_irq_restore(flags); |
| 633 | } | 632 | } |
| 634 | 633 | ||
| @@ -639,15 +638,17 @@ void rcu_irq_exit(void) | |||
| 639 | * we really have exited idle, and must do the appropriate accounting. | 638 | * we really have exited idle, and must do the appropriate accounting. |
| 640 | * The caller must have disabled interrupts. | 639 | * The caller must have disabled interrupts. |
| 641 | */ | 640 | */ |
| 642 | static void rcu_eqs_exit_common(struct rcu_dynticks *rdtp, long long oldval, | 641 | static void rcu_eqs_exit_common(long long oldval, int user) |
| 643 | int user) | ||
| 644 | { | 642 | { |
| 643 | struct rcu_dynticks *rdtp = this_cpu_ptr(&rcu_dynticks); | ||
| 644 | |||
| 645 | rcu_dynticks_task_exit(); | ||
| 645 | smp_mb__before_atomic(); /* Force ordering w/previous sojourn. */ | 646 | smp_mb__before_atomic(); /* Force ordering w/previous sojourn. */ |
| 646 | atomic_inc(&rdtp->dynticks); | 647 | atomic_inc(&rdtp->dynticks); |
| 647 | /* CPUs seeing atomic_inc() must see later RCU read-side crit sects */ | 648 | /* CPUs seeing atomic_inc() must see later RCU read-side crit sects */ |
| 648 | smp_mb__after_atomic(); /* See above. */ | 649 | smp_mb__after_atomic(); /* See above. */ |
| 649 | WARN_ON_ONCE(!(atomic_read(&rdtp->dynticks) & 0x1)); | 650 | WARN_ON_ONCE(!(atomic_read(&rdtp->dynticks) & 0x1)); |
| 650 | rcu_cleanup_after_idle(smp_processor_id()); | 651 | rcu_cleanup_after_idle(); |
| 651 | trace_rcu_dyntick(TPS("End"), oldval, rdtp->dynticks_nesting); | 652 | trace_rcu_dyntick(TPS("End"), oldval, rdtp->dynticks_nesting); |
| 652 | if (!user && !is_idle_task(current)) { | 653 | if (!user && !is_idle_task(current)) { |
| 653 | struct task_struct *idle __maybe_unused = | 654 | struct task_struct *idle __maybe_unused = |
| @@ -678,7 +679,7 @@ static void rcu_eqs_exit(bool user) | |||
| 678 | rdtp->dynticks_nesting += DYNTICK_TASK_NEST_VALUE; | 679 | rdtp->dynticks_nesting += DYNTICK_TASK_NEST_VALUE; |
| 679 | } else { | 680 | } else { |
| 680 | rdtp->dynticks_nesting = DYNTICK_TASK_EXIT_IDLE; | 681 | rdtp->dynticks_nesting = DYNTICK_TASK_EXIT_IDLE; |
| 681 | rcu_eqs_exit_common(rdtp, oldval, user); | 682 | rcu_eqs_exit_common(oldval, user); |
| 682 | } | 683 | } |
| 683 | } | 684 | } |
| 684 | 685 | ||
| @@ -699,7 +700,7 @@ void rcu_idle_exit(void) | |||
| 699 | 700 | ||
| 700 | local_irq_save(flags); | 701 | local_irq_save(flags); |
| 701 | rcu_eqs_exit(false); | 702 | rcu_eqs_exit(false); |
| 702 | rcu_sysidle_exit(this_cpu_ptr(&rcu_dynticks), 0); | 703 | rcu_sysidle_exit(0); |
| 703 | local_irq_restore(flags); | 704 | local_irq_restore(flags); |
| 704 | } | 705 | } |
| 705 | EXPORT_SYMBOL_GPL(rcu_idle_exit); | 706 | EXPORT_SYMBOL_GPL(rcu_idle_exit); |
| @@ -750,8 +751,8 @@ void rcu_irq_enter(void) | |||
| 750 | if (oldval) | 751 | if (oldval) |
| 751 | trace_rcu_dyntick(TPS("++="), oldval, rdtp->dynticks_nesting); | 752 | trace_rcu_dyntick(TPS("++="), oldval, rdtp->dynticks_nesting); |
| 752 | else | 753 | else |
| 753 | rcu_eqs_exit_common(rdtp, oldval, true); | 754 | rcu_eqs_exit_common(oldval, true); |
| 754 | rcu_sysidle_exit(rdtp, 1); | 755 | rcu_sysidle_exit(1); |
| 755 | local_irq_restore(flags); | 756 | local_irq_restore(flags); |
| 756 | } | 757 | } |
| 757 | 758 | ||
| @@ -819,7 +820,7 @@ bool notrace __rcu_is_watching(void) | |||
| 819 | */ | 820 | */ |
| 820 | bool notrace rcu_is_watching(void) | 821 | bool notrace rcu_is_watching(void) |
| 821 | { | 822 | { |
| 822 | int ret; | 823 | bool ret; |
| 823 | 824 | ||
| 824 | preempt_disable(); | 825 | preempt_disable(); |
| 825 | ret = __rcu_is_watching(); | 826 | ret = __rcu_is_watching(); |
| @@ -1647,7 +1648,7 @@ static int rcu_gp_init(struct rcu_state *rsp) | |||
| 1647 | rnp->level, rnp->grplo, | 1648 | rnp->level, rnp->grplo, |
| 1648 | rnp->grphi, rnp->qsmask); | 1649 | rnp->grphi, rnp->qsmask); |
| 1649 | raw_spin_unlock_irq(&rnp->lock); | 1650 | raw_spin_unlock_irq(&rnp->lock); |
| 1650 | cond_resched(); | 1651 | cond_resched_rcu_qs(); |
| 1651 | } | 1652 | } |
| 1652 | 1653 | ||
| 1653 | mutex_unlock(&rsp->onoff_mutex); | 1654 | mutex_unlock(&rsp->onoff_mutex); |
| @@ -1668,7 +1669,7 @@ static int rcu_gp_fqs(struct rcu_state *rsp, int fqs_state_in) | |||
| 1668 | if (fqs_state == RCU_SAVE_DYNTICK) { | 1669 | if (fqs_state == RCU_SAVE_DYNTICK) { |
| 1669 | /* Collect dyntick-idle snapshots. */ | 1670 | /* Collect dyntick-idle snapshots. */ |
| 1670 | if (is_sysidle_rcu_state(rsp)) { | 1671 | if (is_sysidle_rcu_state(rsp)) { |
| 1671 | isidle = 1; | 1672 | isidle = true; |
| 1672 | maxj = jiffies - ULONG_MAX / 4; | 1673 | maxj = jiffies - ULONG_MAX / 4; |
| 1673 | } | 1674 | } |
| 1674 | force_qs_rnp(rsp, dyntick_save_progress_counter, | 1675 | force_qs_rnp(rsp, dyntick_save_progress_counter, |
| @@ -1677,14 +1678,15 @@ static int rcu_gp_fqs(struct rcu_state *rsp, int fqs_state_in) | |||
| 1677 | fqs_state = RCU_FORCE_QS; | 1678 | fqs_state = RCU_FORCE_QS; |
| 1678 | } else { | 1679 | } else { |
| 1679 | /* Handle dyntick-idle and offline CPUs. */ | 1680 | /* Handle dyntick-idle and offline CPUs. */ |
| 1680 | isidle = 0; | 1681 | isidle = false; |
| 1681 | force_qs_rnp(rsp, rcu_implicit_dynticks_qs, &isidle, &maxj); | 1682 | force_qs_rnp(rsp, rcu_implicit_dynticks_qs, &isidle, &maxj); |
| 1682 | } | 1683 | } |
| 1683 | /* Clear flag to prevent immediate re-entry. */ | 1684 | /* Clear flag to prevent immediate re-entry. */ |
| 1684 | if (ACCESS_ONCE(rsp->gp_flags) & RCU_GP_FLAG_FQS) { | 1685 | if (ACCESS_ONCE(rsp->gp_flags) & RCU_GP_FLAG_FQS) { |
| 1685 | raw_spin_lock_irq(&rnp->lock); | 1686 | raw_spin_lock_irq(&rnp->lock); |
| 1686 | smp_mb__after_unlock_lock(); | 1687 | smp_mb__after_unlock_lock(); |
| 1687 | ACCESS_ONCE(rsp->gp_flags) &= ~RCU_GP_FLAG_FQS; | 1688 | ACCESS_ONCE(rsp->gp_flags) = |
| 1689 | ACCESS_ONCE(rsp->gp_flags) & ~RCU_GP_FLAG_FQS; | ||
| 1688 | raw_spin_unlock_irq(&rnp->lock); | 1690 | raw_spin_unlock_irq(&rnp->lock); |
| 1689 | } | 1691 | } |
| 1690 | return fqs_state; | 1692 | return fqs_state; |
| @@ -1736,7 +1738,7 @@ static void rcu_gp_cleanup(struct rcu_state *rsp) | |||
| 1736 | /* smp_mb() provided by prior unlock-lock pair. */ | 1738 | /* smp_mb() provided by prior unlock-lock pair. */ |
| 1737 | nocb += rcu_future_gp_cleanup(rsp, rnp); | 1739 | nocb += rcu_future_gp_cleanup(rsp, rnp); |
| 1738 | raw_spin_unlock_irq(&rnp->lock); | 1740 | raw_spin_unlock_irq(&rnp->lock); |
| 1739 | cond_resched(); | 1741 | cond_resched_rcu_qs(); |
| 1740 | } | 1742 | } |
| 1741 | rnp = rcu_get_root(rsp); | 1743 | rnp = rcu_get_root(rsp); |
| 1742 | raw_spin_lock_irq(&rnp->lock); | 1744 | raw_spin_lock_irq(&rnp->lock); |
| @@ -1785,8 +1787,8 @@ static int __noreturn rcu_gp_kthread(void *arg) | |||
| 1785 | /* Locking provides needed memory barrier. */ | 1787 | /* Locking provides needed memory barrier. */ |
| 1786 | if (rcu_gp_init(rsp)) | 1788 | if (rcu_gp_init(rsp)) |
| 1787 | break; | 1789 | break; |
| 1788 | cond_resched(); | 1790 | cond_resched_rcu_qs(); |
| 1789 | flush_signals(current); | 1791 | WARN_ON(signal_pending(current)); |
| 1790 | trace_rcu_grace_period(rsp->name, | 1792 | trace_rcu_grace_period(rsp->name, |
| 1791 | ACCESS_ONCE(rsp->gpnum), | 1793 | ACCESS_ONCE(rsp->gpnum), |
| 1792 | TPS("reqwaitsig")); | 1794 | TPS("reqwaitsig")); |
| @@ -1828,11 +1830,11 @@ static int __noreturn rcu_gp_kthread(void *arg) | |||
| 1828 | trace_rcu_grace_period(rsp->name, | 1830 | trace_rcu_grace_period(rsp->name, |
| 1829 | ACCESS_ONCE(rsp->gpnum), | 1831 | ACCESS_ONCE(rsp->gpnum), |
| 1830 | TPS("fqsend")); | 1832 | TPS("fqsend")); |
| 1831 | cond_resched(); | 1833 | cond_resched_rcu_qs(); |
| 1832 | } else { | 1834 | } else { |
| 1833 | /* Deal with stray signal. */ | 1835 | /* Deal with stray signal. */ |
| 1834 | cond_resched(); | 1836 | cond_resched_rcu_qs(); |
| 1835 | flush_signals(current); | 1837 | WARN_ON(signal_pending(current)); |
| 1836 | trace_rcu_grace_period(rsp->name, | 1838 | trace_rcu_grace_period(rsp->name, |
| 1837 | ACCESS_ONCE(rsp->gpnum), | 1839 | ACCESS_ONCE(rsp->gpnum), |
| 1838 | TPS("fqswaitsig")); | 1840 | TPS("fqswaitsig")); |
| @@ -1928,7 +1930,7 @@ static void rcu_report_qs_rsp(struct rcu_state *rsp, unsigned long flags) | |||
| 1928 | { | 1930 | { |
| 1929 | WARN_ON_ONCE(!rcu_gp_in_progress(rsp)); | 1931 | WARN_ON_ONCE(!rcu_gp_in_progress(rsp)); |
| 1930 | raw_spin_unlock_irqrestore(&rcu_get_root(rsp)->lock, flags); | 1932 | raw_spin_unlock_irqrestore(&rcu_get_root(rsp)->lock, flags); |
| 1931 | wake_up(&rsp->gp_wq); /* Memory barrier implied by wake_up() path. */ | 1933 | rcu_gp_kthread_wake(rsp); |
| 1932 | } | 1934 | } |
| 1933 | 1935 | ||
| 1934 | /* | 1936 | /* |
| @@ -2210,8 +2212,6 @@ static void rcu_cleanup_dead_cpu(int cpu, struct rcu_state *rsp) | |||
| 2210 | /* Adjust any no-longer-needed kthreads. */ | 2212 | /* Adjust any no-longer-needed kthreads. */ |
| 2211 | rcu_boost_kthread_setaffinity(rnp, -1); | 2213 | rcu_boost_kthread_setaffinity(rnp, -1); |
| 2212 | 2214 | ||
| 2213 | /* Remove the dead CPU from the bitmasks in the rcu_node hierarchy. */ | ||
| 2214 | |||
| 2215 | /* Exclude any attempts to start a new grace period. */ | 2215 | /* Exclude any attempts to start a new grace period. */ |
| 2216 | mutex_lock(&rsp->onoff_mutex); | 2216 | mutex_lock(&rsp->onoff_mutex); |
| 2217 | raw_spin_lock_irqsave(&rsp->orphan_lock, flags); | 2217 | raw_spin_lock_irqsave(&rsp->orphan_lock, flags); |
| @@ -2375,7 +2375,7 @@ static void rcu_do_batch(struct rcu_state *rsp, struct rcu_data *rdp) | |||
| 2375 | * invoked from the scheduling-clock interrupt. If rcu_pending returns | 2375 | * invoked from the scheduling-clock interrupt. If rcu_pending returns |
| 2376 | * false, there is no point in invoking rcu_check_callbacks(). | 2376 | * false, there is no point in invoking rcu_check_callbacks(). |
| 2377 | */ | 2377 | */ |
| 2378 | void rcu_check_callbacks(int cpu, int user) | 2378 | void rcu_check_callbacks(int user) |
| 2379 | { | 2379 | { |
| 2380 | trace_rcu_utilization(TPS("Start scheduler-tick")); | 2380 | trace_rcu_utilization(TPS("Start scheduler-tick")); |
| 2381 | increment_cpu_stall_ticks(); | 2381 | increment_cpu_stall_ticks(); |
| @@ -2393,8 +2393,8 @@ void rcu_check_callbacks(int cpu, int user) | |||
| 2393 | * at least not while the corresponding CPU is online. | 2393 | * at least not while the corresponding CPU is online. |
| 2394 | */ | 2394 | */ |
| 2395 | 2395 | ||
| 2396 | rcu_sched_qs(cpu); | 2396 | rcu_sched_qs(); |
| 2397 | rcu_bh_qs(cpu); | 2397 | rcu_bh_qs(); |
| 2398 | 2398 | ||
| 2399 | } else if (!in_softirq()) { | 2399 | } else if (!in_softirq()) { |
| 2400 | 2400 | ||
| @@ -2405,11 +2405,13 @@ void rcu_check_callbacks(int cpu, int user) | |||
| 2405 | * critical section, so note it. | 2405 | * critical section, so note it. |
| 2406 | */ | 2406 | */ |
| 2407 | 2407 | ||
| 2408 | rcu_bh_qs(cpu); | 2408 | rcu_bh_qs(); |
| 2409 | } | 2409 | } |
| 2410 | rcu_preempt_check_callbacks(cpu); | 2410 | rcu_preempt_check_callbacks(); |
| 2411 | if (rcu_pending(cpu)) | 2411 | if (rcu_pending()) |
| 2412 | invoke_rcu_core(); | 2412 | invoke_rcu_core(); |
| 2413 | if (user) | ||
| 2414 | rcu_note_voluntary_context_switch(current); | ||
| 2413 | trace_rcu_utilization(TPS("End scheduler-tick")); | 2415 | trace_rcu_utilization(TPS("End scheduler-tick")); |
| 2414 | } | 2416 | } |
| 2415 | 2417 | ||
| @@ -2432,7 +2434,7 @@ static void force_qs_rnp(struct rcu_state *rsp, | |||
| 2432 | struct rcu_node *rnp; | 2434 | struct rcu_node *rnp; |
| 2433 | 2435 | ||
| 2434 | rcu_for_each_leaf_node(rsp, rnp) { | 2436 | rcu_for_each_leaf_node(rsp, rnp) { |
| 2435 | cond_resched(); | 2437 | cond_resched_rcu_qs(); |
| 2436 | mask = 0; | 2438 | mask = 0; |
| 2437 | raw_spin_lock_irqsave(&rnp->lock, flags); | 2439 | raw_spin_lock_irqsave(&rnp->lock, flags); |
| 2438 | smp_mb__after_unlock_lock(); | 2440 | smp_mb__after_unlock_lock(); |
| @@ -2449,7 +2451,7 @@ static void force_qs_rnp(struct rcu_state *rsp, | |||
| 2449 | for (; cpu <= rnp->grphi; cpu++, bit <<= 1) { | 2451 | for (; cpu <= rnp->grphi; cpu++, bit <<= 1) { |
| 2450 | if ((rnp->qsmask & bit) != 0) { | 2452 | if ((rnp->qsmask & bit) != 0) { |
| 2451 | if ((rnp->qsmaskinit & bit) != 0) | 2453 | if ((rnp->qsmaskinit & bit) != 0) |
| 2452 | *isidle = 0; | 2454 | *isidle = false; |
| 2453 | if (f(per_cpu_ptr(rsp->rda, cpu), isidle, maxj)) | 2455 | if (f(per_cpu_ptr(rsp->rda, cpu), isidle, maxj)) |
| 2454 | mask |= bit; | 2456 | mask |= bit; |
| 2455 | } | 2457 | } |
| @@ -2505,9 +2507,10 @@ static void force_quiescent_state(struct rcu_state *rsp) | |||
| 2505 | raw_spin_unlock_irqrestore(&rnp_old->lock, flags); | 2507 | raw_spin_unlock_irqrestore(&rnp_old->lock, flags); |
| 2506 | return; /* Someone beat us to it. */ | 2508 | return; /* Someone beat us to it. */ |
| 2507 | } | 2509 | } |
| 2508 | ACCESS_ONCE(rsp->gp_flags) |= RCU_GP_FLAG_FQS; | 2510 | ACCESS_ONCE(rsp->gp_flags) = |
| 2511 | ACCESS_ONCE(rsp->gp_flags) | RCU_GP_FLAG_FQS; | ||
| 2509 | raw_spin_unlock_irqrestore(&rnp_old->lock, flags); | 2512 | raw_spin_unlock_irqrestore(&rnp_old->lock, flags); |
| 2510 | wake_up(&rsp->gp_wq); /* Memory barrier implied by wake_up() path. */ | 2513 | rcu_gp_kthread_wake(rsp); |
| 2511 | } | 2514 | } |
| 2512 | 2515 | ||
| 2513 | /* | 2516 | /* |
| @@ -2925,11 +2928,6 @@ static int synchronize_sched_expedited_cpu_stop(void *data) | |||
| 2925 | * restructure your code to batch your updates, and then use a single | 2928 | * restructure your code to batch your updates, and then use a single |
| 2926 | * synchronize_sched() instead. | 2929 | * synchronize_sched() instead. |
| 2927 | * | 2930 | * |
| 2928 | * Note that it is illegal to call this function while holding any lock | ||
| 2929 | * that is acquired by a CPU-hotplug notifier. And yes, it is also illegal | ||
| 2930 | * to call this function from a CPU-hotplug notifier. Failing to observe | ||
| 2931 | * these restriction will result in deadlock. | ||
| 2932 | * | ||
| 2933 | * This implementation can be thought of as an application of ticket | 2931 | * This implementation can be thought of as an application of ticket |
| 2934 | * locking to RCU, with sync_sched_expedited_started and | 2932 | * locking to RCU, with sync_sched_expedited_started and |
| 2935 | * sync_sched_expedited_done taking on the roles of the halves | 2933 | * sync_sched_expedited_done taking on the roles of the halves |
| @@ -2953,6 +2951,9 @@ static int synchronize_sched_expedited_cpu_stop(void *data) | |||
| 2953 | */ | 2951 | */ |
| 2954 | void synchronize_sched_expedited(void) | 2952 | void synchronize_sched_expedited(void) |
| 2955 | { | 2953 | { |
| 2954 | cpumask_var_t cm; | ||
| 2955 | bool cma = false; | ||
| 2956 | int cpu; | ||
| 2956 | long firstsnap, s, snap; | 2957 | long firstsnap, s, snap; |
| 2957 | int trycount = 0; | 2958 | int trycount = 0; |
| 2958 | struct rcu_state *rsp = &rcu_sched_state; | 2959 | struct rcu_state *rsp = &rcu_sched_state; |
| @@ -2979,14 +2980,34 @@ void synchronize_sched_expedited(void) | |||
| 2979 | */ | 2980 | */ |
| 2980 | snap = atomic_long_inc_return(&rsp->expedited_start); | 2981 | snap = atomic_long_inc_return(&rsp->expedited_start); |
| 2981 | firstsnap = snap; | 2982 | firstsnap = snap; |
| 2982 | get_online_cpus(); | 2983 | if (!try_get_online_cpus()) { |
| 2984 | /* CPU hotplug operation in flight, fall back to normal GP. */ | ||
| 2985 | wait_rcu_gp(call_rcu_sched); | ||
| 2986 | atomic_long_inc(&rsp->expedited_normal); | ||
| 2987 | return; | ||
| 2988 | } | ||
| 2983 | WARN_ON_ONCE(cpu_is_offline(raw_smp_processor_id())); | 2989 | WARN_ON_ONCE(cpu_is_offline(raw_smp_processor_id())); |
| 2984 | 2990 | ||
| 2991 | /* Offline CPUs, idle CPUs, and any CPU we run on are quiescent. */ | ||
| 2992 | cma = zalloc_cpumask_var(&cm, GFP_KERNEL); | ||
| 2993 | if (cma) { | ||
| 2994 | cpumask_copy(cm, cpu_online_mask); | ||
| 2995 | cpumask_clear_cpu(raw_smp_processor_id(), cm); | ||
| 2996 | for_each_cpu(cpu, cm) { | ||
| 2997 | struct rcu_dynticks *rdtp = &per_cpu(rcu_dynticks, cpu); | ||
| 2998 | |||
| 2999 | if (!(atomic_add_return(0, &rdtp->dynticks) & 0x1)) | ||
| 3000 | cpumask_clear_cpu(cpu, cm); | ||
| 3001 | } | ||
| 3002 | if (cpumask_weight(cm) == 0) | ||
| 3003 | goto all_cpus_idle; | ||
| 3004 | } | ||
| 3005 | |||
| 2985 | /* | 3006 | /* |
| 2986 | * Each pass through the following loop attempts to force a | 3007 | * Each pass through the following loop attempts to force a |
| 2987 | * context switch on each CPU. | 3008 | * context switch on each CPU. |
| 2988 | */ | 3009 | */ |
| 2989 | while (try_stop_cpus(cpu_online_mask, | 3010 | while (try_stop_cpus(cma ? cm : cpu_online_mask, |
| 2990 | synchronize_sched_expedited_cpu_stop, | 3011 | synchronize_sched_expedited_cpu_stop, |
| 2991 | NULL) == -EAGAIN) { | 3012 | NULL) == -EAGAIN) { |
| 2992 | put_online_cpus(); | 3013 | put_online_cpus(); |
| @@ -2998,6 +3019,7 @@ void synchronize_sched_expedited(void) | |||
| 2998 | /* ensure test happens before caller kfree */ | 3019 | /* ensure test happens before caller kfree */ |
| 2999 | smp_mb__before_atomic(); /* ^^^ */ | 3020 | smp_mb__before_atomic(); /* ^^^ */ |
| 3000 | atomic_long_inc(&rsp->expedited_workdone1); | 3021 | atomic_long_inc(&rsp->expedited_workdone1); |
| 3022 | free_cpumask_var(cm); | ||
| 3001 | return; | 3023 | return; |
| 3002 | } | 3024 | } |
| 3003 | 3025 | ||
| @@ -3007,6 +3029,7 @@ void synchronize_sched_expedited(void) | |||
| 3007 | } else { | 3029 | } else { |
| 3008 | wait_rcu_gp(call_rcu_sched); | 3030 | wait_rcu_gp(call_rcu_sched); |
| 3009 | atomic_long_inc(&rsp->expedited_normal); | 3031 | atomic_long_inc(&rsp->expedited_normal); |
| 3032 | free_cpumask_var(cm); | ||
| 3010 | return; | 3033 | return; |
| 3011 | } | 3034 | } |
| 3012 | 3035 | ||
| @@ -3016,6 +3039,7 @@ void synchronize_sched_expedited(void) | |||
| 3016 | /* ensure test happens before caller kfree */ | 3039 | /* ensure test happens before caller kfree */ |
| 3017 | smp_mb__before_atomic(); /* ^^^ */ | 3040 | smp_mb__before_atomic(); /* ^^^ */ |
| 3018 | atomic_long_inc(&rsp->expedited_workdone2); | 3041 | atomic_long_inc(&rsp->expedited_workdone2); |
| 3042 | free_cpumask_var(cm); | ||
| 3019 | return; | 3043 | return; |
| 3020 | } | 3044 | } |
| 3021 | 3045 | ||
| @@ -3026,12 +3050,21 @@ void synchronize_sched_expedited(void) | |||
| 3026 | * and they started after our first try, so their grace | 3050 | * and they started after our first try, so their grace |
| 3027 | * period works for us. | 3051 | * period works for us. |
| 3028 | */ | 3052 | */ |
| 3029 | get_online_cpus(); | 3053 | if (!try_get_online_cpus()) { |
| 3054 | /* CPU hotplug operation in flight, use normal GP. */ | ||
| 3055 | wait_rcu_gp(call_rcu_sched); | ||
| 3056 | atomic_long_inc(&rsp->expedited_normal); | ||
| 3057 | free_cpumask_var(cm); | ||
| 3058 | return; | ||
| 3059 | } | ||
| 3030 | snap = atomic_long_read(&rsp->expedited_start); | 3060 | snap = atomic_long_read(&rsp->expedited_start); |
| 3031 | smp_mb(); /* ensure read is before try_stop_cpus(). */ | 3061 | smp_mb(); /* ensure read is before try_stop_cpus(). */ |
| 3032 | } | 3062 | } |
| 3033 | atomic_long_inc(&rsp->expedited_stoppedcpus); | 3063 | atomic_long_inc(&rsp->expedited_stoppedcpus); |
| 3034 | 3064 | ||
| 3065 | all_cpus_idle: | ||
| 3066 | free_cpumask_var(cm); | ||
| 3067 | |||
| 3035 | /* | 3068 | /* |
| 3036 | * Everyone up to our most recent fetch is covered by our grace | 3069 | * Everyone up to our most recent fetch is covered by our grace |
| 3037 | * period. Update the counter, but only if our work is still | 3070 | * period. Update the counter, but only if our work is still |
| @@ -3123,12 +3156,12 @@ static int __rcu_pending(struct rcu_state *rsp, struct rcu_data *rdp) | |||
| 3123 | * by the current CPU, returning 1 if so. This function is part of the | 3156 | * by the current CPU, returning 1 if so. This function is part of the |
| 3124 | * RCU implementation; it is -not- an exported member of the RCU API. | 3157 | * RCU implementation; it is -not- an exported member of the RCU API. |
| 3125 | */ | 3158 | */ |
| 3126 | static int rcu_pending(int cpu) | 3159 | static int rcu_pending(void) |
| 3127 | { | 3160 | { |
| 3128 | struct rcu_state *rsp; | 3161 | struct rcu_state *rsp; |
| 3129 | 3162 | ||
| 3130 | for_each_rcu_flavor(rsp) | 3163 | for_each_rcu_flavor(rsp) |
| 3131 | if (__rcu_pending(rsp, per_cpu_ptr(rsp->rda, cpu))) | 3164 | if (__rcu_pending(rsp, this_cpu_ptr(rsp->rda))) |
| 3132 | return 1; | 3165 | return 1; |
| 3133 | return 0; | 3166 | return 0; |
| 3134 | } | 3167 | } |
| @@ -3138,7 +3171,7 @@ static int rcu_pending(int cpu) | |||
| 3138 | * non-NULL, store an indication of whether all callbacks are lazy. | 3171 | * non-NULL, store an indication of whether all callbacks are lazy. |
| 3139 | * (If there are no callbacks, all of them are deemed to be lazy.) | 3172 | * (If there are no callbacks, all of them are deemed to be lazy.) |
| 3140 | */ | 3173 | */ |
| 3141 | static int __maybe_unused rcu_cpu_has_callbacks(int cpu, bool *all_lazy) | 3174 | static int __maybe_unused rcu_cpu_has_callbacks(bool *all_lazy) |
| 3142 | { | 3175 | { |
| 3143 | bool al = true; | 3176 | bool al = true; |
| 3144 | bool hc = false; | 3177 | bool hc = false; |
| @@ -3146,7 +3179,7 @@ static int __maybe_unused rcu_cpu_has_callbacks(int cpu, bool *all_lazy) | |||
| 3146 | struct rcu_state *rsp; | 3179 | struct rcu_state *rsp; |
| 3147 | 3180 | ||
| 3148 | for_each_rcu_flavor(rsp) { | 3181 | for_each_rcu_flavor(rsp) { |
| 3149 | rdp = per_cpu_ptr(rsp->rda, cpu); | 3182 | rdp = this_cpu_ptr(rsp->rda); |
| 3150 | if (!rdp->nxtlist) | 3183 | if (!rdp->nxtlist) |
| 3151 | continue; | 3184 | continue; |
| 3152 | hc = true; | 3185 | hc = true; |
| @@ -3279,11 +3312,16 @@ static void _rcu_barrier(struct rcu_state *rsp) | |||
| 3279 | continue; | 3312 | continue; |
| 3280 | rdp = per_cpu_ptr(rsp->rda, cpu); | 3313 | rdp = per_cpu_ptr(rsp->rda, cpu); |
| 3281 | if (rcu_is_nocb_cpu(cpu)) { | 3314 | if (rcu_is_nocb_cpu(cpu)) { |
| 3282 | _rcu_barrier_trace(rsp, "OnlineNoCB", cpu, | 3315 | if (!rcu_nocb_cpu_needs_barrier(rsp, cpu)) { |
| 3283 | rsp->n_barrier_done); | 3316 | _rcu_barrier_trace(rsp, "OfflineNoCB", cpu, |
| 3284 | atomic_inc(&rsp->barrier_cpu_count); | 3317 | rsp->n_barrier_done); |
| 3285 | __call_rcu(&rdp->barrier_head, rcu_barrier_callback, | 3318 | } else { |
| 3286 | rsp, cpu, 0); | 3319 | _rcu_barrier_trace(rsp, "OnlineNoCB", cpu, |
| 3320 | rsp->n_barrier_done); | ||
| 3321 | atomic_inc(&rsp->barrier_cpu_count); | ||
| 3322 | __call_rcu(&rdp->barrier_head, | ||
| 3323 | rcu_barrier_callback, rsp, cpu, 0); | ||
| 3324 | } | ||
| 3287 | } else if (ACCESS_ONCE(rdp->qlen)) { | 3325 | } else if (ACCESS_ONCE(rdp->qlen)) { |
| 3288 | _rcu_barrier_trace(rsp, "OnlineQ", cpu, | 3326 | _rcu_barrier_trace(rsp, "OnlineQ", cpu, |
| 3289 | rsp->n_barrier_done); | 3327 | rsp->n_barrier_done); |
| @@ -3442,6 +3480,7 @@ static int rcu_cpu_notify(struct notifier_block *self, | |||
| 3442 | case CPU_UP_PREPARE_FROZEN: | 3480 | case CPU_UP_PREPARE_FROZEN: |
| 3443 | rcu_prepare_cpu(cpu); | 3481 | rcu_prepare_cpu(cpu); |
| 3444 | rcu_prepare_kthreads(cpu); | 3482 | rcu_prepare_kthreads(cpu); |
| 3483 | rcu_spawn_all_nocb_kthreads(cpu); | ||
| 3445 | break; | 3484 | break; |
| 3446 | case CPU_ONLINE: | 3485 | case CPU_ONLINE: |
| 3447 | case CPU_DOWN_FAILED: | 3486 | case CPU_DOWN_FAILED: |
| @@ -3459,8 +3498,10 @@ static int rcu_cpu_notify(struct notifier_block *self, | |||
| 3459 | case CPU_DEAD_FROZEN: | 3498 | case CPU_DEAD_FROZEN: |
| 3460 | case CPU_UP_CANCELED: | 3499 | case CPU_UP_CANCELED: |
| 3461 | case CPU_UP_CANCELED_FROZEN: | 3500 | case CPU_UP_CANCELED_FROZEN: |
| 3462 | for_each_rcu_flavor(rsp) | 3501 | for_each_rcu_flavor(rsp) { |
| 3463 | rcu_cleanup_dead_cpu(cpu, rsp); | 3502 | rcu_cleanup_dead_cpu(cpu, rsp); |
| 3503 | do_nocb_deferred_wakeup(per_cpu_ptr(rsp->rda, cpu)); | ||
| 3504 | } | ||
| 3464 | break; | 3505 | break; |
| 3465 | default: | 3506 | default: |
| 3466 | break; | 3507 | break; |
| @@ -3489,7 +3530,7 @@ static int rcu_pm_notify(struct notifier_block *self, | |||
| 3489 | } | 3530 | } |
| 3490 | 3531 | ||
| 3491 | /* | 3532 | /* |
| 3492 | * Spawn the kthread that handles this RCU flavor's grace periods. | 3533 | * Spawn the kthreads that handle each RCU flavor's grace periods. |
| 3493 | */ | 3534 | */ |
| 3494 | static int __init rcu_spawn_gp_kthread(void) | 3535 | static int __init rcu_spawn_gp_kthread(void) |
| 3495 | { | 3536 | { |
| @@ -3498,6 +3539,7 @@ static int __init rcu_spawn_gp_kthread(void) | |||
| 3498 | struct rcu_state *rsp; | 3539 | struct rcu_state *rsp; |
| 3499 | struct task_struct *t; | 3540 | struct task_struct *t; |
| 3500 | 3541 | ||
| 3542 | rcu_scheduler_fully_active = 1; | ||
| 3501 | for_each_rcu_flavor(rsp) { | 3543 | for_each_rcu_flavor(rsp) { |
| 3502 | t = kthread_run(rcu_gp_kthread, rsp, "%s", rsp->name); | 3544 | t = kthread_run(rcu_gp_kthread, rsp, "%s", rsp->name); |
| 3503 | BUG_ON(IS_ERR(t)); | 3545 | BUG_ON(IS_ERR(t)); |
| @@ -3505,8 +3547,9 @@ static int __init rcu_spawn_gp_kthread(void) | |||
| 3505 | raw_spin_lock_irqsave(&rnp->lock, flags); | 3547 | raw_spin_lock_irqsave(&rnp->lock, flags); |
| 3506 | rsp->gp_kthread = t; | 3548 | rsp->gp_kthread = t; |
| 3507 | raw_spin_unlock_irqrestore(&rnp->lock, flags); | 3549 | raw_spin_unlock_irqrestore(&rnp->lock, flags); |
| 3508 | rcu_spawn_nocb_kthreads(rsp); | ||
| 3509 | } | 3550 | } |
| 3551 | rcu_spawn_nocb_kthreads(); | ||
| 3552 | rcu_spawn_boost_kthreads(); | ||
| 3510 | return 0; | 3553 | return 0; |
| 3511 | } | 3554 | } |
| 3512 | early_initcall(rcu_spawn_gp_kthread); | 3555 | early_initcall(rcu_spawn_gp_kthread); |
| @@ -3738,6 +3781,8 @@ void __init rcu_init(void) | |||
| 3738 | pm_notifier(rcu_pm_notify, 0); | 3781 | pm_notifier(rcu_pm_notify, 0); |
| 3739 | for_each_online_cpu(cpu) | 3782 | for_each_online_cpu(cpu) |
| 3740 | rcu_cpu_notify(NULL, CPU_UP_PREPARE, (void *)(long)cpu); | 3783 | rcu_cpu_notify(NULL, CPU_UP_PREPARE, (void *)(long)cpu); |
| 3784 | |||
| 3785 | rcu_early_boot_tests(); | ||
| 3741 | } | 3786 | } |
| 3742 | 3787 | ||
| 3743 | #include "tree_plugin.h" | 3788 | #include "tree_plugin.h" |
