Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1756566AbZJFGKv (ORCPT ); Tue, 6 Oct 2009 02:10:51 -0400 Received: (majordomo@vger.kernel.org) by vger.kernel.org id S1756549AbZJFGKu (ORCPT ); Tue, 6 Oct 2009 02:10:50 -0400 Received: from mail-yx0-f173.google.com ([209.85.210.173]:33839 "EHLO mail-yx0-f173.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1756208AbZJFGKs (ORCPT ); Tue, 6 Oct 2009 02:10:48 -0400 DomainKey-Signature: a=rsa-sha1; c=nofws; d=gmail.com; s=gamma; h=from:to:cc:subject:date:message-id:x-mailer:in-reply-to:references; b=cC4O0vApn+8cn/tRRrKM2onCNNeSEpCYJvuSrBbxQ8a5RnT74NHxXMHiI+hBJ+zBhm 8smqFQgsEq5+DX4Qnn3Lx2wFRghi5UAHzaU5YYsZFV6sB/CCJrdwdYyjlKtCG6SdlD9/ Hg5suDTUfy8QRZ/avEmydYw+xv2HpYwk8dCg0= From: Tom Zanussi To: linux-kernel@vger.kernel.org Cc: mingo@elte.hu, fweisbec@gmail.com, rostedt@goodmis.org, lizf@cn.fujitsu.com, hch@infradead.org Subject: [RFC][PATCH 6/9] perf trace: Add scripting op for generating empty event handling scripts Date: Tue, 6 Oct 2009 01:09:55 -0500 Message-Id: <1254809398-8078-7-git-send-email-tzanussi@gmail.com> X-Mailer: git-send-email 1.6.4.GIT In-Reply-To: <1254809398-8078-1-git-send-email-tzanussi@gmail.com> References: <1254809398-8078-1-git-send-email-tzanussi@gmail.com> Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 7533 Lines: 244 To give script writers an easy starting point for writing scripts, scripting language support for a particular language can implement a generate_event_handlers() scripting op that will output an empty (or near-empty) set of handlers in the supported language for all the events contained in a give perf.data trace file. This patch adds the generate_event_handlers() scripting op and also adds a Perl implementation that creates a ready-to-run Perl script that can be passed to perf trace for generic event printing. Scripts generated by this implementation print out all the fields for each event (and will detect and generate the proper scripting code for 'flag' and 'symbolic' fields), and will additionally generate handlers for the special 'trace_unhandled', 'trace_begin' and 'trace_end' handlers. Script authors can simply remove the printing code to implement their own custom event handling. Signed-off-by: Tom Zanussi --- tools/perf/builtin-trace.c | 23 +++++++- tools/perf/util/trace-event-perl.c | 114 ++++++++++++++++++++++++++++++++++++ tools/perf/util/trace-event.h | 1 + 3 files changed, 136 insertions(+), 2 deletions(-) diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c index 74aec38..b151e77 100644 --- a/tools/perf/builtin-trace.c +++ b/tools/perf/builtin-trace.c @@ -30,6 +30,7 @@ static u64 sample_type; static char const *script_name; static int do_perl; +static int generate_handlers; static int default_start_script(const char *script __attribute((unused))) { @@ -41,10 +42,16 @@ static int default_stop_script(void) return 0; } +static int default_generate_event_handlers(const char *outfile __attribute ((unused))) +{ + return 0; +} + static struct trace_scripting_operations default_scripting_ops = { .start_script = default_start_script, .stop_script = default_stop_script, .process_event = print_event, + .generate_event_handlers = default_generate_event_handlers, }; static struct trace_scripting_operations *scripting_ops; @@ -263,6 +270,8 @@ static const struct option options[] = { "be more verbose (show symbol address, etc)"), OPT_BOOLEAN('p', "perl", &do_perl, "send output to a Perl script"), + OPT_BOOLEAN('g', "generate-event-handlers", &generate_handlers, + "generate empty event handlers for scripting languages"), OPT_STRING('s', "script", &script_name, "file", "script file name"), OPT_END() @@ -270,11 +279,14 @@ static const struct option options[] = { static int setup_scripting(const char *script) { + if (do_perl && generate_handlers) + goto setup; + if ((do_perl && !script) || (script && !do_perl)) usage_with_options(annotate_usage, options); scripting_ops = &default_scripting_ops; - +setup: if (do_perl) { scripting_ops = setup_perl_scripting(); if (!scripting_ops) @@ -312,9 +324,16 @@ int cmd_trace(int argc, const char **argv, const char *prefix __used) if (err) goto out; + if (generate_handlers) { + trace_report(); + err = scripting_ops->generate_event_handlers("perf-trace.pl"); + goto out; + } + if (script_name) { err = scripting_ops->start_script(script_name); - goto out; + if (err) + goto out; } err = __cmd_trace(); diff --git a/tools/perf/util/trace-event-perl.c b/tools/perf/util/trace-event-perl.c index 1264e14..657b87a 100644 --- a/tools/perf/util/trace-event-perl.c +++ b/tools/perf/util/trace-event-perl.c @@ -356,10 +356,124 @@ static int perl_stop_script(void) return 0; } +static int perl_generate_event_handlers(const char *outfile) +{ + struct event *event = NULL; + struct format_field *f; + int not_first; + FILE *ofp; + + ofp = fopen(outfile, "w"); + if (ofp == NULL) { + fprintf(stderr, "couldn't open %s\n", outfile); + return -1; + } + + fprintf(ofp, "# perf trace event handlers, " + "generated by perf trace -p -g\n\n"); + + fprintf(ofp, "# The common_* event handler fields are the most useful " + "fields common to\n"); + + fprintf(ofp, "# all events. They don't necessarily correspond to " + "the 'common_*' fields\n"); + + fprintf(ofp, "# in the status files. Those fields not available as " + "handler params can\n"); + + fprintf(ofp, "# be retrieved via script functions of the form " + "get_common_*().\n\n"); + + fprintf(ofp, "use lib \"$ENV{'PERF_EXEC_PATH'}/scripts/perl/" + "Perf-Trace-Util/lib\";\n"); + + fprintf(ofp, "use lib \"./Perf-Trace-Util/lib\";\n"); + fprintf(ofp, "use Perf::Trace::Core;\n"); + fprintf(ofp, "use Perf::Trace::Util;\n\n"); + + fprintf(ofp, "sub trace_begin\n{\n # optional\n}\n\n"); + fprintf(ofp, "sub trace_end\n{\n # optional\n}\n\n"); + + while ((event = trace_find_next_event(event))) { + fprintf(ofp, "sub %s::%s\n{\n", event->system, event->name); + fprintf(ofp, " my ("); + + fprintf(ofp, "$event_name, "); + fprintf(ofp, "$common_cpu, "); + fprintf(ofp, "$common_secs, "); + fprintf(ofp, "$common_nsecs, "); + fprintf(ofp, "$common_pid, "); + fprintf(ofp, "$common_comm,\n "); + + not_first = 0; + + for (f = event->format.fields; f; f = f->next) { + if (not_first++) + fprintf(ofp, ", "); + + fprintf(ofp, "$%s", f->name); + } + fprintf(ofp, ") = @_;\n\n"); + + fprintf(ofp, " print_header($event_name, $common_cpu, " + "$common_secs, $common_nsecs, $common_pid, " + "$common_comm);\n\n"); + + fprintf(ofp, " printf(\""); + + not_first = 0; + + for (f = event->format.fields; f; f = f->next) { + if (not_first++) + fprintf(ofp, ", "); + + fprintf(ofp, "%s=", f->name); + if (f->flags & FIELD_IS_STRING) + fprintf(ofp, "%%s"); + else if (f->flags & FIELD_IS_SIGNED) + fprintf(ofp, "%%d"); + else + fprintf(ofp, "%%u"); + } + + fprintf(ofp, "\\n\", "); + + not_first = 0; + + for (f = event->format.fields; f; f = f->next) { + if (not_first++) + fprintf(ofp, ", "); + + fprintf(ofp, "$%s", f->name); + } + + fprintf(ofp, ");\n"); + fprintf(ofp, "}\n\n"); + } + + fprintf(ofp, "sub trace_unhandled\n{\n my ($event_name, " + "$common_cpu, $common_secs, $common_nsecs, $common_pid, " + "$common_comm) = @_;\n\n"); + + fprintf(ofp, " print_header($event_name, $common_cpu, " + "$common_secs, $common_nsecs, $common_pid, " + "$common_comm);\n}\n\n"); + + fprintf(ofp, "sub print_header\n{\n" + " my ($event_name, $cpu, $secs, $nsecs, $pid, $comm) = @_;\n\n" + " printf(\"%%-20s %%5u %%05u.%%09u %%8u %%-20s \", " + "$event_name, $cpu, $secs, $nsecs, $pid, $comm);\n}"); + + fclose(ofp); + + return 0; +} + struct trace_scripting_operations perl_scripting_ops = { .start_script = perl_start_script, .stop_script = perl_stop_script, .process_event = perl_process_event, + .generate_event_handlers = perl_generate_event_handlers, }; #ifdef NO_LIBPERL diff --git a/tools/perf/util/trace-event.h b/tools/perf/util/trace-event.h index f812a8e..582e0eb 100644 --- a/tools/perf/util/trace-event.h +++ b/tools/perf/util/trace-event.h @@ -255,6 +255,7 @@ struct trace_scripting_operations { int (*stop_script) (void); void (*process_event) (int cpu, void *data, int size, unsigned long long nsecs, char *comm); + int (*generate_event_handlers) (const char *outfile); }; extern struct trace_scripting_operations perl_scripting_ops; -- 1.6.4.GIT -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/