Commit a86e9284 authored by Thomas Gleixner's avatar Thomas Gleixner

posix-timers: Document common_clock_get() correctly

Replace another confusing and inaccurate set of comments.
Signed-off-by: default avatarThomas Gleixner <tglx@linutronix.de>
Reviewed-by: default avatarFrederic Weisbecker <frederic@kernel.org>
Link: https://lore.kernel.org/r/20230425183313.409169321@linutronix.de
parent 01679b5d
...@@ -660,20 +660,16 @@ static s64 common_hrtimer_forward(struct k_itimer *timr, ktime_t now) ...@@ -660,20 +660,16 @@ static s64 common_hrtimer_forward(struct k_itimer *timr, ktime_t now)
} }
/* /*
* Get the time remaining on a POSIX.1b interval timer. This function * Get the time remaining on a POSIX.1b interval timer.
* is ALWAYS called with spin_lock_irq on the timer, thus it must not
* mess with irq.
* *
* We have a couple of messes to clean up here. First there is the case * Two issues to handle here:
* of a timer that has a requeue pending. These timers should appear to
* be in the timer list with an expiry as if we were to requeue them
* now.
* *
* The second issue is the SIGEV_NONE timer which may be active but is * 1) The timer has a requeue pending. The return value must appear as
* not really ever put in the timer list (to save system resources). * if the timer has been requeued right now.
* This timer may be expired, and if so, we will do it here. Otherwise *
* it is the same as a requeue pending timer WRT to what we should * 2) The timer is a SIGEV_NONE timer. These timers are never enqueued
* report. * into the hrtimer queue and therefore never expired. Emulate expiry
* here taking #1 into account.
*/ */
void common_timer_get(struct k_itimer *timr, struct itimerspec64 *cur_setting) void common_timer_get(struct k_itimer *timr, struct itimerspec64 *cur_setting)
{ {
...@@ -689,8 +685,12 @@ void common_timer_get(struct k_itimer *timr, struct itimerspec64 *cur_setting) ...@@ -689,8 +685,12 @@ void common_timer_get(struct k_itimer *timr, struct itimerspec64 *cur_setting)
cur_setting->it_interval = ktime_to_timespec64(iv); cur_setting->it_interval = ktime_to_timespec64(iv);
} else if (!timr->it_active) { } else if (!timr->it_active) {
/* /*
* SIGEV_NONE oneshot timers are never queued. Check them * SIGEV_NONE oneshot timers are never queued and therefore
* below. * timr->it_active is always false. The check below
* vs. remaining time will handle this case.
*
* For all other timers there is nothing to update here, so
* return.
*/ */
if (!sig_none) if (!sig_none)
return; return;
...@@ -699,18 +699,29 @@ void common_timer_get(struct k_itimer *timr, struct itimerspec64 *cur_setting) ...@@ -699,18 +699,29 @@ void common_timer_get(struct k_itimer *timr, struct itimerspec64 *cur_setting)
now = kc->clock_get_ktime(timr->it_clock); now = kc->clock_get_ktime(timr->it_clock);
/* /*
* When a requeue is pending or this is a SIGEV_NONE timer move the * If this is an interval timer and either has requeue pending or
* expiry time forward by intervals, so expiry is > now. * is a SIGEV_NONE timer move the expiry time forward by intervals,
* so expiry is > now.
*/ */
if (iv && (timr->it_requeue_pending & REQUEUE_PENDING || sig_none)) if (iv && (timr->it_requeue_pending & REQUEUE_PENDING || sig_none))
timr->it_overrun += kc->timer_forward(timr, now); timr->it_overrun += kc->timer_forward(timr, now);
remaining = kc->timer_remaining(timr, now); remaining = kc->timer_remaining(timr, now);
/* Return 0 only, when the timer is expired and not pending */ /*
* As @now is retrieved before a possible timer_forward() and
* cannot be reevaluated by the compiler @remaining is based on the
* same @now value. Therefore @remaining is consistent vs. @now.
*
* Consequently all interval timers, i.e. @iv > 0, cannot have a
* remaining time <= 0 because timer_forward() guarantees to move
* them forward so that the next timer expiry is > @now.
*/
if (remaining <= 0) { if (remaining <= 0) {
/* /*
* A single shot SIGEV_NONE timer must return 0, when * A single shot SIGEV_NONE timer must return 0, when it is
* it is expired ! * expired! Timers which have a real signal delivery mode
* must return a remaining time greater than 0 because the
* signal has not yet been delivered.
*/ */
if (!sig_none) if (!sig_none)
cur_setting->it_value.tv_nsec = 1; cur_setting->it_value.tv_nsec = 1;
...@@ -719,7 +730,6 @@ void common_timer_get(struct k_itimer *timr, struct itimerspec64 *cur_setting) ...@@ -719,7 +730,6 @@ void common_timer_get(struct k_itimer *timr, struct itimerspec64 *cur_setting)
} }
} }
/* Get the time remaining on a POSIX.1b interval timer. */
static int do_timer_gettime(timer_t timer_id, struct itimerspec64 *setting) static int do_timer_gettime(timer_t timer_id, struct itimerspec64 *setting)
{ {
struct k_itimer *timr; struct k_itimer *timr;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment