From nobody Tue Apr 7 00:42:40 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 8313DECAAD3 for ; Wed, 31 Aug 2022 17:50:14 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231775AbiHaRuL (ORCPT ); Wed, 31 Aug 2022 13:50:11 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:35644 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231939AbiHaRtw (ORCPT ); Wed, 31 Aug 2022 13:49:52 -0400 Received: from mail-yb1-xb49.google.com (mail-yb1-xb49.google.com [IPv6:2607:f8b0:4864:20::b49]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 62FF2332 for ; Wed, 31 Aug 2022 10:49:46 -0700 (PDT) Received: by mail-yb1-xb49.google.com with SMTP id i194-20020a253bcb000000b00676d86fc5d7so2640636yba.9 for ; Wed, 31 Aug 2022 10:49:46 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20210112; h=cc:to:from:subject:references:mime-version:message-id:in-reply-to :date:from:to:cc; bh=FIhE9np411d4p3gN9blVTRPdzI3E6ppyXBOT6UPFbR4=; b=ne9hSOueraTKLt8B5Cb23CIuuHBACsq29lffrVlmCbtJ+wIUo6y/lzIcGacW0pICES ND3eaRFXLukN+o+BTCx6E/CwfDw5PKfyfUAwBfkx6AOgLtzjKxkmtMm9tTMXEq5TJB+o T5UoEd4og4+/s2fdLG8ZcMM+T01avD4CaXvmUR5vRy7qQ7ZjLmfTXsBRS7lyGCARMH7E tJHQaOSAVFlZz4eRNlrsQAFiy8f/kkhs3c4aaZnmjQfDFDEanQMdfKp3/PPOULKsxx4K IZxhp6YtK1161/rjbG2CMiAejR9L95NqM5+2LFilD/hSzDd2LTENesnpRSq+AfA6fXTU fW9w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=cc:to:from:subject:references:mime-version:message-id:in-reply-to :date:x-gm-message-state:from:to:cc; bh=FIhE9np411d4p3gN9blVTRPdzI3E6ppyXBOT6UPFbR4=; b=JCzsref9RnAUkeva3EeqvFaeH2jRmIZm7rFaCzrhqk3dWSdJ74y0ZZEGmX7dvq3yEr taBdowD0C6ffc8s9eXfuKgYk1+3wq9rOLyBLf7WY/oEtN/iWkCZ4Rj7aoR7sUuU0N2wC SACWLQVvdm1Qr/B7sE6C13QFC7JoTxuzOQELyyicuw83Yjaw4QWyatAuAa199exrSnLr 0ezbE7z8Bdja7Z9f9Q2kfFlqCzd2mMJWKLEs//yo/IgbfhajZL3IiYl5cD8qCprwriJa DmjEEGyiDnJzwZs0bPP8czODsRUxu4sONBSFmC3ge02T0Pcj06Fqym8D0LWbhenWTRXv kl9w== X-Gm-Message-State: ACgBeo1eBgcZyPd2E36+VO659WIi+cPGu3xz5TLyC1u2WtnLtrl/3x1g KLbOdMTJrbIRyPdPZxiOpVMc4K5O7Agp X-Google-Smtp-Source: AA6agR4B7PQHzA5GEWgennxyCAc9Ns5xYfYAa5bOnz0OECUYKf6mW+FhxZe1AzmfytNMjb2G3jAMvNJ75M5X X-Received: from irogers.svl.corp.google.com ([2620:15c:2d4:203:c8e4:a3e5:9d09:d3d4]) (user=irogers job=sendgmr) by 2002:a25:4e42:0:b0:696:4c4d:6545 with SMTP id c63-20020a254e42000000b006964c4d6545mr16758166ybb.488.1661968185602; Wed, 31 Aug 2022 10:49:45 -0700 (PDT) Date: Wed, 31 Aug 2022 10:49:20 -0700 In-Reply-To: <20220831174926.579643-1-irogers@google.com> Message-Id: <20220831174926.579643-2-irogers@google.com> Mime-Version: 1.0 References: <20220831174926.579643-1-irogers@google.com> X-Mailer: git-send-email 2.37.2.672.g94769d06f0-goog Subject: [PATCH v2 1/7] perf metric: Return early if no CPU PMU table exists From: Ian Rogers To: Peter Zijlstra , Ingo Molnar , Arnaldo Carvalho de Melo , Mark Rutland , Alexander Shishkin , Jiri Olsa , Namhyung Kim , Andi Kleen , Kan Liang , Thomas Richter , James Clark , Miaoqian Lin , John Garry , Zhengjun Xing , Florian Fischer , linux-perf-users@vger.kernel.org, linux-kernel@vger.kernel.org, perry.taylor@intel.com, caleb.biggers@intel.com, kshipra.bopardikar@intel.com, ahmad.yasin@intel.com Cc: Stephane Eranian , Ian Rogers Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Previous behavior is to segfault if there is no CPU PMU table and a metric is sought. To reproduce compile with NO_JEVENTS=3D1 then request a metric, for example, "perf stat -M IPC true". Fixes: 00facc760903 ("perf jevents: Switch build to use jevents.py") Signed-off-by: Ian Rogers --- tools/perf/util/metricgroup.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tools/perf/util/metricgroup.c b/tools/perf/util/metricgroup.c index ad5cacdecd81..18aae040d61d 100644 --- a/tools/perf/util/metricgroup.c +++ b/tools/perf/util/metricgroup.c @@ -1655,6 +1655,9 @@ int metricgroup__parse_groups(const struct option *op= t, struct evlist *perf_evlist =3D *(struct evlist **)opt->value; const struct pmu_events_table *table =3D pmu_events_table__find(); =20 + if (!table) + return -EINVAL; + return parse_groups(perf_evlist, str, metric_no_group, metric_no_merge, NULL, metric_events, table); } --=20 2.37.2.672.g94769d06f0-goog From nobody Tue Apr 7 00:42:40 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 421A9ECAAD3 for ; Wed, 31 Aug 2022 17:50:30 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231821AbiHaRu2 (ORCPT ); Wed, 31 Aug 2022 13:50:28 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:37422 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232083AbiHaRt7 (ORCPT ); Wed, 31 Aug 2022 13:49:59 -0400 Received: from mail-yw1-x1149.google.com (mail-yw1-x1149.google.com [IPv6:2607:f8b0:4864:20::1149]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 93FC0B855 for ; Wed, 31 Aug 2022 10:49:57 -0700 (PDT) Received: by mail-yw1-x1149.google.com with SMTP id 00721157ae682-340862314d9so193440717b3.3 for ; Wed, 31 Aug 2022 10:49:57 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20210112; h=cc:to:from:subject:references:mime-version:message-id:in-reply-to :date:from:to:cc; bh=wtl4vnbRhxSt4fzqjQ6Yyk9PkVxZDiLFY2fpaAc2xnQ=; b=J6De3RCXPZEOmej3SLXKpHVWB7FO5hMxNSX1Vx1yk+O5hHKG//kmTkSnWsj1Uf5Ell 4LwyLDiG21bWpiwFjGWdS4UlOyNnqEAVyr5BUorkIVM0FsckVz159KX1xXM3RFEJMmtn HvUqItji0UtSCkYHrKosvMUYJCIEcbhja0k2PphSFcMyRYTmVFc+L/OiL92leRzsQQ8k geKHes1DuxiCvYHX9X8DoClZtHqMpC8hPnISgZv+1NRARuYsuWzi2rfFPFTo1Pcxu8KH fcfQMdyK8UYPMgBr4WK66ERDajdZTNprwTCdr+7jOBkAbtgDxpkiP2bxBX8CoZg/Sj37 wo0w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=cc:to:from:subject:references:mime-version:message-id:in-reply-to :date:x-gm-message-state:from:to:cc; bh=wtl4vnbRhxSt4fzqjQ6Yyk9PkVxZDiLFY2fpaAc2xnQ=; b=O+5qojYyCmk0xakt1BwoetHh9kWj7CSfUqvWpglUgCd/EcFxlBd3633EsFaPErKu8s CQfjtkpnwiOp+vRbDCJ9/hSd6aOlST1W/XLnM/Gi0gkk9tIv0bAIc1BaQtCkDr2z8BxV Ks1E8A76bXtTKlZC63MfZsMGKK5IzMwoYFLv73vhWlwvag5PS1ReEaP/9ztCxzOaHDhW Aln5vr506G1AUEtrFDPfrY1p7pEMR8xwrWkTwHdqb0DUzZLEczPVBMCgju8loXyMNj6l zCW110iDWf0MEuVFQKez6YPiuw92UFsUpph9ctr0/wtWmYur0LxZlkdNO0a3h1N3RaZO gQnQ== X-Gm-Message-State: ACgBeo3RijjGAk8iDIpwZ4KqygptuHLwiKA6BfongVMQD3G+3kVB9l7E 76aRGw9UUerX+d/ymiqg5RjZWcQjKFSB X-Google-Smtp-Source: AA6agR5A8muvj1BDAfXKm4+hw5Etoyyqggm9NFRlMECR8Lz3xmrHKLWn+ZMaJqPumek/NZ18Emb6rugLNPwp X-Received: from irogers.svl.corp.google.com ([2620:15c:2d4:203:c8e4:a3e5:9d09:d3d4]) (user=irogers job=sendgmr) by 2002:a81:b601:0:b0:340:d1e7:b213 with SMTP id u1-20020a81b601000000b00340d1e7b213mr16197476ywh.392.1661968196525; Wed, 31 Aug 2022 10:49:56 -0700 (PDT) Date: Wed, 31 Aug 2022 10:49:21 -0700 In-Reply-To: <20220831174926.579643-1-irogers@google.com> Message-Id: <20220831174926.579643-3-irogers@google.com> Mime-Version: 1.0 References: <20220831174926.579643-1-irogers@google.com> X-Mailer: git-send-email 2.37.2.672.g94769d06f0-goog Subject: [PATCH v2 2/7] perf expr: Move the scanner_ctx into the parse_ctx From: Ian Rogers To: Peter Zijlstra , Ingo Molnar , Arnaldo Carvalho de Melo , Mark Rutland , Alexander Shishkin , Jiri Olsa , Namhyung Kim , Andi Kleen , Kan Liang , Thomas Richter , James Clark , Miaoqian Lin , John Garry , Zhengjun Xing , Florian Fischer , linux-perf-users@vger.kernel.org, linux-kernel@vger.kernel.org, perry.taylor@intel.com, caleb.biggers@intel.com, kshipra.bopardikar@intel.com, ahmad.yasin@intel.com Cc: Stephane Eranian , Ian Rogers Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" We currently maintain the two independently and copy from one to the other. This is a burden when additional scanner context values are necessary, so combine them. Signed-off-by: Ian Rogers --- tools/perf/tests/expr.c | 2 +- tools/perf/util/expr.c | 7 ++----- tools/perf/util/expr.h | 10 +++++----- tools/perf/util/metricgroup.c | 4 ++-- tools/perf/util/stat-shadow.c | 2 +- 5 files changed, 11 insertions(+), 14 deletions(-) diff --git a/tools/perf/tests/expr.c b/tools/perf/tests/expr.c index 2efe9e3a63b8..7ca5e37de560 100644 --- a/tools/perf/tests/expr.c +++ b/tools/perf/tests/expr.c @@ -133,7 +133,7 @@ static int test__expr(struct test_suite *t __maybe_unus= ed, int subtest __maybe_u (void **)&val_ptr)); =20 expr__ctx_clear(ctx); - ctx->runtime =3D 3; + ctx->sctx.runtime =3D 3; TEST_ASSERT_VAL("find ids", expr__find_ids("EVENT1\\,param\\=3D?@ + EVENT2\\,param\\=3D?@", NULL, ctx) =3D=3D 0); diff --git a/tools/perf/util/expr.c b/tools/perf/util/expr.c index c15a9852fa41..00bde682e743 100644 --- a/tools/perf/util/expr.c +++ b/tools/perf/util/expr.c @@ -310,7 +310,7 @@ struct expr_parse_ctx *expr__ctx_new(void) free(ctx); return NULL; } - ctx->runtime =3D 0; + ctx->sctx.runtime =3D 0; =20 return ctx; } @@ -344,16 +344,13 @@ static int __expr__parse(double *val, struct expr_parse_ctx *ctx, const char *expr, bool compute_ids) { - struct expr_scanner_ctx scanner_ctx =3D { - .runtime =3D ctx->runtime, - }; YY_BUFFER_STATE buffer; void *scanner; int ret; =20 pr_debug2("parsing metric: %s\n", expr); =20 - ret =3D expr_lex_init_extra(&scanner_ctx, &scanner); + ret =3D expr_lex_init_extra(&ctx->sctx, &scanner); if (ret) return ret; =20 diff --git a/tools/perf/util/expr.h b/tools/perf/util/expr.h index 0403a92d9dcc..07af3d438eb2 100644 --- a/tools/perf/util/expr.h +++ b/tools/perf/util/expr.h @@ -10,17 +10,17 @@ =20 struct metric_ref; =20 +struct expr_scanner_ctx { + int runtime; +}; + struct expr_parse_ctx { struct hashmap *ids; - int runtime; + struct expr_scanner_ctx sctx; }; =20 struct expr_id_data; =20 -struct expr_scanner_ctx { - int runtime; -}; - struct hashmap *ids__new(void); void ids__free(struct hashmap *ids); int ids__insert(struct hashmap *ids, const char *id); diff --git a/tools/perf/util/metricgroup.c b/tools/perf/util/metricgroup.c index 18aae040d61d..b144c3e35264 100644 --- a/tools/perf/util/metricgroup.c +++ b/tools/perf/util/metricgroup.c @@ -215,7 +215,7 @@ static struct metric *metric__new(const struct pmu_even= t *pe, } m->metric_expr =3D pe->metric_expr; m->metric_unit =3D pe->unit; - m->pctx->runtime =3D runtime; + m->pctx->sctx.runtime =3D runtime; m->has_constraint =3D metric_no_group || metricgroup__has_constraint(pe); m->metric_refs =3D NULL; m->evlist =3D NULL; @@ -1626,7 +1626,7 @@ static int parse_groups(struct evlist *perf_evlist, c= onst char *str, } expr->metric_unit =3D m->metric_unit; expr->metric_events =3D metric_events; - expr->runtime =3D m->pctx->runtime; + expr->runtime =3D m->pctx->sctx.runtime; list_add(&expr->nd, &me->head); } =20 diff --git a/tools/perf/util/stat-shadow.c b/tools/perf/util/stat-shadow.c index 788ce5e46470..815af948abb9 100644 --- a/tools/perf/util/stat-shadow.c +++ b/tools/perf/util/stat-shadow.c @@ -911,7 +911,7 @@ static void generic_metric(struct perf_stat_config *con= fig, if (!pctx) return; =20 - pctx->runtime =3D runtime; + pctx->sctx.runtime =3D runtime; i =3D prepare_metric(metric_events, metric_refs, pctx, cpu_map_idx, st); if (i < 0) { expr__ctx_free(pctx); --=20 2.37.2.672.g94769d06f0-goog From nobody Tue Apr 7 00:42:40 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id BFECEECAAD3 for ; Wed, 31 Aug 2022 17:50:35 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231624AbiHaRue (ORCPT ); Wed, 31 Aug 2022 13:50:34 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:36266 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231766AbiHaRuI (ORCPT ); Wed, 31 Aug 2022 13:50:08 -0400 Received: from mail-yb1-xb4a.google.com (mail-yb1-xb4a.google.com [IPv6:2607:f8b0:4864:20::b4a]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 74B9C13F6D for ; Wed, 31 Aug 2022 10:50:06 -0700 (PDT) Received: by mail-yb1-xb4a.google.com with SMTP id y81-20020a253254000000b0069339437485so2636433yby.5 for ; Wed, 31 Aug 2022 10:50:06 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20210112; h=cc:to:from:subject:references:mime-version:message-id:in-reply-to :date:from:to:cc; bh=UUVPQFoHB4SWNXVjnYdqps9D8vjoKXb+eUEK4kYsPDY=; b=JrYRHr4aq2pvt/jT3CJxChuXVG1yWjglVjUr4IcK2lA1iP2BWrEYb6kfEFOQ0X8hK0 HjhkT6DdkBGkBE19qTOtOksK23eRhES60mmOI7bECIRPADVAZxE0N3RzVZjoXDfhslJa gX18RBo/FahJpDTaMAOR5fkJhXuUyBbxRw/rEdceSQ61OoLbG3sBJ79retLkBJmdl7vi eD1gYFizJUzbNaMhdqugTp/JxS0yf0ploA6kQm6obpEEA6nqYL1ObpVofVpvIAzRVBjK IM9iX7CLinOXzuh9n2hAC70G2CVuog1NXqY8JTFGuyZA8s6bdLEnLzOyGXDc4yfMd/lv VirA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=cc:to:from:subject:references:mime-version:message-id:in-reply-to :date:x-gm-message-state:from:to:cc; bh=UUVPQFoHB4SWNXVjnYdqps9D8vjoKXb+eUEK4kYsPDY=; b=8GkN9/lYhiHioPBkEO/qCDw/LaoB+6QuZQI/RP9vms0CoxuCgjtCwNrfU4rgJ9atgn 9GEf7ti8uczPxX2jqDH1IEmeVLi+ZVEotYgT93PmRCpvndR9mHb2cj8Zq4CEKJ2RZqaw rf3/5HarT4brxRMdICCRSHJmF0L5zodDzZ6L7INwm7mw2GNhCr0r1zRzSN/9eno6eOWP XBd3CCgnrvQODGm5ZQT8d2Q/6SepkJm+jJt8e3KIoGfHJ3g65cz9pftR8yKO8082a6Gn qr8Ykt9r4zjUf4fz4DZwLFn79FNehu5WYk8H5VZtZa2tLlVUYaqpFE1hAA2TnEwRmN1x IIfQ== X-Gm-Message-State: ACgBeo0+01y/tYfXwrBphrOfXpuluWHjBQXTO9lxZt/wvLHGiBID5WN7 7TyziDbqw4uMEXzqfXscZEos7pchRgsI X-Google-Smtp-Source: AA6agR44v0jFvcrWOLFGTfGpkKrtvGQ22d0LOEWZXg2fcGQnCUyWj0LegXOpa743x+92Mbi0zFwQNowItNng X-Received: from irogers.svl.corp.google.com ([2620:15c:2d4:203:c8e4:a3e5:9d09:d3d4]) (user=irogers job=sendgmr) by 2002:a81:6d16:0:b0:340:bbed:a2a9 with SMTP id i22-20020a816d16000000b00340bbeda2a9mr17159002ywc.367.1661968205425; Wed, 31 Aug 2022 10:50:05 -0700 (PDT) Date: Wed, 31 Aug 2022 10:49:22 -0700 In-Reply-To: <20220831174926.579643-1-irogers@google.com> Message-Id: <20220831174926.579643-4-irogers@google.com> Mime-Version: 1.0 References: <20220831174926.579643-1-irogers@google.com> X-Mailer: git-send-email 2.37.2.672.g94769d06f0-goog Subject: [PATCH v2 3/7] perf smt: Compute SMT from topology From: Ian Rogers To: Peter Zijlstra , Ingo Molnar , Arnaldo Carvalho de Melo , Mark Rutland , Alexander Shishkin , Jiri Olsa , Namhyung Kim , Andi Kleen , Kan Liang , Thomas Richter , James Clark , Miaoqian Lin , John Garry , Zhengjun Xing , Florian Fischer , linux-perf-users@vger.kernel.org, linux-kernel@vger.kernel.org, perry.taylor@intel.com, caleb.biggers@intel.com, kshipra.bopardikar@intel.com, ahmad.yasin@intel.com Cc: Stephane Eranian , Ian Rogers Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" The topology records sibling threads. Rather than computing SMT using siblings in sysfs, reuse the values in topology. This only applies when the file smt/active isn't available. Signed-off-by: Ian Rogers --- tools/perf/tests/expr.c | 24 ++++++---- tools/perf/util/cputopo.c | 15 +++++++ tools/perf/util/cputopo.h | 2 + tools/perf/util/expr.c | 9 ++-- tools/perf/util/smt.c | 95 ++++----------------------------------- tools/perf/util/smt.h | 5 ++- 6 files changed, 49 insertions(+), 101 deletions(-) diff --git a/tools/perf/tests/expr.c b/tools/perf/tests/expr.c index 7ca5e37de560..db736ed49556 100644 --- a/tools/perf/tests/expr.c +++ b/tools/perf/tests/expr.c @@ -1,4 +1,5 @@ // SPDX-License-Identifier: GPL-2.0 +#include "util/cputopo.h" #include "util/debug.h" #include "util/expr.h" #include "util/header.h" @@ -154,15 +155,20 @@ static int test__expr(struct test_suite *t __maybe_un= used, int subtest __maybe_u (void **)&val_ptr)); =20 /* Only EVENT1 or EVENT2 need be measured depending on the value of smt_o= n. */ - expr__ctx_clear(ctx); - TEST_ASSERT_VAL("find ids", - expr__find_ids("EVENT1 if #smt_on else EVENT2", - NULL, ctx) =3D=3D 0); - TEST_ASSERT_VAL("find ids", hashmap__size(ctx->ids) =3D=3D 1); - TEST_ASSERT_VAL("find ids", hashmap__find(ctx->ids, - smt_on() ? "EVENT1" : "EVENT2", - (void **)&val_ptr)); - + { + struct cpu_topology *topology =3D cpu_topology__new(); + bool smton =3D smt_on(topology); + + cpu_topology__delete(topology); + expr__ctx_clear(ctx); + TEST_ASSERT_VAL("find ids", + expr__find_ids("EVENT1 if #smt_on else EVENT2", + NULL, ctx) =3D=3D 0); + TEST_ASSERT_VAL("find ids", hashmap__size(ctx->ids) =3D=3D 1); + TEST_ASSERT_VAL("find ids", hashmap__find(ctx->ids, + smton ? "EVENT1" : "EVENT2", + (void **)&val_ptr)); + } /* The expression is a constant 1.0 without needing to evaluate EVENT1. */ expr__ctx_clear(ctx); TEST_ASSERT_VAL("find ids", diff --git a/tools/perf/util/cputopo.c b/tools/perf/util/cputopo.c index d275d843c155..511002e52714 100644 --- a/tools/perf/util/cputopo.c +++ b/tools/perf/util/cputopo.c @@ -157,6 +157,21 @@ void cpu_topology__delete(struct cpu_topology *tp) free(tp); } =20 +bool cpu_topology__smt_on(const struct cpu_topology *topology) +{ + for (u32 i =3D 0; i < topology->core_cpus_lists; i++) { + const char *cpu_list =3D topology->core_cpus_list[i]; + + /* + * If there is a need to separate siblings in a core then SMT is + * enabled. + */ + if (strchr(cpu_list, ',') || strchr(cpu_list, '-')) + return true; + } + return false; +} + static bool has_die_topology(void) { char filename[MAXPATHLEN]; diff --git a/tools/perf/util/cputopo.h b/tools/perf/util/cputopo.h index 854e18f9041e..469db775a13c 100644 --- a/tools/perf/util/cputopo.h +++ b/tools/perf/util/cputopo.h @@ -58,6 +58,8 @@ struct hybrid_topology { =20 struct cpu_topology *cpu_topology__new(void); void cpu_topology__delete(struct cpu_topology *tp); +/* Determine from the core list whether SMT was enabled. */ +bool cpu_topology__smt_on(const struct cpu_topology *topology); =20 struct numa_topology *numa_topology__new(void); void numa_topology__delete(struct numa_topology *tp); diff --git a/tools/perf/util/expr.c b/tools/perf/util/expr.c index 00bde682e743..8aa7dafa18b3 100644 --- a/tools/perf/util/expr.c +++ b/tools/perf/util/expr.c @@ -412,11 +412,6 @@ double expr__get_literal(const char *literal) static struct cpu_topology *topology; double result =3D NAN; =20 - if (!strcasecmp("#smt_on", literal)) { - result =3D smt_on() > 0 ? 1.0 : 0.0; - goto out; - } - if (!strcmp("#num_cpus", literal)) { result =3D cpu__max_present_cpu().cpu; goto out; @@ -440,6 +435,10 @@ double expr__get_literal(const char *literal) goto out; } } + if (!strcasecmp("#smt_on", literal)) { + result =3D smt_on(topology) ? 1.0 : 0.0; + goto out; + } if (!strcmp("#num_packages", literal)) { result =3D topology->package_cpus_lists; goto out; diff --git a/tools/perf/util/smt.c b/tools/perf/util/smt.c index 8fed03283c85..ce90c4ee4138 100644 --- a/tools/perf/util/smt.c +++ b/tools/perf/util/smt.c @@ -1,100 +1,23 @@ // SPDX-License-Identifier: GPL-2.0-only -#include -#include -#include -#include +#include #include "api/fs/fs.h" +#include "cputopo.h" #include "smt.h" =20 -/** - * hweight_str - Returns the number of bits set in str. Stops at first non= -hex - * or ',' character. - */ -static int hweight_str(char *str) -{ - int result =3D 0; - - while (*str) { - switch (*str++) { - case '0': - case ',': - break; - case '1': - case '2': - case '4': - case '8': - result++; - break; - case '3': - case '5': - case '6': - case '9': - case 'a': - case 'A': - case 'c': - case 'C': - result +=3D 2; - break; - case '7': - case 'b': - case 'B': - case 'd': - case 'D': - case 'e': - case 'E': - result +=3D 3; - break; - case 'f': - case 'F': - result +=3D 4; - break; - default: - goto done; - } - } -done: - return result; -} - -int smt_on(void) +bool smt_on(const struct cpu_topology *topology) { static bool cached; - static int cached_result; - int cpu; - int ncpu; + static bool cached_result; + int fs_value; =20 if (cached) return cached_result; =20 - if (sysfs__read_int("devices/system/cpu/smt/active", &cached_result) >=3D= 0) { - cached =3D true; - return cached_result; - } - - cached_result =3D 0; - ncpu =3D sysconf(_SC_NPROCESSORS_CONF); - for (cpu =3D 0; cpu < ncpu; cpu++) { - unsigned long long siblings; - char *str; - size_t strlen; - char fn[256]; + if (sysfs__read_int("devices/system/cpu/smt/active", &fs_value) >=3D 0) + cached_result =3D (fs_value =3D=3D 1); + else + cached_result =3D cpu_topology__smt_on(topology); =20 - snprintf(fn, sizeof fn, - "devices/system/cpu/cpu%d/topology/thread_siblings", cpu); - if (sysfs__read_str(fn, &str, &strlen) < 0) { - snprintf(fn, sizeof fn, - "devices/system/cpu/cpu%d/topology/core_cpus", cpu); - if (sysfs__read_str(fn, &str, &strlen) < 0) - continue; - } - /* Entry is hex, but does not have 0x, so need custom parser */ - siblings =3D hweight_str(str); - free(str); - if (siblings > 1) { - cached_result =3D 1; - break; - } - } cached =3D true; return cached_result; } diff --git a/tools/perf/util/smt.h b/tools/perf/util/smt.h index a98d65808f6a..e26999c6b8d4 100644 --- a/tools/perf/util/smt.h +++ b/tools/perf/util/smt.h @@ -2,6 +2,9 @@ #ifndef __SMT_H #define __SMT_H 1 =20 -int smt_on(void); +struct cpu_topology; + +/* Returns true if SMT (aka hyperthreading) is enabled. */ +bool smt_on(const struct cpu_topology *topology); =20 #endif /* __SMT_H */ --=20 2.37.2.672.g94769d06f0-goog From nobody Tue Apr 7 00:42:40 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 76A40ECAAD1 for ; Wed, 31 Aug 2022 17:50:49 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232012AbiHaRur (ORCPT ); Wed, 31 Aug 2022 13:50:47 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:38620 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231966AbiHaRuR (ORCPT ); Wed, 31 Aug 2022 13:50:17 -0400 Received: from mail-yb1-xb4a.google.com (mail-yb1-xb4a.google.com [IPv6:2607:f8b0:4864:20::b4a]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id DEA781AF11 for ; Wed, 31 Aug 2022 10:50:14 -0700 (PDT) Received: by mail-yb1-xb4a.google.com with SMTP id x27-20020a25ac9b000000b0069140cfbbd9so2655271ybi.8 for ; Wed, 31 Aug 2022 10:50:14 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20210112; h=cc:to:from:subject:references:mime-version:message-id:in-reply-to :date:from:to:cc; bh=DV+gDUOPXsEDpKSEUMrteZ0JJtXsJvhmDLffo2hWpR8=; b=HBb+XvmRItArfa2t5gRHf8PcZ1GxONOZ475mZIhqV15S9MNKFUVIiybXVFMVncm9hy SamFWQCwqiU70VJ2JltGjOim0xPwkz80VlPOKbJAxiQ1WVYrNm6SXSGOJ4XQ6vHDEd/R po8Y0+m643ma3R85P6d41Ax67a11/2yjBmJuaVO/M6knVwv5motiuEctD+MzCmjkaDPO d1g+2EVSAsBC1KQ09LRFYCZ1K28n15tqvhg1nQbN2w+C5uyHSeG59ajSer2ytjROK8NY OyZ3oRgpsAyEZApj2PM4+z6L2nmCk1h3WxB1ApSxzcHd1AcV4p5bNnWSkV/V8eM9mqFW iC1g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=cc:to:from:subject:references:mime-version:message-id:in-reply-to :date:x-gm-message-state:from:to:cc; bh=DV+gDUOPXsEDpKSEUMrteZ0JJtXsJvhmDLffo2hWpR8=; b=iNr1PHI3axaXrRSNrPJq+nnph2B2pbL55rcDa1tvNJR0BdIIWxhlq9r6VaR57xYDzC mzljcpZ8c7zJyZsnlspAme57qCmDfXSou6z0xJm7iqipEFyP27ETKzDIxsKtvjA2svTt MTeV0YQFVXmt/PMqHSXd3amsyKznHPBkAr067OvGSEF39byC/DS/syPUcB8T9IA6b1YU F8y389+0KVCxGEBeKqSOVTJf9QFrRI1lXmqQPsW+O9fZpknisifVMxs/82qKdax8KBmu U0RxyBN4YP/OGbOUT9ZghEtow9FGontk1b6zN/S13N8fDZV8yTq3z05qwCYQtrUTT2ED 9I5A== X-Gm-Message-State: ACgBeo1CpUsIQAyDPCUBcWdTPKiOAhI54cy8/5AwzbtQV5LxyXDSmo74 pLCr/G+/EbSIVgV3xLI5fx2VcUxhowpI X-Google-Smtp-Source: AA6agR7KHG0Q/Eku109go1TslC6JmYdAv6tQ1sws4sdXYpB85CQ5uLYs8ghrj+5NvhzsJTTbeRyiDeP2FiMq X-Received: from irogers.svl.corp.google.com ([2620:15c:2d4:203:c8e4:a3e5:9d09:d3d4]) (user=irogers job=sendgmr) by 2002:a25:cf8b:0:b0:695:79fa:14c2 with SMTP id f133-20020a25cf8b000000b0069579fa14c2mr16824533ybg.636.1661968213868; Wed, 31 Aug 2022 10:50:13 -0700 (PDT) Date: Wed, 31 Aug 2022 10:49:23 -0700 In-Reply-To: <20220831174926.579643-1-irogers@google.com> Message-Id: <20220831174926.579643-5-irogers@google.com> Mime-Version: 1.0 References: <20220831174926.579643-1-irogers@google.com> X-Mailer: git-send-email 2.37.2.672.g94769d06f0-goog Subject: [PATCH v2 4/7] perf topology: Add core_wide From: Ian Rogers To: Peter Zijlstra , Ingo Molnar , Arnaldo Carvalho de Melo , Mark Rutland , Alexander Shishkin , Jiri Olsa , Namhyung Kim , Andi Kleen , Kan Liang , Thomas Richter , James Clark , Miaoqian Lin , John Garry , Zhengjun Xing , Florian Fischer , linux-perf-users@vger.kernel.org, linux-kernel@vger.kernel.org, perry.taylor@intel.com, caleb.biggers@intel.com, kshipra.bopardikar@intel.com, ahmad.yasin@intel.com Cc: Stephane Eranian , Ian Rogers Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" It is possible to optimize metrics when all SMT threads (CPUs) on a core are measuring events in system wide mode. For example, TMA metrics defines CORE_CLKS for Sandybrdige as: if SMT is disabled: CPU_CLK_UNHALTED.THREAD if SMT is enabled and recording on all SMT threads: CPU_CLK_UNHALTED.THREAD_ANY / 2 if SMT is enabled and not recording on all SMT threads: (CPU_CLK_UNHALTED.THREAD/2)* (1+CPU_CLK_UNHALTED.ONE_THREAD_ACTIVE/CPU_CLK_UNHALTED.REF_XCLK ) That is two more events are necessary when not gathering counts on all SMT threads. To distinguish all SMT threads on a core vs system wide (all CPUs) call the new property core wide. Add a core wide test that determines the property from user requested CPUs, the topology and system wide. System wide is required as other processes running on a SMT thread will change the counts. Signed-off-by: Ian Rogers --- tools/perf/util/cputopo.c | 46 +++++++++++++++++++++++++++++++++++++++ tools/perf/util/cputopo.h | 3 +++ tools/perf/util/smt.c | 14 ++++++++++++ tools/perf/util/smt.h | 7 ++++++ 4 files changed, 70 insertions(+) diff --git a/tools/perf/util/cputopo.c b/tools/perf/util/cputopo.c index 511002e52714..1a3ff6449158 100644 --- a/tools/perf/util/cputopo.c +++ b/tools/perf/util/cputopo.c @@ -172,6 +172,52 @@ bool cpu_topology__smt_on(const struct cpu_topology *t= opology) return false; } =20 +bool cpu_topology__core_wide(const struct cpu_topology *topology, + const char *user_requested_cpu_list) +{ + struct perf_cpu_map *user_requested_cpus; + + /* + * If user_requested_cpu_list is empty then all CPUs are recorded and so + * core_wide is true. + */ + if (!user_requested_cpu_list) + return true; + + user_requested_cpus =3D perf_cpu_map__new(user_requested_cpu_list); + /* Check that every user requested CPU is the complete set of SMT threads= on a core. */ + for (u32 i =3D 0; i < topology->core_cpus_lists; i++) { + const char *core_cpu_list =3D topology->core_cpus_list[i]; + struct perf_cpu_map *core_cpus =3D perf_cpu_map__new(core_cpu_list); + struct perf_cpu cpu; + int idx; + bool has_first, first =3D true; + + perf_cpu_map__for_each_cpu(cpu, idx, core_cpus) { + if (first) { + has_first =3D perf_cpu_map__has(user_requested_cpus, cpu); + first =3D false; + } else { + /* + * If the first core CPU is user requested then + * all subsequent CPUs in the core must be user + * requested too. If the first CPU isn't user + * requested then none of the others must be + * too. + */ + if (perf_cpu_map__has(user_requested_cpus, cpu) !=3D has_first) { + perf_cpu_map__put(core_cpus); + perf_cpu_map__put(user_requested_cpus); + return false; + } + } + } + perf_cpu_map__put(core_cpus); + } + perf_cpu_map__put(user_requested_cpus); + return true; +} + static bool has_die_topology(void) { char filename[MAXPATHLEN]; diff --git a/tools/perf/util/cputopo.h b/tools/perf/util/cputopo.h index 469db775a13c..969e5920a00e 100644 --- a/tools/perf/util/cputopo.h +++ b/tools/perf/util/cputopo.h @@ -60,6 +60,9 @@ struct cpu_topology *cpu_topology__new(void); void cpu_topology__delete(struct cpu_topology *tp); /* Determine from the core list whether SMT was enabled. */ bool cpu_topology__smt_on(const struct cpu_topology *topology); +/* Are the sets of SMT siblings all enabled or all disabled in user_reques= ted_cpus. */ +bool cpu_topology__core_wide(const struct cpu_topology *topology, + const char *user_requested_cpu_list); =20 struct numa_topology *numa_topology__new(void); void numa_topology__delete(struct numa_topology *tp); diff --git a/tools/perf/util/smt.c b/tools/perf/util/smt.c index ce90c4ee4138..994e9e418227 100644 --- a/tools/perf/util/smt.c +++ b/tools/perf/util/smt.c @@ -21,3 +21,17 @@ bool smt_on(const struct cpu_topology *topology) cached =3D true; return cached_result; } + +bool core_wide(bool system_wide, const char *user_requested_cpu_list, + const struct cpu_topology *topology) +{ + /* If not everything running on a core is being recorded then we can't us= e core_wide. */ + if (!system_wide) + return false; + + /* Cheap case that SMT is disabled and therefore we're inherently core_wi= de. */ + if (!smt_on(topology)) + return true; + + return cpu_topology__core_wide(topology, user_requested_cpu_list); +} diff --git a/tools/perf/util/smt.h b/tools/perf/util/smt.h index e26999c6b8d4..ae9095f2c38c 100644 --- a/tools/perf/util/smt.h +++ b/tools/perf/util/smt.h @@ -7,4 +7,11 @@ struct cpu_topology; /* Returns true if SMT (aka hyperthreading) is enabled. */ bool smt_on(const struct cpu_topology *topology); =20 +/* + * Returns true when system wide and all SMT threads for a core are in the + * user_requested_cpus map. + */ +bool core_wide(bool system_wide, const char *user_requested_cpu_list, + const struct cpu_topology *topology); + #endif /* __SMT_H */ --=20 2.37.2.672.g94769d06f0-goog From nobody Tue Apr 7 00:42:40 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id ED42FECAAD1 for ; Wed, 31 Aug 2022 17:50:54 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231743AbiHaRux (ORCPT ); Wed, 31 Aug 2022 13:50:53 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:36736 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232030AbiHaRuX (ORCPT ); Wed, 31 Aug 2022 13:50:23 -0400 Received: from mail-yw1-x1149.google.com (mail-yw1-x1149.google.com [IPv6:2607:f8b0:4864:20::1149]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 2EF0127CF7 for ; Wed, 31 Aug 2022 10:50:21 -0700 (PDT) Received: by mail-yw1-x1149.google.com with SMTP id 00721157ae682-33f8988daecso200851377b3.12 for ; Wed, 31 Aug 2022 10:50:21 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20210112; h=cc:to:from:subject:references:mime-version:message-id:in-reply-to :date:from:to:cc; bh=O7x06VUny1WCJ5jSjqCJ7MNg10Zy7tcLBLmPAud8Uz8=; b=bBL/aY/COX7dr13JZAVO91/L9R2cA2sjMumCJH6SupSkJP/jUSXfqvu5Gr6Sv3xXkP V5XVzEHUUlO1jybAxfUnBpSchByqH6igaEA2vPn746d0MautUJVZZt+Dlx2viM773IKS kve7eukSwj9QuAvvHKohMH7uo6y3fWD26gFufwuV1HWUhbeYfX6De6ttrAg04j2T/11A 3HINdOWhlt8ae4E8jNLQHRy0uR48PNvh2esmDt1o7vE84aQc0CaeBdJRU58MknFguEeW XWbuIxRdKuaMb4nnUx8VdrWtcJpEq8OOOSqzLrwNgcqsFMOIFmMxN615tJVFQAAgD94j neZg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=cc:to:from:subject:references:mime-version:message-id:in-reply-to :date:x-gm-message-state:from:to:cc; bh=O7x06VUny1WCJ5jSjqCJ7MNg10Zy7tcLBLmPAud8Uz8=; b=OuOZQDVDjrIiBp3u3HFMuA47ZEb+pACjxnvcz8SzlTmYDIOdHKTcXOyLZyLXIWc7lJ A9GVTR7u9/KxdbCD4r4SOgc/0lzv5hyQzBlxgK5yQh6o2YLgXxBRmDIqjAPiVsVzmQvo TpahKMbvLwmr9HD4xh8R+8jkBnR87HpAahbH+PTLbSovU0xyQEEH5TLJI7Y8kF2sCSs+ LuuWroVl+rO4czq2nMmYFtOSny2nno+omXpqwf6I+aL1fFq3LTerl3xlVJDtWEG2mjWg xGDOD+p6n2EXDBxJmTRZBfyapqGkZW16SyW1ZbazJFZ93xhhe5TXfCvKTFAElea1iuqd nO3Q== X-Gm-Message-State: ACgBeo01zUJrFHcXg+Vk9/DxgE/yF8Mg76RvT5WPn+rzMmJ/OtXW8uoJ mcPhxixoxhF9H1yf9WTFys4PLKvlikSG X-Google-Smtp-Source: AA6agR7Reb+rz8coWZuWhV5Z/psyQzkhB6djteex6853ySMfywnmw+Q5549aUw1c+GhCV/Ct/1EyjWPpsYSe X-Received: from irogers.svl.corp.google.com ([2620:15c:2d4:203:c8e4:a3e5:9d09:d3d4]) (user=irogers job=sendgmr) by 2002:a81:ad06:0:b0:33f:77cf:523f with SMTP id l6-20020a81ad06000000b0033f77cf523fmr19164824ywh.173.1661968221618; Wed, 31 Aug 2022 10:50:21 -0700 (PDT) Date: Wed, 31 Aug 2022 10:49:24 -0700 In-Reply-To: <20220831174926.579643-1-irogers@google.com> Message-Id: <20220831174926.579643-6-irogers@google.com> Mime-Version: 1.0 References: <20220831174926.579643-1-irogers@google.com> X-Mailer: git-send-email 2.37.2.672.g94769d06f0-goog Subject: [PATCH v2 5/7] perf stat: Delay metric parsing From: Ian Rogers To: Peter Zijlstra , Ingo Molnar , Arnaldo Carvalho de Melo , Mark Rutland , Alexander Shishkin , Jiri Olsa , Namhyung Kim , Andi Kleen , Kan Liang , Thomas Richter , James Clark , Miaoqian Lin , John Garry , Zhengjun Xing , Florian Fischer , linux-perf-users@vger.kernel.org, linux-kernel@vger.kernel.org, perry.taylor@intel.com, caleb.biggers@intel.com, kshipra.bopardikar@intel.com, ahmad.yasin@intel.com Cc: Stephane Eranian , Ian Rogers Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Having metric parsing as part of argument processing causes issues as flags like metric-no-group may be specified later. It also denies the opportunity to optimize the events on SMT systems where fewer events may be possible if we know the target is system-wide. Move metric parsing to after command line option parsing. Because of how stat runs this moves the parsing after record/report which fail to work with metrics currently anyway. Signed-off-by: Ian Rogers --- tools/perf/builtin-stat.c | 52 +++++++++++++++++++++++++---------- tools/perf/util/metricgroup.c | 3 +- tools/perf/util/metricgroup.h | 2 +- 3 files changed, 39 insertions(+), 18 deletions(-) diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c index 54cd29d07ca8..a59c23f4ffd2 100644 --- a/tools/perf/builtin-stat.c +++ b/tools/perf/builtin-stat.c @@ -191,6 +191,7 @@ static bool append_file; static bool interval_count; static const char *output_name; static int output_fd; +static char *metrics; =20 struct perf_stat { bool record; @@ -1148,14 +1149,23 @@ static int enable_metric_only(const struct option *= opt __maybe_unused, return 0; } =20 -static int parse_metric_groups(const struct option *opt, +static int append_metric_groups(const struct option *opt __maybe_unused, const char *str, int unset __maybe_unused) { - return metricgroup__parse_groups(opt, str, - stat_config.metric_no_group, - stat_config.metric_no_merge, - &stat_config.metric_events); + if (metrics) { + char *tmp; + + if (asprintf(&tmp, "%s,%s", metrics, str) < 0) + return -ENOMEM; + free(metrics); + metrics =3D tmp; + } else { + metrics =3D strdup(str); + if (!metrics) + return -ENOMEM; + } + return 0; } =20 static int parse_control_option(const struct option *opt, @@ -1299,7 +1309,7 @@ static struct option stat_options[] =3D { "measure SMI cost"), OPT_CALLBACK('M', "metrics", &evsel_list, "metric/metric group list", "monitor specified metrics or metric groups (separated by ,)", - parse_metric_groups), + append_metric_groups), OPT_BOOLEAN_FLAG(0, "all-kernel", &stat_config.all_kernel, "Configure all used events to run in kernel space.", PARSE_OPT_EXCLUSIVE), @@ -1792,11 +1802,9 @@ static int add_default_attributes(void) * on an architecture test for such a metric name. */ if (metricgroup__has_metric("transaction")) { - struct option opt =3D { .value =3D &evsel_list }; - - return metricgroup__parse_groups(&opt, "transaction", + return metricgroup__parse_groups(evsel_list, "transaction", stat_config.metric_no_group, - stat_config.metric_no_merge, + stat_config.metric_no_merge, &stat_config.metric_events); } =20 @@ -2182,6 +2190,8 @@ static int __cmd_report(int argc, const char **argv) input_name =3D "perf.data"; } =20 + perf_stat__init_shadow_stats(); + perf_stat.data.path =3D input_name; perf_stat.data.mode =3D PERF_DATA_MODE_READ; =20 @@ -2261,8 +2271,6 @@ int cmd_stat(int argc, const char **argv) argc =3D parse_options_subcommand(argc, argv, stat_options, stat_subcomma= nds, (const char **) stat_usage, PARSE_OPT_STOP_AT_NON_OPTION); - perf_stat__collect_metric_expr(evsel_list); - perf_stat__init_shadow_stats(); =20 if (stat_config.csv_sep) { stat_config.csv_output =3D true; @@ -2429,6 +2437,23 @@ int cmd_stat(int argc, const char **argv) target.system_wide =3D true; } =20 + if ((stat_config.aggr_mode =3D=3D AGGR_THREAD) && (target.system_wide)) + target.per_thread =3D true; + + /* + * Metric parsing needs to be delayed as metrics may optimize events + * knowing the target is system-wide. + */ + if (metrics) { + metricgroup__parse_groups(evsel_list, metrics, + stat_config.metric_no_group, + stat_config.metric_no_merge, + &stat_config.metric_events); + zfree(&metrics); + } + perf_stat__collect_metric_expr(evsel_list); + perf_stat__init_shadow_stats(); + if (add_default_attributes()) goto out; =20 @@ -2448,9 +2473,6 @@ int cmd_stat(int argc, const char **argv) } } =20 - if ((stat_config.aggr_mode =3D=3D AGGR_THREAD) && (target.system_wide)) - target.per_thread =3D true; - if (evlist__fix_hybrid_cpus(evsel_list, target.cpu_list)) { pr_err("failed to use cpu list %s\n", target.cpu_list); goto out; diff --git a/tools/perf/util/metricgroup.c b/tools/perf/util/metricgroup.c index b144c3e35264..9151346a16ab 100644 --- a/tools/perf/util/metricgroup.c +++ b/tools/perf/util/metricgroup.c @@ -1646,13 +1646,12 @@ static int parse_groups(struct evlist *perf_evlist,= const char *str, return ret; } =20 -int metricgroup__parse_groups(const struct option *opt, +int metricgroup__parse_groups(struct evlist *perf_evlist, const char *str, bool metric_no_group, bool metric_no_merge, struct rblist *metric_events) { - struct evlist *perf_evlist =3D *(struct evlist **)opt->value; const struct pmu_events_table *table =3D pmu_events_table__find(); =20 if (!table) diff --git a/tools/perf/util/metricgroup.h b/tools/perf/util/metricgroup.h index 016b3b1a289a..af9ceadaec0f 100644 --- a/tools/perf/util/metricgroup.h +++ b/tools/perf/util/metricgroup.h @@ -64,7 +64,7 @@ struct metric_expr { struct metric_event *metricgroup__lookup(struct rblist *metric_events, struct evsel *evsel, bool create); -int metricgroup__parse_groups(const struct option *opt, +int metricgroup__parse_groups(struct evlist *perf_evlist, const char *str, bool metric_no_group, bool metric_no_merge, --=20 2.37.2.672.g94769d06f0-goog From nobody Tue Apr 7 00:42:40 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 5D45CECAAD3 for ; Wed, 31 Aug 2022 17:51:07 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231828AbiHaRvF (ORCPT ); Wed, 31 Aug 2022 13:51:05 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:40110 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232082AbiHaRue (ORCPT ); Wed, 31 Aug 2022 13:50:34 -0400 Received: from mail-yw1-x114a.google.com (mail-yw1-x114a.google.com [IPv6:2607:f8b0:4864:20::114a]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id CDFA042AE0 for ; Wed, 31 Aug 2022 10:50:30 -0700 (PDT) Received: by mail-yw1-x114a.google.com with SMTP id 00721157ae682-33dc888dc62so209003307b3.4 for ; Wed, 31 Aug 2022 10:50:30 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20210112; h=cc:to:from:subject:references:mime-version:message-id:in-reply-to :date:from:to:cc; bh=nu2rpCUw/Ti/dsFRgrjgAXHPygpYA9VZ4stH1ncWyqY=; b=qP+XCu4ase/9c9Vdh6qQW21bl4ykqRfFAznLlnf/fQWuzXLX9aV150UDl6sUPsAcq1 wteT6EZPHtrwfOIH/81KNHa0PXocRhAeiOqhZMHnbaJlO2+VWAv1HKtkYxSd8vJogWBu IKmMIXuBy2bEBmh8tJ1qUsXbtO7CR4p++aLpMcQQrUFjKVlSOKYM0KRlPXv435Nd3nSH ouq93GobZzFXg4UQ60n3g/pAGa+iktRA7F9O/XZjxIcLCZUZ6+KE2OQB/JjekU5wPfHL XdzpLpxWfL7rDyIjmoA2Kb1R7vogltvao4zmR/gZubhYX0kU65WXAXBpNxH6puThLtWe GSbA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=cc:to:from:subject:references:mime-version:message-id:in-reply-to :date:x-gm-message-state:from:to:cc; bh=nu2rpCUw/Ti/dsFRgrjgAXHPygpYA9VZ4stH1ncWyqY=; b=InKDT1YoNU4RI2w0mxBLKShssMzOdZF2Z/3o/Y6x6c7KW+jLmsZ+WPaPgCWNHHtOp3 3cq+QSlgI7UqfMJybabizlSCsqmSrX+V6LzYqgnogtSIfpJr6tdYsxqA0IuuyypwkduY t9dLBUQYN7X5NG7wKuWYEwtqLjowGi7CyK/fJEaE809UOiUusx7Mmj0DztnZbJ6gqvnG uEM4BjZAiGBiRJ+rNQkMEr2Wu4vx0HStJbNpz2hVNdrrrUm6gNrxsuYZJ4slkQtLObqU y6lBiqZxOL1LtWODOZs+kGLCzt0503+kSa3GXR7RQCcyi/v9F87u6FCMbNBxWqDP3zul PccQ== X-Gm-Message-State: ACgBeo0XFPGJz+9RnxjnQPG91tIByY7oUWJZsQi35XGu5GvY8vV65x+R puB3MYH9lNXKTlGhEs1eaUzTlTdINP68 X-Google-Smtp-Source: AA6agR58twdysv4D5X/IvKiN2yva0WHToCUgkPBVmhXgHoTyK3G2VSAImupbZ8N8Wod3WNC2fPMlR4uHImZK X-Received: from irogers.svl.corp.google.com ([2620:15c:2d4:203:c8e4:a3e5:9d09:d3d4]) (user=irogers job=sendgmr) by 2002:a5b:a4e:0:b0:695:81dc:5343 with SMTP id z14-20020a5b0a4e000000b0069581dc5343mr16265290ybq.402.1661968229793; Wed, 31 Aug 2022 10:50:29 -0700 (PDT) Date: Wed, 31 Aug 2022 10:49:25 -0700 In-Reply-To: <20220831174926.579643-1-irogers@google.com> Message-Id: <20220831174926.579643-7-irogers@google.com> Mime-Version: 1.0 References: <20220831174926.579643-1-irogers@google.com> X-Mailer: git-send-email 2.37.2.672.g94769d06f0-goog Subject: [PATCH v2 6/7] perf metrics: Wire up core_wide From: Ian Rogers To: Peter Zijlstra , Ingo Molnar , Arnaldo Carvalho de Melo , Mark Rutland , Alexander Shishkin , Jiri Olsa , Namhyung Kim , Andi Kleen , Kan Liang , Thomas Richter , James Clark , Miaoqian Lin , John Garry , Zhengjun Xing , Florian Fischer , linux-perf-users@vger.kernel.org, linux-kernel@vger.kernel.org, perry.taylor@intel.com, caleb.biggers@intel.com, kshipra.bopardikar@intel.com, ahmad.yasin@intel.com Cc: Stephane Eranian , Ian Rogers Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Pass state necessary for core_wide into the expression parser. Add system_wide and user_requested_cpu_list to perf_stat_config to make it available at display time. evlist isn't used as the evlist__create_maps, that computes user_requested_cpus, needs the list of events which is generated by the metric. Signed-off-by: Ian Rogers --- tools/perf/builtin-stat.c | 14 ++++ tools/perf/util/expr.c | 13 +++- tools/perf/util/expr.h | 4 +- tools/perf/util/expr.l | 6 +- tools/perf/util/metricgroup.c | 125 ++++++++++++++++++++++++---------- tools/perf/util/metricgroup.h | 2 + tools/perf/util/stat-shadow.c | 11 ++- tools/perf/util/stat.h | 2 + 8 files changed, 134 insertions(+), 43 deletions(-) diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c index a59c23f4ffd2..35185ee1243e 100644 --- a/tools/perf/builtin-stat.c +++ b/tools/perf/builtin-stat.c @@ -1805,6 +1805,8 @@ static int add_default_attributes(void) return metricgroup__parse_groups(evsel_list, "transaction", stat_config.metric_no_group, stat_config.metric_no_merge, + stat_config.user_requested_cpu_list, + stat_config.system_wide, &stat_config.metric_events); } =20 @@ -2440,6 +2442,15 @@ int cmd_stat(int argc, const char **argv) if ((stat_config.aggr_mode =3D=3D AGGR_THREAD) && (target.system_wide)) target.per_thread =3D true; =20 + stat_config.system_wide =3D target.system_wide; + if (target.cpu_list) { + stat_config.user_requested_cpu_list =3D strdup(target.cpu_list); + if (!stat_config.user_requested_cpu_list) { + status =3D -ENOMEM; + goto out; + } + } + /* * Metric parsing needs to be delayed as metrics may optimize events * knowing the target is system-wide. @@ -2448,6 +2459,8 @@ int cmd_stat(int argc, const char **argv) metricgroup__parse_groups(evsel_list, metrics, stat_config.metric_no_group, stat_config.metric_no_merge, + stat_config.user_requested_cpu_list, + stat_config.system_wide, &stat_config.metric_events); zfree(&metrics); } @@ -2638,6 +2651,7 @@ int cmd_stat(int argc, const char **argv) iostat_release(evsel_list); =20 zfree(&stat_config.walltime_run); + zfree(&stat_config.user_requested_cpu_list); =20 if (smi_cost && smi_reset) sysfs__write_int(FREEZE_ON_SMI_PATH, 0); diff --git a/tools/perf/util/expr.c b/tools/perf/util/expr.c index 8aa7dafa18b3..c6827900f8d3 100644 --- a/tools/perf/util/expr.c +++ b/tools/perf/util/expr.c @@ -310,7 +310,9 @@ struct expr_parse_ctx *expr__ctx_new(void) free(ctx); return NULL; } + ctx->sctx.user_requested_cpu_list =3D NULL; ctx->sctx.runtime =3D 0; + ctx->sctx.system_wide =3D false; =20 return ctx; } @@ -332,6 +334,10 @@ void expr__ctx_free(struct expr_parse_ctx *ctx) struct hashmap_entry *cur; size_t bkt; =20 + if (!ctx) + return; + + free(ctx->sctx.user_requested_cpu_list); hashmap__for_each_entry(ctx->ids, cur, bkt) { free((char *)cur->key); free(cur->value); @@ -407,7 +413,7 @@ double arch_get_tsc_freq(void) } #endif =20 -double expr__get_literal(const char *literal) +double expr__get_literal(const char *literal, const struct expr_scanner_ct= x *ctx) { static struct cpu_topology *topology; double result =3D NAN; @@ -439,6 +445,11 @@ double expr__get_literal(const char *literal) result =3D smt_on(topology) ? 1.0 : 0.0; goto out; } + if (!strcmp("#core_wide", literal)) { + result =3D core_wide(ctx->system_wide, ctx->user_requested_cpu_list, top= ology) + ? 1.0 : 0.0; + goto out; + } if (!strcmp("#num_packages", literal)) { result =3D topology->package_cpus_lists; goto out; diff --git a/tools/perf/util/expr.h b/tools/perf/util/expr.h index 07af3d438eb2..d6c1668dc1a0 100644 --- a/tools/perf/util/expr.h +++ b/tools/perf/util/expr.h @@ -11,7 +11,9 @@ struct metric_ref; =20 struct expr_scanner_ctx { + char *user_requested_cpu_list; int runtime; + bool system_wide; }; =20 struct expr_parse_ctx { @@ -55,6 +57,6 @@ int expr__find_ids(const char *expr, const char *one, =20 double expr_id_data__value(const struct expr_id_data *data); double expr_id_data__source_count(const struct expr_id_data *data); -double expr__get_literal(const char *literal); +double expr__get_literal(const char *literal, const struct expr_scanner_ct= x *ctx); =20 #endif diff --git a/tools/perf/util/expr.l b/tools/perf/util/expr.l index 4dc8edbfd9ce..0168a9637330 100644 --- a/tools/perf/util/expr.l +++ b/tools/perf/util/expr.l @@ -79,11 +79,11 @@ static int str(yyscan_t scanner, int token, int runtime) return token; } =20 -static int literal(yyscan_t scanner) +static int literal(yyscan_t scanner, const struct expr_scanner_ctx *sctx) { YYSTYPE *yylval =3D expr_get_lval(scanner); =20 - yylval->num =3D expr__get_literal(expr_get_text(scanner)); + yylval->num =3D expr__get_literal(expr_get_text(scanner), sctx); if (isnan(yylval->num)) return EXPR_ERROR; =20 @@ -108,7 +108,7 @@ min { return MIN; } if { return IF; } else { return ELSE; } source_count { return SOURCE_COUNT; } -{literal} { return literal(yyscanner); } +{literal} { return literal(yyscanner, sctx); } {number} { return value(yyscanner); } {symbol} { return str(yyscanner, ID, sctx->runtime); } "|" { return '|'; } diff --git a/tools/perf/util/metricgroup.c b/tools/perf/util/metricgroup.c index 9151346a16ab..b18da1a62a55 100644 --- a/tools/perf/util/metricgroup.c +++ b/tools/perf/util/metricgroup.c @@ -22,6 +22,7 @@ #include #include #include +#include #include #include #include "util.h" @@ -189,10 +190,24 @@ static bool metricgroup__has_constraint(const struct = pmu_event *pe) return false; } =20 +static void metric__free(struct metric *m) +{ + if (!m) + return; + + free(m->metric_refs); + expr__ctx_free(m->pctx); + free((char *)m->modifier); + evlist__delete(m->evlist); + free(m); +} + static struct metric *metric__new(const struct pmu_event *pe, const char *modifier, bool metric_no_group, - int runtime) + int runtime, + const char *user_requested_cpu_list, + bool system_wide) { struct metric *m; =20 @@ -201,35 +216,34 @@ static struct metric *metric__new(const struct pmu_ev= ent *pe, return NULL; =20 m->pctx =3D expr__ctx_new(); - if (!m->pctx) { - free(m); - return NULL; - } + if (!m->pctx) + goto out_err; =20 m->metric_name =3D pe->metric_name; - m->modifier =3D modifier ? strdup(modifier) : NULL; - if (modifier && !m->modifier) { - expr__ctx_free(m->pctx); - free(m); - return NULL; + m->modifier =3D NULL; + if (modifier) { + m->modifier =3D strdup(modifier); + if (!m->modifier) + goto out_err; } m->metric_expr =3D pe->metric_expr; m->metric_unit =3D pe->unit; + m->pctx->sctx.user_requested_cpu_list =3D NULL; + if (user_requested_cpu_list) { + m->pctx->sctx.user_requested_cpu_list =3D strdup(user_requested_cpu_list= ); + if (!m->pctx->sctx.user_requested_cpu_list) + goto out_err; + } m->pctx->sctx.runtime =3D runtime; + m->pctx->sctx.system_wide =3D system_wide; m->has_constraint =3D metric_no_group || metricgroup__has_constraint(pe); m->metric_refs =3D NULL; m->evlist =3D NULL; =20 return m; -} - -static void metric__free(struct metric *m) -{ - free(m->metric_refs); - expr__ctx_free(m->pctx); - free((char *)m->modifier); - evlist__delete(m->evlist); - free(m); +out_err: + metric__free(m); + return NULL; } =20 static bool contains_metric_id(struct evsel **metric_events, int num_event= s, @@ -874,6 +888,8 @@ struct metricgroup_add_iter_data { int *ret; bool *has_match; bool metric_no_group; + const char *user_requested_cpu_list; + bool system_wide; struct metric *root_metric; const struct visited_metric *visited; const struct pmu_events_table *table; @@ -887,6 +903,8 @@ static int add_metric(struct list_head *metric_list, const struct pmu_event *pe, const char *modifier, bool metric_no_group, + const char *user_requested_cpu_list, + bool system_wide, struct metric *root_metric, const struct visited_metric *visited, const struct pmu_events_table *table); @@ -899,6 +917,8 @@ static int add_metric(struct list_head *metric_list, * @metric_no_group: Should events written to events be grouped "{}" or * global. Grouping is the default but due to multiplexi= ng the * user may override. + * @user_requested_cpu_list: Command line specified CPUs to record on. + * @system_wide: Are events for all processes recorded. * @root_metric: Metrics may reference other metrics to form a tree. In th= is * case the root_metric holds all the IDs and a list of refe= renced * metrics. When adding a root this argument is NULL. @@ -910,6 +930,8 @@ static int add_metric(struct list_head *metric_list, static int resolve_metric(struct list_head *metric_list, const char *modifier, bool metric_no_group, + const char *user_requested_cpu_list, + bool system_wide, struct metric *root_metric, const struct visited_metric *visited, const struct pmu_events_table *table) @@ -956,7 +978,8 @@ static int resolve_metric(struct list_head *metric_list, */ for (i =3D 0; i < pending_cnt; i++) { ret =3D add_metric(metric_list, &pending[i].pe, modifier, metric_no_grou= p, - root_metric, visited, table); + user_requested_cpu_list, system_wide, root_metric, visited, + table); if (ret) break; } @@ -974,6 +997,8 @@ static int resolve_metric(struct list_head *metric_list, * global. Grouping is the default but due to multiplexi= ng the * user may override. * @runtime: A special argument for the parser only known at runtime. + * @user_requested_cpu_list: Command line specified CPUs to record on. + * @system_wide: Are events for all processes recorded. * @root_metric: Metrics may reference other metrics to form a tree. In th= is * case the root_metric holds all the IDs and a list of refe= renced * metrics. When adding a root this argument is NULL. @@ -987,6 +1012,8 @@ static int __add_metric(struct list_head *metric_list, const char *modifier, bool metric_no_group, int runtime, + const char *user_requested_cpu_list, + bool system_wide, struct metric *root_metric, const struct visited_metric *visited, const struct pmu_events_table *table) @@ -1011,7 +1038,8 @@ static int __add_metric(struct list_head *metric_list, * This metric is the root of a tree and may reference other * metrics that are added recursively. */ - root_metric =3D metric__new(pe, modifier, metric_no_group, runtime); + root_metric =3D metric__new(pe, modifier, metric_no_group, runtime, + user_requested_cpu_list, system_wide); if (!root_metric) return -ENOMEM; =20 @@ -1060,8 +1088,9 @@ static int __add_metric(struct list_head *metric_list, ret =3D -EINVAL; } else { /* Resolve referenced metrics. */ - ret =3D resolve_metric(metric_list, modifier, metric_no_group, root_metr= ic, - &visited_node, table); + ret =3D resolve_metric(metric_list, modifier, metric_no_group, + user_requested_cpu_list, system_wide, + root_metric, &visited_node, table); } =20 if (ret) { @@ -1109,6 +1138,8 @@ static int add_metric(struct list_head *metric_list, const struct pmu_event *pe, const char *modifier, bool metric_no_group, + const char *user_requested_cpu_list, + bool system_wide, struct metric *root_metric, const struct visited_metric *visited, const struct pmu_events_table *table) @@ -1119,7 +1150,8 @@ static int add_metric(struct list_head *metric_list, =20 if (!strstr(pe->metric_expr, "?")) { ret =3D __add_metric(metric_list, pe, modifier, metric_no_group, 0, - root_metric, visited, table); + user_requested_cpu_list, system_wide, root_metric, + visited, table); } else { int j, count; =20 @@ -1132,7 +1164,8 @@ static int add_metric(struct list_head *metric_list, =20 for (j =3D 0; j < count && !ret; j++) ret =3D __add_metric(metric_list, pe, modifier, metric_no_group, j, - root_metric, visited, table); + user_requested_cpu_list, system_wide, + root_metric, visited, table); } =20 return ret; @@ -1149,6 +1182,7 @@ static int metricgroup__add_metric_sys_event_iter(con= st struct pmu_event *pe, return 0; =20 ret =3D add_metric(d->metric_list, pe, d->modifier, d->metric_no_group, + d->user_requested_cpu_list, d->system_wide, d->root_metric, d->visited, d->table); if (ret) goto out; @@ -1191,7 +1225,9 @@ struct metricgroup__add_metric_data { struct list_head *list; const char *metric_name; const char *modifier; + const char *user_requested_cpu_list; bool metric_no_group; + bool system_wide; bool has_match; }; =20 @@ -1208,8 +1244,8 @@ static int metricgroup__add_metric_callback(const str= uct pmu_event *pe, =20 data->has_match =3D true; ret =3D add_metric(data->list, pe, data->modifier, data->metric_no_group, - /*root_metric=3D*/NULL, - /*visited_metrics=3D*/NULL, table); + data->user_requested_cpu_list, data->system_wide, + /*root_metric=3D*/NULL, /*visited_metrics=3D*/NULL, table); } return ret; } @@ -1223,12 +1259,16 @@ static int metricgroup__add_metric_callback(const s= truct pmu_event *pe, * @metric_no_group: Should events written to events be grouped "{}" or * global. Grouping is the default but due to multiplexi= ng the * user may override. + * @user_requested_cpu_list: Command line specified CPUs to record on. + * @system_wide: Are events for all processes recorded. * @metric_list: The list that the metric or metric group are added to. * @table: The table that is searched for metrics, most commonly the table= for the * architecture perf is running upon. */ static int metricgroup__add_metric(const char *metric_name, const char *mo= difier, bool metric_no_group, + const char *user_requested_cpu_list, + bool system_wide, struct list_head *metric_list, const struct pmu_events_table *table) { @@ -1242,6 +1282,8 @@ static int metricgroup__add_metric(const char *metric= _name, const char *modifier .metric_name =3D metric_name, .modifier =3D modifier, .metric_no_group =3D metric_no_group, + .user_requested_cpu_list =3D user_requested_cpu_list, + .system_wide =3D system_wide, .has_match =3D false, }; /* @@ -1263,6 +1305,8 @@ static int metricgroup__add_metric(const char *metric= _name, const char *modifier .metric_name =3D metric_name, .modifier =3D modifier, .metric_no_group =3D metric_no_group, + .user_requested_cpu_list =3D user_requested_cpu_list, + .system_wide =3D system_wide, .has_match =3D &has_match, .ret =3D &ret, .table =3D table, @@ -1293,12 +1337,15 @@ static int metricgroup__add_metric(const char *metr= ic_name, const char *modifier * @metric_no_group: Should events written to events be grouped "{}" or * global. Grouping is the default but due to multiplexi= ng the * user may override. + * @user_requested_cpu_list: Command line specified CPUs to record on. + * @system_wide: Are events for all processes recorded. * @metric_list: The list that metrics are added to. * @table: The table that is searched for metrics, most commonly the table= for the * architecture perf is running upon. */ static int metricgroup__add_metric_list(const char *list, bool metric_no_g= roup, - struct list_head *metric_list, + const char *user_requested_cpu_list, + bool system_wide, struct list_head *metric_list, const struct pmu_events_table *table) { char *list_itr, *list_copy, *metric_name, *modifier; @@ -1315,8 +1362,8 @@ static int metricgroup__add_metric_list(const char *l= ist, bool metric_no_group, *modifier++ =3D '\0'; =20 ret =3D metricgroup__add_metric(metric_name, modifier, - metric_no_group, metric_list, - table); + metric_no_group, user_requested_cpu_list, + system_wide, metric_list, table); if (ret =3D=3D -EINVAL) pr_err("Cannot find metric or group `%s'\n", metric_name); =20 @@ -1505,6 +1552,8 @@ static int parse_ids(bool metric_no_merge, struct per= f_pmu *fake_pmu, static int parse_groups(struct evlist *perf_evlist, const char *str, bool metric_no_group, bool metric_no_merge, + const char *user_requested_cpu_list, + bool system_wide, struct perf_pmu *fake_pmu, struct rblist *metric_events_list, const struct pmu_events_table *table) @@ -1518,7 +1567,8 @@ static int parse_groups(struct evlist *perf_evlist, c= onst char *str, if (metric_events_list->nr_entries =3D=3D 0) metricgroup__rblist_init(metric_events_list); ret =3D metricgroup__add_metric_list(str, metric_no_group, - &metric_list, table); + user_requested_cpu_list, + system_wide, &metric_list, table); if (ret) goto out; =20 @@ -1650,6 +1700,8 @@ int metricgroup__parse_groups(struct evlist *perf_evl= ist, const char *str, bool metric_no_group, bool metric_no_merge, + const char *user_requested_cpu_list, + bool system_wide, struct rblist *metric_events) { const struct pmu_events_table *table =3D pmu_events_table__find(); @@ -1657,8 +1709,9 @@ int metricgroup__parse_groups(struct evlist *perf_evl= ist, if (!table) return -EINVAL; =20 - return parse_groups(perf_evlist, str, metric_no_group, - metric_no_merge, NULL, metric_events, table); + return parse_groups(perf_evlist, str, metric_no_group, metric_no_merge, + user_requested_cpu_list, system_wide, + /*fake_pmu=3D*/NULL, metric_events, table); } =20 int metricgroup__parse_groups_test(struct evlist *evlist, @@ -1668,8 +1721,10 @@ int metricgroup__parse_groups_test(struct evlist *ev= list, bool metric_no_merge, struct rblist *metric_events) { - return parse_groups(evlist, str, metric_no_group, - metric_no_merge, &perf_pmu__fake, metric_events, table); + return parse_groups(evlist, str, metric_no_group, metric_no_merge, + /*user_requested_cpu_list=3D*/NULL, + /*system_wide=3D*/false, + &perf_pmu__fake, metric_events, table); } =20 static int metricgroup__has_metric_callback(const struct pmu_event *pe, diff --git a/tools/perf/util/metricgroup.h b/tools/perf/util/metricgroup.h index af9ceadaec0f..732d3a0d3334 100644 --- a/tools/perf/util/metricgroup.h +++ b/tools/perf/util/metricgroup.h @@ -68,6 +68,8 @@ int metricgroup__parse_groups(struct evlist *perf_evlist, const char *str, bool metric_no_group, bool metric_no_merge, + const char *user_requested_cpu_list, + bool system_wide, struct rblist *metric_events); int metricgroup__parse_groups_test(struct evlist *evlist, const struct pmu_events_table *table, diff --git a/tools/perf/util/stat-shadow.c b/tools/perf/util/stat-shadow.c index 815af948abb9..9e1eddeff21b 100644 --- a/tools/perf/util/stat-shadow.c +++ b/tools/perf/util/stat-shadow.c @@ -911,7 +911,10 @@ static void generic_metric(struct perf_stat_config *co= nfig, if (!pctx) return; =20 + if (config->user_requested_cpu_list) + pctx->sctx.user_requested_cpu_list =3D strdup(config->user_requested_cpu= _list); pctx->sctx.runtime =3D runtime; + pctx->sctx.system_wide =3D config->system_wide; i =3D prepare_metric(metric_events, metric_refs, pctx, cpu_map_idx, st); if (i < 0) { expr__ctx_free(pctx); @@ -1304,7 +1307,8 @@ void perf_stat__print_shadow_stats(struct perf_stat_c= onfig *config, core_bound * 100.); } else if (evsel->metric_expr) { generic_metric(config, evsel->metric_expr, evsel->metric_events, NULL, - evsel->name, evsel->metric_name, NULL, 1, cpu_map_idx, out, st); + evsel->name, evsel->metric_name, NULL, 1, + cpu_map_idx, out, st); } else if (runtime_stat_n(st, STAT_NSECS, cpu_map_idx, &rsd) !=3D 0) { char unit =3D ' '; char unit_buf[10] =3D "/sec"; @@ -1329,8 +1333,9 @@ void perf_stat__print_shadow_stats(struct perf_stat_c= onfig *config, if (num++ > 0) out->new_line(config, ctxp); generic_metric(config, mexp->metric_expr, mexp->metric_events, - mexp->metric_refs, evsel->name, mexp->metric_name, - mexp->metric_unit, mexp->runtime, cpu_map_idx, out, st); + mexp->metric_refs, evsel->name, mexp->metric_name, + mexp->metric_unit, mexp->runtime, + cpu_map_idx, out, st); } } if (num =3D=3D 0) diff --git a/tools/perf/util/stat.h b/tools/perf/util/stat.h index 668250022f8c..72713b344b79 100644 --- a/tools/perf/util/stat.h +++ b/tools/perf/util/stat.h @@ -141,6 +141,8 @@ struct perf_stat_config { bool stop_read_counter; bool quiet; bool iostat_run; + char *user_requested_cpu_list; + bool system_wide; FILE *output; unsigned int interval; unsigned int timeout; --=20 2.37.2.672.g94769d06f0-goog From nobody Tue Apr 7 00:42:40 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 39B18ECAAD1 for ; Wed, 31 Aug 2022 17:51:12 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231968AbiHaRvJ (ORCPT ); Wed, 31 Aug 2022 13:51:09 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:40676 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230521AbiHaRuk (ORCPT ); Wed, 31 Aug 2022 13:50:40 -0400 Received: from mail-pf1-x449.google.com (mail-pf1-x449.google.com [IPv6:2607:f8b0:4864:20::449]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 419894E875 for ; Wed, 31 Aug 2022 10:50:38 -0700 (PDT) Received: by mail-pf1-x449.google.com with SMTP id c135-20020a624e8d000000b0053617082770so6389173pfb.8 for ; Wed, 31 Aug 2022 10:50:38 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20210112; h=cc:to:from:subject:references:mime-version:message-id:in-reply-to :date:from:to:cc; bh=hBJ0yO7Shj4BOGRLl4iwSJQIsSnhkgtQ+YJ6SsJa66s=; b=EUrxwLovkSwJ6TvkQKG8Klcqc7EZ7RVJLb38iq+CvHU+quWu0R9+NfCH0WIn1OAuXI QRKBYrqgM7LtbjAKMeZvYVvDy6Z6J6NC+DUpXkVeSXi/+lMIa2o9SH549yRhIUWuXV3X MQfiqxR7PSeFNuz10ifbhUSKXJpdvxhWjfp3aogg9kq/EpMa3irR/9l5vRDDzaOxP/P/ XbnWvNZFTSMgt6WFc6SOQEh9AgmxisyNF/AzIVHfCiWJ6ffdNyeD90ZZKfM+g2rbzPI1 FLkiDoJ1A9ru709SSUUm8CibNMQQ2NgSy1eIedsr/e8TMWU+ZUGpRH2HfNfD6NpuFj40 uJKg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=cc:to:from:subject:references:mime-version:message-id:in-reply-to :date:x-gm-message-state:from:to:cc; bh=hBJ0yO7Shj4BOGRLl4iwSJQIsSnhkgtQ+YJ6SsJa66s=; b=rxB4iz4s1ZyxrdnNOiFYTcmruiiLp6/zw0Wk4VE2t3u1Enq5SeTCic+JoptzltgvDp fLciamrwf0ZoprjarKc8NrxkVlCWEfSGEUPIqOb10OHKyrN1tVHaRK9WoPKnHx6B2PLW woMWWXgLnOEf4wiEO64vNqLwFC/6Q1I5xKBaIeruMV4CpcN296QkaSXSbottA80WO+2r yAT/PZGwvha43z7uZewuZvDPvHH29yT7mfuF3sHyBHVT30Sg8PfZlWplJjBxplEkokBu 1g0EyE/AjEFa9OeqfOVza7OMG7NGoFUJHO9AZgyV6Lcro2RPppTGvAoXNxhQZUTnVscr erFg== X-Gm-Message-State: ACgBeo1vkkL8av1Pe3wWA/ncswKukmf8/76EHofMOSY+YB0NcjP+kDtd uM2hAfuS5OIo4j2BHfkkC/QxK8+i2+7W X-Google-Smtp-Source: AA6agR6KUXTyj1DNwsbVD0rQVcRjyBpcT5UUV8Q3uxsgGqjxyGpUlPH3TVslv1iig/sms+GEgtrglNC5U5Tv X-Received: from irogers.svl.corp.google.com ([2620:15c:2d4:203:c8e4:a3e5:9d09:d3d4]) (user=irogers job=sendgmr) by 2002:a17:90a:e558:b0:1fb:c4b7:1a24 with SMTP id ei24-20020a17090ae55800b001fbc4b71a24mr254671pjb.1.1661968237443; Wed, 31 Aug 2022 10:50:37 -0700 (PDT) Date: Wed, 31 Aug 2022 10:49:26 -0700 In-Reply-To: <20220831174926.579643-1-irogers@google.com> Message-Id: <20220831174926.579643-8-irogers@google.com> Mime-Version: 1.0 References: <20220831174926.579643-1-irogers@google.com> X-Mailer: git-send-email 2.37.2.672.g94769d06f0-goog Subject: [PATCH v2 7/7] perf test: Add basic core_wide expression test From: Ian Rogers To: Peter Zijlstra , Ingo Molnar , Arnaldo Carvalho de Melo , Mark Rutland , Alexander Shishkin , Jiri Olsa , Namhyung Kim , Andi Kleen , Kan Liang , Thomas Richter , James Clark , Miaoqian Lin , John Garry , Zhengjun Xing , Florian Fischer , linux-perf-users@vger.kernel.org, linux-kernel@vger.kernel.org, perry.taylor@intel.com, caleb.biggers@intel.com, kshipra.bopardikar@intel.com, ahmad.yasin@intel.com Cc: Stephane Eranian , Ian Rogers Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Add basic test for coverage, similar to #smt_on. Signed-off-by: Ian Rogers --- tools/perf/tests/expr.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/tools/perf/tests/expr.c b/tools/perf/tests/expr.c index db736ed49556..8bd719766814 100644 --- a/tools/perf/tests/expr.c +++ b/tools/perf/tests/expr.c @@ -158,6 +158,9 @@ static int test__expr(struct test_suite *t __maybe_unus= ed, int subtest __maybe_u { struct cpu_topology *topology =3D cpu_topology__new(); bool smton =3D smt_on(topology); + bool corewide =3D core_wide(/*system_wide=3D*/false, + /*user_requested_cpus=3D*/false, + topology); =20 cpu_topology__delete(topology); expr__ctx_clear(ctx); @@ -168,6 +171,16 @@ static int test__expr(struct test_suite *t __maybe_unu= sed, int subtest __maybe_u TEST_ASSERT_VAL("find ids", hashmap__find(ctx->ids, smton ? "EVENT1" : "EVENT2", (void **)&val_ptr)); + + expr__ctx_clear(ctx); + TEST_ASSERT_VAL("find ids", + expr__find_ids("EVENT1 if #core_wide else EVENT2", + NULL, ctx) =3D=3D 0); + TEST_ASSERT_VAL("find ids", hashmap__size(ctx->ids) =3D=3D 1); + TEST_ASSERT_VAL("find ids", hashmap__find(ctx->ids, + corewide ? "EVENT1" : "EVENT2", + (void **)&val_ptr)); + } /* The expression is a constant 1.0 without needing to evaluate EVENT1. */ expr__ctx_clear(ctx); --=20 2.37.2.672.g94769d06f0-goog