aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/linux/timer.h10
-rw-r--r--kernel/timer.c56
2 files changed, 65 insertions, 1 deletions
diff --git a/include/linux/timer.h b/include/linux/timer.h
index a2d1eb6cb3f0..ea965b857a50 100644
--- a/include/linux/timer.h
+++ b/include/linux/timer.h
@@ -10,13 +10,19 @@
10struct tvec_base; 10struct tvec_base;
11 11
12struct timer_list { 12struct timer_list {
13 /*
14 * All fields that change during normal runtime grouped to the
15 * same cacheline
16 */
13 struct list_head entry; 17 struct list_head entry;
14 unsigned long expires; 18 unsigned long expires;
19 struct tvec_base *base;
15 20
16 void (*function)(unsigned long); 21 void (*function)(unsigned long);
17 unsigned long data; 22 unsigned long data;
18 23
19 struct tvec_base *base; 24 int slack;
25
20#ifdef CONFIG_TIMER_STATS 26#ifdef CONFIG_TIMER_STATS
21 void *start_site; 27 void *start_site;
22 char start_comm[16]; 28 char start_comm[16];
@@ -165,6 +171,8 @@ extern int mod_timer(struct timer_list *timer, unsigned long expires);
165extern int mod_timer_pending(struct timer_list *timer, unsigned long expires); 171extern int mod_timer_pending(struct timer_list *timer, unsigned long expires);
166extern int mod_timer_pinned(struct timer_list *timer, unsigned long expires); 172extern int mod_timer_pinned(struct timer_list *timer, unsigned long expires);
167 173
174extern void set_timer_slack(struct timer_list *time, int slack_hz);
175
168#define TIMER_NOT_PINNED 0 176#define TIMER_NOT_PINNED 0
169#define TIMER_PINNED 1 177#define TIMER_PINNED 1
170/* 178/*
diff --git a/kernel/timer.c b/kernel/timer.c
index 7e12e7bc7ce6..49773f38c9bc 100644
--- a/kernel/timer.c
+++ b/kernel/timer.c
@@ -318,6 +318,24 @@ unsigned long round_jiffies_up_relative(unsigned long j)
318} 318}
319EXPORT_SYMBOL_GPL(round_jiffies_up_relative); 319EXPORT_SYMBOL_GPL(round_jiffies_up_relative);
320 320
321/**
322 * set_timer_slack - set the allowed slack for a timer
323 * @slack_hz: the amount of time (in jiffies) allowed for rounding
324 *
325 * Set the amount of time, in jiffies, that a certain timer has
326 * in terms of slack. By setting this value, the timer subsystem
327 * will schedule the actual timer somewhere between
328 * the time mod_timer() asks for, and that time plus the slack.
329 *
330 * By setting the slack to -1, a percentage of the delay is used
331 * instead.
332 */
333void set_timer_slack(struct timer_list *timer, int slack_hz)
334{
335 timer->slack = slack_hz;
336}
337EXPORT_SYMBOL_GPL(set_timer_slack);
338
321 339
322static inline void set_running_timer(struct tvec_base *base, 340static inline void set_running_timer(struct tvec_base *base,
323 struct timer_list *timer) 341 struct timer_list *timer)
@@ -549,6 +567,7 @@ static void __init_timer(struct timer_list *timer,
549{ 567{
550 timer->entry.next = NULL; 568 timer->entry.next = NULL;
551 timer->base = __raw_get_cpu_var(tvec_bases); 569 timer->base = __raw_get_cpu_var(tvec_bases);
570 timer->slack = -1;
552#ifdef CONFIG_TIMER_STATS 571#ifdef CONFIG_TIMER_STATS
553 timer->start_site = NULL; 572 timer->start_site = NULL;
554 timer->start_pid = -1; 573 timer->start_pid = -1;
@@ -714,6 +733,41 @@ int mod_timer_pending(struct timer_list *timer, unsigned long expires)
714} 733}
715EXPORT_SYMBOL(mod_timer_pending); 734EXPORT_SYMBOL(mod_timer_pending);
716 735
736/*
737 * Decide where to put the timer while taking the slack into account
738 *
739 * Algorithm:
740 * 1) calculate the maximum (absolute) time
741 * 2) calculate the highest bit where the expires and new max are different
742 * 3) use this bit to make a mask
743 * 4) use the bitmask to round down the maximum time, so that all last
744 * bits are zeros
745 */
746static inline
747unsigned long apply_slack(struct timer_list *timer, unsigned long expires)
748{
749 unsigned long expires_limit, mask;
750 int bit;
751
752 expires_limit = expires + timer->slack;
753
754 if (timer->slack < 0) /* auto slack: use 0.4% */
755 expires_limit = expires + (expires - jiffies)/256;
756
757 mask = expires ^ expires_limit;
758
759 if (mask == 0)
760 return expires;
761
762 bit = find_last_bit(&mask, BITS_PER_LONG);
763
764 mask = (1 << bit) - 1;
765
766 expires_limit = expires_limit & ~(mask);
767
768 return expires_limit;
769}
770
717/** 771/**
718 * mod_timer - modify a timer's timeout 772 * mod_timer - modify a timer's timeout
719 * @timer: the timer to be modified 773 * @timer: the timer to be modified
@@ -744,6 +798,8 @@ int mod_timer(struct timer_list *timer, unsigned long expires)
744 if (timer_pending(timer) && timer->expires == expires) 798 if (timer_pending(timer) && timer->expires == expires)
745 return 1; 799 return 1;
746 800
801 expires = apply_slack(timer, expires);
802
747 return __mod_timer(timer, expires, false, TIMER_NOT_PINNED); 803 return __mod_timer(timer, expires, false, TIMER_NOT_PINNED);
748} 804}
749EXPORT_SYMBOL(mod_timer); 805EXPORT_SYMBOL(mod_timer);