Skip to content

Commit f268c37

Browse files
Frederic WeisbeckerPeter Zijlstra
authored andcommitted
tick/nohz: Only check for RCU deferred wakeup on user/guest entry when needed
Checking for and processing RCU-nocb deferred wakeup upon user/guest entry is only relevant when nohz_full runs on the local CPU, otherwise the periodic tick should take care of it. Make sure we don't needlessly pollute these fast-paths as a -3% performance regression on a will-it-scale.per_process_ops has been reported so far. Fixes: 47b8ff1 (entry: Explicitly flush pending rcuog wakeup before last rescheduling point) Fixes: 4ae7dc9 (entry/kvm: Explicitly flush pending rcuog wakeup before last rescheduling point) Reported-by: kernel test robot <[email protected]> Signed-off-by: Frederic Weisbecker <[email protected]> Signed-off-by: Peter Zijlstra (Intel) <[email protected]> Reviewed-by: Paul E. McKenney <[email protected]> Cc: [email protected] Link: https://lkml.kernel.org/r/[email protected]
1 parent 02da26a commit f268c37

File tree

4 files changed

+13
-3
lines changed

4 files changed

+13
-3
lines changed

include/linux/entry-kvm.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
#define __LINUX_ENTRYKVM_H
44

55
#include <linux/entry-common.h>
6+
#include <linux/tick.h>
67

78
/* Transfer to guest mode work */
89
#ifdef CONFIG_KVM_XFER_TO_GUEST_WORK
@@ -57,7 +58,7 @@ int xfer_to_guest_mode_handle_work(struct kvm_vcpu *vcpu);
5758
static inline void xfer_to_guest_mode_prepare(void)
5859
{
5960
lockdep_assert_irqs_disabled();
60-
rcu_nocb_flush_deferred_wakeup();
61+
tick_nohz_user_enter_prepare();
6162
}
6263

6364
/**

include/linux/tick.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
#include <linux/context_tracking_state.h>
1212
#include <linux/cpumask.h>
1313
#include <linux/sched.h>
14+
#include <linux/rcupdate.h>
1415

1516
#ifdef CONFIG_GENERIC_CLOCKEVENTS
1617
extern void __init tick_init(void);
@@ -300,4 +301,10 @@ static inline void tick_nohz_task_switch(void)
300301
__tick_nohz_task_switch();
301302
}
302303

304+
static inline void tick_nohz_user_enter_prepare(void)
305+
{
306+
if (tick_nohz_full_cpu(smp_processor_id()))
307+
rcu_nocb_flush_deferred_wakeup();
308+
}
309+
303310
#endif

kernel/entry/common.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
#include <linux/highmem.h>
66
#include <linux/livepatch.h>
77
#include <linux/audit.h>
8+
#include <linux/tick.h>
89

910
#include "common.h"
1011

@@ -186,7 +187,7 @@ static unsigned long exit_to_user_mode_loop(struct pt_regs *regs,
186187
local_irq_disable_exit_to_user();
187188

188189
/* Check if any of the above work has queued a deferred wakeup */
189-
rcu_nocb_flush_deferred_wakeup();
190+
tick_nohz_user_enter_prepare();
190191

191192
ti_work = READ_ONCE(current_thread_info()->flags);
192193
}
@@ -202,7 +203,7 @@ static void exit_to_user_mode_prepare(struct pt_regs *regs)
202203
lockdep_assert_irqs_disabled();
203204

204205
/* Flush pending rcuog wakeup before the last need_resched() check */
205-
rcu_nocb_flush_deferred_wakeup();
206+
tick_nohz_user_enter_prepare();
206207

207208
if (unlikely(ti_work & EXIT_TO_USER_MODE_WORK))
208209
ti_work = exit_to_user_mode_loop(regs, ti_work);

kernel/time/tick-sched.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -230,6 +230,7 @@ static void tick_sched_handle(struct tick_sched *ts, struct pt_regs *regs)
230230

231231
#ifdef CONFIG_NO_HZ_FULL
232232
cpumask_var_t tick_nohz_full_mask;
233+
EXPORT_SYMBOL_GPL(tick_nohz_full_mask);
233234
bool tick_nohz_full_running;
234235
EXPORT_SYMBOL_GPL(tick_nohz_full_running);
235236
static atomic_t tick_dep_mask;

0 commit comments

Comments
 (0)