aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/time/timer.c
diff options
context:
space:
mode:
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);