[PATCH v1] hrtimer: Fix is_hard/is_soft both false with missing HARD/SOFT flag

From: guoqi0226

Date: Sun Mar 15 2026 - 02:16:03 EST


When hrtimer mode is only ABS/REL (e.g. HRTIMER_MODE_ABS) with no explicit
SOFT/HARD flag, and CONFIG_PREEMPT_RT is disabled, both timer->is_hard and
is_soft become false, violating the hard/soft exclusive design rule.

Enforce correct hard/soft timer via effective_mode:
- Enable softtimer when CONFIG_PREEMPT_RT is enabled and no HARD flag
- Add HRTIMER_MODE_HARD to effective_mode when
CONFIG_PREEMPT_RT is disabled (e.g. HRTIMER_MODE_ABS)
- Compute timer->is_hard as !!(effective_mode & HRTIMER_MODE_HARD)

This ensures exactly one of is_hard/is_soft is true.

Signed-off-by: guoqi0226 <guoqi0226@xxxxxxx>
---
kernel/time/hrtimer.c | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/kernel/time/hrtimer.c b/kernel/time/hrtimer.c
index 860af7a58428..5107d2e69887 100644
--- a/kernel/time/hrtimer.c
+++ b/kernel/time/hrtimer.c
@@ -1618,6 +1618,7 @@ static void __hrtimer_setup(struct hrtimer *timer,
{
bool softtimer = !!(mode & HRTIMER_MODE_SOFT);
struct hrtimer_cpu_base *cpu_base;
+ hrtimer_mode effective_mode = mode;
int base;

/*
@@ -1628,6 +1629,9 @@ static void __hrtimer_setup(struct hrtimer *timer,
*/
if (IS_ENABLED(CONFIG_PREEMPT_RT) && !(mode & HRTIMER_MODE_HARD))
softtimer = true;
+ else if (!IS_ENABLED(CONFIG_PREEMPT_RT) && !(mode & HRTIMER_MODE_HARD) &&
+ !(mode & HRTIMER_MODE_SOFT))
+ effective_mode |= HRTIMER_MODE_HARD;

memset(timer, 0, sizeof(struct hrtimer));

@@ -1644,7 +1648,7 @@ static void __hrtimer_setup(struct hrtimer *timer,
base = softtimer ? HRTIMER_MAX_CLOCK_BASES / 2 : 0;
base += hrtimer_clockid_to_base(clock_id);
timer->is_soft = softtimer;
- timer->is_hard = !!(mode & HRTIMER_MODE_HARD);
+ timer->is_hard = !!(effective_mode & HRTIMER_MODE_HARD);
timer->base = &cpu_base->clock_base[base];
timerqueue_init(&timer->node);

--
2.25.1