From: Frederic Weisbecker <frederic@kernel.org>
To: Marco Crivellari <marco.crivellari@suse.com>
Cc: linux-kernel@vger.kernel.org, Ingo Molnar <mingo@kernel.org>,
Michal Hocko <mhocko@suse.com>,
Aaron Tomlin <atomlin@atomlin.com>,
Marcelo Tosatti <mtosatti@redhat.com>,
"Paul E. McKenney" <paulmck@kernel.org>,
Anna-Maria Behnsen <anna-maria@linutronix.de>,
Thomas Gleixner <tglx@kernel.org>
Subject: Re: [PATCH v2 1/4] tick/nohz: Re-evaluate the tick on return to user space
Date: Wed, 11 Nov 2026 17:25:01 +0100 [thread overview]
Message-ID: <avSW3VBwd1Mym6rJ@localhost.localdomain> (raw)
In-Reply-To: <20261111114406.346953-2-marco.crivellari@suse.com>
Le Wed, Nov 11, 2026 at 12:43:47PM +0100, Marco Crivellari a écrit :
> On nohz_full CPUs the tick is re-evaluated on IRQ exit and on idle exit.
>
> This is not enough on return to user space. If the tick is left running in
> the kernel, for example because a tick dependency was cleared
> (tick_nohz_dep_clear*() don't kick the CPU) or a timer that kept it
> running was cancelled, it fires at least once in userspace before
> tick_nohz_irq_exit() stops it.
>
> Stop it from context tracking right before resuming userspace. When the
> tick is already stopped, the common case, this costs a few flag tests on
> each return to userspace.
>
> Cc: Paul E. McKenney <paulmck@kernel.org>
> Cc: Anna-Maria Behnsen <anna-maria@linutronix.de>
> Cc: Thomas Gleixner <tglx@kernel.org>
> Suggested-by: Frederic Weisbecker <frederic@kernel.org>
> Signed-off-by: Marco Crivellari <marco.crivellari@suse.com>
> ---
> include/linux/tick.h | 8 ++++++++
> kernel/context_tracking.c | 8 ++++++++
> kernel/time/tick-sched.c | 24 ++++++++++++++++++++++++
> 3 files changed, 40 insertions(+)
>
> diff --git a/include/linux/tick.h b/include/linux/tick.h
> index b121c5d53e30..8bfbb053f4fd 100644
> --- a/include/linux/tick.h
> +++ b/include/linux/tick.h
> @@ -269,6 +269,7 @@ static inline void tick_dep_clear_signal(struct signal_struct *signal,
> extern void tick_nohz_full_kick_cpu(int cpu);
> extern void __tick_nohz_task_switch(void);
> extern void __init tick_nohz_full_setup(cpumask_var_t cpumask);
> +extern void __tick_nohz_user_enter(void);
> #else
> static inline bool tick_nohz_full_enabled(void) { return false; }
> static inline bool tick_nohz_full_cpu(int cpu) { return false; }
> @@ -294,6 +295,7 @@ static inline void tick_dep_clear_signal(struct signal_struct *signal,
> static inline void tick_nohz_full_kick_cpu(int cpu) { }
> static inline void __tick_nohz_task_switch(void) { }
> static inline void tick_nohz_full_setup(cpumask_var_t cpumask) { }
> +static inline void __tick_nohz_user_enter(void) { }
> #endif
>
> static inline void tick_nohz_task_switch(void)
> @@ -302,6 +304,12 @@ static inline void tick_nohz_task_switch(void)
> __tick_nohz_task_switch();
> }
>
> +static inline void tick_nohz_user_enter(void)
> +{
> + if (tick_nohz_full_enabled())
> + __tick_nohz_user_enter();
> +}
> +
> static inline void tick_nohz_user_enter_prepare(void)
> {
> if (tick_nohz_full_cpu(smp_processor_id()))
> diff --git a/kernel/context_tracking.c b/kernel/context_tracking.c
> index a743e7ffa6c0..347f99e1880f 100644
> --- a/kernel/context_tracking.c
> +++ b/kernel/context_tracking.c
> @@ -24,6 +24,7 @@
> #include <linux/export.h>
> #include <linux/kprobes.h>
> #include <trace/events/rcu.h>
> +#include <linux/tick.h>
>
>
> DEFINE_PER_CPU(struct context_tracking, context_tracking) = {
> @@ -466,6 +467,13 @@ void noinstr __ct_user_enter(enum ctx_state state)
> */
> if (state == CT_STATE_USER) {
> instrumentation_begin();
> + /*
> + * On nohz_full CPUs the tick may have been left running in the
> + * kernel, e.g. kept by a tick dependency that is now gone.
> + * Stop it now rather than let it interrupt userspace once
> + * more before the next IRQ exit notices.
> + */
> + tick_nohz_user_enter();
You can move that a little bit further, outside "state == CT_STATE_USER", right
before rcu_irq_work_resched(). This will need a new pair of
instrumentation_begin()/end().
This way it also applies before switching to guest.
> trace_user_enter(0);
> vtime_user_enter(current);
> instrumentation_end();
> diff --git a/kernel/time/tick-sched.c b/kernel/time/tick-sched.c
> index c6d86e4da8a9..645dba919386 100644
> --- a/kernel/time/tick-sched.c
> +++ b/kernel/time/tick-sched.c
> @@ -1071,6 +1071,30 @@ static void tick_nohz_full_update_tick(struct tick_sched *ts)
> __tick_nohz_full_update_tick(ts, ktime_get());
> }
>
> +#ifdef CONFIG_NO_HZ_FULL
> +void __tick_nohz_user_enter(void)
> +{
> + struct tick_sched *ts;
> + int cpu;
> +
> + lockdep_assert_irqs_disabled();
> +
> + cpu = smp_processor_id();
> + if (!tick_nohz_full_cpu(cpu))
> + return;
> +
> + ts = this_cpu_ptr(&tick_cpu_sched);
> + if (!tick_sched_flag_test(ts, TS_FLAG_NOHZ))
> + return;
> +
> + if (tick_sched_flag_test(ts, TS_FLAG_STOPPED))
> + return;
> +
> + if (can_stop_full_tick(cpu, ts))
> + tick_nohz_full_stop_tick(ts, cpu);
> +}
> +#endif
Looks like this can move right below the definition of
tick_nohz_full_stop_tick() to avoid more ifdef blocks.
Thanks.
> +
> /*
> * A pending softirq outside an IRQ (or softirq disabled section) context
> * should be waiting for ksoftirqd to handle it. Therefore we shouldn't
> --
> 2.56.0
>
--
Frederic Weisbecker
SUSE Labs
next prev parent reply other threads:[~2026-11-11 16:25 UTC|newest]
Thread overview: 14+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-11-11 11:43 [PATCH v2 0/4] Stop the idle tick on polling idle on nohz_full CPUs Marco Crivellari
2026-11-11 11:43 ` [PATCH v2 1/4] tick/nohz: Re-evaluate the tick on return to user space Marco Crivellari
2026-11-11 16:25 ` Frederic Weisbecker [this message]
2026-11-12 10:36 ` Marco Crivellari
2026-11-11 11:43 ` [PATCH v2 2/4] sched/idle: Don't handle polling idle as dynticks idle Marco Crivellari
2026-11-11 16:57 ` Frederic Weisbecker
2026-11-11 16:58 ` Peter Zijlstra
2026-11-12 10:00 ` Marco Crivellari
2026-11-12 3:27 ` K Prateek Nayak
2026-11-12 10:08 ` Marco Crivellari
2026-11-11 11:43 ` [PATCH v2 3/4] tick/nohz: Remove tick_nohz_idle_restart_tick() Marco Crivellari
2026-11-11 16:59 ` Frederic Weisbecker
2026-11-11 11:43 ` [PATCH v2 4/4] Documentation: no_hz: Add tick stop in polling idle Marco Crivellari
2026-11-11 17:00 ` Frederic Weisbecker
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=avSW3VBwd1Mym6rJ@localhost.localdomain \
--to=frederic@kernel.org \
--cc=anna-maria@linutronix.de \
--cc=atomlin@atomlin.com \
--cc=linux-kernel@vger.kernel.org \
--cc=marco.crivellari@suse.com \
--cc=mhocko@suse.com \
--cc=mingo@kernel.org \
--cc=mtosatti@redhat.com \
--cc=paulmck@kernel.org \
--cc=tglx@kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.