diff options
-rw-r--r-- | include/linux/rcupdate.h | 2 | ||||
-rw-r--r-- | kernel/rcutree.c | 43 |
2 files changed, 45 insertions, 0 deletions
diff --git a/include/linux/rcupdate.h b/include/linux/rcupdate.h index d8b20bfd4795..f818dd165b44 100644 --- a/include/linux/rcupdate.h +++ b/include/linux/rcupdate.h | |||
@@ -193,6 +193,8 @@ extern void rcu_irq_enter(void); | |||
193 | extern void rcu_irq_exit(void); | 193 | extern void rcu_irq_exit(void); |
194 | extern void rcu_user_enter(void); | 194 | extern void rcu_user_enter(void); |
195 | extern void rcu_user_exit(void); | 195 | extern void rcu_user_exit(void); |
196 | extern void rcu_user_enter_after_irq(void); | ||
197 | extern void rcu_user_exit_after_irq(void); | ||
196 | extern void exit_rcu(void); | 198 | extern void exit_rcu(void); |
197 | 199 | ||
198 | /** | 200 | /** |
diff --git a/kernel/rcutree.c b/kernel/rcutree.c index af0dc3472a4b..4138f59fa2f4 100644 --- a/kernel/rcutree.c +++ b/kernel/rcutree.c | |||
@@ -426,6 +426,27 @@ void rcu_user_enter(void) | |||
426 | 426 | ||
427 | 427 | ||
428 | /** | 428 | /** |
429 | * rcu_user_enter_after_irq - inform RCU that we are going to resume userspace | ||
430 | * after the current irq returns. | ||
431 | * | ||
432 | * This is similar to rcu_user_enter() but in the context of a non-nesting | ||
433 | * irq. After this call, RCU enters into idle mode when the interrupt | ||
434 | * returns. | ||
435 | */ | ||
436 | void rcu_user_enter_after_irq(void) | ||
437 | { | ||
438 | unsigned long flags; | ||
439 | struct rcu_dynticks *rdtp; | ||
440 | |||
441 | local_irq_save(flags); | ||
442 | rdtp = &__get_cpu_var(rcu_dynticks); | ||
443 | /* Ensure this irq is interrupting a non-idle RCU state. */ | ||
444 | WARN_ON_ONCE(!(rdtp->dynticks_nesting & DYNTICK_TASK_MASK)); | ||
445 | rdtp->dynticks_nesting = 1; | ||
446 | local_irq_restore(flags); | ||
447 | } | ||
448 | |||
449 | /** | ||
429 | * rcu_irq_exit - inform RCU that current CPU is exiting irq towards idle | 450 | * rcu_irq_exit - inform RCU that current CPU is exiting irq towards idle |
430 | * | 451 | * |
431 | * Exit from an interrupt handler, which might possibly result in entering | 452 | * Exit from an interrupt handler, which might possibly result in entering |
@@ -550,6 +571,28 @@ void rcu_user_exit(void) | |||
550 | } | 571 | } |
551 | 572 | ||
552 | /** | 573 | /** |
574 | * rcu_user_exit_after_irq - inform RCU that we won't resume to userspace | ||
575 | * idle mode after the current non-nesting irq returns. | ||
576 | * | ||
577 | * This is similar to rcu_user_exit() but in the context of an irq. | ||
578 | * This is called when the irq has interrupted a userspace RCU idle mode | ||
579 | * context. When the current non-nesting interrupt returns after this call, | ||
580 | * the CPU won't restore the RCU idle mode. | ||
581 | */ | ||
582 | void rcu_user_exit_after_irq(void) | ||
583 | { | ||
584 | unsigned long flags; | ||
585 | struct rcu_dynticks *rdtp; | ||
586 | |||
587 | local_irq_save(flags); | ||
588 | rdtp = &__get_cpu_var(rcu_dynticks); | ||
589 | /* Ensure we are interrupting an RCU idle mode. */ | ||
590 | WARN_ON_ONCE(rdtp->dynticks_nesting & DYNTICK_TASK_NEST_MASK); | ||
591 | rdtp->dynticks_nesting += DYNTICK_TASK_EXIT_IDLE; | ||
592 | local_irq_restore(flags); | ||
593 | } | ||
594 | |||
595 | /** | ||
553 | * rcu_irq_enter - inform RCU that current CPU is entering irq away from idle | 596 | * rcu_irq_enter - inform RCU that current CPU is entering irq away from idle |
554 | * | 597 | * |
555 | * Enter an interrupt handler, which might possibly result in exiting | 598 | * Enter an interrupt handler, which might possibly result in exiting |