Commit 9c133c46 authored by Alan Stern's avatar Alan Stern Committed by Jens Axboe

Add round_jiffies_up and related routines

This patch (as1158b) adds round_jiffies_up() and friends.  These
routines work like the analogous round_jiffies() functions, except
that they will never round down.

The new routines will be useful for timeouts where we don't care
exactly when the timer expires, provided it doesn't expire too soon.
Signed-off-by: default avatarAlan Stern <stern@rowland.harvard.edu>
Signed-off-by: default avatarJens Axboe <jens.axboe@oracle.com>
parent 89f97496
...@@ -186,4 +186,9 @@ unsigned long __round_jiffies_relative(unsigned long j, int cpu); ...@@ -186,4 +186,9 @@ unsigned long __round_jiffies_relative(unsigned long j, int cpu);
unsigned long round_jiffies(unsigned long j); unsigned long round_jiffies(unsigned long j);
unsigned long round_jiffies_relative(unsigned long j); unsigned long round_jiffies_relative(unsigned long j);
unsigned long __round_jiffies_up(unsigned long j, int cpu);
unsigned long __round_jiffies_up_relative(unsigned long j, int cpu);
unsigned long round_jiffies_up(unsigned long j);
unsigned long round_jiffies_up_relative(unsigned long j);
#endif #endif
...@@ -112,27 +112,8 @@ timer_set_base(struct timer_list *timer, struct tvec_base *new_base) ...@@ -112,27 +112,8 @@ timer_set_base(struct timer_list *timer, struct tvec_base *new_base)
tbase_get_deferrable(timer->base)); tbase_get_deferrable(timer->base));
} }
/** static unsigned long round_jiffies_common(unsigned long j, int cpu,
* __round_jiffies - function to round jiffies to a full second bool force_up)
* @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)
{ {
int rem; int rem;
unsigned long original = j; unsigned long original = j;
...@@ -154,8 +135,9 @@ unsigned long __round_jiffies(unsigned long j, int cpu) ...@@ -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 * 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 * 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. * 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; j = j - rem;
else /* round up */ else /* round up */
j = j - rem + HZ; j = j - rem + HZ;
...@@ -167,6 +149,31 @@ unsigned long __round_jiffies(unsigned long j, int cpu) ...@@ -167,6 +149,31 @@ unsigned long __round_jiffies(unsigned long j, int cpu)
return original; return original;
return j; 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); EXPORT_SYMBOL_GPL(__round_jiffies);
/** /**
...@@ -191,13 +198,10 @@ EXPORT_SYMBOL_GPL(__round_jiffies); ...@@ -191,13 +198,10 @@ EXPORT_SYMBOL_GPL(__round_jiffies);
*/ */
unsigned long __round_jiffies_relative(unsigned long j, int cpu) unsigned long __round_jiffies_relative(unsigned long j, int cpu)
{ {
/* unsigned long j0 = jiffies;
* In theory the following code can skip a jiffy in case jiffies
* increments right between the addition and the later subtraction. /* Use j0 because jiffies might change while we run */
* However since the entire point of this function is to use approximate return round_jiffies_common(j + j0, cpu, false) - j0;
* timeouts, it's entirely ok to not handle that.
*/
return __round_jiffies(j + jiffies, cpu) - jiffies;
} }
EXPORT_SYMBOL_GPL(__round_jiffies_relative); EXPORT_SYMBOL_GPL(__round_jiffies_relative);
...@@ -218,7 +222,7 @@ EXPORT_SYMBOL_GPL(__round_jiffies_relative); ...@@ -218,7 +222,7 @@ EXPORT_SYMBOL_GPL(__round_jiffies_relative);
*/ */
unsigned long round_jiffies(unsigned long j) 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); EXPORT_SYMBOL_GPL(round_jiffies);
...@@ -243,6 +247,71 @@ unsigned long round_jiffies_relative(unsigned long j) ...@@ -243,6 +247,71 @@ unsigned long round_jiffies_relative(unsigned long j)
} }
EXPORT_SYMBOL_GPL(round_jiffies_relative); 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, static inline void set_running_timer(struct tvec_base *base,
struct timer_list *timer) struct timer_list *timer)
......
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