All of lore.kernel.org
 help / color / mirror / Atom feed
From: Ingo Molnar <mingo@elte.hu>
To: Pekka Enberg <penberg@kernel.org>
Cc: Thomas Gleixner <tglx@linutronix.de>,
	Peter Zijlstra <peterz@infradead.org>,
	Steven Rostedt <rostedt@goodmis.org>,
	Arjan van de Ven <arjan@linux.intel.com>,
	Arnaldo Carvalho de Melo <acme@redhat.com>,
	Frederic Weisbecker <fweisbec@gmail.com>,
	linux-kernel@vger.kernel.org,
	Linus Torvalds <torvalds@linux-foundation.org>,
	Andrew Morton <akpm@linux-foundation.org>,
	Darren Hart <dvhart@linux.intel.com>,
	Arjan van de Ven <arjan@infradead.org>
Subject: [patch] trace: Add user-space event tracing/injection
Date: Wed, 17 Nov 2010 13:07:40 +0100	[thread overview]
Message-ID: <20101117120740.GA24972@elte.hu> (raw)
In-Reply-To: <4CE38C53.8090606@kernel.org>


* Pekka Enberg <penberg@kernel.org> wrote:

> (Trimming CC for sanity.)

[ Added back Linus (in case he wants to object to the new prctl()) and lkml. ]

