From nobody Mon Apr 27 13:19:06 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 2608CC43334 for ; Mon, 13 Jun 2022 08:47:55 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S240236AbiFMIrx (ORCPT ); Mon, 13 Jun 2022 04:47:53 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:36546 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S239962AbiFMIrt (ORCPT ); Mon, 13 Jun 2022 04:47:49 -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 134A4EE26 for ; Mon, 13 Jun 2022 01:47:47 -0700 (PDT) Received: by mail-yb1-xb4a.google.com with SMTP id q199-20020a25d9d0000000b00664af83bee9so2584721ybg.9 for ; Mon, 13 Jun 2022 01:47:47 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20210112; h=date:in-reply-to:message-id:mime-version:references:subject:from:to :cc; bh=+TZFSQCPo2Ju+GzmGovbnxDwp60NNa1c3IUVi64MUwE=; b=m2G85oiUaIgx7yZjFlW1pWdakJHDEGzddu/k0tEqME2rscMJFMI+H8NuW+pc2shBsH BdMeTQCNahkzQAHbQu0AvzTcS9EMNjYttG0/RVkKMRqW55ssuntWP4JwNXrDGgiV1cvF bxzbInrxhDHCdhv2miJwkekNpQh5of+v9yCy1kfT1sunfMTjEKrb2yOL6/ow+9gQvq9D nZSfWiYAeeL1l2iwCzw1nEulcFpTO3k/ilDtBfmo3Zrv/0Qa+u7iLcZExFfJ+P3Ib73g sDf0qnD83q+5lYDQ/WdIVjOX/ZDkElteX7LHSuahBInWSLVLPT2kfBzM438uOK5s5bNO fGng== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:date:in-reply-to:message-id:mime-version :references:subject:from:to:cc; bh=+TZFSQCPo2Ju+GzmGovbnxDwp60NNa1c3IUVi64MUwE=; b=Y97+SlQtLmzgNamvm2XUQyrPQxfo0XyLL/0Ady/O0NFEEGmOixW1C/boWB2qv+snxy 06NTEt+FWj2bRnzO8RPiew/Cw6gz5lX3Azg6Nx0f2r1LoHPm0Yq1MWKzmNFsaWCJt2kv 5H4HDchbLXGIq4BH/zhH1Xoac2WcLzF0/UhbVphWtP9LhIBY+7o8xmIhq7ouxsGfmJWI VsdJpRNXcGl7HEphTbxOckOjZoZNQpmbavhI94QpTUOqM34yARuhd25MIRbKcm3xnJGy HVWraoMzTElN46mCHA9E2AxR0ooiAiOtLwTreB1EEPmDVuAGMmJ2tZF6ivcRaijhpPPN fUFA== X-Gm-Message-State: AOAM533EzlLNr3xJSO/TIq0YF0Eb+ShdGu42XH476s3994KikjGPEWFd 17SNvw7n9wp8jxvK3jJlwwKMPnZ86S2V X-Google-Smtp-Source: ABdhPJwSSqRhSBjwM5FE3KlSNKSPK1Bh8G9cCaBSGRqGDpSFwbXBYZ+bGM5GWkMHxTj+CRVGZ7NhoZp56Ncl X-Received: from irogers.svl.corp.google.com ([2620:15c:2cd:202:1256:a8b4:594a:9164]) (user=irogers job=sendgmr) by 2002:a25:e68b:0:b0:65c:7aa5:f901 with SMTP id d133-20020a25e68b000000b0065c7aa5f901mr57398720ybh.147.1655110066202; Mon, 13 Jun 2022 01:47:46 -0700 (PDT) Date: Mon, 13 Jun 2022 01:47:34 -0700 In-Reply-To: <20220613084739.1159111-1-irogers@google.com> Message-Id: <20220613084739.1159111-2-irogers@google.com> Mime-Version: 1.0 References: <20220613084739.1159111-1-irogers@google.com> X-Mailer: git-send-email 2.36.1.476.g0c4daa206d-goog Subject: [PATCH 1/6] perf cpumap: Const map for max From: Ian Rogers To: Peter Zijlstra , Ingo Molnar , Arnaldo Carvalho de Melo , Mark Rutland , Alexander Shishkin , Jiri Olsa , Namhyung Kim , James Clark , Kees Cook , "Gustavo A. R. Silva" , Adrian Hunter , Riccardo Mancini , German Gomez , Colin Ian King , Song Liu , Dave Marchevsky , Athira Rajeev , Alexey Bayduraev , Leo Yan , linux-perf-users@vger.kernel.org, linux-kernel@vger.kernel.org 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" Allows max to be used with const perf_cpu_maps. Signed-off-by: Ian Rogers --- tools/lib/perf/cpumap.c | 2 +- tools/lib/perf/include/perf/cpumap.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/lib/perf/cpumap.c b/tools/lib/perf/cpumap.c index 384d5e076ee4..6cd0be7c1bb4 100644 --- a/tools/lib/perf/cpumap.c +++ b/tools/lib/perf/cpumap.c @@ -309,7 +309,7 @@ bool perf_cpu_map__has(const struct perf_cpu_map *cpus,= struct perf_cpu cpu) return perf_cpu_map__idx(cpus, cpu) !=3D -1; } =20 -struct perf_cpu perf_cpu_map__max(struct perf_cpu_map *map) +struct perf_cpu perf_cpu_map__max(const struct perf_cpu_map *map) { struct perf_cpu result =3D { .cpu =3D -1 diff --git a/tools/lib/perf/include/perf/cpumap.h b/tools/lib/perf/include/= perf/cpumap.h index 24de795b09bb..03aceb72a783 100644 --- a/tools/lib/perf/include/perf/cpumap.h +++ b/tools/lib/perf/include/perf/cpumap.h @@ -23,7 +23,7 @@ LIBPERF_API void perf_cpu_map__put(struct perf_cpu_map *m= ap); LIBPERF_API struct perf_cpu perf_cpu_map__cpu(const struct perf_cpu_map *c= pus, int idx); LIBPERF_API int perf_cpu_map__nr(const struct perf_cpu_map *cpus); LIBPERF_API bool perf_cpu_map__empty(const struct perf_cpu_map *map); -LIBPERF_API struct perf_cpu perf_cpu_map__max(struct perf_cpu_map *map); +LIBPERF_API struct perf_cpu perf_cpu_map__max(const struct perf_cpu_map *m= ap); LIBPERF_API bool perf_cpu_map__has(const struct perf_cpu_map *map, struct = perf_cpu cpu); =20 #define perf_cpu_map__for_each_cpu(cpu, idx, cpus) \ --=20 2.36.1.476.g0c4daa206d-goog From nobody Mon Apr 27 13:19:06 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 7EFFFC433EF for ; Mon, 13 Jun 2022 08:47:57 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S240285AbiFMIr4 (ORCPT ); Mon, 13 Jun 2022 04:47:56 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:36622 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S240229AbiFMIru (ORCPT ); Mon, 13 Jun 2022 04:47:50 -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 0E98F10FEF for ; Mon, 13 Jun 2022 01:47:49 -0700 (PDT) Received: by mail-yw1-x1149.google.com with SMTP id 00721157ae682-310061f47faso48013257b3.9 for ; Mon, 13 Jun 2022 01:47:49 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20210112; h=date:in-reply-to:message-id:mime-version:references:subject:from:to :cc; bh=CO3D4hTzGOfHEmW5/B6ajWEyTv2kPQTJ9KX6c7xDLfk=; b=pdLuOfjOGGpuAIIIUbBK2mNwR2jn9y06YPNqwblzFH9UyjNTaqkPmiN+5spxAEX9dS ljOkNDxuYuvP8qqIWgc7pHoxSeJ8vgaZHiSXlfOk1/A0WoL1nA1oT7oBwr0lImoxTf9a ik8hnEac+5G0rgC3fT107Ri//zEKe44geIb7sy/KQoTcVODUvEJ2rSMV4fGLCSX2lQms A8QK/LiG3xfEMTKWoQWTOiLZT7PHAtoTf+XH0IYZtDWmNJuPllhhAzsrs8y9DuhwNJXb V37Cb++sGxT1mBxvQ/MQ5LSifNgWQDMBAHcLwovryRm8wWHU4vq9JPXgeCSCtpGHUxWq jfZg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:date:in-reply-to:message-id:mime-version :references:subject:from:to:cc; bh=CO3D4hTzGOfHEmW5/B6ajWEyTv2kPQTJ9KX6c7xDLfk=; b=E+kkopYmMtK3Vs0yN5OPGgimhqrdkiF0Nkwui74n1DvzzMT/+1ACxoU0HZ9D1cbOdE /5R9RcNxt+qNAPC2a9p/j3dzGkToefImtmHBH8IX5BYGd7UnnQmxRh5bpJeESC5m4YsP 5cY1p5QKlX5APY31utToj+zG46CGWTnY5bk3WSajoDCFFYxtDPDwnxsxh+Y/N+gh9cWp n/JGgrlgxuQpQOFtY1BZJjWuPiaJ425roScYhy0nVAbq3qfdy0a6XhoXTFaoP6N5YLZP O46OercZBcugxuhpL/a+ZViaC4nM9yjkRJH+qDfNTXmJljbkH9wBihoAduF1g12CCAV8 m9uQ== X-Gm-Message-State: AOAM533sbRYox8/NrrAxsJtghSYM31OxCj2FHLGxzgA72vBAqZT7j9nP bFmKY7DY7mw2ERImlpfCs0enzls0vrjv X-Google-Smtp-Source: ABdhPJyiA7WDdiT+o/vB3cnKSfyG8RTVsZXdEnIl6QLd+ZSHqTvHapOTeZj8NYrr6a2AwWTov4D0SeY4mQLB X-Received: from irogers.svl.corp.google.com ([2620:15c:2cd:202:1256:a8b4:594a:9164]) (user=irogers job=sendgmr) by 2002:a05:6902:191:b0:660:26f4:3318 with SMTP id t17-20020a056902019100b0066026f43318mr60821815ybh.5.1655110068179; Mon, 13 Jun 2022 01:47:48 -0700 (PDT) Date: Mon, 13 Jun 2022 01:47:35 -0700 In-Reply-To: <20220613084739.1159111-1-irogers@google.com> Message-Id: <20220613084739.1159111-3-irogers@google.com> Mime-Version: 1.0 References: <20220613084739.1159111-1-irogers@google.com> X-Mailer: git-send-email 2.36.1.476.g0c4daa206d-goog Subject: [PATCH 2/6] perf cpumap: Synthetic events and const/static From: Ian Rogers To: Peter Zijlstra , Ingo Molnar , Arnaldo Carvalho de Melo , Mark Rutland , Alexander Shishkin , Jiri Olsa , Namhyung Kim , James Clark , Kees Cook , "Gustavo A. R. Silva" , Adrian Hunter , Riccardo Mancini , German Gomez , Colin Ian King , Song Liu , Dave Marchevsky , Athira Rajeev , Alexey Bayduraev , Leo Yan , linux-perf-users@vger.kernel.org, linux-kernel@vger.kernel.org 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" Make the cpumap arguments const to make it clearer they are in rather than out arguments. Make two functions static and remove external declarations. Signed-off-by: Ian Rogers --- tools/perf/util/event.h | 4 ---- tools/perf/util/synthetic-events.c | 20 +++++++++++--------- tools/perf/util/synthetic-events.h | 2 +- 3 files changed, 12 insertions(+), 14 deletions(-) diff --git a/tools/perf/util/event.h b/tools/perf/util/event.h index cdd72e05fd28..2a69e639f6b3 100644 --- a/tools/perf/util/event.h +++ b/tools/perf/util/event.h @@ -461,10 +461,6 @@ size_t perf_event__fprintf(union perf_event *event, st= ruct machine *machine, FIL int kallsyms__get_function_start(const char *kallsyms_filename, const char *symbol_name, u64 *addr); =20 -void *cpu_map_data__alloc(struct perf_cpu_map *map, size_t *size, u16 *typ= e, int *max); -void cpu_map_data__synthesize(struct perf_record_cpu_map_data *data, stru= ct perf_cpu_map *map, - u16 type, int max); - void event_attr_init(struct perf_event_attr *attr); =20 int perf_event_paranoid(void); diff --git a/tools/perf/util/synthetic-events.c b/tools/perf/util/synthetic= -events.c index 27acdc5e5723..b8a42a096502 100644 --- a/tools/perf/util/synthetic-events.c +++ b/tools/perf/util/synthetic-events.c @@ -1184,7 +1184,7 @@ int perf_event__synthesize_thread_map2(struct perf_to= ol *tool, } =20 static void synthesize_cpus(struct cpu_map_entries *cpus, - struct perf_cpu_map *map) + const struct perf_cpu_map *map) { int i, map_nr =3D perf_cpu_map__nr(map); =20 @@ -1195,7 +1195,7 @@ static void synthesize_cpus(struct cpu_map_entries *c= pus, } =20 static void synthesize_mask(struct perf_record_record_cpu_map *mask, - struct perf_cpu_map *map, int max) + const struct perf_cpu_map *map, int max) { int i; =20 @@ -1206,12 +1206,12 @@ static void synthesize_mask(struct perf_record_reco= rd_cpu_map *mask, set_bit(perf_cpu_map__cpu(map, i).cpu, mask->mask); } =20 -static size_t cpus_size(struct perf_cpu_map *map) +static size_t cpus_size(const struct perf_cpu_map *map) { return sizeof(struct cpu_map_entries) + perf_cpu_map__nr(map) * sizeof(u1= 6); } =20 -static size_t mask_size(struct perf_cpu_map *map, int *max) +static size_t mask_size(const struct perf_cpu_map *map, int *max) { int i; =20 @@ -1228,7 +1228,8 @@ static size_t mask_size(struct perf_cpu_map *map, int= *max) return sizeof(struct perf_record_record_cpu_map) + BITS_TO_LONGS(*max) * = sizeof(long); } =20 -void *cpu_map_data__alloc(struct perf_cpu_map *map, size_t *size, u16 *typ= e, int *max) +static void *cpu_map_data__alloc(const struct perf_cpu_map *map, size_t *s= ize, + u16 *type, int *max) { size_t size_cpus, size_mask; bool is_dummy =3D perf_cpu_map__empty(map); @@ -1262,8 +1263,9 @@ void *cpu_map_data__alloc(struct perf_cpu_map *map, s= ize_t *size, u16 *type, int return zalloc(*size); } =20 -void cpu_map_data__synthesize(struct perf_record_cpu_map_data *data, struc= t perf_cpu_map *map, - u16 type, int max) +static void cpu_map_data__synthesize(struct perf_record_cpu_map_data *data, + const struct perf_cpu_map *map, + u16 type, int max) { data->type =3D type; =20 @@ -1278,7 +1280,7 @@ void cpu_map_data__synthesize(struct perf_record_cpu_= map_data *data, struct perf } } =20 -static struct perf_record_cpu_map *cpu_map_event__new(struct perf_cpu_map = *map) +static struct perf_record_cpu_map *cpu_map_event__new(const struct perf_cp= u_map *map) { size_t size =3D sizeof(struct perf_record_cpu_map); struct perf_record_cpu_map *event; @@ -1298,7 +1300,7 @@ static struct perf_record_cpu_map *cpu_map_event__new= (struct perf_cpu_map *map) } =20 int perf_event__synthesize_cpu_map(struct perf_tool *tool, - struct perf_cpu_map *map, + const struct perf_cpu_map *map, perf_event__handler_t process, struct machine *machine) { diff --git a/tools/perf/util/synthetic-events.h b/tools/perf/util/synthetic= -events.h index 78a0450db164..44839190234a 100644 --- a/tools/perf/util/synthetic-events.h +++ b/tools/perf/util/synthetic-events.h @@ -46,7 +46,7 @@ typedef int (*perf_event__handler_t)(struct perf_tool *to= ol, union perf_event *e int perf_event__synthesize_attrs(struct perf_tool *tool, struct evlist *ev= list, perf_event__handler_t process); int perf_event__synthesize_attr(struct perf_tool *tool, struct perf_event_= attr *attr, u32 ids, u64 *id, perf_event__handler_t process); int perf_event__synthesize_build_id(struct perf_tool *tool, struct dso *po= s, u16 misc, perf_event__handler_t process, struct machine *machine); -int perf_event__synthesize_cpu_map(struct perf_tool *tool, struct perf_cpu= _map *cpus, perf_event__handler_t process, struct machine *machine); +int perf_event__synthesize_cpu_map(struct perf_tool *tool, const struct pe= rf_cpu_map *cpus, perf_event__handler_t process, struct machine *machine); int perf_event__synthesize_event_update_cpus(struct perf_tool *tool, struc= t evsel *evsel, perf_event__handler_t process); int perf_event__synthesize_event_update_name(struct perf_tool *tool, struc= t evsel *evsel, perf_event__handler_t process); int perf_event__synthesize_event_update_scale(struct perf_tool *tool, stru= ct evsel *evsel, perf_event__handler_t process); --=20 2.36.1.476.g0c4daa206d-goog From nobody Mon Apr 27 13:19:06 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 02D29C433EF for ; Mon, 13 Jun 2022 08:48:00 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S240316AbiFMIr6 (ORCPT ); Mon, 13 Jun 2022 04:47:58 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:36620 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S240227AbiFMIrw (ORCPT ); Mon, 13 Jun 2022 04:47:52 -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 6204ABEA for ; Mon, 13 Jun 2022 01:47:51 -0700 (PDT) Received: by mail-yw1-x1149.google.com with SMTP id 00721157ae682-30047b94aa8so48070447b3.1 for ; Mon, 13 Jun 2022 01:47:51 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20210112; h=date:in-reply-to:message-id:mime-version:references:subject:from:to :cc; bh=jlLUXMLBK64yscSUpLZfKbiaF8vfOQAkVnrzfyvEsEQ=; b=RfB964hLBJrDKExStE8k0QOIu75yatipiO8Iiqq7WJbfSWN1bWRwpLOzyy3J+RICyP 83DUqBuw5HOJgOZLGp8bNTnWaylkOrlllBgHMgGYSlsntH/oR/xPlFiRK/nTx12twbHJ MMnezexBjAr9MRNILwqxWsu27tEEfC4Kt3BtfIhfkgq7TYQ5AB+9nUxPD4rLbrYtWHCr jT6XHl4AerQFmApFGOf3Z0OwFCHJz1KU2DPa1ZrW0z6QhMp247QLW9YP2SKqhF6dLCWw VBBSjubaUjeJc6J/uvreVhFOmGPI34GUExK/QWiTbnr6WFR+3Lf8SGPx9o9DODzW2W7U vvjQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:date:in-reply-to:message-id:mime-version :references:subject:from:to:cc; bh=jlLUXMLBK64yscSUpLZfKbiaF8vfOQAkVnrzfyvEsEQ=; b=eg/lOBO72PjY1PJ4T5jdAKwYitXhr1oBR3EH2BKvDEwVB/HxRRM8122qkZNSxFaZf7 ikc3R/AnWSrulq5/tmADBKAuIj9N6vM7zTN0UnLI11HAHsmAwn6sR8DNYDtewUXN2yRj iaNIpaBx2zyQd91o2MrymuRJWTR4RVm2vyqgXUumYGvq7x1WyJrnxGM3vHPnlcy+UDZA qSPkK7iinrfJihkZNjxo++WdU+LLkuTz0WsdjeiEYyKlBAcKIVNxS/OjJnudFFNFzp/G xprWUR+sWC4miugkBNS6TQg7+OzCs9gSvc/rPy5qIyJGgNs7YopQqQgbTHVtiMCWMkEA +XDg== X-Gm-Message-State: AOAM532/eoXCaVXMs9FnK+kF/G0J19z5XVoGkxsUh3PBHRsYysICsryh 90J9HDLm0tJQn3fpoct0odsnr4nmv1fz X-Google-Smtp-Source: ABdhPJxchkJW4bSVxtcOJJyVI2IbgadBLF6NhqZ5Z4PGrMlksMIAVMRRTAfO07jwisCbyuv4/r0Nt2YT12P9 X-Received: from irogers.svl.corp.google.com ([2620:15c:2cd:202:1256:a8b4:594a:9164]) (user=irogers job=sendgmr) by 2002:a05:6902:134f:b0:664:6767:b57a with SMTP id g15-20020a056902134f00b006646767b57amr16001891ybu.441.1655110070611; Mon, 13 Jun 2022 01:47:50 -0700 (PDT) Date: Mon, 13 Jun 2022 01:47:36 -0700 In-Reply-To: <20220613084739.1159111-1-irogers@google.com> Message-Id: <20220613084739.1159111-4-irogers@google.com> Mime-Version: 1.0 References: <20220613084739.1159111-1-irogers@google.com> X-Mailer: git-send-email 2.36.1.476.g0c4daa206d-goog Subject: [PATCH 3/6] perf cpumap: Compute mask size in constant time From: Ian Rogers To: Peter Zijlstra , Ingo Molnar , Arnaldo Carvalho de Melo , Mark Rutland , Alexander Shishkin , Jiri Olsa , Namhyung Kim , James Clark , Kees Cook , "Gustavo A. R. Silva" , Adrian Hunter , Riccardo Mancini , German Gomez , Colin Ian King , Song Liu , Dave Marchevsky , Athira Rajeev , Alexey Bayduraev , Leo Yan , linux-perf-users@vger.kernel.org, linux-kernel@vger.kernel.org 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" perf_cpu_map__max computes the cpumap's maximum value, no need to iterate over all values. Signed-off-by: Ian Rogers --- tools/perf/util/synthetic-events.c | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/tools/perf/util/synthetic-events.c b/tools/perf/util/synthetic= -events.c index b8a42a096502..0d87df20ec44 100644 --- a/tools/perf/util/synthetic-events.c +++ b/tools/perf/util/synthetic-events.c @@ -1213,18 +1213,7 @@ static size_t cpus_size(const struct perf_cpu_map *m= ap) =20 static size_t mask_size(const struct perf_cpu_map *map, int *max) { - int i; - - *max =3D 0; - - for (i =3D 0; i < perf_cpu_map__nr(map); i++) { - /* bit position of the cpu is + 1 */ - int bit =3D perf_cpu_map__cpu(map, i).cpu + 1; - - if (bit > *max) - *max =3D bit; - } - + *max =3D perf_cpu_map__max(map).cpu; return sizeof(struct perf_record_record_cpu_map) + BITS_TO_LONGS(*max) * = sizeof(long); } =20 --=20 2.36.1.476.g0c4daa206d-goog From nobody Mon Apr 27 13:19:06 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 A1772C43334 for ; Mon, 13 Jun 2022 08:48:05 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S240368AbiFMIsB (ORCPT ); Mon, 13 Jun 2022 04:48:01 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:37478 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S240304AbiFMIr5 (ORCPT ); Mon, 13 Jun 2022 04:47:57 -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 858C213F6A for ; Mon, 13 Jun 2022 01:47:53 -0700 (PDT) Received: by mail-yb1-xb4a.google.com with SMTP id k73-20020a25244c000000b0065ca88b381aso4522391ybk.2 for ; Mon, 13 Jun 2022 01:47:53 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20210112; h=date:in-reply-to:message-id:mime-version:references:subject:from:to :cc; bh=Mij7LDAjsaqpdDbRwp/XiyhZ7u53hLBGMhINXu+GQlg=; b=b9e6gZHa+cGs6JLKfEACrrjKIMpR/NIFqx++IB6sRTm+hw4bYIbMlRCkDjdTvSML4r DhxLwHLnIIweyckSHb9SEtpzh1GDU7Eo3m+et5RVp7wW+tXHK+vkWnlRnyuBE1KlHxne cRgZBlu+z2dRth7fsBZLAh3dpaAViMDd9vHLLXorahfR9353ad1LNCgkKhAu2purtw2C WkKrvvF9sxsYbLpLLURIIvbi9pig9cdbEvd1JDvyCWwV5cud8WlmCgkOJjvsCeNlMbuy xLIF2zqBh1mpDrHn7/lyEGWksuqoz7IK5XZ8Mn1QnTrZ3u6VwcMuc3L9Qf+cwu0AbLgi olWg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:date:in-reply-to:message-id:mime-version :references:subject:from:to:cc; bh=Mij7LDAjsaqpdDbRwp/XiyhZ7u53hLBGMhINXu+GQlg=; b=SwR+6VW37/2h7RYFXb/3jhx45axzKPEjRHD4oBuI3tvbCJaqfvd4PpGMejC0i8sr6r CpfC+Y2KEwrpFjTdZb5XvnJT7e11BU6lUb2DBLFsBCAa7bL2g1dXffgm18g9YiCtIHSD amfcWfhUMFSw5oJeSwpZNPva0YF/A0UUUPYq9IueTUJEHa6m9PomUzd6tzKcDpG2Oj1e 0/3BtkN8KQJ21UBN8ddnw04+f1e78tyXU5lHy9bwsK3CcQ2cHKf6tLDSpnQk1B37LWp1 ZV4MXFXyEO8mexLkqW9UHDu33S0fAlOkG6b7tt6BDd/q7YXU3zPhLgcPPD+v81OQYKjm cMtw== X-Gm-Message-State: AOAM533NTTUdXuz0R6V/IocTAxsXawbYwxrLnw1KWKJ0JdfXpYjiZobN Iqb7MEehg8NQSnfgJSQHnV3SbfYXJ0vt X-Google-Smtp-Source: ABdhPJxtUIyY5m1LD9lQZ/ISgU2BN+PYHPj8gWgE0q7UYKxZs5lHr9DaJ7SXZJYO2/KNCWf8n+c3ot0FHTfy X-Received: from irogers.svl.corp.google.com ([2620:15c:2cd:202:1256:a8b4:594a:9164]) (user=irogers job=sendgmr) by 2002:a81:71d4:0:b0:30c:3f8e:2f7d with SMTP id m203-20020a8171d4000000b0030c3f8e2f7dmr63376318ywc.500.1655110072646; Mon, 13 Jun 2022 01:47:52 -0700 (PDT) Date: Mon, 13 Jun 2022 01:47:37 -0700 In-Reply-To: <20220613084739.1159111-1-irogers@google.com> Message-Id: <20220613084739.1159111-5-irogers@google.com> Mime-Version: 1.0 References: <20220613084739.1159111-1-irogers@google.com> X-Mailer: git-send-email 2.36.1.476.g0c4daa206d-goog Subject: [PATCH 4/6] perf cpumap: Fix alignment for masks in event encoding From: Ian Rogers To: Peter Zijlstra , Ingo Molnar , Arnaldo Carvalho de Melo , Mark Rutland , Alexander Shishkin , Jiri Olsa , Namhyung Kim , James Clark , Kees Cook , "Gustavo A. R. Silva" , Adrian Hunter , Riccardo Mancini , German Gomez , Colin Ian King , Song Liu , Dave Marchevsky , Athira Rajeev , Alexey Bayduraev , Leo Yan , linux-perf-users@vger.kernel.org, linux-kernel@vger.kernel.org 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" A mask encoding of a cpu map is laid out as: u16 nr u16 long_size unsigned long mask[]; However, the mask may be 8-byte aligned meaning there is a 4-byte pad after long_size. This means 32-bit and 64-bit builds see the mask as being at different offsets. On top of this the structure is in the byte data[] encoded as: u16 type char data[] This means the mask's struct isn't the required 4 or 8 byte aligned, but is offset by 2. Consequently the long reads and writes are causing undefined behavior as the alignment is broken. Fix the mask struct by creating explicit 32 and 64-bit variants, use a union to avoid data[] and casts; the struct must be packed so the layout matches the existing perf.data layout. Taking an address of a member of a packed struct breaks alignment so pass the packed perf_record_cpu_map_data to functions, so they can access variables with the right alignment. As the 64-bit version has 4 bytes of padding, optimizing writing to only write the 32-bit version. Signed-off-by: Ian Rogers --- tools/lib/perf/include/perf/event.h | 36 +++++++++++-- tools/perf/tests/cpumap.c | 19 ++++--- tools/perf/util/cpumap.c | 80 +++++++++++++++++++++++------ tools/perf/util/cpumap.h | 4 +- tools/perf/util/session.c | 30 +++++------ tools/perf/util/synthetic-events.c | 34 +++++++----- 6 files changed, 143 insertions(+), 60 deletions(-) diff --git a/tools/lib/perf/include/perf/event.h b/tools/lib/perf/include/p= erf/event.h index e7758707cadd..d2d32589758a 100644 --- a/tools/lib/perf/include/perf/event.h +++ b/tools/lib/perf/include/perf/event.h @@ -6,6 +6,7 @@ #include #include #include +#include #include /* pid_t */ =20 #define event_contains(obj, mem) ((obj).header.size > offsetof(typeof(obj)= , mem)) @@ -153,20 +154,47 @@ enum { PERF_CPU_MAP__MASK =3D 1, }; =20 +/* + * Array encoding of a perf_cpu_map where nr is the number of entries in c= pu[] + * and each entry is a value for a CPU in the map. + */ struct cpu_map_entries { __u16 nr; __u16 cpu[]; }; =20 -struct perf_record_record_cpu_map { +/* Bitmap encoding of a perf_cpu_map where bitmap entries are 32-bit. */ +struct perf_record_mask_cpu_map32 { + /* Number of mask values. */ __u16 nr; + /* Constant 4. */ __u16 long_size; - unsigned long mask[]; + /* Bitmap data. */ + __u32 mask[]; }; =20 -struct perf_record_cpu_map_data { +/* Bitmap encoding of a perf_cpu_map where bitmap entries are 64-bit. */ +struct perf_record_mask_cpu_map64 { + /* Number of mask values. */ + __u16 nr; + /* Constant 8. */ + __u16 long_size; + /* Legacy padding. */ + char __pad[4]; + /* Bitmap data. */ + __u64 mask[]; +}; + +struct __packed perf_record_cpu_map_data { __u16 type; - char data[]; + union { + /* Used when type =3D=3D PERF_CPU_MAP__CPUS. */ + struct cpu_map_entries cpus_data; + /* Used when type =3D=3D PERF_CPU_MAP__MASK and long_size =3D=3D 4. */ + struct perf_record_mask_cpu_map32 mask32_data; + /* Used when type =3D=3D PERF_CPU_MAP__MASK and long_size =3D=3D 8. */ + struct perf_record_mask_cpu_map64 mask64_data; + }; }; =20 struct perf_record_cpu_map { diff --git a/tools/perf/tests/cpumap.c b/tools/perf/tests/cpumap.c index f94929ebb54b..7ea150cdc137 100644 --- a/tools/perf/tests/cpumap.c +++ b/tools/perf/tests/cpumap.c @@ -17,21 +17,23 @@ static int process_event_mask(struct perf_tool *tool __= maybe_unused, struct machine *machine __maybe_unused) { struct perf_record_cpu_map *map_event =3D &event->cpu_map; - struct perf_record_record_cpu_map *mask; struct perf_record_cpu_map_data *data; struct perf_cpu_map *map; int i; + unsigned int long_size; =20 data =3D &map_event->data; =20 TEST_ASSERT_VAL("wrong type", data->type =3D=3D PERF_CPU_MAP__MASK); =20 - mask =3D (struct perf_record_record_cpu_map *)data->data; + long_size =3D data->mask32_data.long_size; =20 - TEST_ASSERT_VAL("wrong nr", mask->nr =3D=3D 1); + TEST_ASSERT_VAL("wrong long_size", long_size =3D=3D 4 || long_size =3D=3D= 8); + + TEST_ASSERT_VAL("wrong nr", data->mask32_data.nr =3D=3D 1); =20 for (i =3D 0; i < 20; i++) { - TEST_ASSERT_VAL("wrong cpu", test_bit(i, mask->mask)); + TEST_ASSERT_VAL("wrong cpu", perf_record_cpu_map_data__test_bit(i, data)= ); } =20 map =3D cpu_map__new_data(data); @@ -51,7 +53,6 @@ static int process_event_cpus(struct perf_tool *tool __ma= ybe_unused, struct machine *machine __maybe_unused) { struct perf_record_cpu_map *map_event =3D &event->cpu_map; - struct cpu_map_entries *cpus; struct perf_record_cpu_map_data *data; struct perf_cpu_map *map; =20 @@ -59,11 +60,9 @@ static int process_event_cpus(struct perf_tool *tool __m= aybe_unused, =20 TEST_ASSERT_VAL("wrong type", data->type =3D=3D PERF_CPU_MAP__CPUS); =20 - cpus =3D (struct cpu_map_entries *)data->data; - - TEST_ASSERT_VAL("wrong nr", cpus->nr =3D=3D 2); - TEST_ASSERT_VAL("wrong cpu", cpus->cpu[0] =3D=3D 1); - TEST_ASSERT_VAL("wrong cpu", cpus->cpu[1] =3D=3D 256); + TEST_ASSERT_VAL("wrong nr", data->cpus_data.nr =3D=3D 2); + TEST_ASSERT_VAL("wrong cpu", data->cpus_data.cpu[0] =3D=3D 1); + TEST_ASSERT_VAL("wrong cpu", data->cpus_data.cpu[1] =3D=3D 256); =20 map =3D cpu_map__new_data(data); TEST_ASSERT_VAL("wrong nr", perf_cpu_map__nr(map) =3D=3D 2); diff --git a/tools/perf/util/cpumap.c b/tools/perf/util/cpumap.c index 12b2243222b0..ae43fb88f444 100644 --- a/tools/perf/util/cpumap.c +++ b/tools/perf/util/cpumap.c @@ -22,54 +22,102 @@ static int max_node_num; */ static int *cpunode_map; =20 -static struct perf_cpu_map *cpu_map__from_entries(struct cpu_map_entries *= cpus) +bool perf_record_cpu_map_data__test_bit(int i, + const struct perf_record_cpu_map_data *data) +{ + int bit_word32 =3D i / 32; + __u32 bit_mask32 =3D 1U << (i & 31); + int bit_word64 =3D i / 64; + __u64 bit_mask64 =3D ((__u64)1) << (i & 63); + + return (data->mask32_data.long_size =3D=3D 4) + ? (bit_word32 < data->mask32_data.nr) && + (data->mask32_data.mask[bit_word32] & bit_mask32) !=3D 0 + : (bit_word64 < data->mask64_data.nr) && + (data->mask64_data.mask[bit_word64] & bit_mask64) !=3D 0; +} + +/* Read ith mask value from data into the given 64-bit sized bitmap */ +static void perf_record_cpu_map_data__read_one_mask(const struct perf_reco= rd_cpu_map_data *data, + int i, unsigned long *bitmap) +{ +#if __SIZEOF_LONG__ =3D=3D 8 + if (data->mask32_data.long_size =3D=3D 4) + bitmap[0] =3D data->mask32_data.mask[i]; + else + bitmap[0] =3D data->mask64_data.mask[i]; +#else + if (data->mask32_data.long_size =3D=3D 4) { + bitmap[0] =3D data->mask32_data.mask[i]; + bitmap[1] =3D 0; + } else { +#if __BYTE_ORDER__ =3D=3D __ORDER_BIG_ENDIAN__ + bitmap[0] =3D (unsigned long)(data->mask64_data.mask[i] >> 32); + bitmap[1] =3D (unsigned long)data->mask64_data.mask[i]; +#else + bitmap[0] =3D (unsigned long)data->mask64_data.mask[i]; + bitmap[1] =3D (unsigned long)(data->mask64_data.mask[i] >> 32); +#endif + } +#endif +} +static struct perf_cpu_map *cpu_map__from_entries(const struct perf_record= _cpu_map_data *data) { struct perf_cpu_map *map; =20 - map =3D perf_cpu_map__empty_new(cpus->nr); + map =3D perf_cpu_map__empty_new(data->cpus_data.nr); if (map) { unsigned i; =20 - for (i =3D 0; i < cpus->nr; i++) { + for (i =3D 0; i < data->cpus_data.nr; i++) { /* * Special treatment for -1, which is not real cpu number, * and we need to use (int) -1 to initialize map[i], * otherwise it would become 65535. */ - if (cpus->cpu[i] =3D=3D (u16) -1) + if (data->cpus_data.cpu[i] =3D=3D (u16) -1) map->map[i].cpu =3D -1; else - map->map[i].cpu =3D (int) cpus->cpu[i]; + map->map[i].cpu =3D (int) data->cpus_data.cpu[i]; } } =20 return map; } =20 -static struct perf_cpu_map *cpu_map__from_mask(struct perf_record_record_c= pu_map *mask) +static struct perf_cpu_map *cpu_map__from_mask(const struct perf_record_cp= u_map_data *data) { + DECLARE_BITMAP(local_copy, 64); + int weight =3D 0, mask_nr =3D data->mask32_data.nr; struct perf_cpu_map *map; - int nr, nbits =3D mask->nr * mask->long_size * BITS_PER_BYTE; =20 - nr =3D bitmap_weight(mask->mask, nbits); + for (int i =3D 0; i < mask_nr; i++) { + perf_record_cpu_map_data__read_one_mask(data, i, local_copy); + weight +=3D bitmap_weight(local_copy, 64); + } + + map =3D perf_cpu_map__empty_new(weight); + if (!map) + return NULL; =20 - map =3D perf_cpu_map__empty_new(nr); - if (map) { - int cpu, i =3D 0; + for (int i =3D 0, j =3D 0; i < mask_nr; i++) { + int cpus_per_i =3D (i * data->mask32_data.long_size * BITS_PER_BYTE); + int cpu; =20 - for_each_set_bit(cpu, mask->mask, nbits) - map->map[i++].cpu =3D cpu; + perf_record_cpu_map_data__read_one_mask(data, i, local_copy); + for_each_set_bit(cpu, local_copy, 64) + map->map[j++].cpu =3D cpu + cpus_per_i; } return map; =20 } =20 -struct perf_cpu_map *cpu_map__new_data(struct perf_record_cpu_map_data *da= ta) +struct perf_cpu_map *cpu_map__new_data(const struct perf_record_cpu_map_da= ta *data) { if (data->type =3D=3D PERF_CPU_MAP__CPUS) - return cpu_map__from_entries((struct cpu_map_entries *)data->data); + return cpu_map__from_entries(data); else - return cpu_map__from_mask((struct perf_record_record_cpu_map *)data->dat= a); + return cpu_map__from_mask(data); } =20 size_t cpu_map__fprintf(struct perf_cpu_map *map, FILE *fp) diff --git a/tools/perf/util/cpumap.h b/tools/perf/util/cpumap.h index 703ae6d3386e..fa8a5acdcae1 100644 --- a/tools/perf/util/cpumap.h +++ b/tools/perf/util/cpumap.h @@ -37,9 +37,11 @@ struct cpu_aggr_map { =20 struct perf_record_cpu_map_data; =20 +bool perf_record_cpu_map_data__test_bit(int i, const struct perf_record_cp= u_map_data *data); + struct perf_cpu_map *perf_cpu_map__empty_new(int nr); =20 -struct perf_cpu_map *cpu_map__new_data(struct perf_record_cpu_map_data *da= ta); +struct perf_cpu_map *cpu_map__new_data(const struct perf_record_cpu_map_da= ta *data); size_t cpu_map__snprint(struct perf_cpu_map *map, char *buf, size_t size); size_t cpu_map__snprint_mask(struct perf_cpu_map *map, char *buf, size_t s= ize); size_t cpu_map__fprintf(struct perf_cpu_map *map, FILE *fp); diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c index 0aa818977d2b..d52a39ba48e3 100644 --- a/tools/perf/util/session.c +++ b/tools/perf/util/session.c @@ -914,30 +914,30 @@ static void perf_event__cpu_map_swap(union perf_event= *event, bool sample_id_all __maybe_unused) { struct perf_record_cpu_map_data *data =3D &event->cpu_map.data; - struct cpu_map_entries *cpus; - struct perf_record_record_cpu_map *mask; - unsigned i; =20 data->type =3D bswap_16(data->type); =20 switch (data->type) { case PERF_CPU_MAP__CPUS: - cpus =3D (struct cpu_map_entries *)data->data; - - cpus->nr =3D bswap_16(cpus->nr); + data->cpus_data.nr =3D bswap_16(data->cpus_data.nr); =20 - for (i =3D 0; i < cpus->nr; i++) - cpus->cpu[i] =3D bswap_16(cpus->cpu[i]); + for (unsigned i =3D 0; i < data->cpus_data.nr; i++) + data->cpus_data.cpu[i] =3D bswap_16(data->cpus_data.cpu[i]); break; case PERF_CPU_MAP__MASK: - mask =3D (struct perf_record_record_cpu_map *)data->data; - - mask->nr =3D bswap_16(mask->nr); - mask->long_size =3D bswap_16(mask->long_size); + data->mask32_data.long_size =3D bswap_16(data->mask32_data.long_size); =20 - switch (mask->long_size) { - case 4: mem_bswap_32(&mask->mask, mask->nr); break; - case 8: mem_bswap_64(&mask->mask, mask->nr); break; + switch (data->mask32_data.long_size) { + case 4: + data->mask32_data.nr =3D bswap_16(data->mask32_data.nr); + for (unsigned i =3D 0; i < data->mask32_data.nr; i++) + data->mask32_data.mask[i] =3D bswap_32(data->mask32_data.mask[i]); + break; + case 8: + data->mask64_data.nr =3D bswap_16(data->mask64_data.nr); + for (unsigned i =3D 0; i < data->mask64_data.nr; i++) + data->mask64_data.mask[i] =3D bswap_64(data->mask64_data.mask[i]); + break; default: pr_err("cpu_map swap: unsupported long size\n"); } diff --git a/tools/perf/util/synthetic-events.c b/tools/perf/util/synthetic= -events.c index 0d87df20ec44..4fa7d0d7dbcf 100644 --- a/tools/perf/util/synthetic-events.c +++ b/tools/perf/util/synthetic-events.c @@ -1183,27 +1183,33 @@ int perf_event__synthesize_thread_map2(struct perf_= tool *tool, return err; } =20 -static void synthesize_cpus(struct cpu_map_entries *cpus, +static void synthesize_cpus(struct perf_record_cpu_map_data *data, const struct perf_cpu_map *map) { int i, map_nr =3D perf_cpu_map__nr(map); =20 - cpus->nr =3D map_nr; + data->cpus_data.nr =3D map_nr; =20 for (i =3D 0; i < map_nr; i++) - cpus->cpu[i] =3D perf_cpu_map__cpu(map, i).cpu; + data->cpus_data.cpu[i] =3D perf_cpu_map__cpu(map, i).cpu; } =20 -static void synthesize_mask(struct perf_record_record_cpu_map *mask, +static void synthesize_mask(struct perf_record_cpu_map_data *data, const struct perf_cpu_map *map, int max) { - int i; + int idx; + struct perf_cpu cpu; + + /* Due to padding, the 4bytes per entry mask variant is always smaller. */ + data->mask32_data.nr =3D BITS_TO_U32(max); + data->mask32_data.long_size =3D 4; =20 - mask->nr =3D BITS_TO_LONGS(max); - mask->long_size =3D sizeof(long); + perf_cpu_map__for_each_cpu(cpu, idx, map) { + int bit_word =3D cpu.cpu / 32; + __u32 bit_mask =3D 1U << (cpu.cpu & 31); =20 - for (i =3D 0; i < perf_cpu_map__nr(map); i++) - set_bit(perf_cpu_map__cpu(map, i).cpu, mask->mask); + data->mask32_data.mask[bit_word] |=3D bit_mask; + } } =20 static size_t cpus_size(const struct perf_cpu_map *map) @@ -1214,7 +1220,7 @@ static size_t cpus_size(const struct perf_cpu_map *ma= p) static size_t mask_size(const struct perf_cpu_map *map, int *max) { *max =3D perf_cpu_map__max(map).cpu; - return sizeof(struct perf_record_record_cpu_map) + BITS_TO_LONGS(*max) * = sizeof(long); + return sizeof(struct perf_record_mask_cpu_map32) + BITS_TO_U32(*max) * si= zeof(__u32); } =20 static void *cpu_map_data__alloc(const struct perf_cpu_map *map, size_t *s= ize, @@ -1247,7 +1253,7 @@ static void *cpu_map_data__alloc(const struct perf_cp= u_map *map, size_t *size, *type =3D PERF_CPU_MAP__MASK; } =20 - *size +=3D sizeof(struct perf_record_cpu_map_data); + *size +=3D sizeof(__u16); /* For perf_record_cpu_map_data.type. */ *size =3D PERF_ALIGN(*size, sizeof(u64)); return zalloc(*size); } @@ -1260,10 +1266,10 @@ static void cpu_map_data__synthesize(struct perf_re= cord_cpu_map_data *data, =20 switch (type) { case PERF_CPU_MAP__CPUS: - synthesize_cpus((struct cpu_map_entries *) data->data, map); + synthesize_cpus(data, map); break; case PERF_CPU_MAP__MASK: - synthesize_mask((struct perf_record_record_cpu_map *)data->data, map, ma= x); + synthesize_mask(data, map, max); default: break; } @@ -1271,7 +1277,7 @@ static void cpu_map_data__synthesize(struct perf_reco= rd_cpu_map_data *data, =20 static struct perf_record_cpu_map *cpu_map_event__new(const struct perf_cp= u_map *map) { - size_t size =3D sizeof(struct perf_record_cpu_map); + size_t size =3D sizeof(struct perf_event_header); struct perf_record_cpu_map *event; int max; u16 type; --=20 2.36.1.476.g0c4daa206d-goog From nobody Mon Apr 27 13:19:06 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 BBF48C433EF for ; Mon, 13 Jun 2022 08:48:11 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S240414AbiFMIsK (ORCPT ); Mon, 13 Jun 2022 04:48:10 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:37458 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S240294AbiFMIr7 (ORCPT ); Mon, 13 Jun 2022 04:47:59 -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 651A315A1D for ; Mon, 13 Jun 2022 01:47:55 -0700 (PDT) Received: by mail-yw1-x114a.google.com with SMTP id 00721157ae682-30c14765d55so47795607b3.13 for ; Mon, 13 Jun 2022 01:47:55 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20210112; h=date:in-reply-to:message-id:mime-version:references:subject:from:to :cc; bh=RhxA7eRgAfXCkykh9Mqke3rmlCOtyFU0Irt1epvp7hw=; b=aO6EJfsDe0Bb/QFxvO8DR+qXxDniAfiVwqT5kGWllxYcvGCKdQdFkB5LBlBAVWwZEU 7WUP4Uep5dj1d+e4YqGlVmmCeQbG+6nCNPxBsk/bxUO5ASRgjLddoPoKCkX6zN7RCBL9 4Bb7KqWYhJr11dhrA/Zg+CUwsWbE81cK9ppO9m+ueFK/1qq7Rwsg/hXgcSkiFQvzlGQ8 Q587EfeLu/AtVR2ISMaLSPyhIC413ed72prGlG2n2oWSd3dDzR1j+T96z3shCZZVrDtU NwP5NtJkakPm1oY0bd409v4J+wwbYo+x4nBdF10hvjiVyxnGpymHTt2Fm7Je0Nn+075c KsUA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:date:in-reply-to:message-id:mime-version :references:subject:from:to:cc; bh=RhxA7eRgAfXCkykh9Mqke3rmlCOtyFU0Irt1epvp7hw=; b=aDkPx1o67tFdI6syQR6TdILAPksN2NOKoth8W5qX+pqCV/IQhVvt/2vu+IkWhZ+DFs PHJ/2hdk/7ykJjoAiTIW6vFPS6MeCfbJEHvnMPX/wsJAnG8gEpavY/VimAgpkT5WGHyN G6V9frXLU7qQV9icrb14drcVMVYXUh9f3XCDoBa5V24ie+phSe/ZKwmI+61Kus3idf/e vPDp4JGJ7unGZrvOqRburxmlehHDrqjZAEvoLM+pSs2zsp8I0ts2dK7e9nPha5M7vwBz flvX3sT+9cF1+Jbo3Ajg9XuvxSZSBJeAA6qGxWeBvhXzM1OQBxRF2c451m1jQNqLhe1L DBlg== X-Gm-Message-State: AOAM5329OdOJxrOlqG3AWkYW4OpSYi5m3//u9czLaCH57rLK6RTr+nsZ yTGyr8e1F0Wh5HvtfsSYlkFii5UmY/dL X-Google-Smtp-Source: ABdhPJzZDHm+wUOSJAezw4233Neo2oUGrybr8+7WxFrRjWRpu+LupysSqvWoM7QBfjQqqX8/56nO2q1/TNNE X-Received: from irogers.svl.corp.google.com ([2620:15c:2cd:202:1256:a8b4:594a:9164]) (user=irogers job=sendgmr) by 2002:a81:4909:0:b0:30c:34d5:9f2c with SMTP id w9-20020a814909000000b0030c34d59f2cmr63866862ywa.489.1655110075028; Mon, 13 Jun 2022 01:47:55 -0700 (PDT) Date: Mon, 13 Jun 2022 01:47:38 -0700 In-Reply-To: <20220613084739.1159111-1-irogers@google.com> Message-Id: <20220613084739.1159111-6-irogers@google.com> Mime-Version: 1.0 References: <20220613084739.1159111-1-irogers@google.com> X-Mailer: git-send-email 2.36.1.476.g0c4daa206d-goog Subject: [PATCH 5/6] perf events: Prefer union over variable length array From: Ian Rogers To: Peter Zijlstra , Ingo Molnar , Arnaldo Carvalho de Melo , Mark Rutland , Alexander Shishkin , Jiri Olsa , Namhyung Kim , James Clark , Kees Cook , "Gustavo A. R. Silva" , Adrian Hunter , Riccardo Mancini , German Gomez , Colin Ian King , Song Liu , Dave Marchevsky , Athira Rajeev , Alexey Bayduraev , Leo Yan , linux-perf-users@vger.kernel.org, linux-kernel@vger.kernel.org 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 for casts to introduce alignment issues, prefer a union for perf_record_event_update. Signed-off-by: Ian Rogers --- tools/lib/perf/include/perf/event.h | 11 ++++++++++- tools/perf/tests/event_update.c | 14 ++++---------- tools/perf/util/header.c | 24 ++++++++---------------- tools/perf/util/synthetic-events.c | 12 +++++------- 4 files changed, 27 insertions(+), 34 deletions(-) diff --git a/tools/lib/perf/include/perf/event.h b/tools/lib/perf/include/p= erf/event.h index d2d32589758a..21170f5afb61 100644 --- a/tools/lib/perf/include/perf/event.h +++ b/tools/lib/perf/include/perf/event.h @@ -221,7 +221,16 @@ struct perf_record_event_update { struct perf_event_header header; __u64 type; __u64 id; - char data[]; + union { + /* Used when type =3D=3D PERF_EVENT_UPDATE__SCALE. */ + struct perf_record_event_update_scale scale; + /* Used when type =3D=3D PERF_EVENT_UPDATE__UNIT. */ + char unit[0]; + /* Used when type =3D=3D PERF_EVENT_UPDATE__NAME. */ + char name[0]; + /* Used when type =3D=3D PERF_EVENT_UPDATE__CPUS. */ + struct perf_record_event_update_cpus cpus; + }; }; =20 #define MAX_EVENT_NAME 64 diff --git a/tools/perf/tests/event_update.c b/tools/perf/tests/event_updat= e.c index 78db4d704e76..d093a9b878d1 100644 --- a/tools/perf/tests/event_update.c +++ b/tools/perf/tests/event_update.c @@ -21,7 +21,7 @@ static int process_event_unit(struct perf_tool *tool __ma= ybe_unused, =20 TEST_ASSERT_VAL("wrong id", ev->id =3D=3D 123); TEST_ASSERT_VAL("wrong id", ev->type =3D=3D PERF_EVENT_UPDATE__UNIT); - TEST_ASSERT_VAL("wrong unit", !strcmp(ev->data, "KRAVA")); + TEST_ASSERT_VAL("wrong unit", !strcmp(ev->unit, "KRAVA")); return 0; } =20 @@ -31,13 +31,10 @@ static int process_event_scale(struct perf_tool *tool _= _maybe_unused, struct machine *machine __maybe_unused) { struct perf_record_event_update *ev =3D (struct perf_record_event_update = *)event; - struct perf_record_event_update_scale *ev_data; - - ev_data =3D (struct perf_record_event_update_scale *)ev->data; =20 TEST_ASSERT_VAL("wrong id", ev->id =3D=3D 123); TEST_ASSERT_VAL("wrong id", ev->type =3D=3D PERF_EVENT_UPDATE__SCALE); - TEST_ASSERT_VAL("wrong scale", ev_data->scale =3D=3D 0.123); + TEST_ASSERT_VAL("wrong scale", ev->scale.scale =3D=3D 0.123); return 0; } =20 @@ -56,7 +53,7 @@ static int process_event_name(struct perf_tool *tool, =20 TEST_ASSERT_VAL("wrong id", ev->id =3D=3D 123); TEST_ASSERT_VAL("wrong id", ev->type =3D=3D PERF_EVENT_UPDATE__NAME); - TEST_ASSERT_VAL("wrong name", !strcmp(ev->data, tmp->name)); + TEST_ASSERT_VAL("wrong name", !strcmp(ev->name, tmp->name)); return 0; } =20 @@ -66,12 +63,9 @@ static int process_event_cpus(struct perf_tool *tool __m= aybe_unused, struct machine *machine __maybe_unused) { struct perf_record_event_update *ev =3D (struct perf_record_event_update = *)event; - struct perf_record_event_update_cpus *ev_data; struct perf_cpu_map *map; =20 - ev_data =3D (struct perf_record_event_update_cpus *) ev->data; - - map =3D cpu_map__new_data(&ev_data->cpus); + map =3D cpu_map__new_data(&ev->cpus.cpus); =20 TEST_ASSERT_VAL("wrong id", ev->id =3D=3D 123); TEST_ASSERT_VAL("wrong type", ev->type =3D=3D PERF_EVENT_UPDATE__CPUS); diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c index 53332da100e8..108c8da5d2e3 100644 --- a/tools/perf/util/header.c +++ b/tools/perf/util/header.c @@ -4264,8 +4264,6 @@ int perf_event__process_feature(struct perf_session *= session, size_t perf_event__fprintf_event_update(union perf_event *event, FILE *fp) { struct perf_record_event_update *ev =3D &event->event_update; - struct perf_record_event_update_scale *ev_scale; - struct perf_record_event_update_cpus *ev_cpus; struct perf_cpu_map *map; size_t ret; =20 @@ -4273,20 +4271,18 @@ size_t perf_event__fprintf_event_update(union perf_= event *event, FILE *fp) =20 switch (ev->type) { case PERF_EVENT_UPDATE__SCALE: - ev_scale =3D (struct perf_record_event_update_scale *)ev->data; - ret +=3D fprintf(fp, "... scale: %f\n", ev_scale->scale); + ret +=3D fprintf(fp, "... scale: %f\n", ev->scale.scale); break; case PERF_EVENT_UPDATE__UNIT: - ret +=3D fprintf(fp, "... unit: %s\n", ev->data); + ret +=3D fprintf(fp, "... unit: %s\n", ev->unit); break; case PERF_EVENT_UPDATE__NAME: - ret +=3D fprintf(fp, "... name: %s\n", ev->data); + ret +=3D fprintf(fp, "... name: %s\n", ev->name); break; case PERF_EVENT_UPDATE__CPUS: - ev_cpus =3D (struct perf_record_event_update_cpus *)ev->data; ret +=3D fprintf(fp, "... "); =20 - map =3D cpu_map__new_data(&ev_cpus->cpus); + map =3D cpu_map__new_data(&ev->cpus.cpus); if (map) ret +=3D cpu_map__fprintf(map, fp); else @@ -4343,8 +4339,6 @@ int perf_event__process_event_update(struct perf_tool= *tool __maybe_unused, struct evlist **pevlist) { struct perf_record_event_update *ev =3D &event->event_update; - struct perf_record_event_update_scale *ev_scale; - struct perf_record_event_update_cpus *ev_cpus; struct evlist *evlist; struct evsel *evsel; struct perf_cpu_map *map; @@ -4361,19 +4355,17 @@ int perf_event__process_event_update(struct perf_to= ol *tool __maybe_unused, switch (ev->type) { case PERF_EVENT_UPDATE__UNIT: free((char *)evsel->unit); - evsel->unit =3D strdup(ev->data); + evsel->unit =3D strdup(ev->unit); break; case PERF_EVENT_UPDATE__NAME: free(evsel->name); - evsel->name =3D strdup(ev->data); + evsel->name =3D strdup(ev->name); break; case PERF_EVENT_UPDATE__SCALE: - ev_scale =3D (struct perf_record_event_update_scale *)ev->data; - evsel->scale =3D ev_scale->scale; + evsel->scale =3D ev->scale.scale; break; case PERF_EVENT_UPDATE__CPUS: - ev_cpus =3D (struct perf_record_event_update_cpus *)ev->data; - map =3D cpu_map__new_data(&ev_cpus->cpus); + map =3D cpu_map__new_data(&ev->cpus.cpus); if (map) { perf_cpu_map__put(evsel->core.own_cpus); evsel->core.own_cpus =3D map; diff --git a/tools/perf/util/synthetic-events.c b/tools/perf/util/synthetic= -events.c index 4fa7d0d7dbcf..ec54ac1ed96f 100644 --- a/tools/perf/util/synthetic-events.c +++ b/tools/perf/util/synthetic-events.c @@ -1848,7 +1848,7 @@ int perf_event__synthesize_event_update_unit(struct p= erf_tool *tool, struct evse if (ev =3D=3D NULL) return -ENOMEM; =20 - strlcpy(ev->data, evsel->unit, size + 1); + strlcpy(ev->unit, evsel->unit, size + 1); err =3D process(tool, (union perf_event *)ev, NULL, NULL); free(ev); return err; @@ -1865,8 +1865,7 @@ int perf_event__synthesize_event_update_scale(struct = perf_tool *tool, struct evs if (ev =3D=3D NULL) return -ENOMEM; =20 - ev_data =3D (struct perf_record_event_update_scale *)ev->data; - ev_data->scale =3D evsel->scale; + ev->scale.scale =3D evsel->scale; err =3D process(tool, (union perf_event *)ev, NULL, NULL); free(ev); return err; @@ -1883,7 +1882,7 @@ int perf_event__synthesize_event_update_name(struct p= erf_tool *tool, struct evse if (ev =3D=3D NULL) return -ENOMEM; =20 - strlcpy(ev->data, evsel->name, len + 1); + strlcpy(ev->name, evsel->name, len + 1); err =3D process(tool, (union perf_event *)ev, NULL, NULL); free(ev); return err; @@ -1892,7 +1891,7 @@ int perf_event__synthesize_event_update_name(struct p= erf_tool *tool, struct evse int perf_event__synthesize_event_update_cpus(struct perf_tool *tool, struc= t evsel *evsel, perf_event__handler_t process) { - size_t size =3D sizeof(struct perf_record_event_update); + size_t size =3D sizeof(struct perf_event_header) + sizeof(u64) + sizeof(u= 64); struct perf_record_event_update *ev; int max, err; u16 type; @@ -1909,8 +1908,7 @@ int perf_event__synthesize_event_update_cpus(struct p= erf_tool *tool, struct evse ev->type =3D PERF_EVENT_UPDATE__CPUS; ev->id =3D evsel->core.id[0]; =20 - cpu_map_data__synthesize((struct perf_record_cpu_map_data *)ev->data, - evsel->core.own_cpus, type, max); + cpu_map_data__synthesize(&ev->cpus.cpus, evsel->core.own_cpus, type, max); =20 err =3D process(tool, (union perf_event *)ev, NULL, NULL); free(ev); --=20 2.36.1.476.g0c4daa206d-goog From nobody Mon Apr 27 13:19:06 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 834D9C43334 for ; Mon, 13 Jun 2022 08:48:36 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S240390AbiFMIsf (ORCPT ); Mon, 13 Jun 2022 04:48:35 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:37456 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S240394AbiFMIsG (ORCPT ); Mon, 13 Jun 2022 04:48:06 -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 8DB9E17AB4 for ; Mon, 13 Jun 2022 01:47:58 -0700 (PDT) Received: by mail-yw1-x1149.google.com with SMTP id 00721157ae682-313bc9c54acso47900187b3.4 for ; Mon, 13 Jun 2022 01:47:58 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20210112; h=date:in-reply-to:message-id:mime-version:references:subject:from:to :cc; bh=e3k1t6ubd4zJKD6s+EQnq7VGeotywjYalzT/OIoKrJA=; b=LiM33q92XdF2+A+2GjoiHqU+bXy9faQKosr0ApO6xmjU6eDvGPEVxZ1IwI7MqFPS5Z CxYkTl50R/y9PrPd+rFDrJcIy8wS63WyD+ZhRI582fTuQvpmH0IwZAYuwGZz2tl73wn3 JuP7/XtRK0DDMUh7sTKE22U+kwh2TF25Lfh7LNm8UniIX++cMl129pPvj/hyro8UEK17 N1sEPTZL8+7v8pyI0UzS2IMOFFp2b++teui4v33fa0BikxwzMXaTzHwpgSFuRTtEnMMe KK4NeCnRJWOq0+MHeRY6AFMkWjMx6FYx7EM1IjNm1rCWI6Ve83kErvd45g+XkdSpWbU8 wmwg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:date:in-reply-to:message-id:mime-version :references:subject:from:to:cc; bh=e3k1t6ubd4zJKD6s+EQnq7VGeotywjYalzT/OIoKrJA=; b=l1i6oxfCL2ALG26dq0h9fABxL86+ur96zCDcDjmTR3tBw1uVdsNPb6wIhMMfUXvGjz Z4ivMBqLAuV79wQ3loKhLxzkXpqagNYd5gI/2lz3RyxLvImmLh0jNHYyAZzNuLWDsKIE VCn20YjGlhcsdjLr56R8UHF/YXX+o4C+/HSsjUfKIhn2Nb50Fbm5bkTtqPvJ98AU46Fu NwZEsPprj26V1/yD/MXuScrc9xvat0NR7Q1kYCoDqn1WyjAgyXOInG1HK9rOvDNuhuoK gqUjJ9B8soZZPvUThUfQDEC722y+pvD4eWSuogELGD0U/C4kpQkZWRbwinhvZ4q4Iboj vf8Q== X-Gm-Message-State: AOAM533rVS/oSwiIJtJ6qngkiinXuWV8UScaBvTNeNHpPmIa2DshYWbC 4t5YDBGDCnI6b4hhqUJGFxb3Kp8a1KMe X-Google-Smtp-Source: ABdhPJxALdusKhXb2Rj6pP8ilkYN+GxayrwZNrQj93BDDcdQ7PSm0enp6Q5p5hmA/w9NG/t1Bh42I/6fUOTl X-Received: from irogers.svl.corp.google.com ([2620:15c:2cd:202:1256:a8b4:594a:9164]) (user=irogers job=sendgmr) by 2002:a25:db48:0:b0:664:7366:8f13 with SMTP id g69-20020a25db48000000b0066473668f13mr13541736ybf.87.1655110077624; Mon, 13 Jun 2022 01:47:57 -0700 (PDT) Date: Mon, 13 Jun 2022 01:47:39 -0700 In-Reply-To: <20220613084739.1159111-1-irogers@google.com> Message-Id: <20220613084739.1159111-7-irogers@google.com> Mime-Version: 1.0 References: <20220613084739.1159111-1-irogers@google.com> X-Mailer: git-send-email 2.36.1.476.g0c4daa206d-goog Subject: [PATCH 6/6] perf cpumap: Add range data encoding From: Ian Rogers To: Peter Zijlstra , Ingo Molnar , Arnaldo Carvalho de Melo , Mark Rutland , Alexander Shishkin , Jiri Olsa , Namhyung Kim , James Clark , Kees Cook , "Gustavo A. R. Silva" , Adrian Hunter , Riccardo Mancini , German Gomez , Colin Ian King , Song Liu , Dave Marchevsky , Athira Rajeev , Alexey Bayduraev , Leo Yan , linux-perf-users@vger.kernel.org, linux-kernel@vger.kernel.org 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" Often cpumaps encode a range of all CPUs, add a compact encoding that doesn't require a bit mask or list of all CPUs. Signed-off-by: Ian Rogers --- tools/lib/perf/include/perf/event.h | 14 +++ tools/perf/tests/cpumap.c | 52 ++++++++-- tools/perf/util/cpumap.c | 31 +++++- tools/perf/util/session.c | 5 + tools/perf/util/synthetic-events.c | 151 ++++++++++++++-------------- 5 files changed, 166 insertions(+), 87 deletions(-) diff --git a/tools/lib/perf/include/perf/event.h b/tools/lib/perf/include/p= erf/event.h index 21170f5afb61..43f990b8c58b 100644 --- a/tools/lib/perf/include/perf/event.h +++ b/tools/lib/perf/include/perf/event.h @@ -152,6 +152,7 @@ struct perf_record_header_attr { enum { PERF_CPU_MAP__CPUS =3D 0, PERF_CPU_MAP__MASK =3D 1, + PERF_CPU_MAP__RANGE_CPUS =3D 2, }; =20 /* @@ -185,6 +186,17 @@ struct perf_record_mask_cpu_map64 { __u64 mask[]; }; =20 +/* + * An encoding of a CPU map for a range starting at start_cpu through to + * end_cpu. If any_cpu is 1, an any CPU (-1) value (aka dummy value) is pr= esent. + */ +struct perf_record_range_cpu_map { + __u8 any_cpu; + __u8 __pad; + __u16 start_cpu; + __u16 end_cpu; +}; + struct __packed perf_record_cpu_map_data { __u16 type; union { @@ -194,6 +206,8 @@ struct __packed perf_record_cpu_map_data { struct perf_record_mask_cpu_map32 mask32_data; /* Used when type =3D=3D PERF_CPU_MAP__MASK and long_size =3D=3D 8. */ struct perf_record_mask_cpu_map64 mask64_data; + /* Used when type =3D=3D PERF_CPU_MAP__RANGE_CPUS. */ + struct perf_record_range_cpu_map range_cpu_data; }; }; =20 diff --git a/tools/perf/tests/cpumap.c b/tools/perf/tests/cpumap.c index 7ea150cdc137..7c873c6ae3eb 100644 --- a/tools/perf/tests/cpumap.c +++ b/tools/perf/tests/cpumap.c @@ -19,7 +19,6 @@ static int process_event_mask(struct perf_tool *tool __ma= ybe_unused, struct perf_record_cpu_map *map_event =3D &event->cpu_map; struct perf_record_cpu_map_data *data; struct perf_cpu_map *map; - int i; unsigned int long_size; =20 data =3D &map_event->data; @@ -32,16 +31,17 @@ static int process_event_mask(struct perf_tool *tool __= maybe_unused, =20 TEST_ASSERT_VAL("wrong nr", data->mask32_data.nr =3D=3D 1); =20 - for (i =3D 0; i < 20; i++) { + TEST_ASSERT_VAL("wrong cpu", perf_record_cpu_map_data__test_bit(0, data)); + TEST_ASSERT_VAL("wrong cpu", !perf_record_cpu_map_data__test_bit(1, data)= ); + for (int i =3D 2; i <=3D 20; i++) TEST_ASSERT_VAL("wrong cpu", perf_record_cpu_map_data__test_bit(i, data)= ); - } =20 map =3D cpu_map__new_data(data); TEST_ASSERT_VAL("wrong nr", perf_cpu_map__nr(map) =3D=3D 20); =20 - for (i =3D 0; i < 20; i++) { - TEST_ASSERT_VAL("wrong cpu", perf_cpu_map__cpu(map, i).cpu =3D=3D i); - } + TEST_ASSERT_VAL("wrong cpu", perf_cpu_map__cpu(map, 0).cpu =3D=3D 0); + for (int i =3D 2; i <=3D 20; i++) + TEST_ASSERT_VAL("wrong cpu", perf_cpu_map__cpu(map, i - 1).cpu =3D=3D i); =20 perf_cpu_map__put(map); return 0; @@ -73,25 +73,59 @@ static int process_event_cpus(struct perf_tool *tool __= maybe_unused, return 0; } =20 +static int process_event_range_cpus(struct perf_tool *tool __maybe_unused, + union perf_event *event, + struct perf_sample *sample __maybe_unused, + struct machine *machine __maybe_unused) +{ + struct perf_record_cpu_map *map_event =3D &event->cpu_map; + struct perf_record_cpu_map_data *data; + struct perf_cpu_map *map; + + data =3D &map_event->data; + + TEST_ASSERT_VAL("wrong type", data->type =3D=3D PERF_CPU_MAP__RANGE_CPUS); + + TEST_ASSERT_VAL("wrong any_cpu", data->range_cpu_data.any_cpu =3D=3D 0); + TEST_ASSERT_VAL("wrong start_cpu", data->range_cpu_data.start_cpu =3D=3D = 1); + TEST_ASSERT_VAL("wrong end_cpu", data->range_cpu_data.end_cpu =3D=3D 25= 6); + + map =3D cpu_map__new_data(data); + TEST_ASSERT_VAL("wrong nr", perf_cpu_map__nr(map) =3D=3D 256); + TEST_ASSERT_VAL("wrong cpu", perf_cpu_map__cpu(map, 0).cpu =3D=3D 1); + TEST_ASSERT_VAL("wrong cpu", perf_cpu_map__max(map).cpu =3D=3D 256); + TEST_ASSERT_VAL("wrong refcnt", refcount_read(&map->refcnt) =3D=3D 1); + perf_cpu_map__put(map); + return 0; +} + =20 static int test__cpu_map_synthesize(struct test_suite *test __maybe_unused= , int subtest __maybe_unused) { struct perf_cpu_map *cpus; =20 - /* This one is better stores in mask. */ - cpus =3D perf_cpu_map__new("0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,1= 8,19"); + /* This one is better stored in a mask. */ + cpus =3D perf_cpu_map__new("0,2-20"); =20 TEST_ASSERT_VAL("failed to synthesize map", !perf_event__synthesize_cpu_map(NULL, cpus, process_event_mask, NULL)); =20 perf_cpu_map__put(cpus); =20 - /* This one is better stores in cpu values. */ + /* This one is better stored in cpu values. */ cpus =3D perf_cpu_map__new("1,256"); =20 TEST_ASSERT_VAL("failed to synthesize map", !perf_event__synthesize_cpu_map(NULL, cpus, process_event_cpus, NULL)); =20 + perf_cpu_map__put(cpus); + + /* This one is better stored as a range. */ + cpus =3D perf_cpu_map__new("1-256"); + + TEST_ASSERT_VAL("failed to synthesize map", + !perf_event__synthesize_cpu_map(NULL, cpus, process_event_range_cpus, NU= LL)); + perf_cpu_map__put(cpus); return 0; } diff --git a/tools/perf/util/cpumap.c b/tools/perf/util/cpumap.c index ae43fb88f444..2389bd3e19b8 100644 --- a/tools/perf/util/cpumap.c +++ b/tools/perf/util/cpumap.c @@ -112,12 +112,39 @@ static struct perf_cpu_map *cpu_map__from_mask(const = struct perf_record_cpu_map_ =20 } =20 +static struct perf_cpu_map *cpu_map__from_range(const struct perf_record_c= pu_map_data *data) +{ + struct perf_cpu_map *map; + unsigned int i =3D 0; + + map =3D perf_cpu_map__empty_new(data->range_cpu_data.end_cpu - + data->range_cpu_data.start_cpu + 1 + data->range_cpu_data.any_cpu); + if (!map) + return NULL; + + if (data->range_cpu_data.any_cpu) + map->map[i++].cpu =3D -1; + + for (int cpu =3D data->range_cpu_data.start_cpu; cpu <=3D data->range_cpu= _data.end_cpu; + i++, cpu++) + map->map[i].cpu =3D cpu; + + return map; +} + struct perf_cpu_map *cpu_map__new_data(const struct perf_record_cpu_map_da= ta *data) { - if (data->type =3D=3D PERF_CPU_MAP__CPUS) + switch (data->type) { + case PERF_CPU_MAP__CPUS: return cpu_map__from_entries(data); - else + case PERF_CPU_MAP__MASK: return cpu_map__from_mask(data); + case PERF_CPU_MAP__RANGE_CPUS: + return cpu_map__from_range(data); + default: + pr_err("cpu_map__new_data unknown type %d\n", data->type); + return NULL; + } } =20 size_t cpu_map__fprintf(struct perf_cpu_map *map, FILE *fp) diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c index d52a39ba48e3..0acb9de54b06 100644 --- a/tools/perf/util/session.c +++ b/tools/perf/util/session.c @@ -941,6 +941,11 @@ static void perf_event__cpu_map_swap(union perf_event = *event, default: pr_err("cpu_map swap: unsupported long size\n"); } + break; + case PERF_CPU_MAP__RANGE_CPUS: + data->range_cpu_data.start_cpu =3D bswap_16(data->range_cpu_data.start_c= pu); + data->range_cpu_data.end_cpu =3D bswap_16(data->range_cpu_data.end_cpu); + break; default: break; } diff --git a/tools/perf/util/synthetic-events.c b/tools/perf/util/synthetic= -events.c index ec54ac1ed96f..810ed1dc6e6d 100644 --- a/tools/perf/util/synthetic-events.c +++ b/tools/perf/util/synthetic-events.c @@ -1183,93 +1183,97 @@ int perf_event__synthesize_thread_map2(struct perf_= tool *tool, return err; } =20 -static void synthesize_cpus(struct perf_record_cpu_map_data *data, - const struct perf_cpu_map *map) -{ - int i, map_nr =3D perf_cpu_map__nr(map); - - data->cpus_data.nr =3D map_nr; +struct synthesize_cpu_map_data { + const struct perf_cpu_map *map; + int nr; + int min_cpu; + int max_cpu; + int has_any_cpu; + int type; + size_t size; + struct perf_record_cpu_map_data *data; +}; =20 - for (i =3D 0; i < map_nr; i++) - data->cpus_data.cpu[i] =3D perf_cpu_map__cpu(map, i).cpu; +static void synthesize_cpus(struct synthesize_cpu_map_data *data) +{ + data->data->type =3D PERF_CPU_MAP__CPUS; + data->data->cpus_data.nr =3D data->nr; + for (int i =3D 0; i < data->nr; i++) + data->data->cpus_data.cpu[i] =3D perf_cpu_map__cpu(data->map, i).cpu; } =20 -static void synthesize_mask(struct perf_record_cpu_map_data *data, - const struct perf_cpu_map *map, int max) +static void synthesize_mask(struct synthesize_cpu_map_data *data) { int idx; struct perf_cpu cpu; =20 /* Due to padding, the 4bytes per entry mask variant is always smaller. */ - data->mask32_data.nr =3D BITS_TO_U32(max); - data->mask32_data.long_size =3D 4; + data->data->type =3D PERF_CPU_MAP__MASK; + data->data->mask32_data.nr =3D BITS_TO_U32(data->max_cpu); + data->data->mask32_data.long_size =3D 4; =20 - perf_cpu_map__for_each_cpu(cpu, idx, map) { + perf_cpu_map__for_each_cpu(cpu, idx, data->map) { int bit_word =3D cpu.cpu / 32; - __u32 bit_mask =3D 1U << (cpu.cpu & 31); + u32 bit_mask =3D 1U << (cpu.cpu & 31); =20 - data->mask32_data.mask[bit_word] |=3D bit_mask; + data->data->mask32_data.mask[bit_word] |=3D bit_mask; } } =20 -static size_t cpus_size(const struct perf_cpu_map *map) +static void synthesize_range_cpus(struct synthesize_cpu_map_data *data) { - return sizeof(struct cpu_map_entries) + perf_cpu_map__nr(map) * sizeof(u1= 6); + data->data->type =3D PERF_CPU_MAP__RANGE_CPUS; + data->data->range_cpu_data.any_cpu =3D data->has_any_cpu; + data->data->range_cpu_data.start_cpu =3D data->min_cpu; + data->data->range_cpu_data.end_cpu =3D data->max_cpu; } =20 -static size_t mask_size(const struct perf_cpu_map *map, int *max) -{ - *max =3D perf_cpu_map__max(map).cpu; - return sizeof(struct perf_record_mask_cpu_map32) + BITS_TO_U32(*max) * si= zeof(__u32); -} - -static void *cpu_map_data__alloc(const struct perf_cpu_map *map, size_t *s= ize, - u16 *type, int *max) +static void *cpu_map_data__alloc(struct synthesize_cpu_map_data *syn_data, + size_t header_size) { size_t size_cpus, size_mask; - bool is_dummy =3D perf_cpu_map__empty(map); =20 - /* - * Both array and mask data have variable size based - * on the number of cpus and their actual values. - * The size of the 'struct perf_record_cpu_map_data' is: - * - * array =3D size of 'struct cpu_map_entries' + - * number of cpus * sizeof(u64) - * - * mask =3D size of 'struct perf_record_record_cpu_map' + - * maximum cpu bit converted to size of longs - * - * and finally + the size of 'struct perf_record_cpu_map_data'. - */ - size_cpus =3D cpus_size(map); - size_mask =3D mask_size(map, max); + syn_data->nr =3D perf_cpu_map__nr(syn_data->map); + syn_data->has_any_cpu =3D (perf_cpu_map__cpu(syn_data->map, 0).cpu =3D=3D= -1) ? 1 : 0; =20 - if (is_dummy || (size_cpus < size_mask)) { - *size +=3D size_cpus; - *type =3D PERF_CPU_MAP__CPUS; - } else { - *size +=3D size_mask; - *type =3D PERF_CPU_MAP__MASK; + syn_data->min_cpu =3D perf_cpu_map__cpu(syn_data->map, syn_data->has_any_= cpu).cpu; + syn_data->max_cpu =3D perf_cpu_map__max(syn_data->map).cpu; + if (syn_data->max_cpu - syn_data->min_cpu + 1 =3D=3D syn_data->nr - syn_d= ata->has_any_cpu) { + /* A consecutive range of CPUs can be encoded using a range. */ + assert(sizeof(u16) + sizeof(struct perf_record_range_cpu_map) =3D=3D siz= eof(u64)); + syn_data->type =3D PERF_CPU_MAP__RANGE_CPUS; + syn_data->size =3D header_size + sizeof(u64); + return zalloc(syn_data->size); } =20 - *size +=3D sizeof(__u16); /* For perf_record_cpu_map_data.type. */ - *size =3D PERF_ALIGN(*size, sizeof(u64)); - return zalloc(*size); + size_cpus =3D sizeof(u16) + sizeof(struct cpu_map_entries) + syn_data->nr= * sizeof(u16); + /* Due to padding, the 4bytes per entry mask variant is always smaller. */ + size_mask =3D sizeof(u16) + sizeof(struct perf_record_mask_cpu_map32) + + BITS_TO_U32(syn_data->max_cpu) * sizeof(__u32); + if (syn_data->has_any_cpu || size_cpus < size_mask) { + /* Follow the CPU map encoding. */ + syn_data->type =3D PERF_CPU_MAP__CPUS; + syn_data->size =3D header_size + PERF_ALIGN(size_cpus, sizeof(u64)); + return zalloc(syn_data->size); + } + /* Encode using a bitmask. */ + syn_data->type =3D PERF_CPU_MAP__MASK; + syn_data->size =3D header_size + PERF_ALIGN(size_mask, sizeof(u64)); + return zalloc(syn_data->size); } =20 -static void cpu_map_data__synthesize(struct perf_record_cpu_map_data *data, - const struct perf_cpu_map *map, - u16 type, int max) +static void cpu_map_data__synthesize(struct synthesize_cpu_map_data *data) { - data->type =3D type; - - switch (type) { + switch (data->type) { case PERF_CPU_MAP__CPUS: - synthesize_cpus(data, map); + synthesize_cpus(data); break; case PERF_CPU_MAP__MASK: - synthesize_mask(data, map, max); + synthesize_mask(data); + break; + case PERF_CPU_MAP__RANGE_CPUS: + synthesize_range_cpus(data); + break; default: break; } @@ -1277,23 +1281,22 @@ static void cpu_map_data__synthesize(struct perf_re= cord_cpu_map_data *data, =20 static struct perf_record_cpu_map *cpu_map_event__new(const struct perf_cp= u_map *map) { - size_t size =3D sizeof(struct perf_event_header); + struct synthesize_cpu_map_data syn_data =3D { .map =3D map }; struct perf_record_cpu_map *event; - int max; - u16 type; =20 - event =3D cpu_map_data__alloc(map, &size, &type, &max); + + event =3D cpu_map_data__alloc(&syn_data, sizeof(struct perf_event_header)= ); if (!event) return NULL; =20 + syn_data.data =3D &event->data; event->header.type =3D PERF_RECORD_CPU_MAP; - event->header.size =3D size; - event->data.type =3D type; - - cpu_map_data__synthesize(&event->data, map, type, max); + event->header.size =3D syn_data.size; + cpu_map_data__synthesize(&syn_data); return event; } =20 + int perf_event__synthesize_cpu_map(struct perf_tool *tool, const struct perf_cpu_map *map, perf_event__handler_t process, @@ -1891,24 +1894,20 @@ int perf_event__synthesize_event_update_name(struct= perf_tool *tool, struct evse int perf_event__synthesize_event_update_cpus(struct perf_tool *tool, struc= t evsel *evsel, perf_event__handler_t process) { - size_t size =3D sizeof(struct perf_event_header) + sizeof(u64) + sizeof(u= 64); + struct synthesize_cpu_map_data syn_data =3D { .map =3D evsel->core.own_cp= us }; struct perf_record_event_update *ev; - int max, err; - u16 type; - - if (!evsel->core.own_cpus) - return 0; + int err; =20 - ev =3D cpu_map_data__alloc(evsel->core.own_cpus, &size, &type, &max); + ev =3D cpu_map_data__alloc(&syn_data, sizeof(struct perf_event_header)); if (!ev) return -ENOMEM; =20 + syn_data.data =3D &ev->cpus.cpus; ev->header.type =3D PERF_RECORD_EVENT_UPDATE; - ev->header.size =3D (u16)size; + ev->header.size =3D (u16)syn_data.size; ev->type =3D PERF_EVENT_UPDATE__CPUS; ev->id =3D evsel->core.id[0]; - - cpu_map_data__synthesize(&ev->cpus.cpus, evsel->core.own_cpus, type, max); + cpu_map_data__synthesize(&syn_data); =20 err =3D process(tool, (union perf_event *)ev, NULL, NULL); free(ev); --=20 2.36.1.476.g0c4daa206d-goog