Received: by 2002:a05:6a10:a0d1:0:0:0:0 with SMTP id j17csp345027pxa; Wed, 5 Aug 2020 02:39:29 -0700 (PDT) X-Google-Smtp-Source: ABdhPJy2D0+AloCjsVYg3QUSPGAZNCwW5TgEMqWxNeLmoxxCtezeXnKVxqUVY8fkGZuqM2Xfc7pU X-Received: by 2002:a17:906:819:: with SMTP id e25mr2464181ejd.95.1596620369297; Wed, 05 Aug 2020 02:39:29 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1596620369; cv=none; d=google.com; s=arc-20160816; b=M6yqK7GRUqwCDncZ0mCtzRpuoYaVP7YmgT4nvnAXfZYxT704hj4aKbVwooJEV0iZsx L7VPPsQglnxSOPhNzwwTyl4C585xNVDSdh+vlDQu4crqnHbqPRWGAF7SZ7Tj1p+RDyg2 Gsr5Do5ILETMcJ8sdqqnmniGYwu1JT84EmpWM4MNEOqM00/LyuaRyAxVKctJfggMDwZH +UAeYgSRzLlLX6ZNdBOXMGSul1m2DrNGAZXmr0MYZklAhl30INnSUO+FyF32KztmcKNg L1XIvLsSO5P6kxEhITcgRZRoxGvSD0DLTQ45jsEKPNl24Qx1DCk5UCkyJwwcbW/WC6KO whQA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:cc:to:from; bh=NUEwCnf8KJ4l3K7LacQmb3DdNqvmmiL8mOxQDD8knxc=; b=S64M3Xy9nMEjz45uhgxy9/3kUPV4PKLHBluuCQ+0FVJNBL41tQn3XccGRTMUpStaOO Exq2RGK/nR7j2Fp//QhVqP9uHnoGU0/LNhcRBU71p2iMqk/cEMeT8VaCWUeEQrO5oe2Q xa7xIRwKu7iJcwzKhr3yIVqrTocNOa00foNTvHpakPJtYXyS6fi3d91Gp2L2pkDO1dDy NwSg8r97ODUACEu0n0hJEEAS6p0cnLYhuWoZrtyrG5/Frp2e8qq+nbHkQZ4A6n+yVrc4 CkwxcFjaoxFVVk3gfeuDb7doJFFxD3eelOVL3I/DqExi/7Tj/erbfDkDWVbIk24JZwfv /txQ== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id v7si1162181edd.551.2020.08.05.02.39.06; Wed, 05 Aug 2020 02:39:29 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) client-ip=23.128.96.18; Authentication-Results: mx.google.com; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728451AbgHEJg1 convert rfc822-to-8bit (ORCPT + 99 others); Wed, 5 Aug 2020 05:36:27 -0400 Received: from us-smtp-1.mimecast.com ([207.211.31.81]:35490 "EHLO us-smtp-delivery-1.mimecast.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1728384AbgHEJfO (ORCPT ); Wed, 5 Aug 2020 05:35:14 -0400 Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-431-W49K3UtNMWGPErXe8zIwLw-1; Wed, 05 Aug 2020 05:35:04 -0400 X-MC-Unique: W49K3UtNMWGPErXe8zIwLw-1 Received: from smtp.corp.redhat.com (int-mx05.intmail.prod.int.phx2.redhat.com [10.5.11.15]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 449C710059AA; Wed, 5 Aug 2020 09:35:02 +0000 (UTC) Received: from krava.redhat.com (unknown [10.40.194.15]) by smtp.corp.redhat.com (Postfix) with ESMTP id D4A567193A; Wed, 5 Aug 2020 09:34:58 +0000 (UTC) From: Jiri Olsa To: Arnaldo Carvalho de Melo Cc: David Ahern , lkml , Ingo Molnar , Namhyung Kim , Alexander Shishkin , Peter Zijlstra , Michael Petlan , Ian Rogers , Andi Kleen , =?UTF-8?q?Genevi=C3=A8ve=20Bastien?= , Wang Nan , Jeremie Galarneau Subject: [PATCH v2 3/7] perf tools: Store clock references for -k/--clockid option Date: Wed, 5 Aug 2020 11:34:40 +0200 Message-Id: <20200805093444.314999-4-jolsa@kernel.org> In-Reply-To: <20200805093444.314999-1-jolsa@kernel.org> References: <20200805093444.314999-1-jolsa@kernel.org> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.15 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: kernel.org Content-Type: text/plain; charset=WINDOWS-1252 Content-Transfer-Encoding: 8BIT Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Adding new CLOCK_DATA feature that stores reference times when -k/--clockid option is specified. It contains clock id and its reference time together with wall clock time taken at the 'same time', both values are in nanoseconds. The format of data is as below: struct { u32 version; /* version = 1 */ u32 clockid; u64 wall_clock_ns; u64 clockid_time_ns; }; This clock reference times will be used in following changes to display wall clock for perf events. It's available only for recording with clockid specified, because it's the only case where we can get reference time to wallclock time. It's can't do that with perf clock yet. Original-patch-by: David Ahern Signed-off-by: Jiri Olsa --- .../Documentation/perf.data-file-format.txt | 13 ++ tools/perf/builtin-record.c | 41 +++++++ tools/perf/util/env.h | 12 ++ tools/perf/util/header.c | 113 ++++++++++++++++++ tools/perf/util/header.h | 1 + 5 files changed, 180 insertions(+) diff --git a/tools/perf/Documentation/perf.data-file-format.txt b/tools/perf/Documentation/perf.data-file-format.txt index b6472e463284..9ee96640744e 100644 --- a/tools/perf/Documentation/perf.data-file-format.txt +++ b/tools/perf/Documentation/perf.data-file-format.txt @@ -389,6 +389,19 @@ struct { Example: cpu pmu capabilities: branches=32, max_precise=3, pmu_name=icelake + HEADER_CLOCK_DATA = 29, + + Contains clock id and its reference time together with wall clock + time taken at the 'same time', both values are in nanoseconds. + The format of data is as below. + +struct { + u32 version; /* version = 1 */ + u32 clockid; + u64 wall_clock_ns; + u64 clockid_time_ns; +}; + other bits are reserved and should ignored for now HEADER_FEAT_BITS = 256, diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c index eb42d2d9d16b..48d721af0096 100644 --- a/tools/perf/builtin-record.c +++ b/tools/perf/builtin-record.c @@ -71,6 +71,7 @@ #include #include #include +#include struct switch_output { bool enabled; @@ -1204,6 +1205,9 @@ static void record__init_features(struct record *rec) if (!(rec->opts.use_clockid && rec->opts.clockid_res_ns)) perf_header__clear_feat(&session->header, HEADER_CLOCKID); + if (!rec->opts.use_clockid) + perf_header__clear_feat(&session->header, HEADER_CLOCK_DATA); + perf_header__clear_feat(&session->header, HEADER_DIR_FORMAT); if (!record__comp_enabled(rec)) perf_header__clear_feat(&session->header, HEADER_COMPRESSED); @@ -1552,6 +1556,40 @@ static int record__setup_sb_evlist(struct record *rec) return 0; } +static int record__init_clock(struct record *rec) +{ + struct perf_session *session = rec->session; + struct timespec ref_clockid; + struct timeval ref_tod; + u64 ref; + + if (!rec->opts.use_clockid) + return 0; + + session->header.env.clock.clockid = rec->opts.clockid; + + if (gettimeofday(&ref_tod, NULL) != 0) { + pr_err("gettimeofday failed, cannot set reference time.\n"); + return -1; + } + + if (clock_gettime(rec->opts.clockid, &ref_clockid)) { + pr_err("clock_gettime failed, cannot set reference time.\n"); + return -1; + } + + ref = (u64) ref_tod.tv_sec * NSEC_PER_SEC + + (u64) ref_tod.tv_usec * NSEC_PER_USEC; + + session->header.env.clock.tod_ns = ref; + + ref = (u64) ref_clockid.tv_sec * NSEC_PER_SEC + + (u64) ref_clockid.tv_nsec; + + session->header.env.clock.clockid_ns = ref; + return 0; +} + static int __cmd_record(struct record *rec, int argc, const char **argv) { int err; @@ -1631,6 +1669,9 @@ static int __cmd_record(struct record *rec, int argc, const char **argv) return -1; } + if (record__init_clock(rec)) + return -1; + record__init_features(rec); if (rec->opts.use_clockid && rec->opts.clockid_res_ns) diff --git a/tools/perf/util/env.h b/tools/perf/util/env.h index 1ab2682d5d2b..7218f7db57af 100644 --- a/tools/perf/util/env.h +++ b/tools/perf/util/env.h @@ -100,6 +100,18 @@ struct perf_env { /* For fast cpu to numa node lookup via perf_env__numa_node */ int *numa_map; int nr_numa_map; + + /* For real clock time reference. */ + struct { + u64 tod_ns; + u64 clockid_ns; + int clockid; + /* + * enabled is valid for report mode, and is true if above + * values are set, it's set in process_clock_data + */ + bool enabled; + } clock; }; enum perf_compress_type { diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c index 7a67d017d72c..eece94cf6f86 100644 --- a/tools/perf/util/header.c +++ b/tools/perf/util/header.c @@ -46,6 +46,7 @@ #include "util/util.h" // perf_exe() #include "cputopo.h" #include "bpf-event.h" +#include "clockid.h" #include #include @@ -895,6 +896,40 @@ static int write_clockid(struct feat_fd *ff, sizeof(ff->ph->env.clockid_res_ns)); } +static int write_clock_data(struct feat_fd *ff, + struct evlist *evlist __maybe_unused) +{ + u64 *data64; + u32 data32; + int ret; + + /* version */ + data32 = 1; + + ret = do_write(ff, &data32, sizeof(data32)); + if (ret < 0) + return ret; + + /* clockid */ + data32 = ff->ph->env.clock.clockid; + + ret = do_write(ff, &data32, sizeof(data32)); + if (ret < 0) + return ret; + + /* TOD ref time */ + data64 = &ff->ph->env.clock.tod_ns; + + ret = do_write(ff, data64, sizeof(*data64)); + if (ret < 0) + return ret; + + /* clockid ref time */ + data64 = &ff->ph->env.clock.clockid_ns; + + return do_write(ff, data64, sizeof(*data64)); +} + static int write_dir_format(struct feat_fd *ff, struct evlist *evlist __maybe_unused) { @@ -1549,6 +1584,49 @@ static void print_clockid(struct feat_fd *ff, FILE *fp) ff->ph->env.clockid_res_ns * 1000); } +static void print_clock_data(struct feat_fd *ff, FILE *fp) +{ + struct timespec clockid_ns; + char tstr[64], date[64]; + struct timeval tod_ns; + clockid_t clockid; + struct tm ltime; + u64 ref; + + if (!ff->ph->env.clock.enabled) { + fprintf(fp, "# reference time disabled\n"); + return; + } + + /* Compute TOD time. */ + ref = ff->ph->env.clock.tod_ns; + tod_ns.tv_sec = ref / NSEC_PER_SEC; + ref -= tod_ns.tv_sec * NSEC_PER_SEC; + tod_ns.tv_usec = ref / NSEC_PER_USEC; + + /* Compute clockid time. */ + ref = ff->ph->env.clock.clockid_ns; + clockid_ns.tv_sec = ref / NSEC_PER_SEC; + ref -= clockid_ns.tv_sec * NSEC_PER_SEC; + clockid_ns.tv_nsec = ref; + + clockid = ff->ph->env.clock.clockid; + + if (localtime_r(&tod_ns.tv_sec, <ime) == NULL) + snprintf(tstr, sizeof(tstr), ""); + else { + strftime(date, sizeof(date), "%F %T", <ime); + scnprintf(tstr, sizeof(tstr), "%s.%06d", + date, (int) tod_ns.tv_usec); + } + + fprintf(fp, "# clockid: %s (%u)\n", clockid_name(clockid), clockid); + fprintf(fp, "# reference time: %s = %ld.%06d (TOD) = %ld.%09ld (%s)\n", + tstr, tod_ns.tv_sec, (int) tod_ns.tv_usec, + clockid_ns.tv_sec, clockid_ns.tv_nsec, + clockid_name(clockid)); +} + static void print_dir_format(struct feat_fd *ff, FILE *fp) { struct perf_session *session; @@ -2738,6 +2816,40 @@ static int process_clockid(struct feat_fd *ff, return 0; } +static int process_clock_data(struct feat_fd *ff, + void *_data __maybe_unused) +{ + u32 data32; + u64 data64; + + /* version */ + if (do_read_u32(ff, &data32)) + return -1; + + if (data32 != 1) + return -1; + + /* clockid */ + if (do_read_u32(ff, &data32)) + return -1; + + ff->ph->env.clock.clockid = data32; + + /* TOD ref time */ + if (do_read_u64(ff, &data64)) + return -1; + + ff->ph->env.clock.tod_ns = data64; + + /* clockid ref time */ + if (do_read_u64(ff, &data64)) + return -1; + + ff->ph->env.clock.clockid_ns = data64; + ff->ph->env.clock.enabled = true; + return 0; +} + static int process_dir_format(struct feat_fd *ff, void *_data __maybe_unused) { @@ -3008,6 +3120,7 @@ const struct perf_header_feature_ops feat_ops[HEADER_LAST_FEATURE] = { FEAT_OPR(BPF_BTF, bpf_btf, false), FEAT_OPR(COMPRESSED, compressed, false), FEAT_OPR(CPU_PMU_CAPS, cpu_pmu_caps, false), + FEAT_OPR(CLOCK_DATA, clock_data, false), }; struct header_print_data { diff --git a/tools/perf/util/header.h b/tools/perf/util/header.h index 650bd1c7a99b..2aca71763ecf 100644 --- a/tools/perf/util/header.h +++ b/tools/perf/util/header.h @@ -44,6 +44,7 @@ enum { HEADER_BPF_BTF, HEADER_COMPRESSED, HEADER_CPU_PMU_CAPS, + HEADER_CLOCK_DATA, HEADER_LAST_FEATURE, HEADER_FEAT_BITS = 256, }; -- 2.25.4