public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
From: Tim Bird <tim.bird@am.sony.com>
To: linux kernel <linux-kernel@vger.kernel.org>,
	Steven Rostedt <rostedt@goodmis.org>,
	Frederic Weisbecker <fweisbec@gmail.com>,
	Ingo Molnar <mingo@elte.hu>,
	linux kernel <linux-kernel@vger.kernel.org>
Subject: [PATCH 1/2] ftrace: Add duration filtering to function graph tracer
Date: Mon, 6 Jul 2009 16:23:21 -0700	[thread overview]
Message-ID: <4A528769.5020200@am.sony.com> (raw)

Add duration filtering to the function graph tracer.

The duration filter value is set in the 'tracing_thresh'
pseudo-file.  Values are in microseconds (as is customary
for that file).

This adds ring_buffer_peek_previous(), used to help
remove the function entry event from the trace log,
where this is possible.

To use:
 $ cd <debugfs tracing directory>
 $ echo 100 >tracing_thresh
 $ echo function_graph >current_tracer
 $ cat trace

Signed-off-by: Tim Bird <tim.bird@am.sony.com>
---
 include/linux/ring_buffer.h |    3 ++
 kernel/trace/ring_buffer.c  |   33 ++++++++++++++++++++++++++++++
 kernel/trace/trace.c        |   47 ++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 83 insertions(+)

--- a/include/linux/ring_buffer.h
+++ b/include/linux/ring_buffer.h
@@ -136,6 +136,9 @@ int ring_buffer_write(struct ring_buffer
 struct ring_buffer_event *
 ring_buffer_peek(struct ring_buffer *buffer, int cpu, u64 *ts);
 struct ring_buffer_event *
+ring_buffer_peek_previous(struct ring_buffer *buffer,
+			  struct ring_buffer_event *event, int length);
+struct ring_buffer_event *
 ring_buffer_consume(struct ring_buffer *buffer, int cpu, u64 *ts);

 struct ring_buffer_iter *
--- a/kernel/trace/ring_buffer.c
+++ b/kernel/trace/ring_buffer.c
@@ -2523,6 +2523,39 @@ ring_buffer_peek(struct ring_buffer *buf
 }

 /**
+ * ring_buffer_peek_previous - peek at the previous event in the ring buffer
+ * @buffer: The ring buffer to read
+ * @length: The presumed length of the previous event
+ *
+ * This will return the previous data event in the buffer, unless
+ * we are at the beginning of the buffer.
+ */
+struct ring_buffer_event *
+ring_buffer_peek_previous(struct ring_buffer *buffer,
+		struct ring_buffer_event *event, int length)
+{
+	int cpu;
+	struct ring_buffer_per_cpu *cpu_buffer;
+	struct ring_buffer_event *prev_event;
+
+	cpu = raw_smp_processor_id();
+	cpu_buffer = buffer->buffers[cpu];
+
+	prev_event = (void *)event - length - RB_EVNT_HDR_SIZE;
+
+	/* abort if event type != DATA */
+	if (prev_event->type_len > RINGBUF_TYPE_DATA_TYPE_LEN_MAX)
+		return 0;
+
+	/* abort if prev_event < buffer start */
+	if ((void *)prev_event < (void *)cpu_buffer->commit_page)
+		return 0;
+
+	return prev_event;
+}
+
+
+/**
  * ring_buffer_iter_peek - peek at the next event to be read
  * @iter: The ring buffer iterator
  * @ts: The timestamp counter of this event.
--- a/kernel/trace/trace.c
+++ b/kernel/trace/trace.c
@@ -971,6 +971,38 @@ static int __trace_graph_entry(struct tr
 	return 1;
 }

+/* Try to remove the function entry event for the current (return) event from
+ * the ringbuffer.  Note that the current event has already been discarded.
+ * Rewinding the write position of the buffer to overwrite the entry event
+ * can only be done if the entry event immediately precedes the return
+ * event in the trace buffer.
+ *
+ * This should be true about 99% of the time.
+ *
+ * This is an operation fraught with peril.
+ *
+ * The reason for doing this is to save space in the trace buffer when a
+ * tracing_thresh filter is used.
+ */
+static void trace_buffer_discard_func_entry(struct ring_buffer_event *cur_event,
+	struct ftrace_graph_ret_entry *cur_entry)
+{
+	struct ring_buffer_event *prev_event;
+	struct ftrace_graph_ent_entry *prev_entry;
+	unsigned long func;
+
+	func = cur_entry->ret.func;
+	prev_event = ring_buffer_peek_previous(global_trace.buffer, cur_event,
+			sizeof(*prev_entry));
+	if (!prev_event)
+		return;
+
+	prev_entry = ring_buffer_event_data(prev_event);
+	if (func == prev_entry->graph_ent.func) {
+		ring_buffer_event_discard(prev_event);
+	}
+}
+
 static void __trace_graph_return(struct trace_array *tr,
 				struct ftrace_graph_ret *trace,
 				unsigned long flags,
@@ -979,6 +1011,7 @@ static void __trace_graph_return(struct
 	struct ftrace_event_call *call = &event_funcgraph_exit;
 	struct ring_buffer_event *event;
 	struct ftrace_graph_ret_entry *entry;
+	unsigned long long duration;

 	if (unlikely(local_read(&__get_cpu_var(ftrace_cpu_disabled))))
 		return;
@@ -989,6 +1022,20 @@ static void __trace_graph_return(struct
 		return;
 	entry	= ring_buffer_event_data(event);
 	entry->ret				= *trace;
+
+	/* do some special handling for duration filtering */
+	if (tracing_thresh) {
+		duration = trace->rettime - trace->calltime;
+		if (duration < tracing_thresh) {
+			/* abort this item (func exit event) */
+			ring_buffer_discard_commit(global_trace.buffer, event);
+
+			/* try to remove entry event from ring buffer also */
+			trace_buffer_discard_func_entry(event, entry);
+			return;
+		}
+	}
+
 	if (!filter_current_check_discard(call, entry, event))
 		ring_buffer_unlock_commit(global_trace.buffer, event);
 }


             reply	other threads:[~2009-07-06 23:23 UTC|newest]

Thread overview: 5+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2009-07-06 23:23 Tim Bird [this message]
2009-07-07  0:22 ` [PATCH 1/2] ftrace: Add duration filtering to function graph tracer Steven Rostedt
2009-07-07  1:39   ` Tim Bird
2009-07-07  2:15     ` Steven Rostedt
2009-07-07  2:22       ` Tim Bird

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=4A528769.5020200@am.sony.com \
    --to=tim.bird@am.sony.com \
    --cc=fweisbec@gmail.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=mingo@elte.hu \
    --cc=rostedt@goodmis.org \
    /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