diff options
Diffstat (limited to 'kernel/time/timer.c')
| -rw-r--r-- | kernel/time/timer.c | 28 |
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); |