> On 11/16/10 11:04 PM, Thomas Gleixner wrote:
> >'trace' is our shot at improving the situation: it aims at providing a
> >simple to use and straightforward tracing tool based on the perf
> >infrastructure and on the well-known perf profiling workflow:
> >
> >    trace record firefox          # trace firefox and all child tasks,
> >                                    put it into trace.data
> >
> >    trace summary                 # show quick overview of the trace,
> >                                    based on trace.data
> >
> >    trace report                  # detailed traces, based on trace.data
> 
> Nice work guys!
> 
> Does this concept lend itself to tracing latencies in userspace applications that 
> run in virtual machines (e.g. the Java kind)? I'm of course interested in this 
> because of Jato [1] where bunch of interesting things can cause jitter: JIT 
> compilation, GC, kernel, and the actual application doing something (in either 
> native code or JIT'd code). It's important to be able to measure where "slowness" 
> to desktop applications and certain class of server applications comes from to be 
> able to improve things.

Makes quite a bit of sense.

How about the attached patch? It works fine with the simple testcase included in the 
changelog. There's a common-sense limit on the message size - but otherwise it adds 
support for apps to generate a free-form string trace event.

Thanks,

	Ingo

---------------------------------->
Subject: trace: Add user-space event tracing/injection
From: Ingo Molnar <mingo@elte.hu>
Date: Wed Nov 17 10:11:53 CET 2010

This feature (suggested by Darren Hart and Pekka Engberg) allows user-space
programs to print trace events in a very simple and self-contained way:

 #include <sys/prctl.h>
 #include <string.h>

 #define PR_TASK_PERF_USER_TRACE 35

 int main(void)
 {
         char *msg = "Hello World!\n";

         prctl(PR_TASK_PERF_USER_TRACE, msg, strlen(msg));

         return 0;
 }

These show up in 'trace' output as:

 $ trace report
 #
 # trace events of 'sleep 1':
 #
        testit/ 6006 ( 0.002 ms): <"Hello World!">
        testit/ 6006 ( 0.002 ms): <"Hello World!">

Suggested-by: Darren Hart <dvhart@linux.intel.com>
Suggested-by: Pekka Enberg <penberg@kernel.org>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
---
 include/linux/prctl.h       |    2 ++
 include/trace/events/user.h |   32 ++++++++++++++++++++++++++++++++
 kernel/sys.c                |   23 +++++++++++++++++++++++
 kernel/trace/trace_events.c |   34 +++++++++++-----------------------
 tools/perf/builtin-trace.c  |   41 +++++++++++++++++++++++++++++++++++++++++
 5 files changed, 109 insertions(+), 23 deletions(-)

Index: linux/include/linux/prctl.h
===================================================================
--- linux.orig/include/linux/prctl.h
+++ linux/include/linux/prctl.h
@@ -102,4 +102,6 @@
 
 #define PR_MCE_KILL_GET 34
 
+#define PR_TASK_PERF_USER_TRACE			35
+
 #endif /* _LINUX_PRCTL_H */
Index: linux/include/trace/events/user.h
===================================================================
--- /dev/null
+++ linux/include/trace/events/user.h
@@ -0,0 +1,32 @@
+#undef TRACE_SYSTEM
+#define TRACE_SYSTEM user
+
+#if !defined(_TRACE_USER_H) || defined(TRACE_HEADER_MULTI_READ)
+#define _TRACE_USER_H_
+
+#include <linux/tracepoint.h>
+#include <linux/ftrace.h>
+
+TRACE_EVENT(user,
+
+	TP_PROTO(const char *message),
+
+	TP_ARGS(message),
+
+	TP_STRUCT__entry(
+		__string(	message, message);
+	),
+
+	TP_fast_assign(
+		__assign_str(message, message);
+	),
+
+	TP_printk("user %s", __get_str(message))
+);
+
+#undef NO_DEV
+
+#endif /* _TRACE_USER_H_ */
+
+/* This part must be outside protection */
+#include <trace/define_trace.h>
Index: linux/kernel/sys.c
===================================================================
--- linux.orig/kernel/sys.c
+++ linux/kernel/sys.c
@@ -47,6 +47,11 @@
 #include <asm/io.h>
 #include <asm/unistd.h>
 
+#define MAX_USER_TRACE_SIZE 128
+
+#define CREATE_TRACE_POINTS
+#include <trace/events/user.h>
+
 #ifndef SET_UNALIGN_CTL
 # define SET_UNALIGN_CTL(a,b)	(-EINVAL)
 #endif
@@ -1681,6 +1686,24 @@ SYSCALL_DEFINE5(prctl, int, option, unsi
 		case PR_TASK_PERF_EVENTS_ENABLE:
 			error = perf_event_task_enable();
 			break;
+		/*
+		 * Inject a trace event into the current tracing context:
+		 */
+		case PR_TASK_PERF_USER_TRACE:
+		{
+			void __user *uevent_ptr = (void *)arg2;
+			char kstring[MAX_USER_TRACE_SIZE+1];
+			unsigned long uevent_len = arg3;
+
+			if (uevent_len > MAX_USER_TRACE_SIZE)
+				return -EINVAL;
+			if (copy_from_user(kstring, uevent_ptr, uevent_len))
+				return -EFAULT;
+			kstring[uevent_len] = 0;
+
+			trace_user(kstring);
+			return 0;
+		}
 		case PR_GET_TIMERSLACK:
 			error = current->timer_slack_ns;
 			break;
Index: linux/kernel/trace/trace_events.c
===================================================================
--- linux.orig/kernel/trace/trace_events.c
+++ linux/kernel/trace/trace_events.c
@@ -989,8 +989,7 @@ static struct dentry *event_trace_events
 
 	d_events = debugfs_create_dir("events", d_tracer);
 	if (!d_events)
-		pr_warning("Could not create debugfs "
-			   "'events' directory\n");
+		pr_warning("Could not create debugfs 'events' directory\n");
 
 	return d_events;
 }
@@ -1014,15 +1013,13 @@ event_subsystem_dir(const char *name, st
 	/* need to create new entry */
 	system = kmalloc(sizeof(*system), GFP_KERNEL);
 	if (!system) {
-		pr_warning("No memory to create event subsystem %s\n",
-			   name);
+		pr_warning("No memory to create event subsystem %s\n", name);
 		return d_events;
 	}
 
 	system->entry = debugfs_create_dir(name, d_events);
 	if (!system->entry) {
-		pr_warning("Could not create event subsystem %s\n",
-			   name);
+		pr_warning("Could not create event subsystem %s\n", name);
 		kfree(system);
 		return d_events;
 	}
@@ -1041,8 +1038,7 @@ event_subsystem_dir(const char *name, st
 
 	system->filter = kzalloc(sizeof(struct event_filter), GFP_KERNEL);
 	if (!system->filter) {
-		pr_warning("Could not allocate filter for subsystem "
-			   "'%s'\n", name);
+		pr_warning("Could not allocate filter for subsystem '%s'\n", name);
 		return system->entry;
 	}
 
@@ -1051,8 +1047,7 @@ event_subsystem_dir(const char *name, st
 	if (!entry) {
 		kfree(system->filter);
 		system->filter = NULL;
-		pr_warning("Could not create debugfs "
-			   "'%s/filter' entry\n", name);
+		pr_warning("Could not create debugfs '%s/filter' entry\n", name);
 	}
 
 	trace_create_file("enable", 0644, system->entry,
@@ -1081,19 +1076,16 @@ event_create_dir(struct ftrace_event_cal
 
 	call->dir = debugfs_create_dir(call->name, d_events);
 	if (!call->dir) {
-		pr_warning("Could not create debugfs "
-			   "'%s' directory\n", call->name);
+		pr_warning("Could not create debugfs '%s' directory\n", call->name);
 		return -1;
 	}
 
 	if (call->class->reg)
-		trace_create_file("enable", 0644, call->dir, call,
-				  enable);
+		trace_create_file("enable", 0644, call->dir, call, enable);
 
 #ifdef CONFIG_PERF_EVENTS
 	if (call->event.type && call->class->reg)
-		trace_create_file("id", 0444, call->dir, call,
-		 		  id);
+		trace_create_file("id", 0444, call->dir, call, id);
 #endif
 
 	/*
@@ -1104,16 +1096,12 @@ event_create_dir(struct ftrace_event_cal
 	if (list_empty(head)) {
 		ret = call->class->define_fields(call);
 		if (ret < 0) {
-			pr_warning("Could not initialize trace point"
-				   " events/%s\n", call->name);
+			pr_warning("Could not initialize trace point events/%s\n", call->name);
 			return ret;
 		}
 	}
-	trace_create_file("filter", 0644, call->dir, call,
-			  filter);
-
-	trace_create_file("format", 0444, call->dir, call,
-			  format);
+	trace_create_file("filter", 0644, call->dir, call, filter);
+	trace_create_file("format", 0444, call->dir, call, format);
 
 	return 0;
 }
Index: linux/tools/perf/builtin-trace.c
===================================================================
--- linux.orig/tools/perf/builtin-trace.c
+++ linux/tools/perf/builtin-trace.c
@@ -719,6 +719,44 @@ static void vfs_getname(void *data,
 	}
 }
 
+static void user_event(void *data,
+			struct event *event __used,
+			int cpu __used,
+			u64 timestamp __used,
+			struct thread *thread __used)
+{
+	struct thread_data *tdata = get_thread_data(thread);
+	unsigned int i;
+	char *message;
+	u64 t = 0;
+
+	if (!tdata->enabled)
+		return;
+	if (time_filtered(timestamp))
+		return;
+	if (cpu_filtered(cpu))
+		return;
+	if (tdata->entry_time) {
+		t = timestamp - tdata->entry_time;
+		if (filter_duration(t))
+			return;
+	} else if (duration_filter)
+		return;
+
+	print_entry_head(thread, timestamp, t, cpu);
+	message = strdup(raw_field_ptr(event, "message", data));
+
+	/* Sanitize the string a bit before printing it: */
+	for (i = 0; i < strlen(message); i++) {
+		if (message[i] == '\n')
+			message[i] = ' ';
+	}
+
+	color_fprintf(stdout, PERF_COLOR_GREEN, "<\"%s\">\n", message);
+
+	free(message);
+}
+
 static int pagefault_preprocess_sample(const event_t *self,
 				       struct addr_location *al,
 				       struct sample_data *data,
@@ -1036,6 +1074,8 @@ process_raw_event(event_t *self, void *d
 		pagefault_exit(data, event, cpu, timestamp, thread);
 	if (!strcmp(event->name, "vfs_getname"))
 		vfs_getname(data, event, cpu, timestamp, thread);
+	if (!strcmp(event->name, "user"))
+		user_event(data, event, cpu, timestamp, thread);
 
 	if (!scheduler_events && !scheduler_all_events)
 		return;
@@ -1226,6 +1266,7 @@ static const char *record_args[] = {
 	"-e", "sched:sched_stat_sleep:r",
 	"-e", "sched:sched_stat_iowait:r",
 	"-e", "sched:sched_stat_runtime:r",
+	"-e", "user:user:r",
 };
 
 static int __cmd_record(int argc, const char **argv)


  parent reply	other threads:[~2010-11-17 12:08 UTC|newest]

Thread overview: 88+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2010-11-16 21:04 [ANNOUNCE] New utility: 'trace' Thomas Gleixner
2010-11-16 21:27 ` Darren Hart
2010-11-16 21:59   ` Ingo Molnar
2010-11-16 22:03     ` Peter Zijlstra
2010-11-16 22:08       ` Ingo Molnar
2010-11-16 22:09       ` Darren Hart
2010-11-16 22:48         ` Darren Hart
2010-11-16 22:07     ` Darren Hart
2010-11-16 22:17   ` Frederic Weisbecker
2010-11-17  8:30     ` Ingo Molnar
2010-11-17 11:35       ` Peter Zijlstra
2010-11-17 12:53         ` Frederic Weisbecker
2010-11-17 13:02           ` Peter Zijlstra
2010-11-17 13:10             ` Ingo Molnar
2010-11-17 13:36               ` Peter Zijlstra
2010-11-17 13:43                 ` Frederic Weisbecker
2010-11-17 13:53                   ` Peter Zijlstra
2010-11-17 14:10                     ` Frederic Weisbecker
2010-11-17 15:02                       ` Steven Rostedt
2010-11-17 18:13                       ` Ted Ts'o
2010-11-17 18:29                         ` Frederic Weisbecker
2010-11-17 18:30                           ` Darren Hart
2010-11-17 16:49             ` Darren Hart
2010-11-18 23:23       ` Joe Perches
2010-11-16 21:35 ` Ingo Molnar
2010-11-17  1:37 ` Ted Ts'o
2010-11-17  1:47   ` Steven Rostedt
2010-11-17  3:16     ` Ted Ts'o
2010-11-17  3:34       ` Steven Rostedt
2010-11-17 19:00         ` Bob Copeland
2010-11-17 13:24   ` Ingo Molnar
2010-11-17 13:38     ` Peter Zijlstra
2010-11-17 14:00       ` Ingo Molnar
2010-11-17 14:11         ` Peter Zijlstra
2010-11-17 14:18           ` Peter Zijlstra
2010-11-17 14:37             ` Thomas Gleixner
2010-11-17 14:41               ` Peter Zijlstra
2010-11-17 15:41               ` Tom Zanussi
2010-11-17 15:55                 ` Avi Kivity
2010-11-17 15:58                   ` Thomas Gleixner
2010-11-17 16:20                     ` Avi Kivity
2010-11-17 15:59                   ` Peter Zijlstra
2010-11-17 16:08                     ` Avi Kivity
2010-11-17 15:10           ` Steven Rostedt
2010-11-17 15:43             ` Peter Zijlstra
2010-11-17 16:04               ` Steven Rostedt
2010-11-17 16:15               ` Steven Rostedt
2010-11-17 19:40                 ` Darren Hart
2010-11-17 18:23               ` Mathieu Desnoyers
2010-11-18  5:58                 ` Masami Hiramatsu
2010-11-18  6:00               ` Masami Hiramatsu
2010-11-17 15:33           ` Tom Zanussi
2010-11-17 18:36             ` Mathieu Desnoyers
2010-11-17 18:53               ` Tom Zanussi
2010-11-17 19:02                 ` Mathieu Desnoyers
2010-11-17 19:25                   ` Tom Zanussi
2010-11-17 19:25               ` Steven Rostedt
2010-11-17  9:49 ` Philipp Marek
     [not found] ` <4CE38C53.8090606@kernel.org>
2010-11-17 12:07   ` Ingo Molnar [this message]
2010-11-17 12:17     ` [patch] trace: Add user-space event tracing/injection Pekka Enberg
2010-11-17 12:30       ` Ingo Molnar
2010-11-17 12:33         ` Pekka Enberg
2010-11-17 12:42           ` Peter Zijlstra
2010-11-17 12:58             ` Ingo Molnar
2010-11-17 13:09               ` Peter Zijlstra
2010-11-17 13:36                 ` Ingo Molnar
2010-11-17 12:24     ` Ingo Molnar
2010-11-17 12:30       ` Pekka Enberg
2010-11-17 12:29     ` Peter Zijlstra
2010-11-17 12:37       ` Peter Zijlstra
2010-11-17 13:10       ` Frederic Weisbecker
2010-11-17 13:31         ` Peter Zijlstra
2010-11-17 13:33           ` Frederic Weisbecker
2010-11-18  1:18     ` Darren Hart
2010-11-18  8:55       ` Ingo Molnar
2010-11-18 16:25         ` hp
2010-11-18 18:56           ` Ingo Molnar
2010-11-18 19:13             ` AW: " Reichert, Hans-Peter
2010-11-18 17:06         ` Darren Hart
2010-11-17 12:47 ` [ANNOUNCE] New utility: 'trace' Török Edwin
2010-11-17 12:51   ` Peter Zijlstra
2010-11-17 13:05     ` Török Edwin
2010-11-17 13:10       ` Peter Zijlstra
2010-11-17 13:32   ` Frederic Weisbecker
2010-11-18  0:47 ` Ian Munsie
     [not found]   ` <20101118151141.GA3368@redhat.com>
2010-11-19  2:32     ` Ian Munsie
2010-11-19 15:23       ` Jason Baron
     [not found]       ` <4CECACF9.3080907@linux.vnet.ibm.com>
     [not found]         ` <4CFD7182.4060206@linux.vnet.ibm.com>
2010-12-07  4:03           ` PowerPC, ftrace: Add PPC raw syscall tracepoints & ftrace fixes Ian Munsie

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=20101117120740.GA24972@elte.hu \
    --to=mingo@elte.hu \
    --cc=acme@redhat.com \
    --cc=akpm@linux-foundation.org \
    --cc=arjan@infradead.org \
    --cc=arjan@linux.intel.com \
    --cc=dvhart@linux.intel.com \
    --cc=fweisbec@gmail.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=penberg@kernel.org \
    --cc=peterz@infradead.org \
    --cc=rostedt@goodmis.org \
    --cc=tglx@linutronix.de \
    --cc=torvalds@linux-foundation.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 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.