posix-timers: Document common_clock_get() correctly
authorThomas Gleixner <tglx@linutronix.de>
Tue, 25 Apr 2023 18:49:12 +0000 (20:49 +0200)
committerThomas Gleixner <tglx@linutronix.de>
Sun, 18 Jun 2023 20:41:50 +0000 (22:41 +0200)
Replace another confusing and inaccurate set of comments.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Reviewed-by: Frederic Weisbecker <frederic@kernel.org>
Link: https://lore.kernel.org/r/20230425183313.409169321@linutronix.de
kernel/time/posix-timers.c

index 1acdd04e5d26d28c273c13a364bb501c53623df8..e1af74ca80abc12903f437d6a0940f3d69300557 100644 (file)
@@ -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
- * is ALWAYS called with spin_lock_irq on the timer, thus it must not
- * mess with irq.
+ * Get the time remaining on a POSIX.1b interval timer.
  *
- * We have a couple of messes to clean up here.  First there is the case
- * 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.
+ * Two issues to handle here:
  *
- * The second issue is the SIGEV_NONE timer which may be active but is
- * not really ever put in the timer list (to save system resources).
- * 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
- * report.
+ *  1) The timer has a requeue pending. The return value must appear as
+ *     if the timer has been requeued right now.
+ *
+ *  2) The timer is a SIGEV_NONE timer. These timers are never enqueued
+ *     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)
 {
@@ -689,8 +685,12 @@ void common_timer_get(struct k_itimer *timr, struct itimerspec64 *cur_setting)
                cur_setting->it_interval = ktime_to_timespec64(iv);
        } else if (!timr->it_active) {
                /*
-                * SIGEV_NONE oneshot timers are never queued. Check them
-                * below.
+                * SIGEV_NONE oneshot timers are never queued and therefore
+                * 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)
                        return;
@@ -699,18 +699,29 @@ void common_timer_get(struct k_itimer *timr, struct itimerspec64 *cur_setting)
        now = kc->clock_get_ktime(timr->it_clock);
 
        /*
-        * When a requeue is pending or this is a SIGEV_NONE timer move the
-        * expiry time forward by intervals, so expiry is > now.
+        * If this is an interval timer and either has requeue pending or
+        * 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))
                timr->it_overrun += kc->timer_forward(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) {
                /*
-                * A single shot SIGEV_NONE timer must return 0, when
-                * it is expired !
+                * A single shot SIGEV_NONE timer must return 0, when it is
+                * 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)
                        cur_setting->it_value.tv_nsec = 1;
@@ -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)
 {
        struct k_itimer *timr;