|
46 | 46 | #include "util/util.h" // perf_exe()
|
47 | 47 | #include "cputopo.h"
|
48 | 48 | #include "bpf-event.h"
|
| 49 | +#include "clockid.h" |
49 | 50 |
|
50 | 51 | #include <linux/ctype.h>
|
51 | 52 | #include <internal/lib.h>
|
@@ -895,6 +896,40 @@ static int write_clockid(struct feat_fd *ff,
|
895 | 896 | sizeof(ff->ph->env.clockid_res_ns));
|
896 | 897 | }
|
897 | 898 |
|
| 899 | +static int write_clock_data(struct feat_fd *ff, |
| 900 | + struct evlist *evlist __maybe_unused) |
| 901 | +{ |
| 902 | + u64 *data64; |
| 903 | + u32 data32; |
| 904 | + int ret; |
| 905 | + |
| 906 | + /* version */ |
| 907 | + data32 = 1; |
| 908 | + |
| 909 | + ret = do_write(ff, &data32, sizeof(data32)); |
| 910 | + if (ret < 0) |
| 911 | + return ret; |
| 912 | + |
| 913 | + /* clockid */ |
| 914 | + data32 = ff->ph->env.clock.clockid; |
| 915 | + |
| 916 | + ret = do_write(ff, &data32, sizeof(data32)); |
| 917 | + if (ret < 0) |
| 918 | + return ret; |
| 919 | + |
| 920 | + /* TOD ref time */ |
| 921 | + data64 = &ff->ph->env.clock.tod_ns; |
| 922 | + |
| 923 | + ret = do_write(ff, data64, sizeof(*data64)); |
| 924 | + if (ret < 0) |
| 925 | + return ret; |
| 926 | + |
| 927 | + /* clockid ref time */ |
| 928 | + data64 = &ff->ph->env.clock.clockid_ns; |
| 929 | + |
| 930 | + return do_write(ff, data64, sizeof(*data64)); |
| 931 | +} |
| 932 | + |
898 | 933 | static int write_dir_format(struct feat_fd *ff,
|
899 | 934 | struct evlist *evlist __maybe_unused)
|
900 | 935 | {
|
@@ -1549,6 +1584,49 @@ static void print_clockid(struct feat_fd *ff, FILE *fp)
|
1549 | 1584 | ff->ph->env.clockid_res_ns * 1000);
|
1550 | 1585 | }
|
1551 | 1586 |
|
| 1587 | +static void print_clock_data(struct feat_fd *ff, FILE *fp) |
| 1588 | +{ |
| 1589 | + struct timespec clockid_ns; |
| 1590 | + char tstr[64], date[64]; |
| 1591 | + struct timeval tod_ns; |
| 1592 | + clockid_t clockid; |
| 1593 | + struct tm ltime; |
| 1594 | + u64 ref; |
| 1595 | + |
| 1596 | + if (!ff->ph->env.clock.enabled) { |
| 1597 | + fprintf(fp, "# reference time disabled\n"); |
| 1598 | + return; |
| 1599 | + } |
| 1600 | + |
| 1601 | + /* Compute TOD time. */ |
| 1602 | + ref = ff->ph->env.clock.tod_ns; |
| 1603 | + tod_ns.tv_sec = ref / NSEC_PER_SEC; |
| 1604 | + ref -= tod_ns.tv_sec * NSEC_PER_SEC; |
| 1605 | + tod_ns.tv_usec = ref / NSEC_PER_USEC; |
| 1606 | + |
| 1607 | + /* Compute clockid time. */ |
| 1608 | + ref = ff->ph->env.clock.clockid_ns; |
| 1609 | + clockid_ns.tv_sec = ref / NSEC_PER_SEC; |
| 1610 | + ref -= clockid_ns.tv_sec * NSEC_PER_SEC; |
| 1611 | + clockid_ns.tv_nsec = ref; |
| 1612 | + |
| 1613 | + clockid = ff->ph->env.clock.clockid; |
| 1614 | + |
| 1615 | + if (localtime_r(&tod_ns.tv_sec, <ime) == NULL) |
| 1616 | + snprintf(tstr, sizeof(tstr), "<error>"); |
| 1617 | + else { |
| 1618 | + strftime(date, sizeof(date), "%F %T", <ime); |
| 1619 | + scnprintf(tstr, sizeof(tstr), "%s.%06d", |
| 1620 | + date, (int) tod_ns.tv_usec); |
| 1621 | + } |
| 1622 | + |
| 1623 | + fprintf(fp, "# clockid: %s (%u)\n", clockid_name(clockid), clockid); |
| 1624 | + fprintf(fp, "# reference time: %s = %ld.%06d (TOD) = %ld.%09ld (%s)\n", |
| 1625 | + tstr, tod_ns.tv_sec, (int) tod_ns.tv_usec, |
| 1626 | + clockid_ns.tv_sec, clockid_ns.tv_nsec, |
| 1627 | + clockid_name(clockid)); |
| 1628 | +} |
| 1629 | + |
1552 | 1630 | static void print_dir_format(struct feat_fd *ff, FILE *fp)
|
1553 | 1631 | {
|
1554 | 1632 | struct perf_session *session;
|
@@ -2738,6 +2816,40 @@ static int process_clockid(struct feat_fd *ff,
|
2738 | 2816 | return 0;
|
2739 | 2817 | }
|
2740 | 2818 |
|
| 2819 | +static int process_clock_data(struct feat_fd *ff, |
| 2820 | + void *_data __maybe_unused) |
| 2821 | +{ |
| 2822 | + u32 data32; |
| 2823 | + u64 data64; |
| 2824 | + |
| 2825 | + /* version */ |
| 2826 | + if (do_read_u32(ff, &data32)) |
| 2827 | + return -1; |
| 2828 | + |
| 2829 | + if (data32 != 1) |
| 2830 | + return -1; |
| 2831 | + |
| 2832 | + /* clockid */ |
| 2833 | + if (do_read_u32(ff, &data32)) |
| 2834 | + return -1; |
| 2835 | + |
| 2836 | + ff->ph->env.clock.clockid = data32; |
| 2837 | + |
| 2838 | + /* TOD ref time */ |
| 2839 | + if (do_read_u64(ff, &data64)) |
| 2840 | + return -1; |
| 2841 | + |
| 2842 | + ff->ph->env.clock.tod_ns = data64; |
| 2843 | + |
| 2844 | + /* clockid ref time */ |
| 2845 | + if (do_read_u64(ff, &data64)) |
| 2846 | + return -1; |
| 2847 | + |
| 2848 | + ff->ph->env.clock.clockid_ns = data64; |
| 2849 | + ff->ph->env.clock.enabled = true; |
| 2850 | + return 0; |
| 2851 | +} |
| 2852 | + |
2741 | 2853 | static int process_dir_format(struct feat_fd *ff,
|
2742 | 2854 | void *_data __maybe_unused)
|
2743 | 2855 | {
|
@@ -3008,6 +3120,7 @@ const struct perf_header_feature_ops feat_ops[HEADER_LAST_FEATURE] = {
|
3008 | 3120 | FEAT_OPR(BPF_BTF, bpf_btf, false),
|
3009 | 3121 | FEAT_OPR(COMPRESSED, compressed, false),
|
3010 | 3122 | FEAT_OPR(CPU_PMU_CAPS, cpu_pmu_caps, false),
|
| 3123 | + FEAT_OPR(CLOCK_DATA, clock_data, false), |
3011 | 3124 | };
|
3012 | 3125 |
|
3013 | 3126 | struct header_print_data {
|
|
0 commit comments