From: Xiao Guangrong <xiaoguangrong@cn.fujitsu.com>
To: Ingo Molnar <mingo@elte.hu>
Cc: Thomas Gleixner <tglx@linutronix.de>,
Steven Rostedt <rostedt@goodmis.org>,
Frederic Weisbecker <fweisbec@gmail.com>,
Zhaolei <zhaolei@cn.fujitsu.com>,
kosaki.motohiro@jp.fujitsu.com,
Mathieu Desnoyers <mathieu.desnoyers@polymtl.ca>,
Anton Blanchard <anton@samba.org>,
LKML <linux-kernel@vger.kernel.org>
Subject: [PATCH v3 3/4] ftrace: add tracepoint for hrtimer
Date: Fri, 17 Jul 2009 18:18:49 +0800 [thread overview]
Message-ID: <4A605009.8060806@cn.fujitsu.com> (raw)
In-Reply-To: <4A604E46.5050903@cn.fujitsu.com>
Those tracepoints are wanted and useful:
1: We can detect a hrtimer's delay
2: We can monitor the lifecycle and behaviors of a hrtimer
Thus they help in analysing and debuging.
Great thanks to Thomas for giving me so many valuable advices.
Example ftrace output:
insmod-5280 [000] 10798.356372: hrtimer_init: timer=d0b044c0 clockid=CLOCK_REALTIME mode=HRTIMER_MODE_ABS
insmod-5280 [000] 10798.356385: hrtimer_start: timer=d0b044c0 func=hrtimer_fun expires=1246242896000000000 ns softexpires=1246242896000000000 ns
<idle>-0 [000] 10807.982987: hrtimer_expire: timer=d0b044c0 now=1246242896000906503 ns
<idle>-0 [000] 10807.982989: hrtimer_cancel: timer=d0b044c0
<idle>-0 [000] 10807.983562: hrtimer_callback_done: timer=d0b044c0
We expect the hrtimer expires at 1246242896000000000 ns, actually the
hrtimer expires at 1246242896000906503 ns, so it is delayed by
1246242896000906503-1246242896000000000 = 906503 ns.
We also realize the hrtimer's callback started at 10807.982987, and it
finished at 10807.983562, so it's taking 10807.983562-10807.982987=0.6ms.
Changelog:
v1->v2:
1: Remove ktime_to_ns() in TP_fast_assign()
2: Combine debugobjects and trace as Thomas's suggestion
v2->v3:
1: Remove function address from hrtimer_expire and hrtimer_cancel
as Thomas's suggestion
2: Remove debug_and_trace_hrtimer_expire() as Thomas's suggestion
3: Rename trace_hrtimer_entry() and trace_hrtimer_exit() to match this patch
Signed-off-by: Xiao Guangrong <xiaoguangrong@cn.fujitsu.com>
---
include/trace/events/timer.h | 107 ++++++++++++++++++++++++++++++++++--------
kernel/hrtimer.c | 35 +++++++++++---
2 files changed, 115 insertions(+), 27 deletions(-)
diff --git a/include/trace/events/timer.h b/include/trace/events/timer.h
index 967e225..8b22b12 100644
--- a/include/trace/events/timer.h
+++ b/include/trace/events/timer.h
@@ -116,58 +116,125 @@ TRACE_EVENT(timer_cancel,
TP_printk("timer=%p", __entry->timer)
);
+TRACE_EVENT(hrtimer_init,
+
+ TP_PROTO(struct hrtimer *timer, clockid_t clockid, enum hrtimer_mode mode),
+
+ TP_ARGS(timer, clockid, mode),
+
+ TP_STRUCT__entry(
+ __field( void *, timer )
+ __field( clockid_t, clockid )
+ __field( enum hrtimer_mode, mode )
+ ),
+
+ TP_fast_assign(
+ __entry->timer = timer;
+ __entry->clockid = clockid;
+ __entry->mode = mode;
+ ),
+
+ TP_printk("timer=%p clockid=%s mode=%s", __entry->timer,
+ __entry->clockid == CLOCK_REALTIME ?
+ "CLOCK_REALTIME" : "CLOCK_MONOTONIC",
+ __entry->mode == HRTIMER_MODE_ABS ?
+ "HRTIMER_MODE_ABS" : "HRTIMER_MODE_REL")
+);
+
+TRACE_EVENT(hrtimer_start,
+
+ TP_PROTO(struct hrtimer *timer),
+
+ TP_ARGS(timer),
+
+ TP_STRUCT__entry(
+ __field( void *, timer )
+ __field( void *, function )
+ __field( s64, expires )
+ __field( s64, softexpires )
+ ),
+
+ TP_fast_assign(
+ __entry->timer = timer;
+ __entry->function = timer->function;
+ __entry->expires = hrtimer_get_expires(timer).tv64;
+ __entry->softexpires = hrtimer_get_softexpires(timer).tv64;
+ ),
+
+ TP_printk("timer=%p func=%pf expires=%llu ns softexpires=%llu ns",
+ __entry->timer, __entry->function,
+ (unsigned long long)__entry->expires,
+ (unsigned long long)__entry->softexpires)
+);
+
/**
- * hrtimer_entry - called immediately before the high res timer callback
+ * htimmer_expire - called before the high res timer callback
* @timer: pointer to struct hrtimer
*
- * When used in combination with the hrtimer_exit tracepoint we can
+ * When used in combination with the hrtimer_callback_done tracepoint we can
* determine the high res timer latency.
**/
-TRACE_EVENT(hrtimer_entry,
+TRACE_EVENT(hrtimer_expire,
- TP_PROTO(struct hrtimer *timer),
+ TP_PROTO(struct hrtimer *timer, s64 now),
- TP_ARGS(timer),
+ TP_ARGS(timer, now),
TP_STRUCT__entry(
- __field(void *, function)
+ __field( void *, timer )
+ __field( s64, now )
),
TP_fast_assign(
- __entry->function = timer->function;
+ __entry->timer = timer;
+ __entry->now = now;
),
- TP_printk("func=%pf", __entry->function)
+ TP_printk("timer=%p now=%llu ns", __entry->timer,
+ (unsigned long long)__entry->now)
);
/**
- * hrtimer_exit - called immediately after the high res timer returns
+ * hrtimer_callback_done - called immediately after the high res timer returns
* @timer: pointer to struct hrtimer
* @restart: high res timer return value
*
* High res timer will restart if @restart is set to HRTIMER_RESTART.
- * When used in combination with the hrtimer_entry tracepoint we can
+ * When used in combination with the hrtimer_expire tracepoint we can
* determine the high res timer latency.
**/
-TRACE_EVENT(hrtimer_exit,
+TRACE_EVENT(hrtimer_callback_done,
- TP_PROTO(struct hrtimer *timer, int restart),
+ TP_PROTO(struct hrtimer *timer),
- TP_ARGS(timer, restart),
+ TP_ARGS(timer),
TP_STRUCT__entry(
- __field(void *, function)
- __field(int, restart)
+ __field( void *, timer )
),
TP_fast_assign(
- __entry->function = timer->function;
- __entry->restart = restart;
+ __entry->timer = timer;
),
- TP_printk("func=%pf restart=%s", __entry->function,
- (__entry->restart == HRTIMER_RESTART) ?
- "HRTIMER_RESTART" : "HRTIMER_NORESTART")
+ TP_printk("timer=%p", __entry->timer)
+);
+
+TRACE_EVENT(hrtimer_cancel,
+
+ TP_PROTO(struct hrtimer *timer),
+
+ TP_ARGS(timer),
+
+ TP_STRUCT__entry(
+ __field( void *, timer )
+ ),
+
+ TP_fast_assign(
+ __entry->timer = timer;
+ ),
+
+ TP_printk("timer=%p", __entry->timer)
);
#endif /* _TRACE_TIMER_H */
diff --git a/kernel/hrtimer.c b/kernel/hrtimer.c
index 33317e4..bd21c9b 100644
--- a/kernel/hrtimer.c
+++ b/kernel/hrtimer.c
@@ -442,6 +442,26 @@ static inline void debug_hrtimer_activate(struct hrtimer *timer) { }
static inline void debug_hrtimer_deactivate(struct hrtimer *timer) { }
#endif
+static inline void
+debug_and_trace_hrtimer_init(struct hrtimer *timer, clockid_t clockid,
+ enum hrtimer_mode mode)
+{
+ debug_hrtimer_init(timer);
+ trace_hrtimer_init(timer, clockid, mode);
+}
+
+static inline void debug_and_trace_hrtimer_activate(struct hrtimer *timer)
+{
+ debug_hrtimer_activate(timer);
+ trace_hrtimer_start(timer);
+}
+
+static inline void debug_and_trace_hrtimer_deactivate(struct hrtimer *timer)
+{
+ debug_hrtimer_deactivate(timer);
+ trace_hrtimer_cancel(timer);
+}
+
/* High resolution timer related functions */
#ifdef CONFIG_HIGH_RES_TIMERS
@@ -798,7 +818,7 @@ static int enqueue_hrtimer(struct hrtimer *timer,
struct hrtimer *entry;
int leftmost = 1;
- debug_hrtimer_activate(timer);
+ debug_and_trace_hrtimer_activate(timer);
/*
* Find the right place in the rbtree:
@@ -884,7 +904,7 @@ remove_hrtimer(struct hrtimer *timer, struct hrtimer_clock_base *base)
* reprogramming happens in the interrupt handler. This is a
* rare case and less expensive than a smp call.
*/
- debug_hrtimer_deactivate(timer);
+ debug_and_trace_hrtimer_deactivate(timer);
timer_stats_hrtimer_clear_start_info(timer);
reprogram = base->cpu_base == &__get_cpu_var(hrtimer_bases);
__remove_hrtimer(timer, base, HRTIMER_STATE_INACTIVE,
@@ -1118,7 +1138,7 @@ static void __hrtimer_init(struct hrtimer *timer, clockid_t clock_id,
void hrtimer_init(struct hrtimer *timer, clockid_t clock_id,
enum hrtimer_mode mode)
{
- debug_hrtimer_init(timer);
+ debug_and_trace_hrtimer_init(timer, clock_id, mode);
__hrtimer_init(timer, clock_id, mode);
}
EXPORT_SYMBOL_GPL(hrtimer_init);
@@ -1151,7 +1171,7 @@ static void __run_hrtimer(struct hrtimer *timer)
WARN_ON(!irqs_disabled());
- debug_hrtimer_deactivate(timer);
+ debug_and_trace_hrtimer_deactivate(timer);
__remove_hrtimer(timer, base, HRTIMER_STATE_CALLBACK, 0);
timer_stats_account_hrtimer(timer);
fn = timer->function;
@@ -1162,9 +1182,8 @@ static void __run_hrtimer(struct hrtimer *timer)
* the timer base.
*/
spin_unlock(&cpu_base->lock);
- trace_hrtimer_entry(timer);
restart = fn(timer);
- trace_hrtimer_exit(timer, restart);
+ trace_hrtimer_callback_done(timer);
spin_lock(&cpu_base->lock);
/*
@@ -1275,6 +1294,7 @@ void hrtimer_interrupt(struct clock_event_device *dev)
break;
}
+ trace_hrtimer_expire(timer, basenow.tv64);
__run_hrtimer(timer);
}
base++;
@@ -1397,6 +1417,7 @@ void hrtimer_run_queues(void)
hrtimer_get_expires_tv64(timer))
break;
+ trace_hrtimer_expire(timer, base->softirq_time.tv64);
__run_hrtimer(timer);
}
spin_unlock(&cpu_base->lock);
@@ -1573,7 +1594,7 @@ static void migrate_hrtimer_list(struct hrtimer_clock_base *old_base,
while ((node = rb_first(&old_base->active))) {
timer = rb_entry(node, struct hrtimer, node);
BUG_ON(hrtimer_callback_running(timer));
- debug_hrtimer_deactivate(timer);
+ debug_and_trace_hrtimer_deactivate(timer);
/*
* Mark it as STATE_MIGRATE not INACTIVE otherwise the
--
1.6.1.2
next prev parent reply other threads:[~2009-07-17 10:18 UTC|newest]
Thread overview: 15+ messages / expand[flat|nested] mbox.gz Atom feed top
2009-07-17 10:11 [PATCH v3 0/4] ftrace: add tracepoint for timer event Xiao Guangrong
2009-07-17 10:14 ` [PATCH v3 1/4] tracing/events: Add timer and high res timer tracepoints Xiao Guangrong
2009-07-17 10:16 ` [PATCH v3 2/4] ftrace: add tracepoint for timer Xiao Guangrong
2009-07-17 10:18 ` Xiao Guangrong [this message]
2009-07-17 10:50 ` [PATCH v3 3/4] ftrace: add tracepoint for hrtimer Peter Zijlstra
2009-07-20 7:25 ` Xiao Guangrong
2009-07-20 12:09 ` Peter Zijlstra
2009-07-22 9:36 ` Xiao Guangrong
2009-07-22 10:13 ` Peter Zijlstra
2009-07-22 15:36 ` Mathieu Desnoyers
2009-07-23 10:01 ` Xiao Guangrong
2009-07-23 10:07 ` Peter Zijlstra
2009-07-24 9:40 ` Xiao Guangrong
2009-07-24 11:11 ` Peter Zijlstra
2009-07-17 10:20 ` [PATCH v3 4/4] ftrace: add tracepoint for itimer Xiao Guangrong
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=4A605009.8060806@cn.fujitsu.com \
--to=xiaoguangrong@cn.fujitsu.com \
--cc=anton@samba.org \
--cc=fweisbec@gmail.com \
--cc=kosaki.motohiro@jp.fujitsu.com \
--cc=linux-kernel@vger.kernel.org \
--cc=mathieu.desnoyers@polymtl.ca \
--cc=mingo@elte.hu \
--cc=rostedt@goodmis.org \
--cc=tglx@linutronix.de \
--cc=zhaolei@cn.fujitsu.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.