mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: Shashank Mohan Jain <jain.sm@gmail.com>
To: Thomas Gleixner <tglx@kernel.org>,
	John Stultz <jstultz@google.com>,
	Anna-Maria Behnsen <anna-maria@linutronix.de>,
	Frederic Weisbecker <frederic@kernel.org>
Cc: Stephen Boyd <sboyd@kernel.org>,
	Miroslav Lichvar <mlichvar@redhat.com>,
	Shuah Khan <shuah@kernel.org>,
	Todd Poynor <toddpoynor@google.com>,
	linux-kernel@vger.kernel.org, linux-kselftest@vger.kernel.org
Subject: [PATCH 2/3] posix-timers: Report a disarmed SIGEV_NONE timer as disarmed
Date: Sun, 11 Oct 2026 10:49:42 +0530	[thread overview]
Message-ID: <20261011051943.60520-3-jain.sm@gmail.com> (raw)
In-Reply-To: <20261011051943.60520-1-jain.sm@gmail.com>

A SIGEV_NONE timer on a hrtimer or alarmtimer based clock is never
queued. The expiry time stored in the timer is all that
common_timer_get() has to compute the remaining time, and
common_timer_set() leaves it alone when the timer is disarmed with a
zero it_value. timer_gettime() then reports the remaining time of the
previous setting until that time has passed:

	struct sigevent sev = { .sigev_notify = SIGEV_NONE };
	struct itimerspec arm = { .it_value.tv_sec = 100 };
	struct itimerspec disarm = { }, cur;

	timer_create(CLOCK_MONOTONIC, &sev, &t);
	timer_settime(t, 0, &arm, NULL);
	timer_settime(t, 0, &disarm, NULL);
	timer_gettime(t, &cur);

leaves 99.99... seconds in cur.it_value. POSIX wants a zero it_value
for a disarmed timer. Timers which deliver a signal get that from the
POSIX_TIMER_DISARMED check in common_timer_get(), and the CPU time
clocks set the expiry time to 0 in posix_cpu_timer_set(), so they are
not affected. CLOCK_MONOTONIC, CLOCK_BOOTTIME, CLOCK_REALTIME and the
two alarm clocks are.

When a SIGEV_NONE timer is disarmed, move its expiry time into the
past. The timer_arm() callbacks only store the expiry time for such a
timer, so call them with an absolute expiry time of 0, which is not
after the current time of any of these clocks. common_timer_get() then
sees a remaining time which is not positive and reports a zero
it_value.

This is old behaviour: the sequence above gives the same result on a
v6.8 based distribution kernel. The commit which introduced it was
not searched for, hence no Fixes tag.

Tested in qemu with the sequence above on the five clocks, and with
the posix_timers selftest including the test added in the next patch.

Assisted-by: LLM
Signed-off-by: Shashank Mohan Jain <jain.sm@gmail.com>
---
Prepared with Claude Code (Anthropic), model Claude Opus 5.5
(claude-opus-5-5).

 kernel/time/posix-timers.c | 12 ++++++++++--
 1 file changed, 10 insertions(+), 2 deletions(-)

diff --git a/kernel/time/posix-timers.c b/kernel/time/posix-timers.c
index 436ba794cc..f6dd8d34a8 100644
--- a/kernel/time/posix-timers.c
+++ b/kernel/time/posix-timers.c
@@ -904,15 +904,23 @@ int common_timer_set(struct k_itimer *timr, int flags,
 
 	timr->it_status = POSIX_TIMER_DISARMED;
 	posix_timer_set_common(timr, new_setting);
+	sigev_none = timr->it_sigev_notify == SIGEV_NONE;
 
 	/* Keep timer disarmed when it_value is zero */
-	if (!new_setting->it_value.tv_sec && !new_setting->it_value.tv_nsec)
+	if (!new_setting->it_value.tv_sec && !new_setting->it_value.tv_nsec) {
+		/*
+		 * SIGEV_NONE timers are never queued. The expiry time is
+		 * the only information timer_gettime() has to tell whether
+		 * such a timer is armed, so move it into the past.
+		 */
+		if (sigev_none)
+			kc->timer_arm(timr, 0, true, true);
 		return 0;
+	}
 
 	expires = timespec64_to_ktime(new_setting->it_value);
 	if (flags & TIMER_ABSTIME)
 		expires = timens_ktime_to_host(timr->it_clock, expires);
-	sigev_none = timr->it_sigev_notify == SIGEV_NONE;
 
 	if (kc->timer_arm(timr, expires, flags & TIMER_ABSTIME, sigev_none)) {
 		if (!sigev_none)
-- 
2.43.0


  parent reply	other threads:[~2026-10-11  5:20 UTC|newest]

Thread overview: 4+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-10-11  5:19 [PATCH 0/3] timers: Report disarmed alarm timerfds and SIGEV_NONE timers " Shashank Mohan Jain
2026-10-11  5:19 ` [PATCH 1/3] alarmtimer: Reset the expiry time in alarm_init() Shashank Mohan Jain
2026-10-11  5:19 ` Shashank Mohan Jain [this message]
2026-10-11  5:19 ` [PATCH 3/3] selftests/timers: Test timer_gettime() on a disarmed SIGEV_NONE timer Shashank Mohan Jain

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20261011051943.60520-3-jain.sm@gmail.com \
    --to=jain.sm@gmail.com \
    --cc=anna-maria@linutronix.de \
    --cc=frederic@kernel.org \
    --cc=jstultz@google.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-kselftest@vger.kernel.org \
    --cc=mlichvar@redhat.com \
    --cc=sboyd@kernel.org \
    --cc=shuah@kernel.org \
    --cc=tglx@kernel.org \
    --cc=toddpoynor@google.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®