]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
hrtimer: Use hrtimer_start_expires_user() for hrtimer sleepers
authorThomas Gleixner <tglx@kernel.org>
Wed, 8 Apr 2026 11:53:52 +0000 (13:53 +0200)
committerThomas Gleixner <tglx@kernel.org>
Fri, 1 May 2026 19:36:11 +0000 (21:36 +0200)
Most hrtimer sleepers are user controlled and user space can hand arbitrary
expiry values in as long as they are valid timespecs. If the expiry value
is in the past then this requires a full loop through reprogramming the
clock event device, taking the hrtimer interrupt, waking the task and
reprogram again.

Use hrtimer_start_expires_user() which avoids the full round trip by
checking the timer for expiry on enqueue.

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/20260408114952.062400833@kernel.org
kernel/time/hrtimer.c

index 79aaac4711644940fdbf91abea95b524b4b34405..8cfc7aacece1817bb8c9e15b88787c3d202d2c37 100644 (file)
@@ -2315,7 +2315,11 @@ void hrtimer_sleeper_start_expires(struct hrtimer_sleeper *sl, enum hrtimer_mode
        if (IS_ENABLED(CONFIG_PREEMPT_RT) && sl->timer.is_hard)
                mode |= HRTIMER_MODE_HARD;
 
-       hrtimer_start_expires(&sl->timer, mode);
+       /* If already expired, clear the task pointer and set current state to running */
+       if (!hrtimer_start_expires_user(&sl->timer, mode)) {
+               sl->task = NULL;
+               __set_current_state(TASK_RUNNING);
+       }
 }
 EXPORT_SYMBOL_GPL(hrtimer_sleeper_start_expires);