diff options
Diffstat (limited to 'tools/perf/util/header.c')
-rw-r--r-- | tools/perf/util/header.c | 130 |
1 files changed, 128 insertions, 2 deletions
diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c index 7c0e9d587bfa..a326e0d8b5b6 100644 --- a/tools/perf/util/header.c +++ b/tools/perf/util/header.c | |||
@@ -15,9 +15,8 @@ | |||
15 | #include <linux/bitops.h> | 15 | #include <linux/bitops.h> |
16 | #include <linux/stringify.h> | 16 | #include <linux/stringify.h> |
17 | #include <sys/stat.h> | 17 | #include <sys/stat.h> |
18 | #include <sys/types.h> | ||
19 | #include <sys/utsname.h> | 18 | #include <sys/utsname.h> |
20 | #include <unistd.h> | 19 | #include <linux/time64.h> |
21 | 20 | ||
22 | #include "evlist.h" | 21 | #include "evlist.h" |
23 | #include "evsel.h" | 22 | #include "evsel.h" |
@@ -37,6 +36,7 @@ | |||
37 | #include <api/fs/fs.h> | 36 | #include <api/fs/fs.h> |
38 | #include "asm/bug.h" | 37 | #include "asm/bug.h" |
39 | #include "tool.h" | 38 | #include "tool.h" |
39 | #include "time-utils.h" | ||
40 | 40 | ||
41 | #include "sane_ctype.h" | 41 | #include "sane_ctype.h" |
42 | 42 | ||
@@ -1182,6 +1182,20 @@ static int write_stat(struct feat_fd *ff __maybe_unused, | |||
1182 | return 0; | 1182 | return 0; |
1183 | } | 1183 | } |
1184 | 1184 | ||
1185 | static int write_sample_time(struct feat_fd *ff, | ||
1186 | struct perf_evlist *evlist) | ||
1187 | { | ||
1188 | int ret; | ||
1189 | |||
1190 | ret = do_write(ff, &evlist->first_sample_time, | ||
1191 | sizeof(evlist->first_sample_time)); | ||
1192 | if (ret < 0) | ||
1193 | return ret; | ||
1194 | |||
1195 | return do_write(ff, &evlist->last_sample_time, | ||
1196 | sizeof(evlist->last_sample_time)); | ||
1197 | } | ||
1198 | |||
1185 | static void print_hostname(struct feat_fd *ff, FILE *fp) | 1199 | static void print_hostname(struct feat_fd *ff, FILE *fp) |
1186 | { | 1200 | { |
1187 | fprintf(fp, "# hostname : %s\n", ff->ph->env.hostname); | 1201 | fprintf(fp, "# hostname : %s\n", ff->ph->env.hostname); |
@@ -1507,6 +1521,28 @@ static void print_group_desc(struct feat_fd *ff, FILE *fp) | |||
1507 | } | 1521 | } |
1508 | } | 1522 | } |
1509 | 1523 | ||
1524 | static void print_sample_time(struct feat_fd *ff, FILE *fp) | ||
1525 | { | ||
1526 | struct perf_session *session; | ||
1527 | char time_buf[32]; | ||
1528 | double d; | ||
1529 | |||
1530 | session = container_of(ff->ph, struct perf_session, header); | ||
1531 | |||
1532 | timestamp__scnprintf_usec(session->evlist->first_sample_time, | ||
1533 | time_buf, sizeof(time_buf)); | ||
1534 | fprintf(fp, "# time of first sample : %s\n", time_buf); | ||
1535 | |||
1536 | timestamp__scnprintf_usec(session->evlist->last_sample_time, | ||
1537 | time_buf, sizeof(time_buf)); | ||
1538 | fprintf(fp, "# time of last sample : %s\n", time_buf); | ||
1539 | |||
1540 | d = (double)(session->evlist->last_sample_time - | ||
1541 | session->evlist->first_sample_time) / NSEC_PER_MSEC; | ||
1542 | |||
1543 | fprintf(fp, "# sample duration : %10.3f ms\n", d); | ||
1544 | } | ||
1545 | |||
1510 | static int __event_process_build_id(struct build_id_event *bev, | 1546 | static int __event_process_build_id(struct build_id_event *bev, |
1511 | char *filename, | 1547 | char *filename, |
1512 | struct perf_session *session) | 1548 | struct perf_session *session) |
@@ -2148,6 +2184,27 @@ out_free_caches: | |||
2148 | return -1; | 2184 | return -1; |
2149 | } | 2185 | } |
2150 | 2186 | ||
2187 | static int process_sample_time(struct feat_fd *ff, void *data __maybe_unused) | ||
2188 | { | ||
2189 | struct perf_session *session; | ||
2190 | u64 first_sample_time, last_sample_time; | ||
2191 | int ret; | ||
2192 | |||
2193 | session = container_of(ff->ph, struct perf_session, header); | ||
2194 | |||
2195 | ret = do_read_u64(ff, &first_sample_time); | ||
2196 | if (ret) | ||
2197 | return -1; | ||
2198 | |||
2199 | ret = do_read_u64(ff, &last_sample_time); | ||
2200 | if (ret) | ||
2201 | return -1; | ||
2202 | |||
2203 | session->evlist->first_sample_time = first_sample_time; | ||
2204 | session->evlist->last_sample_time = last_sample_time; | ||
2205 | return 0; | ||
2206 | } | ||
2207 | |||
2151 | struct feature_ops { | 2208 | struct feature_ops { |
2152 | int (*write)(struct feat_fd *ff, struct perf_evlist *evlist); | 2209 | int (*write)(struct feat_fd *ff, struct perf_evlist *evlist); |
2153 | void (*print)(struct feat_fd *ff, FILE *fp); | 2210 | void (*print)(struct feat_fd *ff, FILE *fp); |
@@ -2205,6 +2262,7 @@ static const struct feature_ops feat_ops[HEADER_LAST_FEATURE] = { | |||
2205 | FEAT_OPN(AUXTRACE, auxtrace, false), | 2262 | FEAT_OPN(AUXTRACE, auxtrace, false), |
2206 | FEAT_OPN(STAT, stat, false), | 2263 | FEAT_OPN(STAT, stat, false), |
2207 | FEAT_OPN(CACHE, cache, true), | 2264 | FEAT_OPN(CACHE, cache, true), |
2265 | FEAT_OPR(SAMPLE_TIME, sample_time, false), | ||
2208 | }; | 2266 | }; |
2209 | 2267 | ||
2210 | struct header_print_data { | 2268 | struct header_print_data { |
@@ -3258,6 +3316,74 @@ int perf_event__synthesize_attrs(struct perf_tool *tool, | |||
3258 | return err; | 3316 | return err; |
3259 | } | 3317 | } |
3260 | 3318 | ||
3319 | static bool has_unit(struct perf_evsel *counter) | ||
3320 | { | ||
3321 | return counter->unit && *counter->unit; | ||
3322 | } | ||
3323 | |||
3324 | static bool has_scale(struct perf_evsel *counter) | ||
3325 | { | ||
3326 | return counter->scale != 1; | ||
3327 | } | ||
3328 | |||
3329 | int perf_event__synthesize_extra_attr(struct perf_tool *tool, | ||
3330 | struct perf_evlist *evsel_list, | ||
3331 | perf_event__handler_t process, | ||
3332 | bool is_pipe) | ||
3333 | { | ||
3334 | struct perf_evsel *counter; | ||
3335 | int err; | ||
3336 | |||
3337 | /* | ||
3338 | * Synthesize other events stuff not carried within | ||
3339 | * attr event - unit, scale, name | ||
3340 | */ | ||
3341 | evlist__for_each_entry(evsel_list, counter) { | ||
3342 | if (!counter->supported) | ||
3343 | continue; | ||
3344 | |||
3345 | /* | ||
3346 | * Synthesize unit and scale only if it's defined. | ||
3347 | */ | ||
3348 | if (has_unit(counter)) { | ||
3349 | err = perf_event__synthesize_event_update_unit(tool, counter, process); | ||
3350 | if (err < 0) { | ||
3351 | pr_err("Couldn't synthesize evsel unit.\n"); | ||
3352 | return err; | ||
3353 | } | ||
3354 | } | ||
3355 | |||
3356 | if (has_scale(counter)) { | ||
3357 | err = perf_event__synthesize_event_update_scale(tool, counter, process); | ||
3358 | if (err < 0) { | ||
3359 | pr_err("Couldn't synthesize evsel counter.\n"); | ||
3360 | return err; | ||
3361 | } | ||
3362 | } | ||
3363 | |||
3364 | if (counter->own_cpus) { | ||
3365 | err = perf_event__synthesize_event_update_cpus(tool, counter, process); | ||
3366 | if (err < 0) { | ||
3367 | pr_err("Couldn't synthesize evsel cpus.\n"); | ||
3368 | return err; | ||
3369 | } | ||
3370 | } | ||
3371 | |||
3372 | /* | ||
3373 | * Name is needed only for pipe output, | ||
3374 | * perf.data carries event names. | ||
3375 | */ | ||
3376 | if (is_pipe) { | ||
3377 | err = perf_event__synthesize_event_update_name(tool, counter, process); | ||
3378 | if (err < 0) { | ||
3379 | pr_err("Couldn't synthesize evsel name.\n"); | ||
3380 | return err; | ||
3381 | } | ||
3382 | } | ||
3383 | } | ||
3384 | return 0; | ||
3385 | } | ||
3386 | |||
3261 | int perf_event__process_attr(struct perf_tool *tool __maybe_unused, | 3387 | int perf_event__process_attr(struct perf_tool *tool __maybe_unused, |
3262 | union perf_event *event, | 3388 | union perf_event *event, |
3263 | struct perf_evlist **pevlist) | 3389 | struct perf_evlist **pevlist) |