Skip to content

Commit

Permalink
entry: Explicitly flush pending rcuog wakeup before last rescheduling…
Browse files Browse the repository at this point in the history
… 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 <[email protected]>
Signed-off-by: Peter Zijlstra (Intel) <[email protected]>
Signed-off-by: Ingo Molnar <[email protected]>
Cc: [email protected]
Link: https://lkml.kernel.org/r/[email protected]
  • Loading branch information
Frederic Weisbecker authored and Ingo Molnar committed Feb 17, 2021
1 parent f8bb5ca commit 47b8ff1
Show file tree
Hide file tree
Showing 2 changed files with 14 additions and 5 deletions.
7 changes: 7 additions & 0 deletions kernel/entry/common.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}

Expand All @@ -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);

Expand Down
12 changes: 7 additions & 5 deletions kernel/rcu/tree.c
Original file line number Diff line number Diff line change
Expand Up @@ -707,13 +707,15 @@ noinstr void rcu_user_enter(void)
lockdep_assert_irqs_disabled();

/*
* We may be past the last rescheduling opportunity in the entry code.
* Trigger a self IPI that will fire and reschedule once we resume to
* user/guest mode.
* Other than generic entry implementation, we may be past the last
* rescheduling opportunity in the entry code. Trigger a self IPI
* that will fire and reschedule once we resume in user/guest mode.
*/
instrumentation_begin();
if (do_nocb_deferred_wakeup(rdp) && need_resched())
irq_work_queue(this_cpu_ptr(&late_wakeup_work));
if (!IS_ENABLED(CONFIG_GENERIC_ENTRY) || (current->flags & PF_VCPU)) {
if (do_nocb_deferred_wakeup(rdp) && need_resched())
irq_work_queue(this_cpu_ptr(&late_wakeup_work));
}
instrumentation_end();

rcu_eqs_enter(true);
Expand Down

0 comments on commit 47b8ff1

Please sign in to comment.