diff options
-rw-r--r-- | kernel/hrtimer.c | 30 |
1 files changed, 29 insertions, 1 deletions
diff --git a/kernel/hrtimer.c b/kernel/hrtimer.c index bda9cb924276..c2a69b89ac61 100644 --- a/kernel/hrtimer.c +++ b/kernel/hrtimer.c | |||
@@ -1171,6 +1171,29 @@ static void __run_hrtimer(struct hrtimer *timer) | |||
1171 | 1171 | ||
1172 | #ifdef CONFIG_HIGH_RES_TIMERS | 1172 | #ifdef CONFIG_HIGH_RES_TIMERS |
1173 | 1173 | ||
1174 | static int force_clock_reprogram; | ||
1175 | |||
1176 | /* | ||
1177 | * After 5 iteration's attempts, we consider that hrtimer_interrupt() | ||
1178 | * is hanging, which could happen with something that slows the interrupt | ||
1179 | * such as the tracing. Then we force the clock reprogramming for each future | ||
1180 | * hrtimer interrupts to avoid infinite loops and use the min_delta_ns | ||
1181 | * threshold that we will overwrite. | ||
1182 | * The next tick event will be scheduled to 3 times we currently spend on | ||
1183 | * hrtimer_interrupt(). This gives a good compromise, the cpus will spend | ||
1184 | * 1/4 of their time to process the hrtimer interrupts. This is enough to | ||
1185 | * let it running without serious starvation. | ||
1186 | */ | ||
1187 | |||
1188 | static inline void | ||
1189 | hrtimer_interrupt_hanging(struct clock_event_device *dev, | ||
1190 | ktime_t try_time) | ||
1191 | { | ||
1192 | force_clock_reprogram = 1; | ||
1193 | dev->min_delta_ns = (unsigned long)try_time.tv64 * 3; | ||
1194 | printk(KERN_WARNING "hrtimer: interrupt too slow, " | ||
1195 | "forcing clock min delta to %lu ns\n", dev->min_delta_ns); | ||
1196 | } | ||
1174 | /* | 1197 | /* |
1175 | * High resolution timer interrupt | 1198 | * High resolution timer interrupt |
1176 | * Called with interrupts disabled | 1199 | * Called with interrupts disabled |
@@ -1180,6 +1203,7 @@ void hrtimer_interrupt(struct clock_event_device *dev) | |||
1180 | struct hrtimer_cpu_base *cpu_base = &__get_cpu_var(hrtimer_bases); | 1203 | struct hrtimer_cpu_base *cpu_base = &__get_cpu_var(hrtimer_bases); |
1181 | struct hrtimer_clock_base *base; | 1204 | struct hrtimer_clock_base *base; |
1182 | ktime_t expires_next, now; | 1205 | ktime_t expires_next, now; |
1206 | int nr_retries = 0; | ||
1183 | int i; | 1207 | int i; |
1184 | 1208 | ||
1185 | BUG_ON(!cpu_base->hres_active); | 1209 | BUG_ON(!cpu_base->hres_active); |
@@ -1187,6 +1211,10 @@ void hrtimer_interrupt(struct clock_event_device *dev) | |||
1187 | dev->next_event.tv64 = KTIME_MAX; | 1211 | dev->next_event.tv64 = KTIME_MAX; |
1188 | 1212 | ||
1189 | retry: | 1213 | retry: |
1214 | /* 5 retries is enough to notice a hang */ | ||
1215 | if (!(++nr_retries % 5)) | ||
1216 | hrtimer_interrupt_hanging(dev, ktime_sub(ktime_get(), now)); | ||
1217 | |||
1190 | now = ktime_get(); | 1218 | now = ktime_get(); |
1191 | 1219 | ||
1192 | expires_next.tv64 = KTIME_MAX; | 1220 | expires_next.tv64 = KTIME_MAX; |
@@ -1239,7 +1267,7 @@ void hrtimer_interrupt(struct clock_event_device *dev) | |||
1239 | 1267 | ||
1240 | /* Reprogramming necessary ? */ | 1268 | /* Reprogramming necessary ? */ |
1241 | if (expires_next.tv64 != KTIME_MAX) { | 1269 | if (expires_next.tv64 != KTIME_MAX) { |
1242 | if (tick_program_event(expires_next, 0)) | 1270 | if (tick_program_event(expires_next, force_clock_reprogram)) |
1243 | goto retry; | 1271 | goto retry; |
1244 | } | 1272 | } |
1245 | } | 1273 | } |