All of lore.kernel.org
 help / color / mirror / Atom feed
From: "Liang, Kan" <kan.liang@linux.intel.com>
To: Namhyung Kim <namhyung@kernel.org>,
	Adrian Hunter <adrian.hunter@intel.com>
Cc: Arnaldo Carvalho de Melo <acme@kernel.org>,
	Jiri Olsa <jolsa@redhat.com>, Ian Rogers <irogers@google.com>,
	Alexey Bayduraev <alexey.v.bayduraev@linux.intel.com>,
	Leo Yan <leo.yan@linaro.org>,
	linux-kernel <linux-kernel@vger.kernel.org>,
	Stephane Eranian <eranian@google.com>
Subject: Re: [PATCH V2 22/23] perf tools: Allow system-wide events to keep their own CPUs
Date: Fri, 13 May 2022 13:32:42 -0400	[thread overview]
Message-ID: <c60a4a56-3393-22d4-8b22-be1d174da79d@linux.intel.com> (raw)
In-Reply-To: <CAM9d7ch5OY-AXM075aoZ0VwX3WAaui2c0DXNkKryJpVXO93MOA@mail.gmail.com>



On 5/13/2022 12:42 PM, Namhyung Kim wrote:
> On Fri, May 13, 2022 at 9:11 AM Adrian Hunter <adrian.hunter@intel.com> wrote:
>>
>> On 13/05/22 18:46, Liang, Kan wrote:
>>>
>>>
>>> On 5/13/2022 11:21 AM, Adrian Hunter wrote:
>>>> On 13/05/22 17:12, Liang, Kan wrote:
>>>>>
>>>>>
>>>>> On 5/13/2022 12:48 AM, Adrian Hunter wrote:
>>>>>> On 12/05/22 21:53, Namhyung Kim wrote:
>>>>>>> On Thu, May 12, 2022 at 3:35 AM Adrian Hunter <adrian.hunter@intel.com> wrote:
>>>>>>>>
>>>>>>>> On 12/05/22 08:27, Namhyung Kim wrote:
>>>>>>>>> On Fri, May 6, 2022 at 5:27 AM Adrian Hunter <adrian.hunter@intel.com> wrote:
>>>>>>>>>>
>>>>>>>>>> Currently, user_requested_cpus supplants system-wide CPUs when the evlist
>>>>>>>>>> has_user_cpus. Change that so that system-wide events retain their own
>>>>>>>>>> CPUs and they are added to all_cpus.
>>>>>>>>>>
>>>>>>>>>> Acked-by: Ian Rogers <irogers@google.com>
>>>>>>>>>> Signed-off-by: Adrian Hunter <adrian.hunter@intel.com>
>>>>>>>>>> ---
>>>>>>>>>>     tools/lib/perf/evlist.c | 11 +++++------
>>>>>>>>>>     1 file changed, 5 insertions(+), 6 deletions(-)
>>>>>>>>>>
>>>>>>>>>> diff --git a/tools/lib/perf/evlist.c b/tools/lib/perf/evlist.c
>>>>>>>>>> index 1c801f8da44f..9a6801b53274 100644
>>>>>>>>>> --- a/tools/lib/perf/evlist.c
>>>>>>>>>> +++ b/tools/lib/perf/evlist.c
>>>>>>>>>> @@ -40,12 +40,11 @@ static void __perf_evlist__propagate_maps(struct perf_evlist *evlist,
>>>>>>>>>>             * We already have cpus for evsel (via PMU sysfs) so
>>>>>>>>>>             * keep it, if there's no target cpu list defined.
>>>>>>>>>>             */
>>>>>>>>>> -       if (!evsel->own_cpus || evlist->has_user_cpus) {
>>>>>>>>>> -               perf_cpu_map__put(evsel->cpus);
>>>>>>>>>> -               evsel->cpus = perf_cpu_map__get(evlist->user_requested_cpus);
>>>>>>>>>> -       } else if (!evsel->system_wide &&
>>>>>>>>>> -                  !evsel->requires_cpu &&
>>>>>>>>>> -                  perf_cpu_map__empty(evlist->user_requested_cpus)) {
>>>>>>>>>> +       if (!evsel->own_cpus ||
>>>>>>>>>> +           (!evsel->system_wide && evlist->has_user_cpus) ||
>>>>>>>>>> +           (!evsel->system_wide &&
>>>>>>>>>> +            !evsel->requires_cpu &&
>>>>>>>>>> +            perf_cpu_map__empty(evlist->user_requested_cpus))) {
>>>>>>>>>
>>>>>>>>> This is getting hard to understand.  IIUC this propagation basically
>>>>>>>>> sets user requested cpus to evsel unless it has its own cpus, right?
>>>>>>>>
>>>>>>>> I put the conditional logic altogether because that is kernel style but
>>>>>>>> it does make it practically unreadable.
>>>>>>>>
>>>>>>>> If we start with the original logic:
>>>>>>>>
>>>>>>>>            if (!evsel->own_cpus || evlist->has_user_cpus) {
>>>>>>>>                    perf_cpu_map__put(evsel->cpus);
>>>>>>>>                    evsel->cpus = perf_cpu_map__get(evlist->user_requested_cpus);
>>>>>>>>            } else if (!evsel->system_wide && perf_cpu_map__empty(evlist->user_requested_cpus)) {
>>>>>>>>                    perf_cpu_map__put(evsel->cpus);
>>>>>>>>                    evsel->cpus = perf_cpu_map__get(evlist->user_requested_cpus);
>>>>>>>>            } else if (evsel->cpus != evsel->own_cpus) {
>>>>>>>>                    perf_cpu_map__put(evsel->cpus);
>>>>>>>>                    evsel->cpus = perf_cpu_map__get(evsel->own_cpus);
>>>>>>>>            }
>>>>>>>>
>>>>>>>> Then make it more readable, i.e. same functionality
>>>>>>>>
>>>>>>>>            struct perf_cpu_map *cpus;
>>>>>>>>
>>>>>>>>            if (!evsel->own_cpus || evlist->has_user_cpus)
>>>>>>>>                    cpus = evlist->user_requested_cpus;
>>>>>>>>            else if (!evsel->system_wide && perf_cpu_map__empty(evlist->user_requested_cpus))
>>>>>>>>                    cpus = evlist->user_requested_cpus;
>>>>>>>>            else
>>>>>>>>                    cpus = evsel->own_cpus;
>>>>>>>>
>>>>>>>>            if (evsel->cpus != cpus) {
>>>>>>>>                    perf_cpu_map__put(evsel->cpus);
>>>>>>>>                    evsel->cpus = perf_cpu_map__get(cpus);
>>>>>>>>            }
>>>>>>>>
>>>>>>>> Then separate out the conditions, i.e. still same functionality
>>>>>>>>
>>>>>>>>            if (!evsel->own_cpus)
>>>>>>>>                    cpus = evlist->user_requested_cpus;
>>>>>>>>            else if (evlist->has_user_cpus)
>>>>>>>>                    cpus = evlist->user_requested_cpus;
>>>>>>>>            else if (evsel->system_wide)
>>>>>>>>                    cpus = evsel->own_cpus;
>>>>>>>>            else if (perf_cpu_map__empty(evlist->user_requested_cpus)) /* per-thread */
>>>>>>>>                    cpus = evlist->user_requested_cpus;
>>>>>>>>            else
>>>>>>>>                    cpus = evsel->own_cpus;
>>>>>>>>
>>>>>>>> Then add the new requires_cpu flag:
>>>>>>>>
>>>>>>>>            if (!evsel->own_cpus)
>>>>>>>>                    cpus = evlist->user_requested_cpus;
>>>>>>>>            else if (evlist->has_user_cpus)
>>>>>>>>                    cpus = evlist->user_requested_cpus;
>>>>>>>>            else if (evsel->system_wide)
>>>>>>>>                    cpus = evsel->own_cpus;
>>>>>>>> -       else if (perf_cpu_map__empty(evlist->user_requested_cpus)) /* per-thread */
>>>>>>>> +       else if (!evsel->requres_cpu && perf_cpu_map__empty(evlist->user_requested_cpus)) /* per-thread */
>>>>>>>>                    cpus = evlist->user_requested_cpus;
>>>>>>>>            else
>>>>>>>>                    cpus = evsel->own_cpus;
>>>>>>>>
>>>>>>>> Then make system_wide keep own_cpus even if has_user_cpus:
>>>>>>>>
>>>>>>>>            if (!evsel->own_cpus)
>>>>>>>>                    cpus = evlist->user_requested_cpus;
>>>>>>>> +       else if (evsel->system_wide)
>>>>>>>> +               cpus = evsel->own_cpus;
>>>>>>>>            else if (evlist->has_user_cpus)
>>>>>>>>                    cpus = evlist->user_requested_cpus;
>>>>>>>> -       else if (evsel->system_wide)
>>>>>>>> -               cpus = evsel->own_cpus;
>>>>>>>>            else if (!evsel->requres_cpu && perf_cpu_map__empty(evlist->user_requested_cpus)) /* per-thread */
>>>>>>>>                    cpus = evlist->user_requested_cpus;
>>>>>>>>            else
>>>>>>>>                    cpus = evsel->own_cpus;
>>>>>>>>
>>>>>>>> Which leaves:
>>>>>>>>
>>>>>>>>            if (!evsel->own_cpus)
>>>>>>>>                    cpus = evlist->user_requested_cpus;
>>>>>>>>            else if (evsel->system_wide)
>>>>>>>>                    cpus = evsel->own_cpus;
>>>>>>>>            else if (evlist->has_user_cpus)
>>>>>>>>                    cpus = evlist->user_requested_cpus;
>>>>>>>>            else if (!evsel->requres_cpu && perf_cpu_map__empty(evlist->user_requested_cpus)) /* per-thread */
>>>>>>>>                    cpus = evlist->user_requested_cpus;
>>>>>>>>            else
>>>>>>>>                    cpus = evsel->own_cpus;
>>>>>>>>
>>>>>>>> And putting it back together:
>>>>>>>>
>>>>>>>>            if (!evsel->own_cpus ||
>>>>>>>>                (!evsel->system_wide && evlist->has_user_cpus) ||
>>>>>>>>                (!evsel->system_wide &&
>>>>>>>>                 !evsel->requires_cpu &&
>>>>>>>>                 perf_cpu_map__empty(evlist->user_requested_cpus))) {
>>>>>>>>                    cpus = evlist->user_requested_cpus;
>>>>>>>>            else
>>>>>>>>                    cpus = evsel->own_cpus;
>>>>>>>>
>>>>>>>> Perhaps I shouldn't put it together?
>>>>>>>
>>>>>>> Cool, thanks a lot for explaining it in detail.
>>>>>>> I do not oppose your change but little worried about the
>>>>>>> complexity.  And I think we have some issues with uncore
>>>>>>> events already.
>>>>>>
>>>>>> Yes it is a bit complicated because we are handling
>>>>>> many different use cases.
>>>>>>
>>>>>>>
>>>>>>> So do you have any idea where evsel->own_cpus
>>>>>>> doesn't propagate to evsel->cpus?
>>>>>>
>>>>>> We let the user's list of CPUs override it i.e. the
>>>>>> evlist->has_user_cpus case.  Essentially we are expecting
>>>>>> the user to know what they are doing.
>>>>>>
>>>>>>>
>>>>>>> I think evsel->system_wide and evsel->requires_cpu
>>>>>>> can be replaced to check evsel->own_cpus instead.
>>>>>>
>>>>>> Not at the moment because we let the user override
>>>>>> own_cpus.
>>>>>
>>>>> Do we check whether the user's input is valid (match the PMU's cpumask) before the override?
>>>>>
>>>>> I think we know the PMU name. The cpumask of the PMU can be found in the sysfs. So we should have enough information for a sanity check.
>>>>
>>>> For the uncore PMU case, I am not sure what sanity is :-)
>>>>
>>>
>>> For a non-core PMU, e.g., uncore, cstate, power and etc. The cpumask is under the /sys/devices/<PMU>/cpumask. It shows the cpumask which kernel supports. If a end user request a different CPU other that the cpumask, I think it's better throw a waning. It should mitigate the confusion which Namhyung mentioned (uncore -C1,2).
>>
>> So you couldn't get uncore events unless you are also coincidentally wanting to trace CPU 0.
>>
>> I guess really the requrement is not to perf_event_open() an uncore PMU more than once?
>> To figure that out we'd need to be able map CPUs to uncore PMUs?
> 
> We might just use evsel->own_cpus for uncore events and
> if the user-given cpu list contains other cpus it can show an
> warning.
>

Yes, it sounds reasonable.


Thanks,
Kan

  reply	other threads:[~2022-05-13 17:32 UTC|newest]

Thread overview: 70+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-05-06 12:25 [PATCH V2 00/23] perf intel-pt: Better support for perf record --cpu Adrian Hunter
2022-05-06 12:25 ` [PATCH V2 01/23] perf intel-pt: Add a test for system-wide side band Adrian Hunter
2022-05-10 17:18   ` Arnaldo Carvalho de Melo
2022-05-10 17:21     ` Adrian Hunter
2022-05-06 12:25 ` [PATCH V2 02/23] libperf evsel: Add perf_evsel__enable_thread() Adrian Hunter
2022-05-06 17:06   ` Ian Rogers
2022-05-10 17:19   ` Arnaldo Carvalho de Melo
2022-05-06 12:25 ` [PATCH V2 03/23] perf evlist: Use libperf functions in evlist__enable_event_idx() Adrian Hunter
2022-05-10 17:23   ` Arnaldo Carvalho de Melo
2022-05-06 12:25 ` [PATCH V2 04/23] perf auxtrace: Move evlist__enable_event_idx() to auxtrace.c Adrian Hunter
2022-05-10 17:24   ` Arnaldo Carvalho de Melo
2022-05-06 12:25 ` [PATCH V2 05/23] perf auxtrace: Do not mix up mmap idx Adrian Hunter
2022-05-10 17:25   ` Arnaldo Carvalho de Melo
2022-05-06 12:25 ` [PATCH V2 06/23] libperf evlist: Remove ->idx() per_cpu parameter Adrian Hunter
2022-05-10 17:26   ` Arnaldo Carvalho de Melo
2022-05-06 12:25 ` [PATCH V2 07/23] libperf evlist: Move ->idx() into mmap_per_evsel() Adrian Hunter
2022-05-10 17:26   ` Arnaldo Carvalho de Melo
2022-05-06 12:25 ` [PATCH V2 08/23] libperf evlist: Add evsel as a parameter to ->idx() Adrian Hunter
2022-05-10 17:26   ` Arnaldo Carvalho de Melo
2022-05-06 12:25 ` [PATCH V2 09/23] perf auxtrace: Record whether an auxtrace mmap is needed Adrian Hunter
2022-05-10 17:27   ` Arnaldo Carvalho de Melo
2022-05-06 12:25 ` [PATCH V2 10/23] perf auxtrace: Add mmap_needed to auxtrace_mmap_params Adrian Hunter
2022-05-06 20:16   ` Ian Rogers
2022-05-11  7:02     ` Adrian Hunter
2022-05-11  7:01   ` [PATCH V3 " Adrian Hunter
2022-05-06 12:25 ` [PATCH V2 11/23] perf auxtrace: Remove auxtrace_mmap_params__set_idx() per_cpu parameter Adrian Hunter
2022-05-06 20:19   ` Ian Rogers
2022-05-06 12:25 ` [PATCH V2 12/23] perf evlist: Factor out evlist__dummy_event() Adrian Hunter
2022-05-06 12:25 ` [PATCH V2 13/23] perf evlist: Add evlist__add_dummy_on_all_cpus() Adrian Hunter
2022-05-06 13:47   ` Ian Rogers
2022-05-06 15:07     ` Adrian Hunter
2022-05-06 15:35       ` Ian Rogers
2022-05-10 14:55         ` Adrian Hunter
2022-05-10 16:19           ` Ian Rogers
2022-05-10 16:24           ` Arnaldo Carvalho de Melo
2022-05-10 17:32             ` Adrian Hunter
2022-05-11  7:02   ` [PATCH V3 " Adrian Hunter
2022-05-11 22:50     ` Namhyung Kim
2022-05-12  4:33       ` Adrian Hunter
2022-05-12  5:01         ` Namhyung Kim
2022-05-06 12:25 ` [PATCH V2 14/23] perf record: Use evlist__add_dummy_on_all_cpus() in record__config_text_poke() Adrian Hunter
2022-05-06 12:25 ` [PATCH V2 15/23] perf intel-pt: Use evlist__add_dummy_on_all_cpus() for switch tracking Adrian Hunter
2022-05-06 12:25 ` [PATCH V2 16/23] perf intel-pt: Track sideband system-wide when needed Adrian Hunter
2022-05-06 12:25 ` [PATCH V2 17/23] perf tools: Allow all_cpus to be a superset of user_requested_cpus Adrian Hunter
2022-05-06 12:25 ` [PATCH V2 18/23] libperf evlist: Allow mixing per-thread and per-cpu mmaps Adrian Hunter
2022-05-06 12:25 ` [PATCH V2 19/23] libperf evlist: Check nr_mmaps is correct Adrian Hunter
2022-05-06 20:20   ` Ian Rogers
2022-05-06 12:25 ` [PATCH V2 20/23] perf stat: Add requires_cpu flag for uncore Adrian Hunter
2022-05-06 12:25 ` [PATCH V2 21/23] libperf evsel: Add comments for booleans Adrian Hunter
2022-05-06 20:51   ` Ian Rogers
2022-05-11  7:03     ` Adrian Hunter
2022-05-12  5:34       ` Ian Rogers
2022-05-12 11:40         ` Adrian Hunter
2022-05-06 12:26 ` [PATCH V2 22/23] perf tools: Allow system-wide events to keep their own CPUs Adrian Hunter
2022-05-12  5:27   ` Namhyung Kim
2022-05-12 10:34     ` Adrian Hunter
2022-05-12 18:53       ` Namhyung Kim
2022-05-13  4:48         ` Adrian Hunter
2022-05-13 14:12           ` Liang, Kan
2022-05-13 15:21             ` Adrian Hunter
2022-05-13 15:46               ` Liang, Kan
2022-05-13 16:11                 ` Adrian Hunter
2022-05-13 16:42                   ` Namhyung Kim
2022-05-13 17:32                     ` Liang, Kan [this message]
2022-05-14 13:35           ` Arnaldo Carvalho de Melo
2022-05-17 23:31             ` Namhyung Kim
2022-05-06 12:26 ` [PATCH V2 23/23] perf tools: Allow system-wide events to keep their own threads Adrian Hunter
2022-05-08 15:08 ` [PATCH V2 00/23] perf intel-pt: Better support for perf record --cpu Leo Yan
2022-05-09  5:44   ` Adrian Hunter
2022-05-09  8:46     ` Leo Yan

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=c60a4a56-3393-22d4-8b22-be1d174da79d@linux.intel.com \
    --to=kan.liang@linux.intel.com \
    --cc=acme@kernel.org \
    --cc=adrian.hunter@intel.com \
    --cc=alexey.v.bayduraev@linux.intel.com \
    --cc=eranian@google.com \
    --cc=irogers@google.com \
    --cc=jolsa@redhat.com \
    --cc=leo.yan@linaro.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=namhyung@kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.