diff options
Diffstat (limited to 'kernel/rcutiny.c')
| -rw-r--r-- | kernel/rcutiny.c | 26 |
1 files changed, 20 insertions, 6 deletions
diff --git a/kernel/rcutiny.c b/kernel/rcutiny.c index 977296dca0a4..37a5444204d2 100644 --- a/kernel/rcutiny.c +++ b/kernel/rcutiny.c | |||
| @@ -53,7 +53,7 @@ static void __call_rcu(struct rcu_head *head, | |||
| 53 | 53 | ||
| 54 | #include "rcutiny_plugin.h" | 54 | #include "rcutiny_plugin.h" |
| 55 | 55 | ||
| 56 | static long long rcu_dynticks_nesting = DYNTICK_TASK_NESTING; | 56 | static long long rcu_dynticks_nesting = DYNTICK_TASK_EXIT_IDLE; |
| 57 | 57 | ||
| 58 | /* Common code for rcu_idle_enter() and rcu_irq_exit(), see kernel/rcutree.c. */ | 58 | /* Common code for rcu_idle_enter() and rcu_irq_exit(), see kernel/rcutree.c. */ |
| 59 | static void rcu_idle_enter_common(long long oldval) | 59 | static void rcu_idle_enter_common(long long oldval) |
| @@ -88,10 +88,16 @@ void rcu_idle_enter(void) | |||
| 88 | 88 | ||
| 89 | local_irq_save(flags); | 89 | local_irq_save(flags); |
| 90 | oldval = rcu_dynticks_nesting; | 90 | oldval = rcu_dynticks_nesting; |
| 91 | rcu_dynticks_nesting = 0; | 91 | WARN_ON_ONCE((rcu_dynticks_nesting & DYNTICK_TASK_NEST_MASK) == 0); |
| 92 | if ((rcu_dynticks_nesting & DYNTICK_TASK_NEST_MASK) == | ||
| 93 | DYNTICK_TASK_NEST_VALUE) | ||
| 94 | rcu_dynticks_nesting = 0; | ||
| 95 | else | ||
| 96 | rcu_dynticks_nesting -= DYNTICK_TASK_NEST_VALUE; | ||
| 92 | rcu_idle_enter_common(oldval); | 97 | rcu_idle_enter_common(oldval); |
| 93 | local_irq_restore(flags); | 98 | local_irq_restore(flags); |
| 94 | } | 99 | } |
| 100 | EXPORT_SYMBOL_GPL(rcu_idle_enter); | ||
| 95 | 101 | ||
| 96 | /* | 102 | /* |
| 97 | * Exit an interrupt handler towards idle. | 103 | * Exit an interrupt handler towards idle. |
| @@ -140,11 +146,15 @@ void rcu_idle_exit(void) | |||
| 140 | 146 | ||
| 141 | local_irq_save(flags); | 147 | local_irq_save(flags); |
| 142 | oldval = rcu_dynticks_nesting; | 148 | oldval = rcu_dynticks_nesting; |
| 143 | WARN_ON_ONCE(oldval != 0); | 149 | WARN_ON_ONCE(rcu_dynticks_nesting < 0); |
| 144 | rcu_dynticks_nesting = DYNTICK_TASK_NESTING; | 150 | if (rcu_dynticks_nesting & DYNTICK_TASK_NEST_MASK) |
| 151 | rcu_dynticks_nesting += DYNTICK_TASK_NEST_VALUE; | ||
| 152 | else | ||
| 153 | rcu_dynticks_nesting = DYNTICK_TASK_EXIT_IDLE; | ||
| 145 | rcu_idle_exit_common(oldval); | 154 | rcu_idle_exit_common(oldval); |
| 146 | local_irq_restore(flags); | 155 | local_irq_restore(flags); |
| 147 | } | 156 | } |
| 157 | EXPORT_SYMBOL_GPL(rcu_idle_exit); | ||
| 148 | 158 | ||
| 149 | /* | 159 | /* |
| 150 | * Enter an interrupt handler, moving away from idle. | 160 | * Enter an interrupt handler, moving away from idle. |
| @@ -258,7 +268,7 @@ static void __rcu_process_callbacks(struct rcu_ctrlblk *rcp) | |||
| 258 | 268 | ||
| 259 | /* If no RCU callbacks ready to invoke, just return. */ | 269 | /* If no RCU callbacks ready to invoke, just return. */ |
| 260 | if (&rcp->rcucblist == rcp->donetail) { | 270 | if (&rcp->rcucblist == rcp->donetail) { |
| 261 | RCU_TRACE(trace_rcu_batch_start(rcp->name, 0, -1)); | 271 | RCU_TRACE(trace_rcu_batch_start(rcp->name, 0, 0, -1)); |
| 262 | RCU_TRACE(trace_rcu_batch_end(rcp->name, 0, | 272 | RCU_TRACE(trace_rcu_batch_end(rcp->name, 0, |
| 263 | ACCESS_ONCE(rcp->rcucblist), | 273 | ACCESS_ONCE(rcp->rcucblist), |
| 264 | need_resched(), | 274 | need_resched(), |
| @@ -269,7 +279,7 @@ static void __rcu_process_callbacks(struct rcu_ctrlblk *rcp) | |||
| 269 | 279 | ||
| 270 | /* Move the ready-to-invoke callbacks to a local list. */ | 280 | /* Move the ready-to-invoke callbacks to a local list. */ |
| 271 | local_irq_save(flags); | 281 | local_irq_save(flags); |
| 272 | RCU_TRACE(trace_rcu_batch_start(rcp->name, 0, -1)); | 282 | RCU_TRACE(trace_rcu_batch_start(rcp->name, 0, rcp->qlen, -1)); |
| 273 | list = rcp->rcucblist; | 283 | list = rcp->rcucblist; |
| 274 | rcp->rcucblist = *rcp->donetail; | 284 | rcp->rcucblist = *rcp->donetail; |
| 275 | *rcp->donetail = NULL; | 285 | *rcp->donetail = NULL; |
| @@ -319,6 +329,10 @@ static void rcu_process_callbacks(struct softirq_action *unused) | |||
| 319 | */ | 329 | */ |
| 320 | void synchronize_sched(void) | 330 | void synchronize_sched(void) |
| 321 | { | 331 | { |
| 332 | rcu_lockdep_assert(!lock_is_held(&rcu_bh_lock_map) && | ||
| 333 | !lock_is_held(&rcu_lock_map) && | ||
| 334 | !lock_is_held(&rcu_sched_lock_map), | ||
| 335 | "Illegal synchronize_sched() in RCU read-side critical section"); | ||
| 322 | cond_resched(); | 336 | cond_resched(); |
| 323 | } | 337 | } |
| 324 | EXPORT_SYMBOL_GPL(synchronize_sched); | 338 | EXPORT_SYMBOL_GPL(synchronize_sched); |
