|
@@ -425,6 +425,27 @@ void rcu_user_enter(void)
|
|
|
}
|
|
|
|
|
|
|
|
|
+/**
|
|
|
+ * rcu_user_enter_after_irq - inform RCU that we are going to resume userspace
|
|
|
+ * after the current irq returns.
|
|
|
+ *
|
|
|
+ * This is similar to rcu_user_enter() but in the context of a non-nesting
|
|
|
+ * irq. After this call, RCU enters into idle mode when the interrupt
|
|
|
+ * returns.
|
|
|
+ */
|
|
|
+void rcu_user_enter_after_irq(void)
|
|
|
+{
|
|
|
+ unsigned long flags;
|
|
|
+ struct rcu_dynticks *rdtp;
|
|
|
+
|
|
|
+ local_irq_save(flags);
|
|
|
+ rdtp = &__get_cpu_var(rcu_dynticks);
|
|
|
+ /* Ensure this irq is interrupting a non-idle RCU state. */
|
|
|
+ WARN_ON_ONCE(!(rdtp->dynticks_nesting & DYNTICK_TASK_MASK));
|
|
|
+ rdtp->dynticks_nesting = 1;
|
|
|
+ local_irq_restore(flags);
|
|
|
+}
|
|
|
+
|
|
|
/**
|
|
|
* rcu_irq_exit - inform RCU that current CPU is exiting irq towards idle
|
|
|
*
|
|
@@ -549,6 +570,28 @@ void rcu_user_exit(void)
|
|
|
rcu_eqs_exit(1);
|
|
|
}
|
|
|
|
|
|
+/**
|
|
|
+ * rcu_user_exit_after_irq - inform RCU that we won't resume to userspace
|
|
|
+ * idle mode after the current non-nesting irq returns.
|
|
|
+ *
|
|
|
+ * This is similar to rcu_user_exit() but in the context of an irq.
|
|
|
+ * This is called when the irq has interrupted a userspace RCU idle mode
|
|
|
+ * context. When the current non-nesting interrupt returns after this call,
|
|
|
+ * the CPU won't restore the RCU idle mode.
|
|
|
+ */
|
|
|
+void rcu_user_exit_after_irq(void)
|
|
|
+{
|
|
|
+ unsigned long flags;
|
|
|
+ struct rcu_dynticks *rdtp;
|
|
|
+
|
|
|
+ local_irq_save(flags);
|
|
|
+ rdtp = &__get_cpu_var(rcu_dynticks);
|
|
|
+ /* Ensure we are interrupting an RCU idle mode. */
|
|
|
+ WARN_ON_ONCE(rdtp->dynticks_nesting & DYNTICK_TASK_NEST_MASK);
|
|
|
+ rdtp->dynticks_nesting += DYNTICK_TASK_EXIT_IDLE;
|
|
|
+ local_irq_restore(flags);
|
|
|
+}
|
|
|
+
|
|
|
/**
|
|
|
* rcu_irq_enter - inform RCU that current CPU is entering irq away from idle
|
|
|
*
|