diff options
Diffstat (limited to 'kernel/rcu/tree.c')
-rw-r--r-- | kernel/rcu/tree.c | 115 |
1 files changed, 69 insertions, 46 deletions
diff --git a/kernel/rcu/tree.c b/kernel/rcu/tree.c index 1b70cb6fbe3c..133e47223095 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,7 +102,7 @@ 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(struct rcu_data, sname##_data) |
@@ -188,22 +197,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. | 197 | * one since the start of the grace period, this just sets a flag. |
189 | * The caller must have disabled preemption. | 198 | * The caller must have disabled preemption. |
190 | */ | 199 | */ |
191 | void rcu_sched_qs(int cpu) | 200 | void rcu_sched_qs(void) |
192 | { | 201 | { |
193 | struct rcu_data *rdp = &per_cpu(rcu_sched_data, cpu); | 202 | if (!__this_cpu_read(rcu_sched_data.passed_quiesce)) { |
194 | 203 | trace_rcu_grace_period(TPS("rcu_sched"), | |
195 | if (rdp->passed_quiesce == 0) | 204 | __this_cpu_read(rcu_sched_data.gpnum), |
196 | trace_rcu_grace_period(TPS("rcu_sched"), rdp->gpnum, TPS("cpuqs")); | 205 | TPS("cpuqs")); |
197 | rdp->passed_quiesce = 1; | 206 | __this_cpu_write(rcu_sched_data.passed_quiesce, 1); |
207 | } | ||
198 | } | 208 | } |
199 | 209 | ||
200 | void rcu_bh_qs(int cpu) | 210 | void rcu_bh_qs(void) |
201 | { | 211 | { |
202 | struct rcu_data *rdp = &per_cpu(rcu_bh_data, cpu); | 212 | if (!__this_cpu_read(rcu_bh_data.passed_quiesce)) { |
203 | 213 | trace_rcu_grace_period(TPS("rcu_bh"), | |
204 | if (rdp->passed_quiesce == 0) | 214 | __this_cpu_read(rcu_bh_data.gpnum), |
205 | trace_rcu_grace_period(TPS("rcu_bh"), rdp->gpnum, TPS("cpuqs")); | 215 | TPS("cpuqs")); |
206 | rdp->passed_quiesce = 1; | 216 | __this_cpu_write(rcu_bh_data.passed_quiesce, 1); |
217 | } | ||
207 | } | 218 | } |
208 | 219 | ||
209 | static DEFINE_PER_CPU(int, rcu_sched_qs_mask); | 220 | static DEFINE_PER_CPU(int, rcu_sched_qs_mask); |
@@ -278,7 +289,7 @@ static void rcu_momentary_dyntick_idle(void) | |||
278 | void rcu_note_context_switch(int cpu) | 289 | void rcu_note_context_switch(int cpu) |
279 | { | 290 | { |
280 | trace_rcu_utilization(TPS("Start context switch")); | 291 | trace_rcu_utilization(TPS("Start context switch")); |
281 | rcu_sched_qs(cpu); | 292 | rcu_sched_qs(); |
282 | rcu_preempt_note_context_switch(cpu); | 293 | rcu_preempt_note_context_switch(cpu); |
283 | if (unlikely(raw_cpu_read(rcu_sched_qs_mask))) | 294 | if (unlikely(raw_cpu_read(rcu_sched_qs_mask))) |
284 | rcu_momentary_dyntick_idle(); | 295 | rcu_momentary_dyntick_idle(); |
@@ -526,6 +537,7 @@ static void rcu_eqs_enter_common(struct rcu_dynticks *rdtp, long long oldval, | |||
526 | atomic_inc(&rdtp->dynticks); | 537 | atomic_inc(&rdtp->dynticks); |
527 | smp_mb__after_atomic(); /* Force ordering with next sojourn. */ | 538 | smp_mb__after_atomic(); /* Force ordering with next sojourn. */ |
528 | WARN_ON_ONCE(atomic_read(&rdtp->dynticks) & 0x1); | 539 | WARN_ON_ONCE(atomic_read(&rdtp->dynticks) & 0x1); |
540 | rcu_dynticks_task_enter(); | ||
529 | 541 | ||
530 | /* | 542 | /* |
531 | * It is illegal to enter an extended quiescent state while | 543 | * It is illegal to enter an extended quiescent state while |
@@ -642,6 +654,7 @@ void rcu_irq_exit(void) | |||
642 | static void rcu_eqs_exit_common(struct rcu_dynticks *rdtp, long long oldval, | 654 | static void rcu_eqs_exit_common(struct rcu_dynticks *rdtp, long long oldval, |
643 | int user) | 655 | int user) |
644 | { | 656 | { |
657 | rcu_dynticks_task_exit(); | ||
645 | smp_mb__before_atomic(); /* Force ordering w/previous sojourn. */ | 658 | smp_mb__before_atomic(); /* Force ordering w/previous sojourn. */ |
646 | atomic_inc(&rdtp->dynticks); | 659 | atomic_inc(&rdtp->dynticks); |
647 | /* CPUs seeing atomic_inc() must see later RCU read-side crit sects */ | 660 | /* CPUs seeing atomic_inc() must see later RCU read-side crit sects */ |
@@ -819,7 +832,7 @@ bool notrace __rcu_is_watching(void) | |||
819 | */ | 832 | */ |
820 | bool notrace rcu_is_watching(void) | 833 | bool notrace rcu_is_watching(void) |
821 | { | 834 | { |
822 | int ret; | 835 | bool ret; |
823 | 836 | ||
824 | preempt_disable(); | 837 | preempt_disable(); |
825 | ret = __rcu_is_watching(); | 838 | ret = __rcu_is_watching(); |
@@ -1647,7 +1660,7 @@ static int rcu_gp_init(struct rcu_state *rsp) | |||
1647 | rnp->level, rnp->grplo, | 1660 | rnp->level, rnp->grplo, |
1648 | rnp->grphi, rnp->qsmask); | 1661 | rnp->grphi, rnp->qsmask); |
1649 | raw_spin_unlock_irq(&rnp->lock); | 1662 | raw_spin_unlock_irq(&rnp->lock); |
1650 | cond_resched(); | 1663 | cond_resched_rcu_qs(); |
1651 | } | 1664 | } |
1652 | 1665 | ||
1653 | mutex_unlock(&rsp->onoff_mutex); | 1666 | mutex_unlock(&rsp->onoff_mutex); |
@@ -1668,7 +1681,7 @@ static int rcu_gp_fqs(struct rcu_state *rsp, int fqs_state_in) | |||
1668 | if (fqs_state == RCU_SAVE_DYNTICK) { | 1681 | if (fqs_state == RCU_SAVE_DYNTICK) { |
1669 | /* Collect dyntick-idle snapshots. */ | 1682 | /* Collect dyntick-idle snapshots. */ |
1670 | if (is_sysidle_rcu_state(rsp)) { | 1683 | if (is_sysidle_rcu_state(rsp)) { |
1671 | isidle = 1; | 1684 | isidle = true; |
1672 | maxj = jiffies - ULONG_MAX / 4; | 1685 | maxj = jiffies - ULONG_MAX / 4; |
1673 | } | 1686 | } |
1674 | force_qs_rnp(rsp, dyntick_save_progress_counter, | 1687 | force_qs_rnp(rsp, dyntick_save_progress_counter, |
@@ -1677,14 +1690,15 @@ static int rcu_gp_fqs(struct rcu_state *rsp, int fqs_state_in) | |||
1677 | fqs_state = RCU_FORCE_QS; | 1690 | fqs_state = RCU_FORCE_QS; |
1678 | } else { | 1691 | } else { |
1679 | /* Handle dyntick-idle and offline CPUs. */ | 1692 | /* Handle dyntick-idle and offline CPUs. */ |
1680 | isidle = 0; | 1693 | isidle = false; |
1681 | force_qs_rnp(rsp, rcu_implicit_dynticks_qs, &isidle, &maxj); | 1694 | force_qs_rnp(rsp, rcu_implicit_dynticks_qs, &isidle, &maxj); |
1682 | } | 1695 | } |
1683 | /* Clear flag to prevent immediate re-entry. */ | 1696 | /* Clear flag to prevent immediate re-entry. */ |
1684 | if (ACCESS_ONCE(rsp->gp_flags) & RCU_GP_FLAG_FQS) { | 1697 | if (ACCESS_ONCE(rsp->gp_flags) & RCU_GP_FLAG_FQS) { |
1685 | raw_spin_lock_irq(&rnp->lock); | 1698 | raw_spin_lock_irq(&rnp->lock); |
1686 | smp_mb__after_unlock_lock(); | 1699 | smp_mb__after_unlock_lock(); |
1687 | ACCESS_ONCE(rsp->gp_flags) &= ~RCU_GP_FLAG_FQS; | 1700 | ACCESS_ONCE(rsp->gp_flags) = |
1701 | ACCESS_ONCE(rsp->gp_flags) & ~RCU_GP_FLAG_FQS; | ||
1688 | raw_spin_unlock_irq(&rnp->lock); | 1702 | raw_spin_unlock_irq(&rnp->lock); |
1689 | } | 1703 | } |
1690 | return fqs_state; | 1704 | return fqs_state; |
@@ -1736,7 +1750,7 @@ static void rcu_gp_cleanup(struct rcu_state *rsp) | |||
1736 | /* smp_mb() provided by prior unlock-lock pair. */ | 1750 | /* smp_mb() provided by prior unlock-lock pair. */ |
1737 | nocb += rcu_future_gp_cleanup(rsp, rnp); | 1751 | nocb += rcu_future_gp_cleanup(rsp, rnp); |
1738 | raw_spin_unlock_irq(&rnp->lock); | 1752 | raw_spin_unlock_irq(&rnp->lock); |
1739 | cond_resched(); | 1753 | cond_resched_rcu_qs(); |
1740 | } | 1754 | } |
1741 | rnp = rcu_get_root(rsp); | 1755 | rnp = rcu_get_root(rsp); |
1742 | raw_spin_lock_irq(&rnp->lock); | 1756 | raw_spin_lock_irq(&rnp->lock); |
@@ -1785,8 +1799,8 @@ static int __noreturn rcu_gp_kthread(void *arg) | |||
1785 | /* Locking provides needed memory barrier. */ | 1799 | /* Locking provides needed memory barrier. */ |
1786 | if (rcu_gp_init(rsp)) | 1800 | if (rcu_gp_init(rsp)) |
1787 | break; | 1801 | break; |
1788 | cond_resched(); | 1802 | cond_resched_rcu_qs(); |
1789 | flush_signals(current); | 1803 | WARN_ON(signal_pending(current)); |
1790 | trace_rcu_grace_period(rsp->name, | 1804 | trace_rcu_grace_period(rsp->name, |
1791 | ACCESS_ONCE(rsp->gpnum), | 1805 | ACCESS_ONCE(rsp->gpnum), |
1792 | TPS("reqwaitsig")); | 1806 | TPS("reqwaitsig")); |
@@ -1828,11 +1842,11 @@ static int __noreturn rcu_gp_kthread(void *arg) | |||
1828 | trace_rcu_grace_period(rsp->name, | 1842 | trace_rcu_grace_period(rsp->name, |
1829 | ACCESS_ONCE(rsp->gpnum), | 1843 | ACCESS_ONCE(rsp->gpnum), |
1830 | TPS("fqsend")); | 1844 | TPS("fqsend")); |
1831 | cond_resched(); | 1845 | cond_resched_rcu_qs(); |
1832 | } else { | 1846 | } else { |
1833 | /* Deal with stray signal. */ | 1847 | /* Deal with stray signal. */ |
1834 | cond_resched(); | 1848 | cond_resched_rcu_qs(); |
1835 | flush_signals(current); | 1849 | WARN_ON(signal_pending(current)); |
1836 | trace_rcu_grace_period(rsp->name, | 1850 | trace_rcu_grace_period(rsp->name, |
1837 | ACCESS_ONCE(rsp->gpnum), | 1851 | ACCESS_ONCE(rsp->gpnum), |
1838 | TPS("fqswaitsig")); | 1852 | TPS("fqswaitsig")); |
@@ -1928,7 +1942,7 @@ static void rcu_report_qs_rsp(struct rcu_state *rsp, unsigned long flags) | |||
1928 | { | 1942 | { |
1929 | WARN_ON_ONCE(!rcu_gp_in_progress(rsp)); | 1943 | WARN_ON_ONCE(!rcu_gp_in_progress(rsp)); |
1930 | raw_spin_unlock_irqrestore(&rcu_get_root(rsp)->lock, flags); | 1944 | raw_spin_unlock_irqrestore(&rcu_get_root(rsp)->lock, flags); |
1931 | wake_up(&rsp->gp_wq); /* Memory barrier implied by wake_up() path. */ | 1945 | rcu_gp_kthread_wake(rsp); |
1932 | } | 1946 | } |
1933 | 1947 | ||
1934 | /* | 1948 | /* |
@@ -2210,8 +2224,6 @@ static void rcu_cleanup_dead_cpu(int cpu, struct rcu_state *rsp) | |||
2210 | /* Adjust any no-longer-needed kthreads. */ | 2224 | /* Adjust any no-longer-needed kthreads. */ |
2211 | rcu_boost_kthread_setaffinity(rnp, -1); | 2225 | rcu_boost_kthread_setaffinity(rnp, -1); |
2212 | 2226 | ||
2213 | /* Remove the dead CPU from the bitmasks in the rcu_node hierarchy. */ | ||
2214 | |||
2215 | /* Exclude any attempts to start a new grace period. */ | 2227 | /* Exclude any attempts to start a new grace period. */ |
2216 | mutex_lock(&rsp->onoff_mutex); | 2228 | mutex_lock(&rsp->onoff_mutex); |
2217 | raw_spin_lock_irqsave(&rsp->orphan_lock, flags); | 2229 | raw_spin_lock_irqsave(&rsp->orphan_lock, flags); |
@@ -2393,8 +2405,8 @@ void rcu_check_callbacks(int cpu, int user) | |||
2393 | * at least not while the corresponding CPU is online. | 2405 | * at least not while the corresponding CPU is online. |
2394 | */ | 2406 | */ |
2395 | 2407 | ||
2396 | rcu_sched_qs(cpu); | 2408 | rcu_sched_qs(); |
2397 | rcu_bh_qs(cpu); | 2409 | rcu_bh_qs(); |
2398 | 2410 | ||
2399 | } else if (!in_softirq()) { | 2411 | } else if (!in_softirq()) { |
2400 | 2412 | ||
@@ -2405,11 +2417,13 @@ void rcu_check_callbacks(int cpu, int user) | |||
2405 | * critical section, so note it. | 2417 | * critical section, so note it. |
2406 | */ | 2418 | */ |
2407 | 2419 | ||
2408 | rcu_bh_qs(cpu); | 2420 | rcu_bh_qs(); |
2409 | } | 2421 | } |
2410 | rcu_preempt_check_callbacks(cpu); | 2422 | rcu_preempt_check_callbacks(cpu); |
2411 | if (rcu_pending(cpu)) | 2423 | if (rcu_pending(cpu)) |
2412 | invoke_rcu_core(); | 2424 | invoke_rcu_core(); |
2425 | if (user) | ||
2426 | rcu_note_voluntary_context_switch(current); | ||
2413 | trace_rcu_utilization(TPS("End scheduler-tick")); | 2427 | trace_rcu_utilization(TPS("End scheduler-tick")); |
2414 | } | 2428 | } |
2415 | 2429 | ||
@@ -2432,7 +2446,7 @@ static void force_qs_rnp(struct rcu_state *rsp, | |||
2432 | struct rcu_node *rnp; | 2446 | struct rcu_node *rnp; |
2433 | 2447 | ||
2434 | rcu_for_each_leaf_node(rsp, rnp) { | 2448 | rcu_for_each_leaf_node(rsp, rnp) { |
2435 | cond_resched(); | 2449 | cond_resched_rcu_qs(); |
2436 | mask = 0; | 2450 | mask = 0; |
2437 | raw_spin_lock_irqsave(&rnp->lock, flags); | 2451 | raw_spin_lock_irqsave(&rnp->lock, flags); |
2438 | smp_mb__after_unlock_lock(); | 2452 | smp_mb__after_unlock_lock(); |
@@ -2449,7 +2463,7 @@ static void force_qs_rnp(struct rcu_state *rsp, | |||
2449 | for (; cpu <= rnp->grphi; cpu++, bit <<= 1) { | 2463 | for (; cpu <= rnp->grphi; cpu++, bit <<= 1) { |
2450 | if ((rnp->qsmask & bit) != 0) { | 2464 | if ((rnp->qsmask & bit) != 0) { |
2451 | if ((rnp->qsmaskinit & bit) != 0) | 2465 | if ((rnp->qsmaskinit & bit) != 0) |
2452 | *isidle = 0; | 2466 | *isidle = false; |
2453 | if (f(per_cpu_ptr(rsp->rda, cpu), isidle, maxj)) | 2467 | if (f(per_cpu_ptr(rsp->rda, cpu), isidle, maxj)) |
2454 | mask |= bit; | 2468 | mask |= bit; |
2455 | } | 2469 | } |
@@ -2505,9 +2519,10 @@ static void force_quiescent_state(struct rcu_state *rsp) | |||
2505 | raw_spin_unlock_irqrestore(&rnp_old->lock, flags); | 2519 | raw_spin_unlock_irqrestore(&rnp_old->lock, flags); |
2506 | return; /* Someone beat us to it. */ | 2520 | return; /* Someone beat us to it. */ |
2507 | } | 2521 | } |
2508 | ACCESS_ONCE(rsp->gp_flags) |= RCU_GP_FLAG_FQS; | 2522 | ACCESS_ONCE(rsp->gp_flags) = |
2523 | ACCESS_ONCE(rsp->gp_flags) | RCU_GP_FLAG_FQS; | ||
2509 | raw_spin_unlock_irqrestore(&rnp_old->lock, flags); | 2524 | raw_spin_unlock_irqrestore(&rnp_old->lock, flags); |
2510 | wake_up(&rsp->gp_wq); /* Memory barrier implied by wake_up() path. */ | 2525 | rcu_gp_kthread_wake(rsp); |
2511 | } | 2526 | } |
2512 | 2527 | ||
2513 | /* | 2528 | /* |
@@ -2925,11 +2940,6 @@ static int synchronize_sched_expedited_cpu_stop(void *data) | |||
2925 | * restructure your code to batch your updates, and then use a single | 2940 | * restructure your code to batch your updates, and then use a single |
2926 | * synchronize_sched() instead. | 2941 | * synchronize_sched() instead. |
2927 | * | 2942 | * |
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 | 2943 | * This implementation can be thought of as an application of ticket |
2934 | * locking to RCU, with sync_sched_expedited_started and | 2944 | * locking to RCU, with sync_sched_expedited_started and |
2935 | * sync_sched_expedited_done taking on the roles of the halves | 2945 | * sync_sched_expedited_done taking on the roles of the halves |
@@ -2979,7 +2989,12 @@ void synchronize_sched_expedited(void) | |||
2979 | */ | 2989 | */ |
2980 | snap = atomic_long_inc_return(&rsp->expedited_start); | 2990 | snap = atomic_long_inc_return(&rsp->expedited_start); |
2981 | firstsnap = snap; | 2991 | firstsnap = snap; |
2982 | get_online_cpus(); | 2992 | if (!try_get_online_cpus()) { |
2993 | /* CPU hotplug operation in flight, fall back to normal GP. */ | ||
2994 | wait_rcu_gp(call_rcu_sched); | ||
2995 | atomic_long_inc(&rsp->expedited_normal); | ||
2996 | return; | ||
2997 | } | ||
2983 | WARN_ON_ONCE(cpu_is_offline(raw_smp_processor_id())); | 2998 | WARN_ON_ONCE(cpu_is_offline(raw_smp_processor_id())); |
2984 | 2999 | ||
2985 | /* | 3000 | /* |
@@ -3026,7 +3041,12 @@ void synchronize_sched_expedited(void) | |||
3026 | * and they started after our first try, so their grace | 3041 | * and they started after our first try, so their grace |
3027 | * period works for us. | 3042 | * period works for us. |
3028 | */ | 3043 | */ |
3029 | get_online_cpus(); | 3044 | if (!try_get_online_cpus()) { |
3045 | /* CPU hotplug operation in flight, use normal GP. */ | ||
3046 | wait_rcu_gp(call_rcu_sched); | ||
3047 | atomic_long_inc(&rsp->expedited_normal); | ||
3048 | return; | ||
3049 | } | ||
3030 | snap = atomic_long_read(&rsp->expedited_start); | 3050 | snap = atomic_long_read(&rsp->expedited_start); |
3031 | smp_mb(); /* ensure read is before try_stop_cpus(). */ | 3051 | smp_mb(); /* ensure read is before try_stop_cpus(). */ |
3032 | } | 3052 | } |
@@ -3442,6 +3462,7 @@ static int rcu_cpu_notify(struct notifier_block *self, | |||
3442 | case CPU_UP_PREPARE_FROZEN: | 3462 | case CPU_UP_PREPARE_FROZEN: |
3443 | rcu_prepare_cpu(cpu); | 3463 | rcu_prepare_cpu(cpu); |
3444 | rcu_prepare_kthreads(cpu); | 3464 | rcu_prepare_kthreads(cpu); |
3465 | rcu_spawn_all_nocb_kthreads(cpu); | ||
3445 | break; | 3466 | break; |
3446 | case CPU_ONLINE: | 3467 | case CPU_ONLINE: |
3447 | case CPU_DOWN_FAILED: | 3468 | case CPU_DOWN_FAILED: |
@@ -3489,7 +3510,7 @@ static int rcu_pm_notify(struct notifier_block *self, | |||
3489 | } | 3510 | } |
3490 | 3511 | ||
3491 | /* | 3512 | /* |
3492 | * Spawn the kthread that handles this RCU flavor's grace periods. | 3513 | * Spawn the kthreads that handle each RCU flavor's grace periods. |
3493 | */ | 3514 | */ |
3494 | static int __init rcu_spawn_gp_kthread(void) | 3515 | static int __init rcu_spawn_gp_kthread(void) |
3495 | { | 3516 | { |
@@ -3498,6 +3519,7 @@ static int __init rcu_spawn_gp_kthread(void) | |||
3498 | struct rcu_state *rsp; | 3519 | struct rcu_state *rsp; |
3499 | struct task_struct *t; | 3520 | struct task_struct *t; |
3500 | 3521 | ||
3522 | rcu_scheduler_fully_active = 1; | ||
3501 | for_each_rcu_flavor(rsp) { | 3523 | for_each_rcu_flavor(rsp) { |
3502 | t = kthread_run(rcu_gp_kthread, rsp, "%s", rsp->name); | 3524 | t = kthread_run(rcu_gp_kthread, rsp, "%s", rsp->name); |
3503 | BUG_ON(IS_ERR(t)); | 3525 | BUG_ON(IS_ERR(t)); |
@@ -3505,8 +3527,9 @@ static int __init rcu_spawn_gp_kthread(void) | |||
3505 | raw_spin_lock_irqsave(&rnp->lock, flags); | 3527 | raw_spin_lock_irqsave(&rnp->lock, flags); |
3506 | rsp->gp_kthread = t; | 3528 | rsp->gp_kthread = t; |
3507 | raw_spin_unlock_irqrestore(&rnp->lock, flags); | 3529 | raw_spin_unlock_irqrestore(&rnp->lock, flags); |
3508 | rcu_spawn_nocb_kthreads(rsp); | ||
3509 | } | 3530 | } |
3531 | rcu_spawn_nocb_kthreads(); | ||
3532 | rcu_spawn_boost_kthreads(); | ||
3510 | return 0; | 3533 | return 0; |
3511 | } | 3534 | } |
3512 | early_initcall(rcu_spawn_gp_kthread); | 3535 | early_initcall(rcu_spawn_gp_kthread); |