From: Thomas Gleixner <tglx@kernel.org>
To: Peter Zijlstra <peterz@infradead.org>
Cc: Borislav Petkov <bp@alien8.de>, Calvin Owens <calvin@wbinvd.org>,
Petr Mladek <pmladek@suse.com>,
linux-kernel@vger.kernel.org, arighi@nvidia.com,
yaozhenguo1@gmail.com, tj@kernel.org,
feng.tang@linux.alibaba.com, lirongqing@baidu.com,
realwujing@gmail.com, hu.shengming@zte.com.cn,
dianders@chromium.org, joel.granados@kernel.org,
Ingo Molnar <mingo@redhat.com>,
Juri Lelli <juri.lelli@redhat.com>,
Vincent Guittot <vincent.guittot@linaro.org>,
Dietmar Eggemann <dietmar.eggemann@arm.com>,
Steven Rostedt <rostedt@goodmis.org>,
Ben Segall <bsegall@google.com>, Mel Gorman <mgorman@suse.de>,
Valentin Schneider <vschneid@redhat.com>,
Frederic Weisbecker <frederic@kernel.org>,
Anna-Maria Behnsen <anna-maria@linutronix.de>,
x86@kernel.org
Subject: Re: [PATCH] clockevents: Prevent timer interrupt starvation
Date: Fri, 03 Apr 2026 18:17:15 +0200 [thread overview]
Message-ID: <87341c6mt0.ffs@tglx> (raw)
In-Reply-To: <20260403121648.GZ3738010@noisy.programming.kicks-ass.net>
On Fri, Apr 03 2026 at 14:16, Peter Zijlstra wrote:
> On Thu, Apr 02, 2026 at 07:07:49PM +0200, Thomas Gleixner wrote:
> /**
> @@ -324,16 +325,31 @@ int clockevents_program_event(struct clock_event_device *dev, ktime_t expires,
> return dev->set_next_ktime(expires, dev);
>
> delta = ktime_to_ns(ktime_sub(expires, ktime_get()));
> - if (delta <= 0)
> - return force ? clockevents_program_min_delta(dev) : -ETIME;
> + if (delta <= 0) {
> + rc = -ETIME;
> + goto error;
> + }
That's not working in the case that user space manages to set the expiry
time so it stays in the min_delta_ns window, which is doable. I just
tried. Then we are back to square one.
Less convoluted but untested version of my initial idea below.
Thanks,
tglx
---
--- a/include/linux/clockchips.h
+++ b/include/linux/clockchips.h
@@ -80,6 +80,7 @@ enum clock_event_state {
* @shift: nanoseconds to cycles divisor (power of two)
* @state_use_accessors:current state of the device, assigned by the core code
* @features: features
+ * @next_event_forced: True if the last programming was a forced event
* @retries: number of forced programming retries
* @set_state_periodic: switch state to periodic
* @set_state_oneshot: switch state to oneshot
@@ -108,6 +109,7 @@ struct clock_event_device {
u32 shift;
enum clock_event_state state_use_accessors;
unsigned int features;
+ unsigned int next_event_forced;
unsigned long retries;
int (*set_state_periodic)(struct clock_event_device *);
--- a/kernel/time/clockevents.c
+++ b/kernel/time/clockevents.c
@@ -172,6 +172,7 @@ void clockevents_shutdown(struct clock_e
{
clockevents_switch_state(dev, CLOCK_EVT_STATE_SHUTDOWN);
dev->next_event = KTIME_MAX;
+ dev->next_event_forced = 0;
}
/**
@@ -224,13 +225,7 @@ static int clockevents_increase_min_delt
return 0;
}
-/**
- * clockevents_program_min_delta - Set clock event device to the minimum delay.
- * @dev: device to program
- *
- * Returns 0 on success, -ETIME when the retry loop failed.
- */
-static int clockevents_program_min_delta(struct clock_event_device *dev)
+static int __clockevents_program_min_delta(struct clock_event_device *dev)
{
unsigned long long clc;
int64_t delta;
@@ -263,13 +258,7 @@ static int clockevents_program_min_delta
#else /* CONFIG_GENERIC_CLOCKEVENTS_MIN_ADJUST */
-/**
- * clockevents_program_min_delta - Set clock event device to the minimum delay.
- * @dev: device to program
- *
- * Returns 0 on success, -ETIME when the retry loop failed.
- */
-static int clockevents_program_min_delta(struct clock_event_device *dev)
+static int __clockevents_program_min_delta(struct clock_event_device *dev)
{
unsigned long long clc;
int64_t delta = 0;
@@ -293,6 +282,21 @@ static int clockevents_program_min_delta
#endif /* CONFIG_GENERIC_CLOCKEVENTS_MIN_ADJUST */
/**
+ * clockevents_program_min_delta - Set clock event device to the minimum delay.
+ * @dev: device to program
+ *
+ * Returns 0 on success, -ETIME when the retry loop failed.
+ */
+static int clockevents_program_min_delta(struct clock_event_device *dev)
+{
+ if (dev->next_event_forced)
+ return 0;
+
+ dev->next_event_forced = 1;
+ return __clockevents_program_min_delta(dev);
+}
+
+/**
* clockevents_program_event - Reprogram the clock event device.
* @dev: device to program
* @expires: absolute expiry time (monotonic clock)
@@ -324,16 +328,18 @@ int clockevents_program_event(struct clo
return dev->set_next_ktime(expires, dev);
delta = ktime_to_ns(ktime_sub(expires, ktime_get()));
- if (delta <= 0)
- return force ? clockevents_program_min_delta(dev) : -ETIME;
- delta = min(delta, (int64_t) dev->max_delta_ns);
- delta = max(delta, (int64_t) dev->min_delta_ns);
+ if (!dev->next_event_forced || delta > dev->min_delta_ns) {
- clc = ((unsigned long long) delta * dev->mult) >> dev->shift;
- rc = dev->set_next_event((unsigned long) clc, dev);
+ delta = min(delta, (int64_t) dev->max_delta_ns);
+ delta = max(delta, (int64_t) dev->min_delta_ns);
+ clc = ((unsigned long long) delta * dev->mult) >> dev->shift;
+ rc = dev->set_next_event((unsigned long) clc, dev);
+ if (!rc)
+ return 0;
+ }
- return (rc && force) ? clockevents_program_min_delta(dev) : rc;
+ return force ? clockevents_program_min_delta(dev) : rc;
}
/*
--- a/kernel/time/hrtimer.c
+++ b/kernel/time/hrtimer.c
@@ -1888,6 +1888,7 @@ void hrtimer_interrupt(struct clock_even
BUG_ON(!cpu_base->hres_active);
cpu_base->nr_events++;
dev->next_event = KTIME_MAX;
+ dev->next_event_forced = 0;
raw_spin_lock_irqsave(&cpu_base->lock, flags);
entry_time = now = hrtimer_update_base(cpu_base);
--- a/kernel/time/tick-common.c
+++ b/kernel/time/tick-common.c
@@ -110,6 +110,7 @@ void tick_handle_periodic(struct clock_e
int cpu = smp_processor_id();
ktime_t next = dev->next_event;
+ dev->next_event_forced = 0;
tick_periodic(cpu);
/*
--- a/kernel/time/tick-sched.c
+++ b/kernel/time/tick-sched.c
@@ -1513,6 +1513,7 @@ static void tick_nohz_lowres_handler(str
struct tick_sched *ts = this_cpu_ptr(&tick_cpu_sched);
dev->next_event = KTIME_MAX;
+ dev->next_event_forced = 0;
if (likely(tick_nohz_handler(&ts->sched_timer) == HRTIMER_RESTART))
tick_program_event(hrtimer_get_expires(&ts->sched_timer), 1);
next prev parent reply other threads:[~2026-04-03 16:17 UTC|newest]
Thread overview: 23+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-03-24 23:32 [BUG] Random hard lockup with userspace %ip on 7.0-rc5 Calvin Owens
2026-03-25 9:03 ` Petr Mladek
2026-03-25 16:56 ` Thomas Gleixner
2026-04-01 1:58 ` Calvin Owens
2026-04-01 15:01 ` Thomas Gleixner
2026-04-01 15:12 ` Borislav Petkov
2026-04-01 16:34 ` Borislav Petkov
2026-04-02 17:07 ` [PATCH] clockevents: Prevent timer interrupt starvation Thomas Gleixner
2026-04-03 5:11 ` Calvin Owens
2026-04-03 14:41 ` Thomas Gleixner
2026-04-03 15:58 ` Calvin Owens
2026-04-03 19:00 ` Thomas Gleixner
2026-04-04 0:15 ` Calvin Owens
2026-04-08 8:52 ` Thomas Gleixner
2026-04-03 12:16 ` Peter Zijlstra
2026-04-03 14:43 ` Thomas Gleixner
2026-04-03 16:17 ` Thomas Gleixner [this message]
2026-04-03 21:01 ` Peter Zijlstra
2026-04-03 21:24 ` Thomas Gleixner
2026-04-03 22:14 ` Thomas Gleixner
2026-04-03 22:21 ` Peter Zijlstra
2026-03-27 1:36 ` [BUG] Random hard lockup with userspace %ip on 7.0-rc5 Feng Tang
2026-03-27 15:36 ` Calvin Owens
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=87341c6mt0.ffs@tglx \
--to=tglx@kernel.org \
--cc=anna-maria@linutronix.de \
--cc=arighi@nvidia.com \
--cc=bp@alien8.de \
--cc=bsegall@google.com \
--cc=calvin@wbinvd.org \
--cc=dianders@chromium.org \
--cc=dietmar.eggemann@arm.com \
--cc=feng.tang@linux.alibaba.com \
--cc=frederic@kernel.org \
--cc=hu.shengming@zte.com.cn \
--cc=joel.granados@kernel.org \
--cc=juri.lelli@redhat.com \
--cc=linux-kernel@vger.kernel.org \
--cc=lirongqing@baidu.com \
--cc=mgorman@suse.de \
--cc=mingo@redhat.com \
--cc=peterz@infradead.org \
--cc=pmladek@suse.com \
--cc=realwujing@gmail.com \
--cc=rostedt@goodmis.org \
--cc=tj@kernel.org \
--cc=vincent.guittot@linaro.org \
--cc=vschneid@redhat.com \
--cc=x86@kernel.org \
--cc=yaozhenguo1@gmail.com \
/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.