Skip to content

Commit 9c133c4

Browse files
AlanSternJens Axboe
authored andcommitted
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: Alan Stern <stern@rowland.harvard.edu> Signed-off-by: Jens Axboe <jens.axboe@oracle.com>
1 parent 89f9749 commit 9c133c4

File tree

2 files changed

+104
-30
lines changed

2 files changed

+104
-30
lines changed

include/linux/timer.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -186,4 +186,9 @@ unsigned long __round_jiffies_relative(unsigned long j, int cpu);
186186
unsigned long round_jiffies(unsigned long j);
187187
unsigned long round_jiffies_relative(unsigned long j);
188188

189+
unsigned long __round_jiffies_up(unsigned long j, int cpu);
190+
unsigned long __round_jiffies_up_relative(unsigned long j, int cpu);
191+
unsigned long round_jiffies_up(unsigned long j);
192+
unsigned long round_jiffies_up_relative(unsigned long j);
193+
189194
#endif

kernel/timer.c

Lines changed: 99 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -112,27 +112,8 @@ timer_set_base(struct timer_list *timer, struct tvec_base *new_base)
112112
tbase_get_deferrable(timer->base));
113113
}
114114

115-
/**
116-
* __round_jiffies - function to round jiffies to a full second
117-
* @j: the time in (absolute) jiffies that should be rounded
118-
* @cpu: the processor number on which the timeout will happen
119-
*
120-
* __round_jiffies() rounds an absolute time in the future (in jiffies)
121-
* up or down to (approximately) full seconds. This is useful for timers
122-
* for which the exact time they fire does not matter too much, as long as
123-
* they fire approximately every X seconds.
124-
*
125-
* By rounding these timers to whole seconds, all such timers will fire
126-
* at the same time, rather than at various times spread out. The goal
127-
* of this is to have the CPU wake up less, which saves power.
128-
*
129-
* The exact rounding is skewed for each processor to avoid all
130-
* processors firing at the exact same time, which could lead
131-
* to lock contention or spurious cache line bouncing.
132-
*
133-
* The return value is the rounded version of the @j parameter.
134-
*/
135-
unsigned long __round_jiffies(unsigned long j, int cpu)
115+
static unsigned long round_jiffies_common(unsigned long j, int cpu,
116+
bool force_up)
136117
{
137118
int rem;
138119
unsigned long original = j;
@@ -154,8 +135,9 @@ unsigned long __round_jiffies(unsigned long j, int cpu)
154135
* due to delays of the timer irq, long irq off times etc etc) then
155136
* we should round down to the whole second, not up. Use 1/4th second
156137
* as cutoff for this rounding as an extreme upper bound for this.
138+
* But never round down if @force_up is set.
157139
*/
158-
if (rem < HZ/4) /* round down */
140+
if (rem < HZ/4 && !force_up) /* round down */
159141
j = j - rem;
160142
else /* round up */
161143
j = j - rem + HZ;
@@ -167,6 +149,31 @@ unsigned long __round_jiffies(unsigned long j, int cpu)
167149
return original;
168150
return j;
169151
}
152+
153+
/**
154+
* __round_jiffies - function to round jiffies to a full second
155+
* @j: the time in (absolute) jiffies that should be rounded
156+
* @cpu: the processor number on which the timeout will happen
157+
*
158+
* __round_jiffies() rounds an absolute time in the future (in jiffies)
159+
* up or down to (approximately) full seconds. This is useful for timers
160+
* for which the exact time they fire does not matter too much, as long as
161+
* they fire approximately every X seconds.
162+
*
163+
* By rounding these timers to whole seconds, all such timers will fire
164+
* at the same time, rather than at various times spread out. The goal
165+
* of this is to have the CPU wake up less, which saves power.
166+
*
167+
* The exact rounding is skewed for each processor to avoid all
168+
* processors firing at the exact same time, which could lead
169+
* to lock contention or spurious cache line bouncing.
170+
*
171+
* The return value is the rounded version of the @j parameter.
172+
*/
173+
unsigned long __round_jiffies(unsigned long j, int cpu)
174+
{
175+
return round_jiffies_common(j, cpu, false);
176+
}
170177
EXPORT_SYMBOL_GPL(__round_jiffies);
171178

