]> git.proxmox.com Git - mirror_ubuntu-jammy-kernel.git/commitdiff
timers: Add comments about calc_index() ceiling work
authorFrederic Weisbecker <frederic@kernel.org>
Fri, 17 Jul 2020 14:05:44 +0000 (16:05 +0200)
committerThomas Gleixner <tglx@linutronix.de>
Fri, 17 Jul 2020 19:55:22 +0000 (21:55 +0200)
calc_index() adds 1 unit of the level granularity to the expiry passed
in parameter to ensure that the timer doesn't expire too early. Add a
comment to explain that and the resulting layout in the wheel.

Suggested-by: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: Frederic Weisbecker <frederic@kernel.org>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Tested-by: Juri Lelli <juri.lelli@redhat.com>
Link: https://lkml.kernel.org/r/20200717140551.29076-6-frederic@kernel.org
kernel/time/timer.c

index 2af08a169564d1508af5992b0984c5d0311ed7a1..af1c08b0b168cad7a624aa903299753e9a06c306 100644 (file)
@@ -156,7 +156,8 @@ EXPORT_SYMBOL(jiffies_64);
 
 /*
  * The time start value for each level to select the bucket at enqueue
- * time.
+ * time. We start from the last possible delta of the previous level
+ * so that we can later add an extra LVL_GRAN(n) to n (see calc_index()).
  */
 #define LVL_START(n)   ((LVL_SIZE - 1) << (((n) - 1) * LVL_CLK_SHIFT))
 
@@ -490,6 +491,15 @@ static inline void timer_set_idx(struct timer_list *timer, unsigned int idx)
 static inline unsigned calc_index(unsigned long expires, unsigned lvl,
                                  unsigned long *bucket_expiry)
 {
+
+       /*
+        * The timer wheel has to guarantee that a timer does not fire
+        * early. Early expiry can happen due to:
+        * - Timer is armed at the edge of a tick
+        * - Truncation of the expiry time in the outer wheel levels
+        *
+        * Round up with level granularity to prevent this.
+        */
        expires = (expires + LVL_GRAN(lvl)) >> LVL_SHIFT(lvl);
        *bucket_expiry = expires << LVL_SHIFT(lvl);
        return LVL_OFFS(lvl) + (expires & LVL_MASK);