aboutsummaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
authorPeter Zijlstra <peterz@infradead.org>2015-03-30 18:19:31 -0400
committerArnaldo Carvalho de Melo <acme@redhat.com>2015-04-08 09:04:55 -0400
commit814c8c38e13c7050259c72f89bb01f3fc903f642 (patch)
treebcefeebf548cb2bef07ee42b81518a19ccfe7795 /tools
parentff5f3bbd40bfb8632f826f1f83223d95363f36af (diff)
perf record: Add clockid parameter
Teach perf-record about the new perf_event_attr::{use_clockid, clockid} fields. Add a simple parameter to set the clock (if any) to be used for the events to be recorded into the data file. Since we store the entire perf_event_attr in the EVENT_DESC section we also already store the used clockid in the data file. Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org> Acked-by: David Ahern <dsahern@gmail.com> Cc: "H. Peter Anvin" <hpa@zytor.com> Cc: Adrian Hunter <adrian.hunter@intel.com> Cc: Andrew Morton <akpm@linux-foundation.org> Cc: Jiri Olsa <jolsa@redhat.com> Cc: John Stultz <john.stultz@linaro.org> Cc: Linus Torvalds <torvalds@linux-foundation.org> Cc: Stephane Eranian <eranian@google.com> Cc: Thomas Gleixner <tglx@linutronix.de> Cc: Yunlong Song <yunlong.song@huawei.com> Link: http://lkml.kernel.org/r/20150407154851.GR23123@twins.programming.kicks-ass.net [ Conditionally define CLOCK_BOOTTIME, at least rhel6 doesn't have it - dsahern Ditto for CLOCK_MONOTONIC_RAW, sles11sp2 doesn't have it - yunlong.song ] Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Diffstat (limited to 'tools')
-rw-r--r--tools/perf/Documentation/perf-record.txt7
-rw-r--r--tools/perf/builtin-record.c87
-rw-r--r--tools/perf/perf.h2
-rw-r--r--tools/perf/util/evsel.c59
-rw-r--r--tools/perf/util/header.c3
5 files changed, 154 insertions, 4 deletions
diff --git a/tools/perf/Documentation/perf-record.txt b/tools/perf/Documentation/perf-record.txt
index 355c4f5569b5..4847a793de65 100644
--- a/tools/perf/Documentation/perf-record.txt
+++ b/tools/perf/Documentation/perf-record.txt
@@ -250,6 +250,13 @@ is off by default.
250--running-time:: 250--running-time::
251Record running and enabled time for read events (:S) 251Record running and enabled time for read events (:S)
252 252
253-k::
254--clockid::
255Sets the clock id to use for the various time fields in the perf_event_type
256records. See clock_gettime(). In particular CLOCK_MONOTONIC and
257CLOCK_MONOTONIC_RAW are supported, some events might also allow
258CLOCK_BOOTTIME, CLOCK_REALTIME and CLOCK_TAI.
259
253SEE ALSO 260SEE ALSO
254-------- 261--------
255linkperf:perf-stat[1], linkperf:perf-list[1] 262linkperf:perf-stat[1], linkperf:perf-list[1]
diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index 18aad239b401..ac610488d2e1 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -711,6 +711,90 @@ static int perf_record_config(const char *var, const char *value, void *cb)
711 return perf_default_config(var, value, cb); 711 return perf_default_config(var, value, cb);
712} 712}
713 713
714struct clockid_map {
715 const char *name;
716 int clockid;
717};
718
719#define CLOCKID_MAP(n, c) \
720 { .name = n, .clockid = (c), }
721
722#define CLOCKID_END { .name = NULL, }
723
724
725/*
726 * Add the missing ones, we need to build on many distros...
727 */
728#ifndef CLOCK_MONOTONIC_RAW
729#define CLOCK_MONOTONIC_RAW 4
730#endif
731#ifndef CLOCK_BOOTTIME
732#define CLOCK_BOOTTIME 7
733#endif
734#ifndef CLOCK_TAI
735#define CLOCK_TAI 11
736#endif
737
738static const struct clockid_map clockids[] = {
739 /* available for all events, NMI safe */
740 CLOCKID_MAP("monotonic", CLOCK_MONOTONIC),
741 CLOCKID_MAP("monotonic_raw", CLOCK_MONOTONIC_RAW),
742
743 /* available for some events */
744 CLOCKID_MAP("realtime", CLOCK_REALTIME),
745 CLOCKID_MAP("boottime", CLOCK_BOOTTIME),
746 CLOCKID_MAP("tai", CLOCK_TAI),
747
748 /* available for the lazy */
749 CLOCKID_MAP("mono", CLOCK_MONOTONIC),
750 CLOCKID_MAP("raw", CLOCK_MONOTONIC_RAW),
751 CLOCKID_MAP("real", CLOCK_REALTIME),
752 CLOCKID_MAP("boot", CLOCK_BOOTTIME),
753
754 CLOCKID_END,
755};
756
757static int parse_clockid(const struct option *opt, const char *str, int unset)
758{
759 struct record_opts *opts = (struct record_opts *)opt->value;
760 const struct clockid_map *cm;
761 const char *ostr = str;
762
763 if (unset) {
764 opts->use_clockid = 0;
765 return 0;
766 }
767
768 /* no arg passed */
769 if (!str)
770 return 0;
771
772 /* no setting it twice */
773 if (opts->use_clockid)
774 return -1;
775
776 opts->use_clockid = true;
777
778 /* if its a number, we're done */
779 if (sscanf(str, "%d", &opts->clockid) == 1)
780 return 0;
781
782 /* allow a "CLOCK_" prefix to the name */
783 if (!strncasecmp(str, "CLOCK_", 6))
784 str += 6;
785
786 for (cm = clockids; cm->name; cm++) {
787 if (!strcasecmp(str, cm->name)) {
788 opts->clockid = cm->clockid;
789 return 0;
790 }
791 }
792
793 opts->use_clockid = false;
794 ui__warning("unknown clockid %s, check man page\n", ostr);
795 return -1;
796}
797
714static const char * const __record_usage[] = { 798static const char * const __record_usage[] = {
715 "perf record [<options>] [<command>]", 799 "perf record [<options>] [<command>]",
716 "perf record [<options>] -- <command> [<options>]", 800 "perf record [<options>] -- <command> [<options>]",
@@ -842,6 +926,9 @@ struct option __record_options[] = {
842 "Sample machine registers on interrupt"), 926 "Sample machine registers on interrupt"),
843 OPT_BOOLEAN(0, "running-time", &record.opts.running_time, 927 OPT_BOOLEAN(0, "running-time", &record.opts.running_time,
844 "Record running/enabled time of read (:S) events"), 928 "Record running/enabled time of read (:S) events"),
929 OPT_CALLBACK('k', "clockid", &record.opts,
930 "clockid", "clockid to use for events, see clock_gettime()",
931 parse_clockid),
845 OPT_END() 932 OPT_END()
846}; 933};
847 934
diff --git a/tools/perf/perf.h b/tools/perf/perf.h
index c38a085a5571..e14bb637255c 100644
--- a/tools/perf/perf.h
+++ b/tools/perf/perf.h
@@ -62,6 +62,8 @@ struct record_opts {
62 u64 user_interval; 62 u64 user_interval;
63 bool sample_transaction; 63 bool sample_transaction;
64 unsigned initial_delay; 64 unsigned initial_delay;
65 bool use_clockid;
66 clockid_t clockid;
65}; 67};
66 68
67struct option; 69struct option;
diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c
index 358e5954baa8..d190f99a3a97 100644
--- a/tools/perf/util/evsel.c
+++ b/tools/perf/util/evsel.c
@@ -32,8 +32,12 @@ static struct {
32 bool exclude_guest; 32 bool exclude_guest;
33 bool mmap2; 33 bool mmap2;
34 bool cloexec; 34 bool cloexec;
35 bool clockid;
36 bool clockid_wrong;
35} perf_missing_features; 37} perf_missing_features;
36 38
39static clockid_t clockid;
40
37static int perf_evsel__no_extra_init(struct perf_evsel *evsel __maybe_unused) 41static int perf_evsel__no_extra_init(struct perf_evsel *evsel __maybe_unused)
38{ 42{
39 return 0; 43 return 0;
@@ -761,6 +765,12 @@ void perf_evsel__config(struct perf_evsel *evsel, struct record_opts *opts)
761 attr->disabled = 0; 765 attr->disabled = 0;
762 attr->enable_on_exec = 0; 766 attr->enable_on_exec = 0;
763 } 767 }
768
769 clockid = opts->clockid;
770 if (opts->use_clockid) {
771 attr->use_clockid = 1;
772 attr->clockid = opts->clockid;
773 }
764} 774}
765 775
766static int perf_evsel__alloc_fd(struct perf_evsel *evsel, int ncpus, int nthreads) 776static int perf_evsel__alloc_fd(struct perf_evsel *evsel, int ncpus, int nthreads)
@@ -1036,7 +1046,6 @@ static size_t perf_event_attr__fprintf(struct perf_event_attr *attr, FILE *fp)
1036 ret += PRINT_ATTR2(exclude_user, exclude_kernel); 1046 ret += PRINT_ATTR2(exclude_user, exclude_kernel);
1037 ret += PRINT_ATTR2(exclude_hv, exclude_idle); 1047 ret += PRINT_ATTR2(exclude_hv, exclude_idle);
1038 ret += PRINT_ATTR2(mmap, comm); 1048 ret += PRINT_ATTR2(mmap, comm);
1039 ret += PRINT_ATTR2(mmap2, comm_exec);
1040 ret += PRINT_ATTR2(freq, inherit_stat); 1049 ret += PRINT_ATTR2(freq, inherit_stat);
1041 ret += PRINT_ATTR2(enable_on_exec, task); 1050 ret += PRINT_ATTR2(enable_on_exec, task);
1042 ret += PRINT_ATTR2(watermark, precise_ip); 1051 ret += PRINT_ATTR2(watermark, precise_ip);
@@ -1044,6 +1053,9 @@ static size_t perf_event_attr__fprintf(struct perf_event_attr *attr, FILE *fp)
1044 ret += PRINT_ATTR2(exclude_host, exclude_guest); 1053 ret += PRINT_ATTR2(exclude_host, exclude_guest);
1045 ret += PRINT_ATTR2N("excl.callchain_kern", exclude_callchain_kernel, 1054 ret += PRINT_ATTR2N("excl.callchain_kern", exclude_callchain_kernel,
1046 "excl.callchain_user", exclude_callchain_user); 1055 "excl.callchain_user", exclude_callchain_user);
1056 ret += PRINT_ATTR2(mmap2, comm_exec);
1057 ret += __PRINT_ATTR("%u",,use_clockid);
1058
1047 1059
1048 ret += PRINT_ATTR_U32(wakeup_events); 1060 ret += PRINT_ATTR_U32(wakeup_events);
1049 ret += PRINT_ATTR_U32(wakeup_watermark); 1061 ret += PRINT_ATTR_U32(wakeup_watermark);
@@ -1055,6 +1067,7 @@ static size_t perf_event_attr__fprintf(struct perf_event_attr *attr, FILE *fp)
1055 ret += PRINT_ATTR_X64(branch_sample_type); 1067 ret += PRINT_ATTR_X64(branch_sample_type);
1056 ret += PRINT_ATTR_X64(sample_regs_user); 1068 ret += PRINT_ATTR_X64(sample_regs_user);
1057 ret += PRINT_ATTR_U32(sample_stack_user); 1069 ret += PRINT_ATTR_U32(sample_stack_user);
1070 ret += PRINT_ATTR_U32(clockid);
1058 ret += PRINT_ATTR_X64(sample_regs_intr); 1071 ret += PRINT_ATTR_X64(sample_regs_intr);
1059 1072
1060 ret += fprintf(fp, "%.60s\n", graph_dotted_line); 1073 ret += fprintf(fp, "%.60s\n", graph_dotted_line);
@@ -1085,6 +1098,12 @@ static int __perf_evsel__open(struct perf_evsel *evsel, struct cpu_map *cpus,
1085 } 1098 }
1086 1099
1087fallback_missing_features: 1100fallback_missing_features:
1101 if (perf_missing_features.clockid_wrong)
1102 evsel->attr.clockid = CLOCK_MONOTONIC; /* should always work */
1103 if (perf_missing_features.clockid) {
1104 evsel->attr.use_clockid = 0;
1105 evsel->attr.clockid = 0;
1106 }
1088 if (perf_missing_features.cloexec) 1107 if (perf_missing_features.cloexec)
1089 flags &= ~(unsigned long)PERF_FLAG_FD_CLOEXEC; 1108 flags &= ~(unsigned long)PERF_FLAG_FD_CLOEXEC;
1090 if (perf_missing_features.mmap2) 1109 if (perf_missing_features.mmap2)
@@ -1122,6 +1141,17 @@ retry_open:
1122 goto try_fallback; 1141 goto try_fallback;
1123 } 1142 }
1124 set_rlimit = NO_CHANGE; 1143 set_rlimit = NO_CHANGE;
1144
1145 /*
1146 * If we succeeded but had to kill clockid, fail and
1147 * have perf_evsel__open_strerror() print us a nice
1148 * error.
1149 */
1150 if (perf_missing_features.clockid ||
1151 perf_missing_features.clockid_wrong) {
1152 err = -EINVAL;
1153 goto out_close;
1154 }
1125 } 1155 }
1126 } 1156 }
1127 1157
@@ -1155,7 +1185,17 @@ try_fallback:
1155 if (err != -EINVAL || cpu > 0 || thread > 0) 1185 if (err != -EINVAL || cpu > 0 || thread > 0)
1156 goto out_close; 1186 goto out_close;
1157 1187
1158 if (!perf_missing_features.cloexec && (flags & PERF_FLAG_FD_CLOEXEC)) { 1188 /*
1189 * Must probe features in the order they were added to the
1190 * perf_event_attr interface.
1191 */
1192 if (!perf_missing_features.clockid_wrong && evsel->attr.use_clockid) {
1193 perf_missing_features.clockid_wrong = true;
1194 goto fallback_missing_features;
1195 } else if (!perf_missing_features.clockid && evsel->attr.use_clockid) {
1196 perf_missing_features.clockid = true;
1197 goto fallback_missing_features;
1198 } else if (!perf_missing_features.cloexec && (flags & PERF_FLAG_FD_CLOEXEC)) {
1159 perf_missing_features.cloexec = true; 1199 perf_missing_features.cloexec = true;
1160 goto fallback_missing_features; 1200 goto fallback_missing_features;
1161 } else if (!perf_missing_features.mmap2 && evsel->attr.mmap2) { 1201 } else if (!perf_missing_features.mmap2 && evsel->attr.mmap2) {
@@ -2063,9 +2103,7 @@ int perf_evsel__fprintf(struct perf_evsel *evsel,
2063 if_print(exclude_hv); 2103 if_print(exclude_hv);
2064 if_print(exclude_idle); 2104 if_print(exclude_idle);
2065 if_print(mmap); 2105 if_print(mmap);
2066 if_print(mmap2);
2067 if_print(comm); 2106 if_print(comm);
2068 if_print(comm_exec);
2069 if_print(freq); 2107 if_print(freq);
2070 if_print(inherit_stat); 2108 if_print(inherit_stat);
2071 if_print(enable_on_exec); 2109 if_print(enable_on_exec);
@@ -2076,10 +2114,17 @@ int perf_evsel__fprintf(struct perf_evsel *evsel,
2076 if_print(sample_id_all); 2114 if_print(sample_id_all);
2077 if_print(exclude_host); 2115 if_print(exclude_host);
2078 if_print(exclude_guest); 2116 if_print(exclude_guest);
2117 if_print(mmap2);
2118 if_print(comm_exec);
2119 if_print(use_clockid);
2079 if_print(__reserved_1); 2120 if_print(__reserved_1);
2080 if_print(wakeup_events); 2121 if_print(wakeup_events);
2081 if_print(bp_type); 2122 if_print(bp_type);
2082 if_print(branch_sample_type); 2123 if_print(branch_sample_type);
2124 if_print(sample_regs_user);
2125 if_print(sample_stack_user);
2126 if_print(clockid);
2127 if_print(sample_regs_intr);
2083 } 2128 }
2084out: 2129out:
2085 fputc('\n', fp); 2130 fputc('\n', fp);
@@ -2158,6 +2203,12 @@ int perf_evsel__open_strerror(struct perf_evsel *evsel, struct target *target,
2158 "The PMU counters are busy/taken by another profiler.\n" 2203 "The PMU counters are busy/taken by another profiler.\n"
2159 "We found oprofile daemon running, please stop it and try again."); 2204 "We found oprofile daemon running, please stop it and try again.");
2160 break; 2205 break;
2206 case EINVAL:
2207 if (perf_missing_features.clockid)
2208 return scnprintf(msg, size, "clockid feature not supported.");
2209 if (perf_missing_features.clockid_wrong)
2210 return scnprintf(msg, size, "wrong clockid (%d).", clockid);
2211 break;
2161 default: 2212 default:
2162 break; 2213 break;
2163 } 2214 }
diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c
index fb432153e2aa..de5f4669ba5f 100644
--- a/tools/perf/util/header.c
+++ b/tools/perf/util/header.c
@@ -1098,6 +1098,9 @@ static void print_event_desc(struct perf_header *ph, int fd, FILE *fp)
1098 } 1098 }
1099 fprintf(fp, " }"); 1099 fprintf(fp, " }");
1100 } 1100 }
1101 if (evsel->attr.use_clockid)
1102 fprintf(fp, ", clockid = %d", evsel->attr.clockid);
1103
1101 1104
1102 fputc('\n', fp); 1105 fputc('\n', fp);
1103 } 1106 }