diff options
Diffstat (limited to 'kernel/hrtimer.c')
| -rw-r--r-- | kernel/hrtimer.c | 122 |
1 files changed, 77 insertions, 45 deletions
diff --git a/kernel/hrtimer.c b/kernel/hrtimer.c index 6d7020490f94..d2f9239dc6ba 100644 --- a/kernel/hrtimer.c +++ b/kernel/hrtimer.c | |||
| @@ -557,7 +557,7 @@ hrtimer_force_reprogram(struct hrtimer_cpu_base *cpu_base, int skip_equal) | |||
| 557 | static int hrtimer_reprogram(struct hrtimer *timer, | 557 | static int hrtimer_reprogram(struct hrtimer *timer, |
| 558 | struct hrtimer_clock_base *base) | 558 | struct hrtimer_clock_base *base) |
| 559 | { | 559 | { |
| 560 | ktime_t *expires_next = &__get_cpu_var(hrtimer_bases).expires_next; | 560 | struct hrtimer_cpu_base *cpu_base = &__get_cpu_var(hrtimer_bases); |
| 561 | ktime_t expires = ktime_sub(hrtimer_get_expires(timer), base->offset); | 561 | ktime_t expires = ktime_sub(hrtimer_get_expires(timer), base->offset); |
| 562 | int res; | 562 | int res; |
| 563 | 563 | ||
| @@ -582,7 +582,16 @@ static int hrtimer_reprogram(struct hrtimer *timer, | |||
| 582 | if (expires.tv64 < 0) | 582 | if (expires.tv64 < 0) |
| 583 | return -ETIME; | 583 | return -ETIME; |
| 584 | 584 | ||
| 585 | if (expires.tv64 >= expires_next->tv64) | 585 | if (expires.tv64 >= cpu_base->expires_next.tv64) |
| 586 | return 0; | ||
| 587 | |||
| 588 | /* | ||
| 589 | * If a hang was detected in the last timer interrupt then we | ||
| 590 | * do not schedule a timer which is earlier than the expiry | ||
| 591 | * which we enforced in the hang detection. We want the system | ||
| 592 | * to make progress. | ||
| 593 | */ | ||
| 594 | if (cpu_base->hang_detected) | ||
| 586 | return 0; | 595 | return 0; |
| 587 | 596 | ||
| 588 | /* | 597 | /* |
| @@ -590,7 +599,7 @@ static int hrtimer_reprogram(struct hrtimer *timer, | |||
| 590 | */ | 599 | */ |
| 591 | res = tick_program_event(expires, 0); | 600 | res = tick_program_event(expires, 0); |
| 592 | if (!IS_ERR_VALUE(res)) | 601 | if (!IS_ERR_VALUE(res)) |
| 593 | *expires_next = expires; | 602 | cpu_base->expires_next = expires; |
| 594 | return res; | 603 | return res; |
| 595 | } | 604 | } |
| 596 | 605 | ||
| @@ -726,8 +735,6 @@ static int hrtimer_switch_to_hres(void) | |||
| 726 | /* "Retrigger" the interrupt to get things going */ | 735 | /* "Retrigger" the interrupt to get things going */ |
| 727 | retrigger_next_event(NULL); | 736 | retrigger_next_event(NULL); |
| 728 | local_irq_restore(flags); | 737 | local_irq_restore(flags); |
| 729 | printk(KERN_DEBUG "Switched to high resolution mode on CPU %d\n", | ||
| 730 | smp_processor_id()); | ||
| 731 | return 1; | 738 | return 1; |
| 732 | } | 739 | } |
| 733 | 740 | ||
| @@ -749,17 +756,33 @@ static inline void hrtimer_init_timer_hres(struct hrtimer *timer) { } | |||
| 749 | 756 | ||
| 750 | #endif /* CONFIG_HIGH_RES_TIMERS */ | 757 | #endif /* CONFIG_HIGH_RES_TIMERS */ |
| 751 | 758 | ||
| 752 | #ifdef CONFIG_TIMER_STATS | 759 | static inline void timer_stats_hrtimer_set_start_info(struct hrtimer *timer) |
| 753 | void __timer_stats_hrtimer_set_start_info(struct hrtimer *timer, void *addr) | ||
| 754 | { | 760 | { |
| 761 | #ifdef CONFIG_TIMER_STATS | ||
| 755 | if (timer->start_site) | 762 | if (timer->start_site) |
| 756 | return; | 763 | return; |
| 757 | 764 | timer->start_site = __builtin_return_address(0); | |
| 758 | timer->start_site = addr; | ||
| 759 | memcpy(timer->start_comm, current->comm, TASK_COMM_LEN); | 765 | memcpy(timer->start_comm, current->comm, TASK_COMM_LEN); |
| 760 | timer->start_pid = current->pid; | 766 | timer->start_pid = current->pid; |
| 767 | #endif | ||
| 761 | } | 768 | } |
| 769 | |||
| 770 | static inline void timer_stats_hrtimer_clear_start_info(struct hrtimer *timer) | ||
| 771 | { | ||
| 772 | #ifdef CONFIG_TIMER_STATS | ||
| 773 | timer->start_site = NULL; | ||
| 774 | #endif | ||
| 775 | } | ||
| 776 | |||
| 777 | static inline void timer_stats_account_hrtimer(struct hrtimer *timer) | ||
| 778 | { | ||
| 779 | #ifdef CONFIG_TIMER_STATS | ||
| 780 | if (likely(!timer_stats_active)) | ||
| 781 | return; | ||
| 782 | timer_stats_update_stats(timer, timer->start_pid, timer->start_site, | ||
| 783 | timer->function, timer->start_comm, 0); | ||
| 762 | #endif | 784 | #endif |
| 785 | } | ||
| 763 | 786 | ||
| 764 | /* | 787 | /* |
| 765 | * Counterpart to lock_hrtimer_base above: | 788 | * Counterpart to lock_hrtimer_base above: |
| @@ -1219,29 +1242,6 @@ static void __run_hrtimer(struct hrtimer *timer, ktime_t *now) | |||
| 1219 | 1242 | ||
| 1220 | #ifdef CONFIG_HIGH_RES_TIMERS | 1243 | #ifdef CONFIG_HIGH_RES_TIMERS |
| 1221 | 1244 | ||
| 1222 | static int force_clock_reprogram; | ||
| 1223 | |||
| 1224 | /* | ||
| 1225 | * After 5 iteration's attempts, we consider that hrtimer_interrupt() | ||
| 1226 | * is hanging, which could happen with something that slows the interrupt | ||
| 1227 | * such as the tracing. Then we force the clock reprogramming for each future | ||
| 1228 | * hrtimer interrupts to avoid infinite loops and use the min_delta_ns | ||
| 1229 | * threshold that we will overwrite. | ||
| 1230 | * The next tick event will be scheduled to 3 times we currently spend on | ||
| 1231 | * hrtimer_interrupt(). This gives a good compromise, the cpus will spend | ||
| 1232 | * 1/4 of their time to process the hrtimer interrupts. This is enough to | ||
| 1233 | * let it running without serious starvation. | ||
| 1234 | */ | ||
| 1235 | |||
| 1236 | static inline void | ||
| 1237 | hrtimer_interrupt_hanging(struct clock_event_device *dev, | ||
| 1238 | ktime_t try_time) | ||
| 1239 | { | ||
| 1240 | force_clock_reprogram = 1; | ||
| 1241 | dev->min_delta_ns = (unsigned long)try_time.tv64 * 3; | ||
| 1242 | printk(KERN_WARNING "hrtimer: interrupt too slow, " | ||
| 1243 | "forcing clock min delta to %lu ns\n", dev->min_delta_ns); | ||
| 1244 | } | ||
| 1245 | /* | 1245 | /* |
| 1246 | * High resolution timer interrupt | 1246 | * High resolution timer interrupt |
| 1247 | * Called with interrupts disabled | 1247 | * Called with interrupts disabled |
| @@ -1250,21 +1250,15 @@ void hrtimer_interrupt(struct clock_event_device *dev) | |||
| 1250 | { | 1250 | { |
| 1251 | struct hrtimer_cpu_base *cpu_base = &__get_cpu_var(hrtimer_bases); | 1251 | struct hrtimer_cpu_base *cpu_base = &__get_cpu_var(hrtimer_bases); |
| 1252 | struct hrtimer_clock_base *base; | 1252 | struct hrtimer_clock_base *base; |
| 1253 | ktime_t expires_next, now; | 1253 | ktime_t expires_next, now, entry_time, delta; |
| 1254 | int nr_retries = 0; | 1254 | int i, retries = 0; |
| 1255 | int i; | ||
| 1256 | 1255 | ||
| 1257 | BUG_ON(!cpu_base->hres_active); | 1256 | BUG_ON(!cpu_base->hres_active); |
| 1258 | cpu_base->nr_events++; | 1257 | cpu_base->nr_events++; |
| 1259 | dev->next_event.tv64 = KTIME_MAX; | 1258 | dev->next_event.tv64 = KTIME_MAX; |
| 1260 | 1259 | ||
| 1261 | retry: | 1260 | entry_time = now = ktime_get(); |
| 1262 | /* 5 retries is enough to notice a hang */ | 1261 | retry: |
| 1263 | if (!(++nr_retries % 5)) | ||
| 1264 | hrtimer_interrupt_hanging(dev, ktime_sub(ktime_get(), now)); | ||
| 1265 | |||
| 1266 | now = ktime_get(); | ||
| 1267 | |||
| 1268 | expires_next.tv64 = KTIME_MAX; | 1262 | expires_next.tv64 = KTIME_MAX; |
| 1269 | 1263 | ||
| 1270 | spin_lock(&cpu_base->lock); | 1264 | spin_lock(&cpu_base->lock); |
| @@ -1326,10 +1320,48 @@ void hrtimer_interrupt(struct clock_event_device *dev) | |||
| 1326 | spin_unlock(&cpu_base->lock); | 1320 | spin_unlock(&cpu_base->lock); |
| 1327 | 1321 | ||
| 1328 | /* Reprogramming necessary ? */ | 1322 | /* Reprogramming necessary ? */ |
| 1329 | if (expires_next.tv64 != KTIME_MAX) { | 1323 | if (expires_next.tv64 == KTIME_MAX || |
| 1330 | if (tick_program_event(expires_next, force_clock_reprogram)) | 1324 | !tick_program_event(expires_next, 0)) { |
| 1331 | goto retry; | 1325 | cpu_base->hang_detected = 0; |
| 1326 | return; | ||
| 1332 | } | 1327 | } |
| 1328 | |||
| 1329 | /* | ||
| 1330 | * The next timer was already expired due to: | ||
| 1331 | * - tracing | ||
| 1332 | * - long lasting callbacks | ||
| 1333 | * - being scheduled away when running in a VM | ||
| 1334 | * | ||
| 1335 | * We need to prevent that we loop forever in the hrtimer | ||
| 1336 | * interrupt routine. We give it 3 attempts to avoid | ||
| 1337 | * overreacting on some spurious event. | ||
| 1338 | */ | ||
| 1339 | now = ktime_get(); | ||
| 1340 | cpu_base->nr_retries++; | ||
| 1341 | if (++retries < 3) | ||
| 1342 | goto retry; | ||
| 1343 | /* | ||
| 1344 | * Give the system a chance to do something else than looping | ||
| 1345 | * here. We stored the entry time, so we know exactly how long | ||
| 1346 | * we spent here. We schedule the next event this amount of | ||
| 1347 | * time away. | ||
| 1348 | */ | ||
| 1349 | cpu_base->nr_hangs++; | ||
| 1350 | cpu_base->hang_detected = 1; | ||
| 1351 | delta = ktime_sub(now, entry_time); | ||
| 1352 | if (delta.tv64 > cpu_base->max_hang_time.tv64) | ||
| 1353 | cpu_base->max_hang_time = delta; | ||
| 1354 | /* | ||
| 1355 | * Limit it to a sensible value as we enforce a longer | ||
| 1356 | * delay. Give the CPU at least 100ms to catch up. | ||
| 1357 | */ | ||
| 1358 | if (delta.tv64 > 100 * NSEC_PER_MSEC) | ||
| 1359 | expires_next = ktime_add_ns(now, 100 * NSEC_PER_MSEC); | ||
| 1360 | else | ||
| 1361 | expires_next = ktime_add(now, delta); | ||
| 1362 | tick_program_event(expires_next, 1); | ||
| 1363 | printk_once(KERN_WARNING "hrtimer: interrupt took %llu ns\n", | ||
| 1364 | ktime_to_ns(delta)); | ||
| 1333 | } | 1365 | } |
| 1334 | 1366 | ||
| 1335 | /* | 1367 | /* |
