linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Arnaldo Carvalho de Melo <arnaldo.melo@gmail.com>
To: kan.liang@linux.intel.com
Cc: jolsa@redhat.com, peterz@infradead.org, mingo@redhat.com,
	linux-kernel@vger.kernel.org, namhyung@kernel.org,
	adrian.hunter@intel.com, mathieu.poirier@linaro.org,
	ravi.bangoria@linux.ibm.com, alexey.budankov@linux.intel.com,
	vitaly.slobodskoy@intel.com, pavel.gerasimov@intel.com,
	mpe@ellerman.id.au, eranian@google.com, ak@linux.intel.com
Subject: Re: [PATCH V3 01/17] perf pmu: Add support for PMU capabilities
Date: Wed, 18 Mar 2020 16:47:22 -0300	[thread overview]
Message-ID: <20200318194722.GR11531@kernel.org> (raw)
In-Reply-To: <20200313183319.17739-2-kan.liang@linux.intel.com>

Em Fri, Mar 13, 2020 at 11:33:03AM -0700, kan.liang@linux.intel.com escreveu:
> From: Kan Liang <kan.liang@linux.intel.com>
> 
> The PMU capabilities information, which is located at
> /sys/bus/event_source/devices/<dev>/caps, is required by perf tool.
> For example, the max LBR information is required to stitch LBR call
> stack.
> 
> Add perf_pmu__caps_parse() to parse the PMU capabilities information.
> The information is stored in a list.
> 
> Add perf_pmu__scan_caps() to scan the capabilities one by one.
> 
> The following patch will store the capabilities information in perf
> header.
> 
> Reviewed-by: Andi Kleen <ak@linux.intel.com>
> Signed-off-by: Kan Liang <kan.liang@linux.intel.com>
> ---
>  tools/perf/util/pmu.c | 98 +++++++++++++++++++++++++++++++++++++++++++
>  tools/perf/util/pmu.h | 12 ++++++
>  2 files changed, 110 insertions(+)
> 
> diff --git a/tools/perf/util/pmu.c b/tools/perf/util/pmu.c
> index 8b99fd312aae..4cdfbb669567 100644
> --- a/tools/perf/util/pmu.c
> +++ b/tools/perf/util/pmu.c
> @@ -844,6 +844,7 @@ static struct perf_pmu *pmu_lookup(const char *name)
>  
>  	INIT_LIST_HEAD(&pmu->format);
>  	INIT_LIST_HEAD(&pmu->aliases);
> +	INIT_LIST_HEAD(&pmu->caps);
>  	list_splice(&format, &pmu->format);
>  	list_splice(&aliases, &pmu->aliases);
>  	list_add_tail(&pmu->list, &pmus);
> @@ -1565,3 +1566,100 @@ int perf_pmu__scan_file(struct perf_pmu *pmu, const char *name, const char *fmt,
>  	va_end(args);
>  	return ret;
>  }
> +
> +static int perf_pmu__new_caps(struct list_head *list, char *name, char *value)
> +{
> +	struct perf_pmu_caps *caps;
> +
> +	caps = zalloc(sizeof(*caps));
> +	if (!caps)
> +		return -ENOMEM;

Since there will be a v4 for other reasons, please combine the
declaration plus assignment when possible, like above, i.e. make it:

+	struct perf_pmu_caps *caps = zalloc(sizeof(*caps));
+
+	if (!caps)
+		return -ENOMEM;

> +
> +	caps->name = strdup(name);
> +	if (!caps->name)
> +		goto free_caps;
> +	caps->value = strndup(value, strlen(value) - 1);
> +	if (!caps->value)
> +		goto free_name;
> +	list_add_tail(&caps->list, list);
> +	return 0;
> +
> +free_name:
> +	free(caps->name);

In these cases I think this is preferred:

	zfree(&caps->name);

> +free_caps:
> +	free(caps);
> +
> +	return -ENOMEM;
> +}
> +
> +/*
> + * Reading/parsing the given pmu capabilities, which should be located at:
> + * /sys/bus/event_source/devices/<dev>/caps as sysfs group attributes.
> + * Return the number of capabilities
> + */
> +int perf_pmu__caps_parse(struct perf_pmu *pmu)
> +{
> +	struct stat st;
> +	char caps_path[PATH_MAX];
> +	const char *sysfs = sysfs__mountpoint();
> +	DIR *caps_dir;
> +	struct dirent *evt_ent;
> +	int nr_caps = 0;
> +
> +	if (!sysfs)
> +		return -1;
> +
> +	snprintf(caps_path, PATH_MAX,
> +		 "%s" EVENT_SOURCE_DEVICE_PATH "%s/caps", sysfs, pmu->name);
> +
> +	if (stat(caps_path, &st) < 0)
> +		return 0;	/* no error if caps does not exist */
> +
> +	caps_dir = opendir(caps_path);
> +	if (!caps_dir)
> +		return -EINVAL;
> +
> +	while ((evt_ent = readdir(caps_dir)) != NULL) {
> +		char path[PATH_MAX + NAME_MAX + 1];
> +		char *name = evt_ent->d_name;
> +		char value[128];
> +		FILE *file;
> +
> +		if (!strcmp(name, ".") || !strcmp(name, ".."))
> +			continue;
> +
> +		snprintf(path, sizeof(path), "%s/%s", caps_path, name);
> +
> +		file = fopen(path, "r");
> +		if (!file)
> +			break;

I haven't looked at what is in such directories that would justify still
returning whatever was read so far when failing to read one of its
files, is this sensible? Care to explain a bit why you think so? Looks
fishy :-\

> +
> +		if (!fgets(value, sizeof(value), file) ||
> +		    (perf_pmu__new_caps(&pmu->caps, name, value) < 0)) {
> +			fclose(file);
> +			break;
> +		}
> +
> +		nr_caps++;
> +		fclose(file);
> +	}
> +
> +	closedir(caps_dir);
> +
> +	return nr_caps;
> +}
> +
> +struct perf_pmu_caps *perf_pmu__scan_caps(struct perf_pmu *pmu,
> +					  struct perf_pmu_caps *caps)
> +{
> +	if (!pmu)
> +		return NULL;
> +
> +	if (!caps)
> +		caps = list_prepare_entry(caps, &pmu->caps, list);
> +
> +	list_for_each_entry_continue(caps, &pmu->caps, list)
> +		return caps;

Why not:

	return caps ? list_next_entry(caps) : list_first_entry(&pmu->caps, struct perf_pmu_caps, list);

Nah, it'll return the head after the last entry, not NULL, argh.

Anyway, looks like a confusing API :-\

I'll see how it is used in the following patches...

> +
> +	return NULL;
> +}
> diff --git a/tools/perf/util/pmu.h b/tools/perf/util/pmu.h
> index 6737e3d5d568..a228e27ae462 100644
> --- a/tools/perf/util/pmu.h
> +++ b/tools/perf/util/pmu.h
> @@ -21,6 +21,12 @@ enum {
>  
>  struct perf_event_attr;
>  
> +struct perf_pmu_caps {
> +	char *name;
> +	char *value;
> +	struct list_head list;
> +};
> +
>  struct perf_pmu {
>  	char *name;
>  	__u32 type;
> @@ -32,6 +38,7 @@ struct perf_pmu {
>  	struct perf_cpu_map *cpus;
>  	struct list_head format;  /* HEAD struct perf_pmu_format -> list */
>  	struct list_head aliases; /* HEAD struct perf_pmu_alias -> list */
> +	struct list_head caps;    /* HEAD struct perf_pmu_caps -> list */
>  	struct list_head list;    /* ELEM */
>  };
>  
> @@ -102,4 +109,9 @@ struct pmu_events_map *perf_pmu__find_map(struct perf_pmu *pmu);
>  
>  int perf_pmu__convert_scale(const char *scale, char **end, double *sval);
>  
> +int perf_pmu__caps_parse(struct perf_pmu *pmu);
> +
> +struct perf_pmu_caps *perf_pmu__scan_caps(struct perf_pmu *pmu,
> +					  struct perf_pmu_caps *caps);
> +
>  #endif /* __PMU_H */
> -- 
> 2.17.1
> 

-- 

- Arnaldo

  reply	other threads:[~2020-03-18 19:47 UTC|newest]

Thread overview: 26+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-03-13 18:33 [PATCH V3 00/17] Stitch LBR call stack (Perf Tools) kan.liang
2020-03-13 18:33 ` [PATCH V3 01/17] perf pmu: Add support for PMU capabilities kan.liang
2020-03-18 19:47   ` Arnaldo Carvalho de Melo [this message]
2020-03-19 13:07     ` Liang, Kan
2020-03-13 18:33 ` [PATCH V3 02/17] perf header: Support CPU " kan.liang
2020-03-18 19:49   ` Arnaldo Carvalho de Melo
2020-03-13 18:33 ` [PATCH V3 03/17] perf record: Clear HEADER_CPU_PMU_CAPS for non LBR call stack mode kan.liang
2020-03-13 18:33 ` [PATCH V3 04/17] perf stat: Clear HEADER_CPU_PMU_CAPS kan.liang
2020-03-13 18:33 ` [PATCH V3 05/17] perf machine: Remove the indent in resolve_lbr_callchain_sample kan.liang
2020-03-18 19:50   ` Arnaldo Carvalho de Melo
2020-03-13 18:33 ` [PATCH V3 06/17] perf machine: Refine the function for LBR call stack reconstruction kan.liang
2020-03-13 18:33 ` [PATCH V3 07/17] perf machine: Factor out lbr_callchain_add_kernel_ip() kan.liang
2020-03-13 18:33 ` [PATCH V3 08/17] perf machine: Factor out lbr_callchain_add_lbr_ip() kan.liang
2020-03-13 18:33 ` [PATCH V3 09/17] perf thread: Add a knob for LBR stitch approach kan.liang
2020-03-13 18:33 ` [PATCH V3 10/17] perf tools: Save previous sample for LBR stitching approach kan.liang
2020-03-18 12:14   ` Jiri Olsa
2020-03-18 14:20     ` Liang, Kan
2020-03-13 18:33 ` [PATCH V3 11/17] perf tools: Save previous cursor nodes " kan.liang
2020-03-13 18:33 ` [PATCH V3 12/17] perf tools: Stitch LBR call stack kan.liang
2020-03-13 18:33 ` [PATCH V3 13/17] perf report: Add option to enable the LBR stitching approach kan.liang
2020-03-13 18:33 ` [PATCH V3 14/17] perf script: " kan.liang
2020-03-13 18:33 ` [PATCH V3 15/17] perf top: " kan.liang
2020-03-18 12:14   ` Jiri Olsa
2020-03-18 14:19     ` Liang, Kan
2020-03-13 18:33 ` [PATCH V3 16/17] perf c2c: " kan.liang
2020-03-13 18:33 ` [PATCH V3 17/17] perf hist: Add fast path for duplicate entries check kan.liang

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=20200318194722.GR11531@kernel.org \
    --to=arnaldo.melo@gmail.com \
    --cc=adrian.hunter@intel.com \
    --cc=ak@linux.intel.com \
    --cc=alexey.budankov@linux.intel.com \
    --cc=eranian@google.com \
    --cc=jolsa@redhat.com \
    --cc=kan.liang@linux.intel.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=mathieu.poirier@linaro.org \
    --cc=mingo@redhat.com \
    --cc=mpe@ellerman.id.au \
    --cc=namhyung@kernel.org \
    --cc=pavel.gerasimov@intel.com \
    --cc=peterz@infradead.org \
    --cc=ravi.bangoria@linux.ibm.com \
    --cc=vitaly.slobodskoy@intel.com \
    /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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).