diff options
Diffstat (limited to 'kernel/timer.c')
-rw-r--r-- | kernel/timer.c | 35 |
1 files changed, 24 insertions, 11 deletions
diff --git a/kernel/timer.c b/kernel/timer.c index 8d185a1677cc..706fe4c53e82 100644 --- a/kernel/timer.c +++ b/kernel/timer.c | |||
@@ -95,6 +95,11 @@ static inline unsigned int tbase_get_deferrable(struct tvec_base *base) | |||
95 | return ((unsigned int)(unsigned long)base & TIMER_DEFERRABLE); | 95 | return ((unsigned int)(unsigned long)base & TIMER_DEFERRABLE); |
96 | } | 96 | } |
97 | 97 | ||
98 | static inline unsigned int tbase_get_irqsafe(struct tvec_base *base) | ||
99 | { | ||
100 | return ((unsigned int)(unsigned long)base & TIMER_IRQSAFE); | ||
101 | } | ||
102 | |||
98 | static inline struct tvec_base *tbase_get_base(struct tvec_base *base) | 103 | static inline struct tvec_base *tbase_get_base(struct tvec_base *base) |
99 | { | 104 | { |
100 | return ((struct tvec_base *)((unsigned long)base & ~TIMER_FLAG_MASK)); | 105 | return ((struct tvec_base *)((unsigned long)base & ~TIMER_FLAG_MASK)); |
@@ -1002,14 +1007,14 @@ EXPORT_SYMBOL(try_to_del_timer_sync); | |||
1002 | * | 1007 | * |
1003 | * Synchronization rules: Callers must prevent restarting of the timer, | 1008 | * Synchronization rules: Callers must prevent restarting of the timer, |
1004 | * otherwise this function is meaningless. It must not be called from | 1009 | * otherwise this function is meaningless. It must not be called from |
1005 | * interrupt contexts. The caller must not hold locks which would prevent | 1010 | * interrupt contexts unless the timer is an irqsafe one. The caller must |
1006 | * completion of the timer's handler. The timer's handler must not call | 1011 | * not hold locks which would prevent completion of the timer's |
1007 | * add_timer_on(). Upon exit the timer is not queued and the handler is | 1012 | * handler. The timer's handler must not call add_timer_on(). Upon exit the |
1008 | * not running on any CPU. | 1013 | * timer is not queued and the handler is not running on any CPU. |
1009 | * | 1014 | * |
1010 | * Note: You must not hold locks that are held in interrupt context | 1015 | * Note: For !irqsafe timers, you must not hold locks that are held in |
1011 | * while calling this function. Even if the lock has nothing to do | 1016 | * interrupt context while calling this function. Even if the lock has |
1012 | * with the timer in question. Here's why: | 1017 | * nothing to do with the timer in question. Here's why: |
1013 | * | 1018 | * |
1014 | * CPU0 CPU1 | 1019 | * CPU0 CPU1 |
1015 | * ---- ---- | 1020 | * ---- ---- |
@@ -1046,7 +1051,7 @@ int del_timer_sync(struct timer_list *timer) | |||
1046 | * don't use it in hardirq context, because it | 1051 | * don't use it in hardirq context, because it |
1047 | * could lead to deadlock. | 1052 | * could lead to deadlock. |
1048 | */ | 1053 | */ |
1049 | WARN_ON(in_irq()); | 1054 | WARN_ON(in_irq() && !tbase_get_irqsafe(timer->base)); |
1050 | for (;;) { | 1055 | for (;;) { |
1051 | int ret = try_to_del_timer_sync(timer); | 1056 | int ret = try_to_del_timer_sync(timer); |
1052 | if (ret >= 0) | 1057 | if (ret >= 0) |
@@ -1153,19 +1158,27 @@ static inline void __run_timers(struct tvec_base *base) | |||
1153 | while (!list_empty(head)) { | 1158 | while (!list_empty(head)) { |
1154 | void (*fn)(unsigned long); | 1159 | void (*fn)(unsigned long); |
1155 | unsigned long data; | 1160 | unsigned long data; |
1161 | bool irqsafe; | ||
1156 | 1162 | ||
1157 | timer = list_first_entry(head, struct timer_list,entry); | 1163 | timer = list_first_entry(head, struct timer_list,entry); |
1158 | fn = timer->function; | 1164 | fn = timer->function; |
1159 | data = timer->data; | 1165 | data = timer->data; |
1166 | irqsafe = tbase_get_irqsafe(timer->base); | ||
1160 | 1167 | ||
1161 | timer_stats_account_timer(timer); | 1168 | timer_stats_account_timer(timer); |
1162 | 1169 | ||
1163 | base->running_timer = timer; | 1170 | base->running_timer = timer; |
1164 | detach_expired_timer(timer, base); | 1171 | detach_expired_timer(timer, base); |
1165 | 1172 | ||
1166 | spin_unlock_irq(&base->lock); | 1173 | if (irqsafe) { |
1167 | call_timer_fn(timer, fn, data); | 1174 | spin_unlock(&base->lock); |
1168 | spin_lock_irq(&base->lock); | 1175 | call_timer_fn(timer, fn, data); |
1176 | spin_lock(&base->lock); | ||
1177 | } else { | ||
1178 | spin_unlock_irq(&base->lock); | ||
1179 | call_timer_fn(timer, fn, data); | ||
1180 | spin_lock_irq(&base->lock); | ||
1181 | } | ||
1169 | } | 1182 | } |
1170 | } | 1183 | } |
1171 | base->running_timer = NULL; | 1184 | base->running_timer = NULL; |