aboutsummaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
Diffstat (limited to 'tools')
-rw-r--r--tools/perf/Documentation/perf-script.txt5
-rw-r--r--tools/perf/builtin-script.c141
2 files changed, 130 insertions, 16 deletions
diff --git a/tools/perf/Documentation/perf-script.txt b/tools/perf/Documentation/perf-script.txt
index 29ad94293cd2..b73cf589c109 100644
--- a/tools/perf/Documentation/perf-script.txt
+++ b/tools/perf/Documentation/perf-script.txt
@@ -112,6 +112,11 @@ OPTIONS
112--debug-mode:: 112--debug-mode::
113 Do various checks like samples ordering and lost events. 113 Do various checks like samples ordering and lost events.
114 114
115-f::
116--fields
117 Comma separated list of fields to print. Options are:
118 comm, tid, pid, time, cpu, event, trace
119
115SEE ALSO 120SEE ALSO
116-------- 121--------
117linkperf:perf-record[1], linkperf:perf-script-perl[1], 122linkperf:perf-record[1], linkperf:perf-script-perl[1],
diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c
index 0a79da21df23..c046e6e8600a 100644
--- a/tools/perf/builtin-script.c
+++ b/tools/perf/builtin-script.c
@@ -20,6 +20,38 @@ static u64 last_timestamp;
20static u64 nr_unordered; 20static u64 nr_unordered;
21extern const struct option record_options[]; 21extern const struct option record_options[];
22 22
23enum perf_output_field {
24 PERF_OUTPUT_COMM = 1U << 0,
25 PERF_OUTPUT_TID = 1U << 1,
26 PERF_OUTPUT_PID = 1U << 2,
27 PERF_OUTPUT_TIME = 1U << 3,
28 PERF_OUTPUT_CPU = 1U << 4,
29 PERF_OUTPUT_EVNAME = 1U << 5,
30 PERF_OUTPUT_TRACE = 1U << 6,
31};
32
33struct output_option {
34 const char *str;
35 enum perf_output_field field;
36} all_output_options[] = {
37 {.str = "comm", .field = PERF_OUTPUT_COMM},
38 {.str = "tid", .field = PERF_OUTPUT_TID},
39 {.str = "pid", .field = PERF_OUTPUT_PID},
40 {.str = "time", .field = PERF_OUTPUT_TIME},
41 {.str = "cpu", .field = PERF_OUTPUT_CPU},
42 {.str = "event", .field = PERF_OUTPUT_EVNAME},
43 {.str = "trace", .field = PERF_OUTPUT_TRACE},
44};
45
46/* default set to maintain compatibility with current format */
47static u64 output_fields = PERF_OUTPUT_COMM | PERF_OUTPUT_TID | \
48 PERF_OUTPUT_CPU | PERF_OUTPUT_TIME | \
49 PERF_OUTPUT_EVNAME | PERF_OUTPUT_TRACE;
50
51static bool output_set_by_user;
52
53#define PRINT_FIELD(x) (output_fields & PERF_OUTPUT_##x)
54
23static void print_sample_start(struct perf_sample *sample, 55static void print_sample_start(struct perf_sample *sample,
24 struct thread *thread) 56 struct thread *thread)
25{ 57{
@@ -28,24 +60,45 @@ static void print_sample_start(struct perf_sample *sample,
28 const char *evname = NULL; 60 const char *evname = NULL;
29 unsigned long secs; 61 unsigned long secs;
30 unsigned long usecs; 62 unsigned long usecs;
31 unsigned long long nsecs = sample->time; 63 unsigned long long nsecs;
64
65 if (PRINT_FIELD(COMM)) {
66 if (latency_format)
67 printf("%8.8s ", thread->comm);
68 else
69 printf("%16s ", thread->comm);
70 }
32 71
33 if (latency_format) 72 if (PRINT_FIELD(PID) && PRINT_FIELD(TID))
34 printf("%8.8s-%-5d %3d", thread->comm, sample->tid, sample->cpu); 73 printf("%5d/%-5d ", sample->pid, sample->tid);
35 else 74 else if (PRINT_FIELD(PID))
36 printf("%16s-%-5d [%03d]", thread->comm, sample->tid, sample->cpu); 75 printf("%5d ", sample->pid);
76 else if (PRINT_FIELD(TID))
77 printf("%5d ", sample->tid);
78
79 if (PRINT_FIELD(CPU)) {
80 if (latency_format)
81 printf("%3d ", sample->cpu);
82 else
83 printf("[%03d] ", sample->cpu);
84 }
37 85
38 secs = nsecs / NSECS_PER_SEC; 86 if (PRINT_FIELD(TIME)) {
39 nsecs -= secs * NSECS_PER_SEC; 87 nsecs = sample->time;
40 usecs = nsecs / NSECS_PER_USEC; 88 secs = nsecs / NSECS_PER_SEC;
41 printf(" %5lu.%06lu: ", secs, usecs); 89 nsecs -= secs * NSECS_PER_SEC;
90 usecs = nsecs / NSECS_PER_USEC;
91 printf("%5lu.%06lu: ", secs, usecs);
92 }
42 93
43 type = trace_parse_common_type(sample->raw_data); 94 if (PRINT_FIELD(EVNAME)) {
44 event = trace_find_event(type); 95 type = trace_parse_common_type(sample->raw_data);
45 if (event) 96 event = trace_find_event(type);
46 evname = event->name; 97 if (event)
98 evname = event->name;
47 99
48 printf("%s: ", evname ? evname : "(unknown)"); 100 printf("%s: ", evname ? evname : "(unknown)");
101 }
49} 102}
50 103
51static void process_event(union perf_event *event __unused, 104static void process_event(union perf_event *event __unused,
@@ -54,7 +107,11 @@ static void process_event(union perf_event *event __unused,
54 struct thread *thread) 107 struct thread *thread)
55{ 108{
56 print_sample_start(sample, thread); 109 print_sample_start(sample, thread);
57 print_trace_event(sample->cpu, sample->raw_data, sample->raw_size); 110
111 if (PRINT_FIELD(TRACE))
112 print_trace_event(sample->cpu, sample->raw_data,
113 sample->raw_size);
114
58 printf("\n"); 115 printf("\n");
59} 116}
60 117
@@ -311,6 +368,48 @@ static int parse_scriptname(const struct option *opt __used,
311 return 0; 368 return 0;
312} 369}
313 370
371static int parse_output_fields(const struct option *opt __used,
372 const char *arg, int unset __used)
373{
374 char *tok;
375 int i, imax = sizeof(all_output_options) / sizeof(struct output_option);
376 int rc = 0;
377 char *str = strdup(arg);
378
379 if (!str)
380 return -ENOMEM;
381
382 tok = strtok(str, ",");
383 if (!tok) {
384 fprintf(stderr, "Invalid field string.");
385 return -EINVAL;
386 }
387
388 output_fields = 0;
389 while (1) {
390 for (i = 0; i < imax; ++i) {
391 if (strcmp(tok, all_output_options[i].str) == 0) {
392 output_fields |= all_output_options[i].field;
393 break;
394 }
395 }
396 if (i == imax) {
397 fprintf(stderr, "Invalid field requested.");
398 rc = -EINVAL;
399 break;
400 }
401
402 tok = strtok(NULL, ",");
403 if (!tok)
404 break;
405 }
406
407 output_set_by_user = true;
408
409 free(str);
410 return rc;
411}
412
314/* Helper function for filesystems that return a dent->d_type DT_UNKNOWN */ 413/* Helper function for filesystems that return a dent->d_type DT_UNKNOWN */
315static int is_directory(const char *base_path, const struct dirent *dent) 414static int is_directory(const char *base_path, const struct dirent *dent)
316{ 415{
@@ -623,6 +722,9 @@ static const struct option options[] = {
623 "input file name"), 722 "input file name"),
624 OPT_BOOLEAN('d', "debug-mode", &debug_mode, 723 OPT_BOOLEAN('d', "debug-mode", &debug_mode,
625 "do various checks like samples ordering and lost events"), 724 "do various checks like samples ordering and lost events"),
725 OPT_CALLBACK('f', "fields", NULL, "str",
726 "comma separated output fields. Options: comm,tid,pid,time,cpu,event,trace",
727 parse_output_fields),
626 728
627 OPT_END() 729 OPT_END()
628}; 730};
@@ -809,8 +911,15 @@ int cmd_script(int argc, const char **argv, const char *prefix __used)
809 911
810 if (generate_script_lang) { 912 if (generate_script_lang) {
811 struct stat perf_stat; 913 struct stat perf_stat;
914 int input;
915
916 if (output_set_by_user) {
917 fprintf(stderr,
918 "custom fields not supported for generated scripts");
919 return -1;
920 }
812 921
813 int input = open(input_name, O_RDONLY); 922 input = open(input_name, O_RDONLY);
814 if (input < 0) { 923 if (input < 0) {
815 perror("failed to open file"); 924 perror("failed to open file");
816 exit(-1); 925 exit(-1);