|
@@ -112,27 +112,8 @@ timer_set_base(struct timer_list *timer, struct tvec_base *new_base)
|
|
|
tbase_get_deferrable(timer->base));
|
|
|
}
|
|
|
|
|
|
-/**
|
|
|
- * __round_jiffies - function to round jiffies to a full second
|
|
|
- * @j: the time in (absolute) jiffies that should be rounded
|
|
|
- * @cpu: the processor number on which the timeout will happen
|
|
|
- *
|
|
|
- * __round_jiffies() rounds an absolute time in the future (in jiffies)
|
|
|
- * up or down to (approximately) full seconds. This is useful for timers
|
|
|
- * for which the exact time they fire does not matter too much, as long as
|
|
|
- * they fire approximately every X seconds.
|
|
|
- *
|
|
|
- * By rounding these timers to whole seconds, all such timers will fire
|
|
|
- * at the same time, rather than at various times spread out. The goal
|
|
|
- * of this is to have the CPU wake up less, which saves power.
|
|
|
- *
|
|
|
- * The exact rounding is skewed for each processor to avoid all
|
|
|
- * processors firing at the exact same time, which could lead
|
|
|
- * to lock contention or spurious cache line bouncing.
|
|
|
- *
|
|
|
- * The return value is the rounded version of the @j parameter.
|
|
|
- */
|
|
|
-unsigned long __round_jiffies(unsigned long j, int cpu)
|
|
|
+static unsigned long round_jiffies_common(unsigned long j, int cpu,
|
|
|
+ bool force_up)
|
|
|
{
|
|
|
int rem;
|
|
|
unsigned long original = j;
|
|
@@ -154,8 +135,9 @@ unsigned long __round_jiffies(unsigned long j, int cpu)
|
|
|
* due to delays of the timer irq, long irq off times etc etc) then
|
|
|
* we should round down to the whole second, not up. Use 1/4th second
|
|
|
* as cutoff for this rounding as an extreme upper bound for this.
|
|
|
+ * But never round down if @force_up is set.
|
|
|
*/
|
|
|
- if (rem < HZ/4) /* round down */
|
|
|
+ if (rem < HZ/4 && !force_up) /* round down */
|
|
|
j = j - rem;
|
|
|
else /* round up */
|
|
|
j = j - rem + HZ;
|
|
@@ -167,6 +149,31 @@ unsigned long __round_jiffies(unsigned long j, int cpu)
|
|
|
return original;
|
|
|
return j;
|
|
|
}
|
|
|
+
|
|
|
+/**
|
|
|
+ * __round_jiffies - function to round jiffies to a full second
|
|
|
+ * @j: the time in (absolute) jiffies that should be rounded
|
|
|
+ * @cpu: the processor number on which the timeout will happen
|
|
|
+ *
|
|
|
+ * __round_jiffies() rounds an absolute time in the future (in jiffies)
|
|
|
+ * up or down to (approximately) full seconds. This is useful for timers
|
|
|
+ * for which the exact time they fire does not matter too much, as long as
|
|
|
+ * they fire approximately every X seconds.
|
|
|
+ *
|
|
|
+ * By rounding these timers to whole seconds, all such timers will fire
|
|
|
+ * at the same time, rather than at various times spread out. The goal
|
|
|
+ * of this is to have the CPU wake up less, which saves power.
|
|
|
+ *
|
|
|
+ * The exact rounding is skewed for each processor to avoid all
|
|
|
+ * processors firing at the exact same time, which could lead
|
|
|
+ * to lock contention or spurious cache line bouncing.
|
|
|
+ *
|
|
|
+ * The return value is the rounded version of the @j parameter.
|
|
|
+ */
|
|
|
+unsigned long __round_jiffies(unsigned long j, int cpu)
|
|
|
+{
|
|
|
+ return round_jiffies_common(j, cpu, false);
|
|
|
+}
|
|
|
EXPORT_SYMBOL_GPL(__round_jiffies);
|
|
|
|
|
|
/**
|
|
@@ -191,13 +198,10 @@ EXPORT_SYMBOL_GPL(__round_jiffies);
|
|
|
*/
|
|
|
unsigned long __round_jiffies_relative(unsigned long j, int cpu)
|
|
|
{
|
|
|
- /*
|
|
|
- * In theory the following code can skip a jiffy in case jiffies
|
|
|
- * increments right between the addition and the later subtraction.
|
|
|
- * However since the entire point of this function is to use approximate
|
|
|
- * timeouts, it's entirely ok to not handle that.
|
|
|
- */
|
|
|
- return __round_jiffies(j + jiffies, cpu) - jiffies;
|
|
|
+ unsigned long j0 = jiffies;
|
|
|
+
|
|
|
+ /* Use j0 because jiffies might change while we run */
|
|
|
+ return round_jiffies_common(j + j0, cpu, false) - j0;
|
|
|
}
|
|
|
EXPORT_SYMBOL_GPL(__round_jiffies_relative);
|
|
|
|
|
@@ -218,7 +222,7 @@ EXPORT_SYMBOL_GPL(__round_jiffies_relative);
|
|
|
*/
|
|
|
unsigned long round_jiffies(unsigned long j)
|
|
|
{
|
|
|
- return __round_jiffies(j, raw_smp_processor_id());
|
|
|
+ return round_jiffies_common(j, raw_smp_processor_id(), false);
|
|
|
}
|
|
|
EXPORT_SYMBOL_GPL(round_jiffies);
|
|
|
|
|
@@ -243,6 +247,71 @@ unsigned long round_jiffies_relative(unsigned long j)
|
|
|
}
|
|
|
EXPORT_SYMBOL_GPL(round_jiffies_relative);
|
|
|
|
|
|
+/**
|
|
|
+ * __round_jiffies_up - function to round jiffies up to a full second
|
|
|
+ * @j: the time in (absolute) jiffies that should be rounded
|
|
|
+ * @cpu: the processor number on which the timeout will happen
|
|
|
+ *
|
|
|
+ * This is the same as __round_jiffies() except that it will never
|
|
|
+ * round down. This is useful for timeouts for which the exact time
|
|
|
+ * of firing does not matter too much, as long as they don't fire too
|
|
|
+ * early.
|
|
|
+ */
|
|
|
+unsigned long __round_jiffies_up(unsigned long j, int cpu)
|
|
|
+{
|
|
|
+ return round_jiffies_common(j, cpu, true);
|
|
|
+}
|
|
|
+EXPORT_SYMBOL_GPL(__round_jiffies_up);
|
|
|
+
|
|
|
+/**
|
|
|
+ * __round_jiffies_up_relative - function to round jiffies up to a full second
|
|
|
+ * @j: the time in (relative) jiffies that should be rounded
|
|
|
+ * @cpu: the processor number on which the timeout will happen
|
|
|
+ *
|
|
|
+ * This is the same as __round_jiffies_relative() except that it will never
|
|
|
+ * round down. This is useful for timeouts for which the exact time
|
|
|
+ * of firing does not matter too much, as long as they don't fire too
|
|
|
+ * early.
|
|
|
+ */
|
|
|
+unsigned long __round_jiffies_up_relative(unsigned long j, int cpu)
|
|
|
+{
|
|
|
+ unsigned long j0 = jiffies;
|
|
|
+
|
|
|
+ /* Use j0 because jiffies might change while we run */
|
|
|
+ return round_jiffies_common(j + j0, cpu, true) - j0;
|
|
|
+}
|
|
|
+EXPORT_SYMBOL_GPL(__round_jiffies_up_relative);
|
|
|
+
|
|
|
+/**
|
|
|
+ * round_jiffies_up - function to round jiffies up to a full second
|
|
|
+ * @j: the time in (absolute) jiffies that should be rounded
|
|
|
+ *
|
|
|
+ * This is the same as round_jiffies() except that it will never
|
|
|
+ * round down. This is useful for timeouts for which the exact time
|
|
|
+ * of firing does not matter too much, as long as they don't fire too
|
|
|
+ * early.
|
|
|
+ */
|
|
|
+unsigned long round_jiffies_up(unsigned long j)
|
|
|
+{
|
|
|
+ return round_jiffies_common(j, raw_smp_processor_id(), true);
|
|
|
+}
|
|
|
+EXPORT_SYMBOL_GPL(round_jiffies_up);
|
|
|
+
|
|
|
+/**
|
|
|
+ * round_jiffies_up_relative - function to round jiffies up to a full second
|
|
|
+ * @j: the time in (relative) jiffies that should be rounded
|
|
|
+ *
|
|
|
+ * This is the same as round_jiffies_relative() except that it will never
|
|
|
+ * round down. This is useful for timeouts for which the exact time
|
|
|
+ * of firing does not matter too much, as long as they don't fire too
|
|
|
+ * early.
|
|
|
+ */
|
|
|
+unsigned long round_jiffies_up_relative(unsigned long j)
|
|
|
+{
|
|
|
+ return __round_jiffies_up_relative(j, raw_smp_processor_id());
|
|
|
+}
|
|
|
+EXPORT_SYMBOL_GPL(round_jiffies_up_relative);
|
|
|
+
|
|
|
|
|
|
static inline void set_running_timer(struct tvec_base *base,
|
|
|
struct timer_list *timer)
|