172179
/**
@@ -191,13 +198,10 @@ EXPORT_SYMBOL_GPL(__round_jiffies);
191198
*/
192199
unsigned long __round_jiffies_relative(unsigned long j, int cpu)
193200
{
194-
/*
195-
* In theory the following code can skip a jiffy in case jiffies
196-
* increments right between the addition and the later subtraction.
197-
* However since the entire point of this function is to use approximate
198-
* timeouts, it's entirely ok to not handle that.
199-
*/
200-
return __round_jiffies(j + jiffies, cpu) - jiffies;
201+
unsigned long j0 = jiffies;
202+
203+
/* Use j0 because jiffies might change while we run */
204+
return round_jiffies_common(j + j0, cpu, false) - j0;
201205
}
202206
EXPORT_SYMBOL_GPL(__round_jiffies_relative);
203207

@@ -218,7 +222,7 @@ EXPORT_SYMBOL_GPL(__round_jiffies_relative);
218222
*/
219223
unsigned long round_jiffies(unsigned long j)
220224
{
221-
return __round_jiffies(j, raw_smp_processor_id());
225+
return round_jiffies_common(j, raw_smp_processor_id(), false);
222226
}
223227
EXPORT_SYMBOL_GPL(round_jiffies);
224228

@@ -243,6 +247,71 @@ unsigned long round_jiffies_relative(unsigned long j)
243247
}
244248
EXPORT_SYMBOL_GPL(round_jiffies_relative);
245249

250+
/**
251+
* __round_jiffies_up - function to round jiffies up to a full second
252+
* @j: the time in (absolute) jiffies that should be rounded
253+
* @cpu: the processor number on which the timeout will happen
254+
*
255+
* This is the same as __round_jiffies() except that it will never
256+
* round down. This is useful for timeouts for which the exact time
257+
* of firing does not matter too much, as long as they don't fire too
258+
* early.
259+
*/
260+
unsigned long __round_jiffies_up(unsigned long j, int cpu)
261+
{
262+
return round_jiffies_common(j, cpu, true);
263+
}
264+
EXPORT_SYMBOL_GPL(__round_jiffies_up);
265+
266+
/**
267+
* __round_jiffies_up_relative - function to round jiffies up to a full second
268+
* @j: the time in (relative) jiffies that should be rounded
269+
* @cpu: the processor number on which the timeout will happen
270+
*
271+
* This is the same as __round_jiffies_relative() except that it will never
272+
* round down. This is useful for timeouts for which the exact time
273+
* of firing does not matter too much, as long as they don't fire too
274+
* early.
275+
*/
276+
unsigned long __round_jiffies_up_relative(unsigned long j, int cpu)
277+
{
278+
unsigned long j0 = jiffies;
279+
280+
/* Use j0 because jiffies might change while we run */
281+
return round_jiffies_common(j + j0, cpu, true) - j0;
282+
}
283+
EXPORT_SYMBOL_GPL(__round_jiffies_up_relative);
284+
285+
/**
286+
* round_jiffies_up - function to round jiffies up to a full second
287+
* @j: the time in (absolute) jiffies that should be rounded
288+
*
289+
* This is the same as round_jiffies() except that it will never
290+
* round down. This is useful for timeouts for which the exact time
291+
* of firing does not matter too much, as long as they don't fire too
292+
* early.
293+
*/
294+
unsigned long round_jiffies_up(unsigned long j)
295+
{
296+
return round_jiffies_common(j, raw_smp_processor_id(), true);
297+
}
298+
EXPORT_SYMBOL_GPL(round_jiffies_up);
299+
300+
/**
301+
* round_jiffies_up_relative - function to round jiffies up to a full second
302+
* @j: the time in (relative) jiffies that should be rounded
303+
*
304+
* This is the same as round_jiffies_relative() except that it will never
305+
* round down. This is useful for timeouts for which the exact time
306+
* of firing does not matter too much, as long as they don't fire too
307+
* early.
308+
*/
309+
unsigned long round_jiffies_up_relative(unsigned long j)
310+
{
311+
return __round_jiffies_up_relative(j, raw_smp_processor_id());
312+
}
313+
EXPORT_SYMBOL_GPL(round_jiffies_up_relative);
314+
246315

247316
static inline void set_running_timer(struct tvec_base *base,
248317
struct timer_list *timer)

0 commit comments

Comments
 (0)