From: Binoy Jayan <binoy.jayan@linaro.org>
To: "Steven Rostedt (Red Hat)" <rostedt@goodmis.org>,
Thomas Gleixner <tglx@linutronix.de>
Cc: Ingo Molnar <mingo@redhat.com>,
Daniel Wagner <daniel.wagner@bmw-carit.de>,
Arnd Bergmann <arnd@arndb.de>,
linux-kernel@vger.kernel.org,
Masami <masami.hiramatsu@linaro.org>,
Mark Brown <mark.brown@linaro.org>,
Binoy Jayan <binoy.jayan@linaro.org>,
Carsten Emde <C.Emde@osadl.org>
Subject: [RFC PATCH v7 3/5] tracing: Add preemptirqsoff timing events
Date: Tue, 20 Sep 2016 19:21:55 +0530 [thread overview]
Message-ID: <1474379517-7705-4-git-send-email-binoy.jayan@linaro.org> (raw)
In-Reply-To: <1474379517-7705-1-git-send-email-binoy.jayan@linaro.org>
Potential sources of latencies are code segments where interrupts,
preemption or both are disabled (aka critical sections). To create
histograms of potential sources of latency, the kernel stores the time
stamp at the start of a critical section, determines the time elapsed
when the end of the section is reached, and increments the frequency
counter of that latency value - irrespective of whether any concurrently
running process is affected by latency or not.
With the tracepoints for irqs off, preempt off and critical timing added
at the end of the critical sections, the potential sources of latencies
which occur in these sections can be measured in nanoseconds. With the
hist triggers in place, the histogram plots may be generated, with per-cpu
breakdown of events captured. It is based on linux kernel's event
infrastructure.
The following filter(s) may be used to with the histograms
'hist:key=latency.log2:val=hitcount:sort=latency'
'hist:key=ltype,latency:val=hitcount:sort=latency if cpu==1'
'hist:key=ltype:val=latency:sort=ltype if ltype==0 && cpu==2'
Where ltype is
1: IRQSOFF latency
2: PREEMPTOFF Latency
3: Critical Timings
Enable one or more of the following tracers to capture the associated
latencies i.e. irq/preempt/critical timing
In '/sys/kernel/debug/tracing'
echo irqsoff > current_tracer - irq and critical time latencies
echo preemptoff > current_tracer - preempt and critical time latencies
echo preemptirqsoff > current_tracer - irq, preempt and critical timing
[
- Initial work and idea by Carsten as part of PREEMPT_RT patch series
Link: https://git.kernel.org/cgit/linux/kernel/git/rt/linux-stable-rt.git/commit/?h=v3.14-rt-rebase&id=56d50cc34943bbba12b8c5942ee1ae3b29f73acb
No code was taken from the RT patch.
- RFC using hist infrastructure code by Daniel.
- Got it re-written in shape as Daniel suggested to take over author ship.
]
Cc: Carsten Emde <C.Emde@osadl.org>
Cc: Daniel Wagner <daniel.wagner@bmw-carit.de>
Signed-off-by: Binoy Jayan <binoy.jayan@linaro.org>
---
include/trace/events/latency.h | 62 ++++++++++++++++++++++++++++++++++++++++++
kernel/trace/trace_irqsoff.c | 43 +++++++++++++++++++----------
2 files changed, 91 insertions(+), 14 deletions(-)
create mode 100644 include/trace/events/latency.h
diff --git a/include/trace/events/latency.h b/include/trace/events/latency.h
new file mode 100644
index 0000000..66442d5
--- /dev/null
+++ b/include/trace/events/latency.h
@@ -0,0 +1,62 @@
+#undef TRACE_SYSTEM
+#define TRACE_SYSTEM latency
+
+#if !defined(_TRACE_HIST_H) || defined(TRACE_HEADER_MULTI_READ)
+#define _TRACE_HIST_H
+
+#include <linux/tracepoint.h>
+
+#ifndef __TRACE_LATENCY_TYPE
+#define __TRACE_LATENCY_TYPE
+
+enum latency_type {
+ LT_NONE,
+ LT_IRQ,
+ LT_PREEMPT,
+ LT_CRITTIME,
+ LT_MAX
+};
+
+TRACE_DEFINE_ENUM(LT_IRQ);
+TRACE_DEFINE_ENUM(LT_PREEMPT);
+TRACE_DEFINE_ENUM(LT_CRITTIME);
+
+#define show_ltype(type) \
+ __print_symbolic(type, \
+ { LT_IRQ, "IRQ" }, \
+ { LT_PREEMPT, "PREEMPT" }, \
+ { LT_CRITTIME, "CRIT_TIME" })
+#endif
+
+DECLARE_EVENT_CLASS(latency_template,
+ TP_PROTO(int ltype, u64 latency),
+
+ TP_ARGS(ltype, latency),
+
+ TP_STRUCT__entry(
+ __field(int, ltype)
+ __field(u64, latency)
+ ),
+
+ TP_fast_assign(
+ __entry->ltype = ltype;
+ __entry->latency = latency;
+ ),
+
+ TP_printk("ltype=%s(%d), latency=%lu", show_ltype(__entry->ltype),
+ __entry->ltype, (unsigned long) __entry->latency)
+);
+
+/**
+ * latency_preemptirqsoff - called when a cpu exits state of preemption / irq
+ * @ltype: type of the critical section. Refer 'show_ltype'
+ * @latency: latency in nano seconds
+ */
+DEFINE_EVENT(latency_template, latency_preemptirqsoff,
+ TP_PROTO(int ltype, u64 latency),
+ TP_ARGS(ltype, latency));
+
+#endif /* _TRACE_HIST_H */
+
+/* This part must be outside protection */
+#include <trace/define_trace.h>
diff --git a/kernel/trace/trace_irqsoff.c b/kernel/trace/trace_irqsoff.c
index 03cdff8..4f7442d 100644
--- a/kernel/trace/trace_irqsoff.c
+++ b/kernel/trace/trace_irqsoff.c
@@ -13,9 +13,14 @@
#include <linux/uaccess.h>
#include <linux/module.h>
#include <linux/ftrace.h>
+#include <linux/percpu-defs.h>
+#include <trace/events/sched.h>
#include "trace.h"
+#define CREATE_TRACE_POINTS
+#include <trace/events/latency.h>
+
static struct trace_array *irqsoff_trace __read_mostly;
static int tracer_enabled __read_mostly;
@@ -298,11 +303,18 @@ static bool report_latency(struct trace_array *tr, cycle_t delta)
return true;
}
+static inline void latency_preemptirqsoff_timing(enum latency_type type,
+ cycle_t delta)
+{
+ trace_latency_preemptirqsoff(type, (u64) delta);
+}
+
static void
check_critical_timing(struct trace_array *tr,
struct trace_array_cpu *data,
unsigned long parent_ip,
- int cpu)
+ int cpu,
+ enum latency_type ltype)
{
cycle_t T0, T1, delta;
unsigned long flags;
@@ -312,6 +324,7 @@ check_critical_timing(struct trace_array *tr,
T1 = ftrace_now(cpu);
delta = T1-T0;
+ latency_preemptirqsoff_timing(ltype, delta);
local_save_flags(flags);
pc = preempt_count();
@@ -351,7 +364,8 @@ out:
}
static inline void
-start_critical_timing(unsigned long ip, unsigned long parent_ip)
+start_critical_timing(unsigned long ip, unsigned long parent_ip,
+ enum latency_type ltype)
{
int cpu;
struct trace_array *tr = irqsoff_trace;
@@ -387,7 +401,8 @@ start_critical_timing(unsigned long ip, unsigned long parent_ip)
}
static inline void
-stop_critical_timing(unsigned long ip, unsigned long parent_ip)
+stop_critical_timing(unsigned long ip, unsigned long parent_ip,
+ enum latency_type ltype)
{
int cpu;
struct trace_array *tr = irqsoff_trace;
@@ -414,7 +429,7 @@ stop_critical_timing(unsigned long ip, unsigned long parent_ip)
local_save_flags(flags);
__trace_function(tr, ip, parent_ip, flags, preempt_count());
- check_critical_timing(tr, data, parent_ip ? : ip, cpu);
+ check_critical_timing(tr, data, parent_ip ? : ip, cpu, ltype);
data->critical_start = 0;
atomic_dec(&data->disabled);
}
@@ -423,14 +438,14 @@ stop_critical_timing(unsigned long ip, unsigned long parent_ip)
void start_critical_timings(void)
{
if (preempt_trace() || irq_trace())
- start_critical_timing(CALLER_ADDR0, CALLER_ADDR1);
+ start_critical_timing(CALLER_ADDR0, CALLER_ADDR1, LT_CRITTIME);
}
EXPORT_SYMBOL_GPL(start_critical_timings);
void stop_critical_timings(void)
{
if (preempt_trace() || irq_trace())
- stop_critical_timing(CALLER_ADDR0, CALLER_ADDR1);
+ stop_critical_timing(CALLER_ADDR0, CALLER_ADDR1, LT_CRITTIME);
}
EXPORT_SYMBOL_GPL(stop_critical_timings);
@@ -439,13 +454,13 @@ EXPORT_SYMBOL_GPL(stop_critical_timings);
void time_hardirqs_on(unsigned long a0, unsigned long a1)
{
if (!preempt_trace() && irq_trace())
- stop_critical_timing(a0, a1);
+ stop_critical_timing(a0, a1, LT_IRQ);
}
void time_hardirqs_off(unsigned long a0, unsigned long a1)
{
if (!preempt_trace() && irq_trace())
- start_critical_timing(a0, a1);
+ start_critical_timing(a0, a1, LT_IRQ);
}
#else /* !CONFIG_PROVE_LOCKING */
@@ -472,28 +487,28 @@ inline void print_irqtrace_events(struct task_struct *curr)
void trace_hardirqs_on(void)
{
if (!preempt_trace() && irq_trace())
- stop_critical_timing(CALLER_ADDR0, CALLER_ADDR1);
+ stop_critical_timing(CALLER_ADDR0, CALLER_ADDR1, LT_IRQ);
}
EXPORT_SYMBOL(trace_hardirqs_on);
void trace_hardirqs_off(void)
{
if (!preempt_trace() && irq_trace())
- start_critical_timing(CALLER_ADDR0, CALLER_ADDR1);
+ start_critical_timing(CALLER_ADDR0, CALLER_ADDR1, LT_IRQ);
}
EXPORT_SYMBOL(trace_hardirqs_off);
__visible void trace_hardirqs_on_caller(unsigned long caller_addr)
{
if (!preempt_trace() && irq_trace())
- stop_critical_timing(CALLER_ADDR0, caller_addr);
+ stop_critical_timing(CALLER_ADDR0, caller_addr, LT_IRQ);
}
EXPORT_SYMBOL(trace_hardirqs_on_caller);
__visible void trace_hardirqs_off_caller(unsigned long caller_addr)
{
if (!preempt_trace() && irq_trace())
- start_critical_timing(CALLER_ADDR0, caller_addr);
+ start_critical_timing(CALLER_ADDR0, caller_addr, LT_IRQ);
}
EXPORT_SYMBOL(trace_hardirqs_off_caller);
@@ -504,13 +519,13 @@ EXPORT_SYMBOL(trace_hardirqs_off_caller);
void trace_preempt_on(unsigned long a0, unsigned long a1)
{
if (preempt_trace() && !irq_trace())
- stop_critical_timing(a0, a1);
+ stop_critical_timing(a0, a1, LT_PREEMPT);
}
void trace_preempt_off(unsigned long a0, unsigned long a1)
{
if (preempt_trace() && !irq_trace())
- start_critical_timing(a0, a1);
+ start_critical_timing(a0, a1, LT_PREEMPT);
}
#endif /* CONFIG_PREEMPT_TRACER */
--
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project
next prev parent reply other threads:[~2016-09-20 13:56 UTC|newest]
Thread overview: 12+ messages / expand[flat|nested] mbox.gz Atom feed top
2016-09-20 13:51 [RFC PATCH v7 0/5] *** Latency histograms *** Binoy Jayan
2016-09-20 13:51 ` [RFC PATCH v7 1/5] tracing: Dereference pointers without RCU checks Binoy Jayan
2016-09-20 13:51 ` [RFC PATCH v7 2/5] tracing: Add hist trigger support for generic fields Binoy Jayan
2016-09-20 13:51 ` Binoy Jayan [this message]
2016-09-20 13:51 ` [RFC PATCH v7 4/5] tracing: Measure delayed hrtimer offset latency Binoy Jayan
2016-09-20 14:19 ` Thomas Gleixner
2016-09-21 6:06 ` Binoy Jayan
2016-09-21 15:58 ` Thomas Gleixner
2016-09-22 9:14 ` Binoy Jayan
2016-09-22 17:28 ` Thomas Gleixner
2016-09-22 19:23 ` Mark Brown
2016-09-20 13:51 ` [RFC PATCH v7 5/5] tracing: wakeup latency events and histograms Binoy Jayan
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=1474379517-7705-4-git-send-email-binoy.jayan@linaro.org \
--to=binoy.jayan@linaro.org \
--cc=C.Emde@osadl.org \
--cc=arnd@arndb.de \
--cc=daniel.wagner@bmw-carit.de \
--cc=linux-kernel@vger.kernel.org \
--cc=mark.brown@linaro.org \
--cc=masami.hiramatsu@linaro.org \
--cc=mingo@redhat.com \
--cc=rostedt@goodmis.org \
--cc=tglx@linutronix.de \
/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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).