aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorXiao Guangrong <xiaoguangrong@cn.fujitsu.com>2009-08-09 22:51:23 -0400
committerThomas Gleixner <tglx@linutronix.de>2009-08-29 08:10:06 -0400
commitc6a2a1770245f654f35f60e1458d4356680f9519 (patch)
tree0a015269ca839ac2fe91b3d86955997bf7b8686d
parent2b022e3d4bf9885f781221c59d86283a2cdfc2ed (diff)
hrtimer: Add tracepoint for hrtimers
Add tracepoints which cover the life cycle of a hrtimer. The tracepoints are integrated with the already existing debug_object debug points as far as possible. [ tglx: Fixed comments, made output conistent, easier to read and parse. Fixed output for 32bit archs which do not use the scalar representation of ktime_t. Hand current time to trace_hrtimer_expiry_entry instead of calling get_time() inside of the trace assignment. ] Signed-off-by: Xiao Guangrong <xiaoguangrong@cn.fujitsu.com> Cc: Steven Rostedt <rostedt@goodmis.org> Cc: Frederic Weisbecker <fweisbec@gmail.com> Cc: Mathieu Desnoyers <mathieu.desnoyers@polymtl.ca> Cc: Anton Blanchard <anton@samba.org> Cc: Peter Zijlstra <peterz@infradead.org> Cc: KOSAKI Motohiro <kosaki.motohiro@jp.fujitsu.com> Cc: Zhaolei <zhaolei@cn.fujitsu.com> LKML-Reference: <4A7F8B2B.5020908@cn.fujitsu.com> Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
-rw-r--r--include/trace/events/timer.h139
-rw-r--r--kernel/hrtimer.c40
2 files changed, 171 insertions, 8 deletions
diff --git a/include/trace/events/timer.h b/include/trace/events/timer.h
index 725892a93b49..df3c07fa0cb8 100644
--- a/include/trace/events/timer.h
+++ b/include/trace/events/timer.h
@@ -5,6 +5,7 @@
5#define _TRACE_TIMER_H 5#define _TRACE_TIMER_H
6 6
7#include <linux/tracepoint.h> 7#include <linux/tracepoint.h>
8#include <linux/hrtimer.h>
8#include <linux/timer.h> 9#include <linux/timer.h>
9 10
10/** 11/**
@@ -131,6 +132,144 @@ TRACE_EVENT(timer_cancel,
131 TP_printk("timer %p", __entry->timer) 132 TP_printk("timer %p", __entry->timer)
132); 133);
133 134
135/**
136 * hrtimer_init - called when the hrtimer is initialized
137 * @timer: pointer to struct hrtimer
138 * @clockid: the hrtimers clock
139 * @mode: the hrtimers mode
140 */
141TRACE_EVENT(hrtimer_init,
142
143 TP_PROTO(struct hrtimer *timer, clockid_t clockid,
144 enum hrtimer_mode mode),
145
146 TP_ARGS(timer, clockid, mode),
147
148 TP_STRUCT__entry(
149 __field( void *, timer )
150 __field( clockid_t, clockid )
151 __field( enum hrtimer_mode, mode )
152 ),
153
154 TP_fast_assign(
155 __entry->timer = timer;
156 __entry->clockid = clockid;
157 __entry->mode = mode;
158 ),
159
160 TP_printk("hrtimer %p, clockid %s, mode %s", __entry->timer,
161 __entry->clockid == CLOCK_REALTIME ?
162 "CLOCK_REALTIME" : "CLOCK_MONOTONIC",
163 __entry->mode == HRTIMER_MODE_ABS ?
164 "HRTIMER_MODE_ABS" : "HRTIMER_MODE_REL")
165);
166
167/**
168 * hrtimer_start - called when the hrtimer is started
169 * @timer: pointer to struct hrtimer
170 */
171TRACE_EVENT(hrtimer_start,
172
173 TP_PROTO(struct hrtimer *timer),
174
175 TP_ARGS(timer),
176
177 TP_STRUCT__entry(
178 __field( void *, timer )
179 __field( void *, function )
180 __field( s64, expires )
181 __field( s64, softexpires )
182 ),
183
184 TP_fast_assign(
185 __entry->timer = timer;
186 __entry->function = timer->function;
187 __entry->expires = hrtimer_get_expires(timer).tv64;
188 __entry->softexpires = hrtimer_get_softexpires(timer).tv64;
189 ),
190
191 TP_printk("hrtimer %p, func %pf, expires %llu, softexpires %llu",
192 __entry->timer, __entry->function,
193 (unsigned long long)ktime_to_ns((ktime_t) {
194 .tv64 = __entry->expires }),
195 (unsigned long long)ktime_to_ns((ktime_t) {
196 .tv64 = __entry->softexpires }))
197);
198
199/**
200 * htimmer_expire_entry - called immediately before the hrtimer callback
201 * @timer: pointer to struct hrtimer
202 * @now: pointer to variable which contains current time of the
203 * timers base.
204 *
205 * Allows to determine the timer latency.
206 */
207TRACE_EVENT(hrtimer_expire_entry,
208
209 TP_PROTO(struct hrtimer *timer, ktime_t *now),
210
211 TP_ARGS(timer, now),
212
213 TP_STRUCT__entry(
214 __field( void *, timer )
215 __field( s64, now )
216 ),
217
218 TP_fast_assign(
219 __entry->timer = timer;
220 __entry->now = now->tv64;
221 ),
222
223 TP_printk("hrtimer %p, now %llu", __entry->timer,
224 (unsigned long long)ktime_to_ns((ktime_t) {
225 .tv64 = __entry->now }))
226 );
227
228/**
229 * hrtimer_expire_exit - called immediately after the hrtimer callback returns
230 * @timer: pointer to struct hrtimer
231 *
232 * When used in combination with the hrtimer_expire_entry tracepoint we can
233 * determine the runtime of the callback function.
234 */
235TRACE_EVENT(hrtimer_expire_exit,
236
237 TP_PROTO(struct hrtimer *timer),
238
239 TP_ARGS(timer),
240
241 TP_STRUCT__entry(
242 __field( void *, timer )
243 ),
244
245 TP_fast_assign(
246 __entry->timer = timer;
247 ),
248
249 TP_printk("hrtimer %p", __entry->timer)
250);
251
252/**
253 * hrtimer_cancel - called when the hrtimer is canceled
254 * @timer: pointer to struct hrtimer
255 */
256TRACE_EVENT(hrtimer_cancel,
257
258 TP_PROTO(struct hrtimer *timer),
259
260 TP_ARGS(timer),
261
262 TP_STRUCT__entry(
263 __field( void *, timer )
264 ),
265
266 TP_fast_assign(
267 __entry->timer = timer;
268 ),
269
270 TP_printk("hrtimer %p", __entry->timer)
271);
272
134#endif /* _TRACE_TIMER_H */ 273#endif /* _TRACE_TIMER_H */
135 274
136/* This part must be outside protection */ 275/* This part must be outside protection */
diff --git a/kernel/hrtimer.c b/kernel/hrtimer.c
index e2f91ecc01a8..b44d1b07377b 100644
--- a/kernel/hrtimer.c
+++ b/kernel/hrtimer.c
@@ -48,6 +48,8 @@
48 48
49#include <asm/uaccess.h> 49#include <asm/uaccess.h>
50 50
51#include <trace/events/timer.h>
52
51/* 53/*
52 * The timer bases: 54 * The timer bases:
53 * 55 *
@@ -441,6 +443,26 @@ static inline void debug_hrtimer_activate(struct hrtimer *timer) { }
441static inline void debug_hrtimer_deactivate(struct hrtimer *timer) { } 443static inline void debug_hrtimer_deactivate(struct hrtimer *timer) { }
442#endif 444#endif
443 445
446static inline void
447debug_init(struct hrtimer *timer, clockid_t clockid,
448 enum hrtimer_mode mode)
449{
450 debug_hrtimer_init(timer);
451 trace_hrtimer_init(timer, clockid, mode);
452}
453
454static inline void debug_activate(struct hrtimer *timer)
455{
456 debug_hrtimer_activate(timer);
457 trace_hrtimer_start(timer);
458}
459
460static inline void debug_deactivate(struct hrtimer *timer)
461{
462 debug_hrtimer_deactivate(timer);
463 trace_hrtimer_cancel(timer);
464}
465
444/* High resolution timer related functions */ 466/* High resolution timer related functions */
445#ifdef CONFIG_HIGH_RES_TIMERS 467#ifdef CONFIG_HIGH_RES_TIMERS
446 468
@@ -797,7 +819,7 @@ static int enqueue_hrtimer(struct hrtimer *timer,
797 struct hrtimer *entry; 819 struct hrtimer *entry;
798 int leftmost = 1; 820 int leftmost = 1;
799 821
800 debug_hrtimer_activate(timer); 822 debug_activate(timer);
801 823
802 /* 824 /*
803 * Find the right place in the rbtree: 825 * Find the right place in the rbtree:
@@ -883,7 +905,7 @@ remove_hrtimer(struct hrtimer *timer, struct hrtimer_clock_base *base)
883 * reprogramming happens in the interrupt handler. This is a 905 * reprogramming happens in the interrupt handler. This is a
884 * rare case and less expensive than a smp call. 906 * rare case and less expensive than a smp call.
885 */ 907 */
886 debug_hrtimer_deactivate(timer); 908 debug_deactivate(timer);
887 timer_stats_hrtimer_clear_start_info(timer); 909 timer_stats_hrtimer_clear_start_info(timer);
888 reprogram = base->cpu_base == &__get_cpu_var(hrtimer_bases); 910 reprogram = base->cpu_base == &__get_cpu_var(hrtimer_bases);
889 __remove_hrtimer(timer, base, HRTIMER_STATE_INACTIVE, 911 __remove_hrtimer(timer, base, HRTIMER_STATE_INACTIVE,
@@ -1116,7 +1138,7 @@ static void __hrtimer_init(struct hrtimer *timer, clockid_t clock_id,
1116void hrtimer_init(struct hrtimer *timer, clockid_t clock_id, 1138void hrtimer_init(struct hrtimer *timer, clockid_t clock_id,
1117 enum hrtimer_mode mode) 1139 enum hrtimer_mode mode)
1118{ 1140{
1119 debug_hrtimer_init(timer); 1141 debug_init(timer, clock_id, mode);
1120 __hrtimer_init(timer, clock_id, mode); 1142 __hrtimer_init(timer, clock_id, mode);
1121} 1143}
1122EXPORT_SYMBOL_GPL(hrtimer_init); 1144EXPORT_SYMBOL_GPL(hrtimer_init);
@@ -1140,7 +1162,7 @@ int hrtimer_get_res(const clockid_t which_clock, struct timespec *tp)
1140} 1162}
1141EXPORT_SYMBOL_GPL(hrtimer_get_res); 1163EXPORT_SYMBOL_GPL(hrtimer_get_res);
1142 1164
1143static void __run_hrtimer(struct hrtimer *timer) 1165static void __run_hrtimer(struct hrtimer *timer, ktime_t *now)
1144{ 1166{
1145 struct hrtimer_clock_base *base = timer->base; 1167 struct hrtimer_clock_base *base = timer->base;
1146 struct hrtimer_cpu_base *cpu_base = base->cpu_base; 1168 struct hrtimer_cpu_base *cpu_base = base->cpu_base;
@@ -1149,7 +1171,7 @@ static void __run_hrtimer(struct hrtimer *timer)
1149 1171
1150 WARN_ON(!irqs_disabled()); 1172 WARN_ON(!irqs_disabled());
1151 1173
1152 debug_hrtimer_deactivate(timer); 1174 debug_deactivate(timer);
1153 __remove_hrtimer(timer, base, HRTIMER_STATE_CALLBACK, 0); 1175 __remove_hrtimer(timer, base, HRTIMER_STATE_CALLBACK, 0);
1154 timer_stats_account_hrtimer(timer); 1176 timer_stats_account_hrtimer(timer);
1155 fn = timer->function; 1177 fn = timer->function;
@@ -1160,7 +1182,9 @@ static void __run_hrtimer(struct hrtimer *timer)
1160 * the timer base. 1182 * the timer base.
1161 */ 1183 */
1162 spin_unlock(&cpu_base->lock); 1184 spin_unlock(&cpu_base->lock);
1185 trace_hrtimer_expire_entry(timer, now);
1163 restart = fn(timer); 1186 restart = fn(timer);
1187 trace_hrtimer_expire_exit(timer);
1164 spin_lock(&cpu_base->lock); 1188 spin_lock(&cpu_base->lock);
1165 1189
1166 /* 1190 /*
@@ -1271,7 +1295,7 @@ void hrtimer_interrupt(struct clock_event_device *dev)
1271 break; 1295 break;
1272 } 1296 }
1273 1297
1274 __run_hrtimer(timer); 1298 __run_hrtimer(timer, &basenow);
1275 } 1299 }
1276 base++; 1300 base++;
1277 } 1301 }
@@ -1393,7 +1417,7 @@ void hrtimer_run_queues(void)
1393 hrtimer_get_expires_tv64(timer)) 1417 hrtimer_get_expires_tv64(timer))
1394 break; 1418 break;
1395 1419
1396 __run_hrtimer(timer); 1420 __run_hrtimer(timer, &base->softirq_time);
1397 } 1421 }
1398 spin_unlock(&cpu_base->lock); 1422 spin_unlock(&cpu_base->lock);
1399 } 1423 }
@@ -1569,7 +1593,7 @@ static void migrate_hrtimer_list(struct hrtimer_clock_base *old_base,
1569 while ((node = rb_first(&old_base->active))) { 1593 while ((node = rb_first(&old_base->active))) {
1570 timer = rb_entry(node, struct hrtimer, node); 1594 timer = rb_entry(node, struct hrtimer, node);
1571 BUG_ON(hrtimer_callback_running(timer)); 1595 BUG_ON(hrtimer_callback_running(timer));
1572 debug_hrtimer_deactivate(timer); 1596 debug_deactivate(timer);
1573 1597
1574 /* 1598 /*
1575 * Mark it as STATE_MIGRATE not INACTIVE otherwise the 1599 * Mark it as STATE_MIGRATE not INACTIVE otherwise the