From: Thomas Gleixner Date: Tue, 24 Feb 2026 16:35:56 +0000 (+0100) Subject: sched/hrtick: Avoid tiny hrtick rearms X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=c8cdb9b516407a0b8c653c9c1d6f0931c3864384;p=thirdparty%2Fkernel%2Flinux.git sched/hrtick: Avoid tiny hrtick rearms Tiny adjustments to the hrtick expiry time below 5 microseconds are just causing extra work for no real value. Filter them out when restarting the hrtick. Signed-off-by: Thomas Gleixner Signed-off-by: Peter Zijlstra (Intel) Link: https://patch.msgid.link/20260224163429.340593047@kernel.org --- diff --git a/kernel/sched/core.c b/kernel/sched/core.c index a868f0a4159e7..5bc446e1b3d66 100644 --- a/kernel/sched/core.c +++ b/kernel/sched/core.c @@ -903,12 +903,24 @@ static enum hrtimer_restart hrtick(struct hrtimer *timer) return HRTIMER_NORESTART; } -static void __hrtick_restart(struct rq *rq) +static inline bool hrtick_needs_rearm(struct hrtimer *timer, ktime_t expires) +{ + /* + * Queued is false when the timer is not started or currently + * running the callback. In both cases, restart. If queued check + * whether the expiry time actually changes substantially. + */ + return !hrtimer_is_queued(timer) || + abs(expires - hrtimer_get_expires(timer)) > 5000; +} + +static void hrtick_cond_restart(struct rq *rq) { struct hrtimer *timer = &rq->hrtick_timer; ktime_t time = rq->hrtick_time; - hrtimer_start(timer, time, HRTIMER_MODE_ABS_PINNED_HARD); + if (hrtick_needs_rearm(timer, time)) + hrtimer_start(timer, time, HRTIMER_MODE_ABS_PINNED_HARD); } /* @@ -920,7 +932,7 @@ static void __hrtick_start(void *arg) struct rq_flags rf; rq_lock(rq, &rf); - __hrtick_restart(rq); + hrtick_cond_restart(rq); rq_unlock(rq, &rf); } @@ -950,9 +962,11 @@ void hrtick_start(struct rq *rq, u64 delay) } rq->hrtick_time = ktime_add_ns(ktime_get(), delta); + if (!hrtick_needs_rearm(&rq->hrtick_timer, rq->hrtick_time)) + return; if (rq == this_rq()) - __hrtick_restart(rq); + hrtimer_start(&rq->hrtick_timer, rq->hrtick_time, HRTIMER_MODE_ABS_PINNED_HARD); else smp_call_function_single_async(cpu_of(rq), &rq->hrtick_csd); } @@ -966,7 +980,7 @@ static inline void hrtick_schedule_exit(struct rq *rq) { if (rq->hrtick_sched & HRTICK_SCHED_START) { rq->hrtick_time = ktime_add_ns(ktime_get(), rq->hrtick_delay); - __hrtick_restart(rq); + hrtick_cond_restart(rq); } else if (idle_rq(rq)) { /* * No need for using hrtimer_is_active(). The timer is CPU local