summaryrefslogtreecommitdiff
path: root/kernel/time
diff options
context:
space:
mode:
authorThomas Gleixner <tglx@kernel.org>2026-04-08 13:54:11 +0200
committerThomas Gleixner <tglx@kernel.org>2026-05-01 21:36:12 +0200
commit183d00b727139cf3b4be78d66a5602ce71a3acec (patch)
tree6e8d6d002245fbf1ea6c567b5866ce9ec576dfda /kernel/time
parentacc071343d29c2361619b05ad50ea3de9ef9a3ac (diff)
downloadlinux-next-183d00b727139cf3b4be78d66a5602ce71a3acec.tar.gz
linux-next-183d00b727139cf3b4be78d66a5602ce71a3acec.zip
alarmtimer: Provide alarm_start_timer()
Alarm timers utilize hrtimers for normal operation and only switch to the RTC on suspend. In order to catch already expired timers early and without going through a timer interrupt cycle, provide a new start function which internally uses hrtimer_start_range_ns_user(). If hrtimer_start_range_ns_user() detects an already expired timer, it does not queue it. In that case remove the timer from the alarm base as well. Return the status queued or not back to the caller to handle the early expiry. Signed-off-by: Thomas Gleixner <tglx@kernel.org> Reviewed-by: Frederic Weisbecker <frederic@kernel.org> Acked-by: John Stultz <jstultz@google.com> Link: https://patch.msgid.link/20260408114952.332822525@kernel.org
Diffstat (limited to 'kernel/time')
-rw-r--r--kernel/time/alarmtimer.c28
1 files changed, 28 insertions, 0 deletions
diff --git a/kernel/time/alarmtimer.c b/kernel/time/alarmtimer.c
index e10021be190f..2348b0839114 100644
--- a/kernel/time/alarmtimer.c
+++ b/kernel/time/alarmtimer.c
@@ -369,6 +369,34 @@ void alarm_start_relative(struct alarm *alarm, ktime_t start)
}
EXPORT_SYMBOL_GPL(alarm_start_relative);
+/**
+ * alarm_start_timer - Sets an alarm to fire
+ * @alarm: Pointer to alarm to set
+ * @expires: Expiry time
+ * @relative: True if @expires is relative
+ *
+ * Returns: True if the alarm was queued. False if it already expired
+ */
+bool alarm_start_timer(struct alarm *alarm, ktime_t expires, bool relative)
+{
+ struct alarm_base *base = &alarm_bases[alarm->type];
+
+ if (relative)
+ expires = ktime_add_safe(expires, base->get_ktime());
+
+ trace_alarmtimer_start(alarm, base->get_ktime());
+
+ guard(spinlock_irqsave)(&base->lock);
+ alarm->node.expires = expires;
+ alarmtimer_enqueue(base, alarm);
+ if (!hrtimer_start_range_ns_user(&alarm->timer, expires, 0, HRTIMER_MODE_ABS)) {
+ alarmtimer_dequeue(base, alarm);
+ return false;
+ }
+ return true;
+}
+EXPORT_SYMBOL_GPL(alarm_start_timer);
+
void alarm_restart(struct alarm *alarm)
{
struct alarm_base *base = &alarm_bases[alarm->type];