diff --git a/include/linux/alarmtimer.h b/include/linux/alarmtimer.h index 3ffa5341dce2..14d729fe0fd6 100644 --- a/include/linux/alarmtimer.h +++ b/include/linux/alarmtimer.h @@ -42,8 +42,14 @@ struct alarm { void *data; }; +static __always_inline ktime_t alarm_get_expires(struct alarm *alarm) +{ + return alarm->node.expires; +} + void alarm_init(struct alarm *alarm, enum alarmtimer_type type, void (*function)(struct alarm *, ktime_t)); +bool alarm_start_timer(struct alarm *alarm, ktime_t expires, bool relative); void alarm_start(struct alarm *alarm, ktime_t start); void alarm_start_relative(struct alarm *alarm, ktime_t start); void alarm_restart(struct alarm *alarm); 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];