diff options
Diffstat (limited to 'tools/perf/builtin-script.c')
-rw-r--r-- | tools/perf/builtin-script.c | 171 |
1 files changed, 122 insertions, 49 deletions
diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c index ac574ea23917..6cf811acc41b 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 */ |
52 | static u64 output_fields[PERF_TYPE_MAX] = { | 52 | static 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 | ||
66 | static bool output_set_by_user; | 87 | static 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 | ||
70 | static int perf_session__check_attr(struct perf_session *session, | 99 | static 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 | ||
579 | out: | ||
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; |