summaryrefslogtreecommitdiffstats
path: root/kernel/entry
diff options
context:
space:
mode:
authorFrederic Weisbecker <frederic@kernel.org>2021-02-01 00:05:47 +0100
committerIngo Molnar <mingo@kernel.org>2021-02-17 14:12:43 +0100
commit47b8ff194c1fd73d58dc339b597d466fe48c8958 (patch)
treec3b9ec587a22b4f365f6d3492d2f2552492d7d07 /kernel/entry
parentf8bb5cae9616224a39cbb399de382d36ac41df10 (diff)
downloadlinux-stable-47b8ff194c1fd73d58dc339b597d466fe48c8958.tar.gz
linux-stable-47b8ff194c1fd73d58dc339b597d466fe48c8958.tar.bz2
linux-stable-47b8ff194c1fd73d58dc339b597d466fe48c8958.zip
entry: Explicitly flush pending rcuog wakeup before last rescheduling point
Following the idle loop model, cleanly check for pending rcuog wakeup before the last rescheduling point on resuming to user mode. This way we can avoid to do it from rcu_user_enter() with the last resort self-IPI hack that enforces rescheduling. Signed-off-by: Frederic Weisbecker <frederic@kernel.org> Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org> Signed-off-by: Ingo Molnar <mingo@kernel.org> Cc: stable@vger.kernel.org Link: https://lkml.kernel.org/r/20210131230548.32970-5-frederic@kernel.org
Diffstat (limited to 'kernel/entry')
-rw-r--r--kernel/entry/common.c7
1 files changed, 7 insertions, 0 deletions
diff --git a/kernel/entry/common.c b/kernel/entry/common.c
index f09cae37ddd5..8442e5c9cfa2 100644
--- a/kernel/entry/common.c
+++ b/kernel/entry/common.c
@@ -184,6 +184,10 @@ static unsigned long exit_to_user_mode_loop(struct pt_regs *regs,
* enabled above.
*/
local_irq_disable_exit_to_user();
+
+ /* Check if any of the above work has queued a deferred wakeup */
+ rcu_nocb_flush_deferred_wakeup();
+
ti_work = READ_ONCE(current_thread_info()->flags);
}
@@ -197,6 +201,9 @@ static void exit_to_user_mode_prepare(struct pt_regs *regs)
lockdep_assert_irqs_disabled();
+ /* Flush pending rcuog wakeup before the last need_resched() check */
+ rcu_nocb_flush_deferred_wakeup();
+
if (unlikely(ti_work & EXIT_TO_USER_MODE_WORK))
ti_work = exit_to_user_mode_loop(regs, ti_work);