summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Gleixner <tglx@kernel.org>2026-04-08 13:54:01 +0200
committerThomas Gleixner <tglx@kernel.org>2026-05-01 21:36:12 +0200
commitcfb7fe3fdd4ca1d37da1ed15a1897d4a27c47a8a (patch)
tree0df10623b12923494bda0a8f8b5c15c7fb1c48ff
parent6fdb2677a594ab38eade927919bbd4d9688bfa1c (diff)
downloadlinux-cfb7fe3fdd4ca1d37da1ed15a1897d4a27c47a8a.tar.gz
linux-cfb7fe3fdd4ca1d37da1ed15a1897d4a27c47a8a.zip
posix-timers: Handle the timer_[re]arm() return value
The [re]arm callbacks will return true when the timer was queued and false if it was already expired at enqueue time. In both cases the call sites can trivially queue the signal right there, when the timer was already expired. That avoids a full round trip through the hrtimer interrupt. Signed-off-by: Thomas Gleixner <tglx@kernel.org> Reviewed-by: Frederic Weisbecker <frederic@kernel.org> Acked-by: Peter Zijlstra (Intel) <peterz@infradead.org> Link: https://patch.msgid.link/20260408114952.198028466@kernel.org
-rw-r--r--kernel/time/posix-timers.c22
1 files changed, 17 insertions, 5 deletions
diff --git a/kernel/time/posix-timers.c b/kernel/time/posix-timers.c
index da04ed42bf82..db62cfac169d 100644
--- a/kernel/time/posix-timers.c
+++ b/kernel/time/posix-timers.c
@@ -299,6 +299,8 @@ static bool common_hrtimer_rearm(struct k_itimer *timr)
static bool __posixtimer_deliver_signal(struct kernel_siginfo *info, struct k_itimer *timr)
{
+ bool queued;
+
guard(spinlock)(&timr->it_lock);
/*
@@ -312,12 +314,18 @@ static bool __posixtimer_deliver_signal(struct kernel_siginfo *info, struct k_it
if (!timr->it_interval || WARN_ON_ONCE(timr->it_status != POSIX_TIMER_REQUEUE_PENDING))
return true;
- timr->kclock->timer_rearm(timr);
- timr->it_status = POSIX_TIMER_ARMED;
+ /* timer_rearm() updates timr::it_overrun */
+ queued = timr->kclock->timer_rearm(timr);
+
timr->it_overrun_last = timr->it_overrun;
timr->it_overrun = -1LL;
++timr->it_signal_seq;
info->si_overrun = timer_overrun_to_int(timr);
+
+ if (queued)
+ timr->it_status = POSIX_TIMER_ARMED;
+ else
+ posix_timer_queue_signal(timr);
return true;
}
@@ -905,9 +913,13 @@ int common_timer_set(struct k_itimer *timr, int flags,
expires = timens_ktime_to_host(timr->it_clock, expires);
sigev_none = timr->it_sigev_notify == SIGEV_NONE;
- kc->timer_arm(timr, expires, flags & TIMER_ABSTIME, sigev_none);
- if (!sigev_none)
- timr->it_status = POSIX_TIMER_ARMED;
+ if (kc->timer_arm(timr, expires, flags & TIMER_ABSTIME, sigev_none)) {
+ if (!sigev_none)
+ timr->it_status = POSIX_TIMER_ARMED;
+ } else {
+ /* Timer was already expired, queue the signal */
+ posix_timer_queue_signal(timr);
+ }
return 0;
}