linux/kernel/time
Thomas Gleixner bd5956166d hrtimer: Provide hrtimer_start_range_ns_user()
Calvin reported an odd NMI watchdog lockup which claims that the CPU locked
up in user space. He provided a reproducer, which set's up a timerfd based
timer and then rearms it in a loop with an absolute expiry time of 1ns.

As the expiry time is in the past, the timer ends up as the first expiring
timer in the per CPU hrtimer base and the clockevent device is programmed
with the minimum delta value. If the machine is fast enough, this ends up
in a endless loop of programming the delta value to the minimum value
defined by the clock event device, before the timer interrupt can fire,
which starves the interrupt and consequently triggers the lockup detector
because the hrtimer callback of the lockup mechanism is never invoked.

The clockevents code already has a last resort mechanism to prevent that,
but it's sensible to catch such issues before trying to reprogram the clock
event device.

Provide a variant of hrtimer_start_range_ns(), which sanity checks the
timer after queueing it. It does not so before because the timer might be
armed and therefore needs to be dequeued. also we optimize for the latest
possible point to check, so that the clock event prevention is avoided as
much as possible.

If the timer is already expired _before_ the clock event is reprogrammed,
remove the timer from the queue and signal to the caller that the operation
failed by returning false.

That allows the caller to take immediate action without going through the
loops and hoops of the hrtimer interrupt.

The queueing code can't invoke the timer callback as the caller might hold
a lock which is taken in the callback.

Add a tracepoint which allows to analyze the expired at start situation.

Reported-by: Calvin Owens <calvin@wbinvd.org>
Signed-off-by: Thomas Gleixner <tglx@kernel.org>
Tested-by: Calvin Owens <calvin@wbinvd.org>
Reviewed-by: Frederic Weisbecker <frederic@kernel.org>
Acked-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Link: https://patch.msgid.link/20260408114951.995031895@kernel.org
2026-05-01 21:36:11 +02:00
..
.kunitconfig time/kunit: Add .kunitconfig 2026-02-24 08:41:51 +01:00
alarmtimer.c Merge branch 'timers/urgent' into timers/core 2026-04-11 07:58:33 +02:00
clockevents.c clockevents: Add missing resets of the next_event_forced flag 2026-04-16 21:22:04 +02:00
clocksource-wdtest.c clocksource: Rewrite watchdog code completely 2026-03-20 13:36:32 +01:00
clocksource.c clocksource: Rewrite watchdog code completely 2026-03-20 13:36:32 +01:00
hrtimer.c hrtimer: Provide hrtimer_start_range_ns_user() 2026-05-01 21:36:11 +02:00
itimer.c timers/itimer: Avoid direct access to hrtimer clockbase 2025-09-09 12:27:17 +02:00
jiffies.c Linux 7.0-rc4 2026-03-21 08:02:36 +01:00
Kconfig Update to the VDSO subsystem: 2026-04-14 10:53:44 -07:00
Makefile timens: Remove dependency on the vDSO 2026-03-26 15:44:23 +01:00
namespace_internal.h timens: Remove dependency on the vDSO 2026-03-26 15:44:23 +01:00
namespace_vdso.c mm.git review status for linus..mm-stable 2026-04-15 12:59:16 -07:00
namespace.c timens: Use task_lock guard in timens_get*() 2026-04-01 17:13:36 +02:00
ntp_internal.h ntp: Rename __do_adjtimex() to ntp_adjtimex() 2025-06-19 14:28:23 +02:00
ntp.c ntp: Use ktime_get_ntp_seconds() 2025-06-19 14:28:24 +02:00
posix-clock.c Convert 'alloc_obj' family to use the new default GFP_KERNEL argument 2026-02-21 17:09:51 -08:00
posix-cpu-timers.c hrtimer: Store time as ktime_t in restart block 2025-11-14 16:31:19 +01:00
posix-stubs.c posix-timers: Get rid of [COMPAT_]SYS_NI() uses 2023-12-20 21:30:27 -08:00
posix-timers.c posix-timers: Fix stale function name in comment 2026-03-28 14:18:13 +01:00
posix-timers.h timekeeping: Add minimal posix-timers support for auxiliary clocks 2025-06-27 20:13:12 +02:00
sched_clock.c time/sched_clock: Use ACCESS_PRIVATE() to evaluate hrtimer::function 2026-01-13 18:08:57 +01:00
sleep_timeout.c treewide, timers: Rename from_timer() to timer_container_of() 2025-06-08 09:07:37 +02:00
test_udelay.c time: Add MODULE_DESCRIPTION() to time test modules 2024-06-03 11:18:50 +02:00
tick-broadcast-hrtimer.c clockevents: Remove redundant CLOCK_EVT_FEAT_KTIME 2026-02-27 16:40:06 +01:00
tick-broadcast.c clockevents: Add missing resets of the next_event_forced flag 2026-04-16 21:22:04 +02:00
tick-common.c clockevents: Prevent timer interrupt starvation 2026-04-10 22:45:38 +02:00
tick-internal.h cpufreq: ondemand: Simplify idle cputime granularity test 2026-01-28 22:24:58 +01:00
tick-legacy.c
tick-oneshot.c treewide: Update email address 2026-01-11 06:09:11 -10:00
tick-sched.c Merge branch 'timers/urgent' into timers/core 2026-04-11 07:58:33 +02:00
tick-sched.h tick/sched: Fix struct tick_sched doc warnings 2024-04-01 10:36:35 +02:00
time_test.c time/kunit: Document handling of negative years of is_leap() 2026-02-02 12:37:54 +01:00
time.c time/jiffies: Mark jiffies_64_to_clock_t() notrace 2026-03-11 10:33:12 +01:00
timeconst.bc
timeconv.c
timecounter.c time/timecounter: Inline timecounter_cyc2time() 2025-12-15 20:16:49 +01:00
timekeeping_debug.c timekeeping: Add percpu counter for tracking floor swap events 2024-10-10 10:20:46 +02:00
timekeeping_internal.h timekeeping: Provide ktime_get_ntp_seconds() 2025-06-19 14:28:23 +02:00
timekeeping.c Linux 7.0-rc4 2026-03-21 08:02:36 +01:00
timekeeping.h timekeeping: Provide infrastructure for coupled clockevents 2026-02-27 16:40:08 +01:00
timer_list.c timer_list: Print offset as signed integer 2026-03-12 12:15:54 +01:00
timer_migration.c cgroup: Fixes for v7.0-rc2 2026-03-03 14:25:18 -08:00
timer_migration.h timers/migration: Rename 'online' bit to 'available' 2025-11-20 20:17:31 +01:00
timer.c timers: Get this_cpu once while clearing the idle state 2026-03-24 23:21:30 +01:00
vsyscall.c vdso/vsyscall: Avoid slow division loop in auxiliary clock update 2025-09-03 11:55:11 +02:00