Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

perf script: Add generic perl handler to process events

The current perf scripting facility only supports tracepoints. This
patch implements a generic perl handler to support other events than
tracepoints too.

This patch introduces a function process_event() that is called by perf
for each sample. The function is called with byte streams as arguments
containing information about the event, its attributes, the sample and
raw data. Perl's unpack() function can easily be used for byte decoding.
The following is the default implementation for process_event() that can
also be generated with perf script:

# Packed byte string args of process_event():
#
# $event: union perf_event util/event.h
# $attr: struct perf_event_attr linux/perf_event.h
# $sample: struct perf_sample util/event.h
# $raw_data: perf_sample->raw_data util/event.h

sub process_event
{
my ($event, $attr, $sample, $raw_data) = @_;

my @event = unpack("LSS", $event);
my @attr = unpack("LLQQQQQLLQQ", $attr);
my @sample = unpack("QLLQQQQQLL", $sample);
my @raw_data = unpack("C*", $raw_data);

use Data::Dumper;
print Dumper \@event, \@attr, \@sample, \@raw_data;
}

Cc: Ingo Molnar <mingo@elte.hu>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Stephane Eranian <eranian@google.com>
Link: http://lkml.kernel.org/r/1323969824-9711-4-git-send-email-robert.richter@amd.com
Signed-off-by: Robert Richter <robert.richter@amd.com>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>

authored by

Robert Richter and committed by
Arnaldo Carvalho de Melo
37a058ea b1e5a9be

+67 -6
+67 -6
tools/perf/util/scripting-engines/trace-event-perl.c
··· 30 30 #include "../thread.h" 31 31 #include "../event.h" 32 32 #include "../trace-event.h" 33 + #include "../evsel.h" 33 34 34 35 #include <EXTERN.h> 35 36 #include <perl.h> ··· 248 247 return event; 249 248 } 250 249 251 - static void perl_process_event(union perf_event *pevent __unused, 252 - struct perf_sample *sample, 253 - struct perf_evsel *evsel, 254 - struct machine *machine __unused, 255 - struct thread *thread) 250 + static void perl_process_tracepoint(union perf_event *pevent __unused, 251 + struct perf_sample *sample, 252 + struct perf_evsel *evsel, 253 + struct machine *machine __unused, 254 + struct thread *thread) 256 255 { 257 256 struct format_field *field; 258 257 static char handler[256]; ··· 267 266 char *comm = thread->comm; 268 267 269 268 dSP; 269 + 270 + if (evsel->attr.type != PERF_TYPE_TRACEPOINT) 271 + return; 270 272 271 273 type = trace_parse_common_type(data); 272 274 ··· 336 332 PUTBACK; 337 333 FREETMPS; 338 334 LEAVE; 335 + } 336 + 337 + static void perl_process_event_generic(union perf_event *pevent __unused, 338 + struct perf_sample *sample, 339 + struct perf_evsel *evsel __unused, 340 + struct machine *machine __unused, 341 + struct thread *thread __unused) 342 + { 343 + dSP; 344 + 345 + if (!get_cv("process_event", 0)) 346 + return; 347 + 348 + ENTER; 349 + SAVETMPS; 350 + PUSHMARK(SP); 351 + XPUSHs(sv_2mortal(newSVpvn((const char *)pevent, pevent->header.size))); 352 + XPUSHs(sv_2mortal(newSVpvn((const char *)&evsel->attr, sizeof(evsel->attr)))); 353 + XPUSHs(sv_2mortal(newSVpvn((const char *)sample, sizeof(*sample)))); 354 + XPUSHs(sv_2mortal(newSVpvn((const char *)sample->raw_data, sample->raw_size))); 355 + PUTBACK; 356 + call_pv("process_event", G_SCALAR); 357 + SPAGAIN; 358 + PUTBACK; 359 + FREETMPS; 360 + LEAVE; 361 + } 362 + 363 + static void perl_process_event(union perf_event *pevent, 364 + struct perf_sample *sample, 365 + struct perf_evsel *evsel, 366 + struct machine *machine, 367 + struct thread *thread) 368 + { 369 + perl_process_tracepoint(pevent, sample, evsel, machine, thread); 370 + perl_process_event_generic(pevent, sample, evsel, machine, thread); 339 371 } 340 372 341 373 static void run_start_sub(void) ··· 595 555 fprintf(ofp, "sub print_header\n{\n" 596 556 "\tmy ($event_name, $cpu, $secs, $nsecs, $pid, $comm) = @_;\n\n" 597 557 "\tprintf(\"%%-20s %%5u %%05u.%%09u %%8u %%-20s \",\n\t " 598 - "$event_name, $cpu, $secs, $nsecs, $pid, $comm);\n}"); 558 + "$event_name, $cpu, $secs, $nsecs, $pid, $comm);\n}\n"); 559 + 560 + fprintf(ofp, 561 + "\n# Packed byte string args of process_event():\n" 562 + "#\n" 563 + "# $event:\tunion perf_event\tutil/event.h\n" 564 + "# $attr:\tstruct perf_event_attr\tlinux/perf_event.h\n" 565 + "# $sample:\tstruct perf_sample\tutil/event.h\n" 566 + "# $raw_data:\tperf_sample->raw_data\tutil/event.h\n" 567 + "\n" 568 + "sub process_event\n" 569 + "{\n" 570 + "\tmy ($event, $attr, $sample, $raw_data) = @_;\n" 571 + "\n" 572 + "\tmy @event\t= unpack(\"LSS\", $event);\n" 573 + "\tmy @attr\t= unpack(\"LLQQQQQLLQQ\", $attr);\n" 574 + "\tmy @sample\t= unpack(\"QLLQQQQQLL\", $sample);\n" 575 + "\tmy @raw_data\t= unpack(\"C*\", $raw_data);\n" 576 + "\n" 577 + "\tuse Data::Dumper;\n" 578 + "\tprint Dumper \\@event, \\@attr, \\@sample, \\@raw_data;\n" 579 + "}\n"); 599 580 600 581 fclose(ofp); 601 582