aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBjoern Brandenburg <bbb@mpi-sws.org>2016-03-18 13:07:39 -0400
committerBjoern Brandenburg <bbb@mpi-sws.org>2017-05-26 17:12:38 -0400
commit13113c878cbcfdedcf339a20d85c473011937dff (patch)
tree48d4a076a66edac6034d416b65e4f59dd667c220
parent81129a9d240efb1030e3e68784480dbbd95e5fff (diff)
Hook into hrtimer to report large latencies
-rw-r--r--include/linux/hrtimer.h3
-rw-r--r--kernel/time/hrtimer.c29
2 files changed, 32 insertions, 0 deletions
diff --git a/include/linux/hrtimer.h b/include/linux/hrtimer.h
index 5e00f80b1535..720063df0ac0 100644
--- a/include/linux/hrtimer.h
+++ b/include/linux/hrtimer.h
@@ -109,6 +109,9 @@ struct hrtimer {
109 void *start_site; 109 void *start_site;
110 char start_comm[16]; 110 char start_comm[16];
111#endif 111#endif
112#ifdef CONFIG_REPORT_TIMER_LATENCY
113 ktime_t when_added;
114#endif
112}; 115};
113 116
114/** 117/**
diff --git a/kernel/time/hrtimer.c b/kernel/time/hrtimer.c
index a78e3558d0b6..b4824e1dbc6d 100644
--- a/kernel/time/hrtimer.c
+++ b/kernel/time/hrtimer.c
@@ -990,6 +990,10 @@ void hrtimer_start_range_ns(struct hrtimer *timer, ktime_t tim,
990 990
991 tim = hrtimer_update_lowres(timer, tim, mode); 991 tim = hrtimer_update_lowres(timer, tim, mode);
992 992
993#ifdef CONFIG_REPORT_TIMER_LATENCY
994 timer->when_added = base->get_time();
995#endif
996
993 hrtimer_set_expires_range_ns(timer, tim, delta_ns); 997 hrtimer_set_expires_range_ns(timer, tim, delta_ns);
994 998
995 /* Switch the timer base, if necessary: */ 999 /* Switch the timer base, if necessary: */
@@ -1274,6 +1278,9 @@ static void __hrtimer_run_queues(struct hrtimer_cpu_base *cpu_base, ktime_t now)
1274{ 1278{
1275 struct hrtimer_clock_base *base = cpu_base->clock_base; 1279 struct hrtimer_clock_base *base = cpu_base->clock_base;
1276 unsigned int active = cpu_base->active_bases; 1280 unsigned int active = cpu_base->active_bases;
1281#ifdef CONFIG_REPORT_TIMER_LATENCY
1282 ktime_t was_exp_nxt = cpu_base->expires_next;
1283#endif
1277 1284
1278 for (; active; base++, active >>= 1) { 1285 for (; active; base++, active >>= 1) {
1279 struct timerqueue_node *node; 1286 struct timerqueue_node *node;
@@ -1304,6 +1311,28 @@ static void __hrtimer_run_queues(struct hrtimer_cpu_base *cpu_base, ktime_t now)
1304 if (basenow.tv64 < hrtimer_get_softexpires_tv64(timer)) 1311 if (basenow.tv64 < hrtimer_get_softexpires_tv64(timer))
1305 break; 1312 break;
1306 1313
1314#ifdef CONFIG_REPORT_TIMER_LATENCY
1315 if (cpu_base->hres_active &&
1316 (basenow.tv64 >=
1317 hrtimer_get_expires_tv64(timer) +
1318 ((s64) CONFIG_REPORT_TIMER_LATENCY_THRESHOLD))) {
1319 printk_ratelimited(KERN_WARNING
1320 "WARNING: P%d timer latency:%lld now:%lld "
1321 "basenow:%lld exp:%lld soft-exp:%lld "
1322 "nxt:%lld added:%lld "
1323 "timer:%p fn:%p"
1324 "\n",
1325 smp_processor_id(),
1326 basenow.tv64 - hrtimer_get_expires_tv64(timer),
1327 now.tv64, basenow.tv64,
1328 hrtimer_get_expires_tv64(timer),
1329 hrtimer_get_softexpires_tv64(timer),
1330 was_exp_nxt.tv64,
1331 timer->when_added.tv64,
1332 timer, timer->function);
1333 }
1334#endif
1335
1307 __run_hrtimer(cpu_base, base, timer, &basenow); 1336 __run_hrtimer(cpu_base, base, timer, &basenow);
1308 } 1337 }
1309 } 1338 }