Received: by 2002:a05:7412:8d10:b0:f3:1519:9f41 with SMTP id bj16csp5324787rdb; Wed, 13 Dec 2023 05:48:48 -0800 (PST) X-Google-Smtp-Source: AGHT+IEdFzqH1uhvPcbHryYVzXN9bN4PDKxRCsJPaGhXek/Rg9hJ4m9TX3K6ViaFCGtFVrlGpLw7 X-Received: by 2002:a17:90a:5d93:b0:286:a962:d4de with SMTP id t19-20020a17090a5d9300b00286a962d4demr3866720pji.49.1702475327644; Wed, 13 Dec 2023 05:48:47 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1702475327; cv=none; d=google.com; s=arc-20160816; b=PKMjF3UWrjKkzO+2n+SAeAcF6pq9MUiCGYrXkA1b+TgU9MH1EeY2TcKhnRg4amwR2f x4WJp9ffs9LIZaCrEn6f2dwthYg2f8yPbxhNY4liivzlp6/gAaElJOb4E7EMJz4jDyfe ZvlPWcZm7TOqtqrtAGc9gvxpwTou+jRfv2x2TvkxcvZHCq6GtCoIRGjOMX3M7cT4B9Oj gILkhuTdY8Xd0b9mZBXIXCCRXXfk6fgMA6IkxrypvsOevurO0y7QJlBJh6zVZ73CXMOW urTswDxvO0sdHZV1NUBu+Ffeikn7Vp3dpNx93fp4nVJSDrbwOO64qWGqKVOlgyws3kGI 5h7w== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:in-reply-to:from :references:cc:to:content-language:subject:user-agent:mime-version :date:message-id; bh=szTyDIIiIlU5Q8hmzUoY0Qrpng589u62l8CPA6RC+74=; fh=5EP3x1uDWWBI9dywppNETb2J5CyUqdqYJErdwPGhe68=; b=0+eXJlQGxM1TRSAZOlY8BYUXHVV903M33F8qnQjaWMI9Ks513J0WTptIu5TUvFPC4d CoyYRjd8pkIgcACiF//Z41klIVR+b66/485p9FgEf9FJOnQvsC2cB1NuW5N0ba0DvCMM GegMUqHz6UcP4nd1/rH8O97KnscPiY5alf2XbT0xmgSCJgriVTcNTc71Y5eRPiIh6Bvr 5RqS2H3JOawfvxc6tDB11fMKTRVlNt56vF0wcEPGsrcDQDzb1VUuk4AAzoqoT9BpkuJV 7s29V3mbku0+5o0cm9rL9Yzggndlu4XV+xb6YMEHJwIqNH80MEOhQCggp//v1FJf40E8 h11g== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::3:8 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=arm.com Return-Path: Received: from fry.vger.email (fry.vger.email. [2620:137:e000::3:8]) by mx.google.com with ESMTPS id ot6-20020a17090b3b4600b00286942b512dsi1857891pjb.6.2023.12.13.05.48.46 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 13 Dec 2023 05:48:47 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::3:8 as permitted sender) client-ip=2620:137:e000::3:8; Authentication-Results: mx.google.com; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::3:8 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=arm.com Received: from out1.vger.email (depot.vger.email [IPv6:2620:137:e000::3:0]) by fry.vger.email (Postfix) with ESMTP id 68A9D804082A; Wed, 13 Dec 2023 05:48:44 -0800 (PST) X-Virus-Status: Clean X-Virus-Scanned: clamav-milter 0.103.11 at fry.vger.email Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1378983AbjLMNs2 (ORCPT + 99 others); Wed, 13 Dec 2023 08:48:28 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:43812 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1378960AbjLMNs1 (ORCPT ); Wed, 13 Dec 2023 08:48:27 -0500 Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by lindbergh.monkeyblade.net (Postfix) with ESMTP id E88E8EA; Wed, 13 Dec 2023 05:48:32 -0800 (PST) Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id 92B8FC15; Wed, 13 Dec 2023 05:49:18 -0800 (PST) Received: from [192.168.1.3] (unknown [172.31.20.19]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id 2E8DE3F738; Wed, 13 Dec 2023 05:48:27 -0800 (PST) Message-ID: Date: Wed, 13 Dec 2023 13:48:22 +0000 MIME-Version: 1.0 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:102.0) Gecko/20100101 Thunderbird/102.15.1 Subject: Re: [PATCH v1 06/14] libperf cpumap: Add any, empty and min helpers Content-Language: en-US To: Ian Rogers Cc: Peter Zijlstra , Ingo Molnar , Arnaldo Carvalho de Melo , Mark Rutland , Alexander Shishkin , Jiri Olsa , Namhyung Kim , Adrian Hunter , Suzuki K Poulose , Mike Leach , Leo Yan , John Garry , Will Deacon , Thomas Gleixner , Darren Hart , Davidlohr Bueso , =?UTF-8?Q?Andr=c3=a9_Almeida?= , Kan Liang , K Prateek Nayak , Sean Christopherson , Paolo Bonzini , Kajol Jain , Athira Rajeev , Andrew Jones , Alexandre Ghiti , Atish Patra , "Steinar H. Gunderson" , Yang Jihong , Yang Li , Changbin Du , Sandipan Das , Ravi Bangoria , Paran Lee , Nick Desaulniers , Huacai Chen , Yanteng Si , linux-perf-users@vger.kernel.org, linux-kernel@vger.kernel.org, coresight@lists.linaro.org, linux-arm-kernel@lists.infradead.org, bpf@vger.kernel.org References: <20231129060211.1890454-1-irogers@google.com> <20231129060211.1890454-7-irogers@google.com> <94e3745c-8c2b-bdf3-f331-1cbe56574d48@arm.com> From: James Clark In-Reply-To: Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-Spam-Status: No, score=-1.5 required=5.0 tests=HEADER_FROM_DIFFERENT_DOMAINS, MAILING_LIST_MULTI,NICE_REPLY_A,SPF_HELO_NONE,SPF_PASS, T_SCC_BODY_TEXT_LINE autolearn=unavailable autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on fry.vger.email Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org X-Greylist: Sender passed SPF test, not delayed by milter-greylist-4.6.4 (fry.vger.email [0.0.0.0]); Wed, 13 Dec 2023 05:48:44 -0800 (PST) On 12/12/2023 20:27, Ian Rogers wrote: > On Tue, Dec 12, 2023 at 7:06 AM James Clark wrote: >> >> >> >> On 29/11/2023 06:02, Ian Rogers wrote: >>> Additional helpers to better replace >>> perf_cpu_map__has_any_cpu_or_is_empty. >>> >>> Signed-off-by: Ian Rogers >>> --- >>> tools/lib/perf/cpumap.c | 27 +++++++++++++++++++++++++++ >>> tools/lib/perf/include/perf/cpumap.h | 16 ++++++++++++++++ >>> tools/lib/perf/libperf.map | 4 ++++ >>> 3 files changed, 47 insertions(+) >>> >>> diff --git a/tools/lib/perf/cpumap.c b/tools/lib/perf/cpumap.c >>> index 49fc98e16514..7403819da8fd 100644 >>> --- a/tools/lib/perf/cpumap.c >>> +++ b/tools/lib/perf/cpumap.c >>> @@ -316,6 +316,19 @@ bool perf_cpu_map__has_any_cpu_or_is_empty(const struct perf_cpu_map *map) >>> return map ? __perf_cpu_map__cpu(map, 0).cpu == -1 : true; >>> } >>> >>> +bool perf_cpu_map__is_any_cpu_or_is_empty(const struct perf_cpu_map *map) >>> +{ >>> + if (!map) >>> + return true; >>> + >>> + return __perf_cpu_map__nr(map) == 1 && __perf_cpu_map__cpu(map, 0).cpu == -1; >>> +} >> >> I'm struggling to understand the relevance of the difference between >> has_any and is_any I see that there is a slight difference, but could it >> not be refactored out so we only need one? > > Yep, that's what these changes are working toward. For has any the set > {-1, 0, 1} would return true while is any will return false. > Previously the has any behavior was called "empty" which I think is > actively misleading. > >> Do you ever get an 'any' map that has more than 1 entry? It's quite a >> subtle difference that is_any returns false if the first one is 'any' >> but then there are subsequent entries. Whereas has_any would return >> true. I'm not sure if future readers would be able to appreciate that. >> >> I see has_any is only used twice, both on evlist->all_cpus. Is there >> something about that member that means it could have a map that has an >> 'any' mixed with CPUs? Wouldn't that have the same result as a normal >> 'any' anyway? > > The dummy event may be opened on any CPU but then a particular event > may be opened on certain CPUs. We merge CPU maps in places like evlist > so that we can iterate the appropriate CPUs for events and > open/enable/disable/close all events on a certain CPU at the same time > (we also set the affinity to that CPU to avoid IPIs). What I'm hoping > to do in these changes is reduce the ambiguity, the corner cases are > by their nature unusual. > > An example of a corner case is, uncore events often get opened just on > CPU 0 but on a multi-socket system you may have a CPU 32 that also > needs to open the event. Previous code treated the CPU map index and > value it contained pretty interchangeably. This is often fine for the > core PMU but is clearly wrong in this uncore case, {0, 32} has indexes > 0 and 1 but those indexes don't match the CPU numbers. The case of -1 > has often previously been called dummy but I'm trying to call it the > "any CPU" case to match the perf_event_open man page (I'm hoping it > also makes it less ambiguous with any CPU being used with a particular > event like cycles, calling it dummy makes the event sound like it may > have sideband data). The difference between "all CPUs" and "any CPU" > is that an evsel for all CPUs would need the event opening > individually on each CPU, while any CPU events are a single open call. > Any CPU is only valid to perf_event_open if a PID is specified. > Depending on the set up there could be overlaps in what they count but > hopefully it is clearer what the distinction is. I believe the case of > "any CPU" and specific CPU numbers is more common with aux buffers and > Adrian has mentioned needing it for intel-pt. > > Thanks, > Ian > Thanks for explaining. I suppose I didn't realise that 'any' could be merged with per-cpu maps, but it makes sense. >>> + >>> +bool perf_cpu_map__is_empty(const struct perf_cpu_map *map) >>> +{ >>> + return map == NULL; >>> +} >>> + >>> int perf_cpu_map__idx(const struct perf_cpu_map *cpus, struct perf_cpu cpu) >>> { >>> int low, high; >>> @@ -372,6 +385,20 @@ bool perf_cpu_map__has_any_cpu(const struct perf_cpu_map *map) >>> return map && __perf_cpu_map__cpu(map, 0).cpu == -1; >>> } >>> >>> +struct perf_cpu perf_cpu_map__min(const struct perf_cpu_map *map) >>> +{ >>> + struct perf_cpu cpu, result = { >>> + .cpu = -1 >>> + }; >>> + int idx; >>> + >>> + perf_cpu_map__for_each_cpu_skip_any(cpu, idx, map) { >>> + result = cpu; >>> + break; >>> + } >>> + return result; >>> +} >>> + >>> struct perf_cpu perf_cpu_map__max(const struct perf_cpu_map *map) >>> { >>> struct perf_cpu result = { >>> diff --git a/tools/lib/perf/include/perf/cpumap.h b/tools/lib/perf/include/perf/cpumap.h >>> index dbe0a7352b64..523e4348fc96 100644 >>> --- a/tools/lib/perf/include/perf/cpumap.h >>> +++ b/tools/lib/perf/include/perf/cpumap.h >>> @@ -50,6 +50,22 @@ LIBPERF_API int perf_cpu_map__nr(const struct perf_cpu_map *cpus); >>> * perf_cpu_map__has_any_cpu_or_is_empty - is map either empty or has the "any CPU"/dummy value. >>> */ >>> LIBPERF_API bool perf_cpu_map__has_any_cpu_or_is_empty(const struct perf_cpu_map *map); >>> +/** >>> + * perf_cpu_map__is_any_cpu_or_is_empty - is map either empty or the "any CPU"/dummy value. >>> + */ >>> +LIBPERF_API bool perf_cpu_map__is_any_cpu_or_is_empty(const struct perf_cpu_map *map); >>> +/** >>> + * perf_cpu_map__is_empty - does the map contain no values and it doesn't >>> + * contain the special "any CPU"/dummy value. >>> + */ >>> +LIBPERF_API bool perf_cpu_map__is_empty(const struct perf_cpu_map *map); >>> +/** >>> + * perf_cpu_map__min - the minimum CPU value or -1 if empty or just the "any CPU"/dummy value. >>> + */ >>> +LIBPERF_API struct perf_cpu perf_cpu_map__min(const struct perf_cpu_map *map); >>> +/** >>> + * perf_cpu_map__max - the maximum CPU value or -1 if empty or just the "any CPU"/dummy value. >>> + */ >>> LIBPERF_API struct perf_cpu perf_cpu_map__max(const struct perf_cpu_map *map); >>> LIBPERF_API bool perf_cpu_map__has(const struct perf_cpu_map *map, struct perf_cpu cpu); >>> LIBPERF_API bool perf_cpu_map__equal(const struct perf_cpu_map *lhs, >>> diff --git a/tools/lib/perf/libperf.map b/tools/lib/perf/libperf.map >>> index 10b3f3722642..2aa79b696032 100644 >>> --- a/tools/lib/perf/libperf.map >>> +++ b/tools/lib/perf/libperf.map >>> @@ -10,6 +10,10 @@ LIBPERF_0.0.1 { >>> perf_cpu_map__nr; >>> perf_cpu_map__cpu; >>> perf_cpu_map__has_any_cpu_or_is_empty; >>> + perf_cpu_map__is_any_cpu_or_is_empty; >>> + perf_cpu_map__is_empty; >>> + perf_cpu_map__has_any_cpu; >>> + perf_cpu_map__min; >>> perf_cpu_map__max; >>> perf_cpu_map__has; >>> perf_thread_map__new_array;