aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/time/timer.c
diff options
context:
space:
mode:
authorThomas Gleixner <tglx@linutronix.de>2016-10-24 05:55:10 -0400
committerThomas Gleixner <tglx@linutronix.de>2016-10-25 10:27:39 -0400
commit4da9152a4308dcbf611cde399c695c359fc9145f (patch)
treeef634a7c192d03dd1f04b82f20ef58e78b55b3be /kernel/time/timer.c
parentb831275a3553c32091222ac619cfddd73a5553fb (diff)
timers: Lock base for same bucket optimization
Linus stumbled over the unlocked modification of the timer expiry value in mod_timer() which is an optimization for timers which stay in the same bucket - due to the bucket granularity - despite their expiry time getting updated. The optimization itself still makes sense even if we take the lock, because in case that the bucket stays the same, we avoid the pointless queue/enqueue dance. Make the check and the modification of timer->expires protected by the base lock and shuffle the remaining code around so we can keep the lock held when we actually have to requeue the timer to a different bucket. Fixes: f00c0afdfa62 ("timers: Implement optimization for same expiry time in mod_timer()") Reported-by: Linus Torvalds <torvalds@linux-foundation.org> Signed-off-by: Thomas Gleixner <tglx@linutronix.de> Link: http://lkml.kernel.org/r/alpine.DEB.2.20.1610241711220.4983@nanos Cc: stable@vger.kernel.org Cc: Andrew Morton <akpm@linux-foundation.org> Cc: Peter Zijlstra <peterz@infradead.org>
Diffstat (limited to 'kernel/time/timer.c')
-rw-r--r--kernel/time/timer.c28
1 files changed, 17 insertions, 11 deletions
diff --git a/kernel/time/timer.c b/kernel/time/timer.c
index 0d4b91c5a374..ccf913038f9f 100644
--- a/kernel/time/timer.c
+++ b/kernel/time/timer.c
@@ -971,6 +971,8 @@ __mod_timer(struct timer_list *timer, unsigned long expires, bool pending_only)
971 unsigned long clk = 0, flags; 971 unsigned long clk = 0, flags;
972 int ret = 0; 972 int ret = 0;
973 973
974 BUG_ON(!timer->function);
975
974 /* 976 /*
975 * This is a common optimization triggered by the networking code - if 977 * This is a common optimization triggered by the networking code - if
976 * the timer is re-modified to have the same timeout or ends up in the 978 * the timer is re-modified to have the same timeout or ends up in the
@@ -979,13 +981,16 @@ __mod_timer(struct timer_list *timer, unsigned long expires, bool pending_only)
979 if (timer_pending(timer)) { 981 if (timer_pending(timer)) {
980 if (timer->expires == expires) 982 if (timer->expires == expires)
981 return 1; 983 return 1;
984
982 /* 985 /*
983 * Take the current timer_jiffies of base, but without holding 986 * We lock timer base and calculate the bucket index right
984 * the lock! 987 * here. If the timer ends up in the same bucket, then we
988 * just update the expiry time and avoid the whole
989 * dequeue/enqueue dance.
985 */ 990 */
986 base = get_timer_base(timer->flags); 991 base = lock_timer_base(timer, &flags);
987 clk = base->clk;
988 992
993 clk = base->clk;
989 idx = calc_wheel_index(expires, clk); 994 idx = calc_wheel_index(expires, clk);
990 995
991 /* 996 /*
@@ -995,14 +1000,14 @@ __mod_timer(struct timer_list *timer, unsigned long expires, bool pending_only)
995 */ 1000 */
996 if (idx == timer_get_idx(timer)) { 1001 if (idx == timer_get_idx(timer)) {
997 timer->expires = expires; 1002 timer->expires = expires;
998 return 1; 1003 ret = 1;
1004 goto out_unlock;
999 } 1005 }
1006 } else {
1007 base = lock_timer_base(timer, &flags);
1000 } 1008 }
1001 1009
1002 timer_stats_timer_set_start_info(timer); 1010 timer_stats_timer_set_start_info(timer);
1003 BUG_ON(!timer->function);
1004
1005 base = lock_timer_base(timer, &flags);
1006 1011
1007 ret = detach_if_pending(timer, base, false); 1012 ret = detach_if_pending(timer, base, false);
1008 if (!ret && pending_only) 1013 if (!ret && pending_only)
@@ -1035,9 +1040,10 @@ __mod_timer(struct timer_list *timer, unsigned long expires, bool pending_only)
1035 timer->expires = expires; 1040 timer->expires = expires;
1036 /* 1041 /*
1037 * If 'idx' was calculated above and the base time did not advance 1042 * If 'idx' was calculated above and the base time did not advance
1038 * between calculating 'idx' and taking the lock, only enqueue_timer() 1043 * between calculating 'idx' and possibly switching the base, only
1039 * and trigger_dyntick_cpu() is required. Otherwise we need to 1044 * enqueue_timer() and trigger_dyntick_cpu() is required. Otherwise
1040 * (re)calculate the wheel index via internal_add_timer(). 1045 * we need to (re)calculate the wheel index via
1046 * internal_add_timer().
1041 */ 1047 */
1042 if (idx != UINT_MAX && clk == base->clk) { 1048 if (idx != UINT_MAX && clk == base->clk) {
1043 enqueue_timer(base, timer, idx); 1049 enqueue_timer(base, timer, idx);