aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf/builtin-script.c
diff options
context:
space:
mode:
authorDavid Ahern <daahern@cisco.com>2011-03-17 12:03:21 -0400
committerArnaldo Carvalho de Melo <acme@redhat.com>2011-03-30 13:43:11 -0400
commit2c9e45f7a287384e1382932597e41a9a567811ba (patch)
treeeb52ca0be0f02bf93fb77c53e8eb5cf97019a74c /tools/perf/builtin-script.c
parentae18cbfe9f147085426635763f1fe0c68f1071e2 (diff)
perf script: If type not given fields apply to all event types
Allow: perf script -f <fields> to be equivalent to: perf script -f trace:<fields> -f sw:<fields> -f hw:<fields> i.e., the specified fields apply to all event types if the type string is not given. The field (-f) arguments are processed in the order received. A later usage can reset a prior request. e.g., -f trace: -f comm,tid,time,sym The first -f suppresses trace events (field list is ""), but then the second invocation sets the fields to comm,tid,time,sym. In this case a warning is given to the user: "Overriding previous field request for all events." Alternativey, consider the order: -f comm,tid,time,sym -f trace: The first -f sets the fields for all events and the second -f suppresses trace events. The user is given a warning message about the override, and the result of the above is that only S/W and H/W events are displayed with the given fields. For the 'wildcard' option if a user selected field is invalid for an event type, a message is displayed to the user that the option is ignored for that type. For example: perf script -f comm,tid,trace 2>&1 | less 'trace' not valid for hardware events. Ignoring. 'trace' not valid for software events. Ignoring. Alternatively, if the type is given an invalid field is specified it is an error. For example: perf script -v -f sw:comm,tid,trace 2>&1 | less 'trace' not valid for software events. At this point usage is displayed, and perf-script exits. Finally, a user may not set fields to none for all event types. i.e., -f "" is not allowed. Cc: Frederic Weisbecker <fweisbec@gmail.com> Cc: Ingo Molnar <mingo@elte.hu> Cc: Paul Mackerras <paulus@samba.org> Cc: Peter Zijlstra <peterz@infradead.org> Cc: linux-kernel@vger.kernel.org LPU-Reference: <1300377801-27246-1-git-send-email-daahern@cisco.com> Signed-off-by: David Ahern <daahern@cisco.com> Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Diffstat (limited to 'tools/perf/builtin-script.c')
-rw-r--r--tools/perf/builtin-script.c171
1 files changed, 122 insertions, 49 deletions
diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c
index ac574ea2391..6cf811acc41 100644
--- a/tools/perf/builtin-script.c
+++ b/tools/perf/builtin-script.c
@@ -49,23 +49,52 @@ struct output_option {
49}; 49};
50 50
51/* default set to maintain compatibility with current format */ 51/* default set to maintain compatibility with current format */
52static u64 output_fields[PERF_TYPE_MAX] = { 52static struct {
53 [PERF_TYPE_HARDWARE] = PERF_OUTPUT_COMM | PERF_OUTPUT_TID | \ 53 bool user_set;
54 PERF_OUTPUT_CPU | PERF_OUTPUT_TIME | \ 54 u64 fields;
55 PERF_OUTPUT_EVNAME | PERF_OUTPUT_SYM, 55 u64 invalid_fields;
56 56} output[PERF_TYPE_MAX] = {
57 [PERF_TYPE_SOFTWARE] = PERF_OUTPUT_COMM | PERF_OUTPUT_TID | \ 57
58 PERF_OUTPUT_CPU | PERF_OUTPUT_TIME | \ 58 [PERF_TYPE_HARDWARE] = {
59 PERF_OUTPUT_EVNAME | PERF_OUTPUT_SYM, 59 .user_set = false,
60 60
61 [PERF_TYPE_TRACEPOINT] = PERF_OUTPUT_COMM | PERF_OUTPUT_TID | \ 61 .fields = PERF_OUTPUT_COMM | PERF_OUTPUT_TID |
62 PERF_OUTPUT_CPU | PERF_OUTPUT_TIME | \ 62 PERF_OUTPUT_CPU | PERF_OUTPUT_TIME |
63 PERF_OUTPUT_EVNAME | PERF_OUTPUT_TRACE, 63 PERF_OUTPUT_EVNAME | PERF_OUTPUT_SYM,
64
65 .invalid_fields = PERF_OUTPUT_TRACE,
66 },
67
68 [PERF_TYPE_SOFTWARE] = {
69 .user_set = false,
70
71 .fields = PERF_OUTPUT_COMM | PERF_OUTPUT_TID |
72 PERF_OUTPUT_CPU | PERF_OUTPUT_TIME |
73 PERF_OUTPUT_EVNAME | PERF_OUTPUT_SYM,
74
75 .invalid_fields = PERF_OUTPUT_TRACE,
76 },
77
78 [PERF_TYPE_TRACEPOINT] = {
79 .user_set = false,
80
81 .fields = PERF_OUTPUT_COMM | PERF_OUTPUT_TID |
82 PERF_OUTPUT_CPU | PERF_OUTPUT_TIME |
83 PERF_OUTPUT_EVNAME | PERF_OUTPUT_TRACE,
84 },
64}; 85};
65 86
66static bool output_set_by_user; 87static bool output_set_by_user(void)
88{
89 int j;
90 for (j = 0; j < PERF_TYPE_MAX; ++j) {
91 if (output[j].user_set)
92 return true;
93 }
94 return false;
95}
67 96
68#define PRINT_FIELD(x) (output_fields[attr->type] & PERF_OUTPUT_##x) 97#define PRINT_FIELD(x) (output[attr->type].fields & PERF_OUTPUT_##x)
69 98
70static int perf_session__check_attr(struct perf_session *session, 99static int perf_session__check_attr(struct perf_session *session,
71 struct perf_event_attr *attr) 100 struct perf_event_attr *attr)
@@ -168,7 +197,7 @@ static void process_event(union perf_event *event __unused,
168{ 197{
169 struct perf_event_attr *attr = &evsel->attr; 198 struct perf_event_attr *attr = &evsel->attr;
170 199
171 if (output_fields[attr->type] == 0) 200 if (output[attr->type].fields == 0)
172 return; 201 return;
173 202
174 if (perf_session__check_attr(session, attr) < 0) 203 if (perf_session__check_attr(session, attr) < 0)
@@ -451,6 +480,7 @@ static int parse_output_fields(const struct option *opt __used,
451{ 480{
452 char *tok; 481 char *tok;
453 int i, imax = sizeof(all_output_options) / sizeof(struct output_option); 482 int i, imax = sizeof(all_output_options) / sizeof(struct output_option);
483 int j;
454 int rc = 0; 484 int rc = 0;
455 char *str = strdup(arg); 485 char *str = strdup(arg);
456 int type = -1; 486 int type = -1;
@@ -458,52 +488,95 @@ static int parse_output_fields(const struct option *opt __used,
458 if (!str) 488 if (!str)
459 return -ENOMEM; 489 return -ENOMEM;
460 490
461 tok = strtok(str, ":"); 491 /* first word can state for which event type the user is specifying
462 if (!tok) { 492 * the fields. If no type exists, the specified fields apply to all
463 fprintf(stderr, 493 * event types found in the file minus the invalid fields for a type.
464 "Invalid field string - not prepended with type.");
465 return -EINVAL;
466 }
467
468 /* first word should state which event type user
469 * is specifying the fields
470 */ 494 */
471 if (!strcmp(tok, "hw")) 495 tok = strchr(str, ':');
472 type = PERF_TYPE_HARDWARE; 496 if (tok) {
473 else if (!strcmp(tok, "sw")) 497 *tok = '\0';
474 type = PERF_TYPE_SOFTWARE; 498 tok++;
475 else if (!strcmp(tok, "trace")) 499 if (!strcmp(str, "hw"))
476 type = PERF_TYPE_TRACEPOINT; 500 type = PERF_TYPE_HARDWARE;
477 else { 501 else if (!strcmp(str, "sw"))
478 fprintf(stderr, "Invalid event type in field string."); 502 type = PERF_TYPE_SOFTWARE;
479 return -EINVAL; 503 else if (!strcmp(str, "trace"))
504 type = PERF_TYPE_TRACEPOINT;
505 else {
506 fprintf(stderr, "Invalid event type in field string.\n");
507 return -EINVAL;
508 }
509
510 if (output[type].user_set)
511 pr_warning("Overriding previous field request for %s events.\n",
512 event_type(type));
513
514 output[type].fields = 0;
515 output[type].user_set = true;
516
517 } else {
518 tok = str;
519 if (strlen(str) == 0) {
520 fprintf(stderr,
521 "Cannot set fields to 'none' for all event types.\n");
522 rc = -EINVAL;
523 goto out;
524 }
525
526 if (output_set_by_user())
527 pr_warning("Overriding previous field request for all events.\n");
528
529 for (j = 0; j < PERF_TYPE_MAX; ++j) {
530 output[j].fields = 0;
531 output[j].user_set = true;
532 }
480 } 533 }
481 534
482 output_fields[type] = 0; 535 tok = strtok(tok, ",");
483 while (1) { 536 while (tok) {
484 tok = strtok(NULL, ",");
485 if (!tok)
486 break;
487 for (i = 0; i < imax; ++i) { 537 for (i = 0; i < imax; ++i) {
488 if (strcmp(tok, all_output_options[i].str) == 0) { 538 if (strcmp(tok, all_output_options[i].str) == 0)
489 output_fields[type] |= all_output_options[i].field;
490 break; 539 break;
491 }
492 } 540 }
493 if (i == imax) { 541 if (i == imax) {
494 fprintf(stderr, "Invalid field requested."); 542 fprintf(stderr, "Invalid field requested.\n");
495 rc = -EINVAL; 543 rc = -EINVAL;
496 break; 544 goto out;
497 } 545 }
498 }
499 546
500 if (output_fields[type] == 0) { 547 if (type == -1) {
501 pr_debug("No fields requested for %s type. " 548 /* add user option to all events types for
502 "Events will not be displayed\n", event_type(type)); 549 * which it is valid
550 */
551 for (j = 0; j < PERF_TYPE_MAX; ++j) {
552 if (output[j].invalid_fields & all_output_options[i].field) {
553 pr_warning("\'%s\' not valid for %s events. Ignoring.\n",
554 all_output_options[i].str, event_type(j));
555 } else
556 output[j].fields |= all_output_options[i].field;
557 }
558 } else {
559 if (output[type].invalid_fields & all_output_options[i].field) {
560 fprintf(stderr, "\'%s\' not valid for %s events.\n",
561 all_output_options[i].str, event_type(type));
562
563 rc = -EINVAL;
564 goto out;
565 }
566 output[type].fields |= all_output_options[i].field;
567 }
568
569 tok = strtok(NULL, ",");
503 } 570 }
504 571
505 output_set_by_user = true; 572 if (type >= 0) {
573 if (output[type].fields == 0) {
574 pr_debug("No fields requested for %s type. "
575 "Events will not be displayed.\n", event_type(type));
576 }
577 }
506 578
579out:
507 free(str); 580 free(str);
508 return rc; 581 return rc;
509} 582}
@@ -1020,7 +1093,7 @@ int cmd_script(int argc, const char **argv, const char *prefix __used)
1020 struct stat perf_stat; 1093 struct stat perf_stat;
1021 int input; 1094 int input;
1022 1095
1023 if (output_set_by_user) { 1096 if (output_set_by_user()) {
1024 fprintf(stderr, 1097 fprintf(stderr,
1025 "custom fields not supported for generated scripts"); 1098 "custom fields not supported for generated scripts");
1026 return -1; 1099 return -1;