public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
From: Arnaldo Carvalho de Melo <acme@kernel.org>
To: Wang Nan <wangnan0@huawei.com>
Cc: arnaldo.melo@gmail.com, linux-kernel@vger.kernel.org,
	He Kuang <hekuang@huawei.com>,
	Arnaldo Carvalho de Melo <acme@redhat.com>,
	Jiri Olsa <jolsa@kernel.org>,
	Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>,
	Namhyung Kim <namhyung@kernel.org>, Zefan Li <lizefan@huawei.com>,
	pi3orama@163.com
Subject: Re: [PATCH 02/17] perf tools: Add evlist channel helpers
Date: Fri, 13 May 2016 10:05:16 -0300	[thread overview]
Message-ID: <20160513130516.GH11346@kernel.org> (raw)
In-Reply-To: <1463126174-119290-3-git-send-email-wangnan0@huawei.com>

Em Fri, May 13, 2016 at 07:55:59AM +0000, Wang Nan escreveu:
> In this commit sereval helpers are introduced to support the principle

                 several

> of channel. Channels hold different groups of evsels which configured
> differently. It will be used for overwritable evsels, which allows perf

why not use multiple evlists? An "evlist" is a "list of evsels", why do
we need yet another way of grouping evlists?

- Arnaldo

> record some events continuously while capture snapshot for other events
> when something happen. Tracking events (mmap, mmap2, fork, exit ...)
> are another possible events worth to be put into a separated channel.
> 
> Channels are represented by an array with channel flags. Each channel
> contains evlist->nr_mmaps mmaps. Channels are configured before
> perf_evlist__mmap_ex(). During that function nr_mmaps mmaps for each
> channel are allocated together as a big array.
> perf_evlist__channel_idx() converts index in the big array and the
> channel number. For API functions which accept idx, _ex() versions are
> introduced to accept selecting an mmap from a channel.
> 
> Signed-off-by: Wang Nan <wangnan0@huawei.com>
> Signed-off-by: He Kuang <hekuang@huawei.com>
> Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
> Cc: Jiri Olsa <jolsa@kernel.org>
> Cc: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
> Cc: Namhyung Kim <namhyung@kernel.org>
> Cc: Zefan Li <lizefan@huawei.com>
> Cc: pi3orama@163.com
> ---
>  tools/perf/builtin-record.c |   6 ++
>  tools/perf/util/evlist.c    | 130 ++++++++++++++++++++++++++++++++++++++++++--
>  tools/perf/util/evlist.h    |  58 ++++++++++++++++++++
>  3 files changed, 188 insertions(+), 6 deletions(-)
> 
> diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
> index f3679c4..6e44834 100644
> --- a/tools/perf/builtin-record.c
> +++ b/tools/perf/builtin-record.c
> @@ -316,6 +316,12 @@ try_again:
>  		goto out;
>  	}
>  
> +	perf_evlist__channel_reset(evlist);
> +	rc = perf_evlist__channel_add(evlist, 0, true);
> +	if (rc < 0)
> +		goto out;
> +	rc = 0;
> +
>  	if (perf_evlist__mmap_ex(evlist, opts->mmap_pages, false,
>  				 opts->auxtrace_mmap_pages,
>  				 opts->auxtrace_snapshot_mode) < 0) {
> diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c
> index 5e86972..6c11b9e 100644
> --- a/tools/perf/util/evlist.c
> +++ b/tools/perf/util/evlist.c
> @@ -679,6 +679,33 @@ static struct perf_evsel *perf_evlist__event2evsel(struct perf_evlist *evlist,
>  	return NULL;
>  }
>  
> +int perf_evlist__channel_idx(struct perf_evlist *evlist,
> +			     int *p_channel, int *p_idx)
> +{
> +	int channel = *p_channel;
> +	int _idx = *p_idx;
> +
> +	if (_idx < 0)
> +		return -EINVAL;
> +	/*
> +	 * Negative channel means caller explicitly use real index.
> +	 */
> +	if (channel < 0) {
> +		channel = perf_evlist__idx_channel(evlist, _idx);
> +		_idx = _idx % evlist->nr_mmaps;
> +	}
> +	if (channel < 0)
> +		return channel;
> +	if (channel >= PERF_EVLIST__NR_CHANNELS)
> +		return -E2BIG;
> +	if (_idx >= evlist->nr_mmaps)
> +		return -E2BIG;
> +
> +	*p_channel = channel;
> +	*p_idx = evlist->nr_mmaps * channel + _idx;
> +	return 0;
> +}
> +
>  /* When check_messup is true, 'end' must points to a good entry */
>  static union perf_event *
>  perf_mmap__read(struct perf_mmap *md, bool check_messup, u64 start,
> @@ -756,11 +783,19 @@ __perf_evlist__mmap_read(struct perf_mmap *md, bool overwrite, u64 head,
>  	return perf_mmap__read(md, overwrite, old, head, prev);
>  }
>  
> -union perf_event *perf_evlist__mmap_read(struct perf_evlist *evlist, int idx)
> +union perf_event *perf_evlist__mmap_read_ex(struct perf_evlist *evlist,
> +					    int channel, int idx)
>  {
>  	struct perf_mmap *md = &evlist->mmap[idx];
> -	u64 head;
> -	u64 old = md->prev;
> +	u64 head, old;
> +	int err = perf_evlist__channel_idx(evlist, &channel, &idx);
> +
> +	if (err || !perf_evlist__channel_is_enabled(evlist, channel)) {
> +		pr_err("ERROR: invalid mmap index: channel %d, idx: %d\n",
> +		       channel, idx);
> +		return NULL;
> +	}
> +	old = md->prev;
>  
>  	/*
>  	 * Check if event was unmapped due to a POLLHUP/POLLERR.
> @@ -824,6 +859,11 @@ void perf_evlist__mmap_read_catchup(struct perf_evlist *evlist, int idx)
>  	md->prev = head;
>  }
>  
> +union perf_event *perf_evlist__mmap_read(struct perf_evlist *evlist, int idx)
> +{
> +	return perf_evlist__mmap_read_ex(evlist, -1, idx);
> +}
> +
>  static bool perf_mmap__empty(struct perf_mmap *md)
>  {
>  	return perf_mmap__read_head(md) == md->prev && !md->auxtrace_mmap.base;
> @@ -842,10 +882,18 @@ static void perf_evlist__mmap_put(struct perf_evlist *evlist, int idx)
>  		__perf_evlist__munmap(evlist, idx);
>  }
>  
> -void perf_evlist__mmap_consume(struct perf_evlist *evlist, int idx)
> +void perf_evlist__mmap_consume_ex(struct perf_evlist *evlist,
> +				  int channel, int idx)
>  {
> +	int err = perf_evlist__channel_idx(evlist, &channel, &idx);
>  	struct perf_mmap *md = &evlist->mmap[idx];
>  
> +	if (err || !perf_evlist__channel_is_enabled(evlist, channel)) {
> +		pr_err("ERROR: invalid mmap index: channel %d, idx: %d\n",
> +		       channel, idx);
> +		return;
> +	}
> +
>  	if (!evlist->overwrite) {
>  		u64 old = md->prev;
>  
> @@ -856,6 +904,11 @@ void perf_evlist__mmap_consume(struct perf_evlist *evlist, int idx)
>  		perf_evlist__mmap_put(evlist, idx);
>  }
>  
> +void perf_evlist__mmap_consume(struct perf_evlist *evlist, int idx)
> +{
> +	perf_evlist__mmap_consume_ex(evlist, -1, idx);
> +}
> +
>  int __weak auxtrace_mmap__mmap(struct auxtrace_mmap *mm __maybe_unused,
>  			       struct auxtrace_mmap_params *mp __maybe_unused,
>  			       void *userpg __maybe_unused,
> @@ -901,7 +954,7 @@ void perf_evlist__munmap(struct perf_evlist *evlist)
>  	if (evlist->mmap == NULL)
>  		return;
>  
> -	for (i = 0; i < evlist->nr_mmaps; i++)
> +	for (i = 0; i < perf_evlist__mmap_nr(evlist); i++)
>  		__perf_evlist__munmap(evlist, i);
>  
>  	zfree(&evlist->mmap);
> @@ -909,10 +962,17 @@ void perf_evlist__munmap(struct perf_evlist *evlist)
>  
>  static int perf_evlist__alloc_mmap(struct perf_evlist *evlist)
>  {
> +	int total_mmaps;
> +
>  	evlist->nr_mmaps = cpu_map__nr(evlist->cpus);
>  	if (cpu_map__empty(evlist->cpus))
>  		evlist->nr_mmaps = thread_map__nr(evlist->threads);
> -	evlist->mmap = zalloc(evlist->nr_mmaps * sizeof(struct perf_mmap));
> +
> +	total_mmaps = perf_evlist__mmap_nr(evlist);
> +	if (!total_mmaps)
> +		return -EINVAL;
> +
> +	evlist->mmap = zalloc(total_mmaps * sizeof(struct perf_mmap));
>  	return evlist->mmap != NULL ? 0 : -ENOMEM;
>  }
>  
> @@ -1221,6 +1281,12 @@ int perf_evlist__mmap_ex(struct perf_evlist *evlist, unsigned int pages,
>  int perf_evlist__mmap(struct perf_evlist *evlist, unsigned int pages,
>  		      bool overwrite)
>  {
> +	int err;
> +
> +	perf_evlist__channel_reset(evlist);
> +	err = perf_evlist__channel_add(evlist, 0, true);
> +	if (err < 0)
> +		return err;
>  	return perf_evlist__mmap_ex(evlist, pages, overwrite, 0, false);
>  }
>  
> @@ -1862,3 +1928,55 @@ perf_evlist__find_evsel_by_str(struct perf_evlist *evlist,
>  
>  	return NULL;
>  }
> +
> +int perf_evlist__channel_nr(struct perf_evlist *evlist)
> +{
> +	int i;
> +
> +	for (i = PERF_EVLIST__NR_CHANNELS - 1; i >= 0; i--) {
> +		unsigned long flags = evlist->channel_flags[i];
> +
> +		if (flags & PERF_EVLIST__CHANNEL_ENABLED)
> +			return i + 1;
> +	}
> +	return 0;
> +}
> +
> +int perf_evlist__mmap_nr(struct perf_evlist *evlist)
> +{
> +	return evlist->nr_mmaps * perf_evlist__channel_nr(evlist);
> +}
> +
> +void perf_evlist__channel_reset(struct perf_evlist *evlist)
> +{
> +	int i;
> +
> +	BUG_ON(evlist->mmap);
> +
> +	for (i = 0; i < PERF_EVLIST__NR_CHANNELS; i++)
> +		evlist->channel_flags[i] = 0;
> +}
> +
> +int perf_evlist__channel_add(struct perf_evlist *evlist,
> +			     unsigned long flag,
> +			     bool is_default)
> +{
> +	int n = perf_evlist__channel_nr(evlist);
> +	unsigned long *flags = evlist->channel_flags;
> +
> +	BUG_ON(evlist->mmap);
> +
> +	if (n >= PERF_EVLIST__NR_CHANNELS) {
> +		pr_debug("ERROR: too many channels. Increase PERF_EVLIST__NR_CHANNELS\n");
> +		return -ENOSPC;
> +	}
> +
> +	if (is_default) {
> +		memmove(&flags[1], &flags[0],
> +			sizeof(evlist->channel_flags) -
> +			sizeof(evlist->channel_flags[0]));
> +		n = 0;
> +	}
> +	flags[n] = flag | PERF_EVLIST__CHANNEL_ENABLED;
> +	return n;
> +}
> diff --git a/tools/perf/util/evlist.h b/tools/perf/util/evlist.h
> index 85d1b59..4cb5d3a 100644
> --- a/tools/perf/util/evlist.h
> +++ b/tools/perf/util/evlist.h
> @@ -20,6 +20,11 @@ struct record_opts;
>  #define PERF_EVLIST__HLIST_BITS 8
>  #define PERF_EVLIST__HLIST_SIZE (1 << PERF_EVLIST__HLIST_BITS)
>  
> +#define PERF_EVLIST__NR_CHANNELS	1
> +enum perf_evlist_mmap_flag {
> +	PERF_EVLIST__CHANNEL_ENABLED	= 1,
> +};
> +
>  /**
>   * struct perf_mmap - perf's ring buffer mmap details
>   *
> @@ -52,6 +57,7 @@ struct perf_evlist {
>  		pid_t	pid;
>  	} workload;
>  	struct fdarray	 pollfd;
> +	unsigned long channel_flags[PERF_EVLIST__NR_CHANNELS];
>  	struct perf_mmap *mmap;
>  	struct thread_map *threads;
>  	struct cpu_map	  *cpus;
> @@ -127,13 +133,65 @@ struct perf_evsel *perf_evlist__id2evsel_strict(struct perf_evlist *evlist,
>  
>  struct perf_sample_id *perf_evlist__id2sid(struct perf_evlist *evlist, u64 id);
>  
> +union perf_event *perf_evlist__mmap_read_ex(struct perf_evlist *evlist,
> +					    int channel, int idx);
>  union perf_event *perf_evlist__mmap_read(struct perf_evlist *evlist, int idx);
>  
>  union perf_event *perf_evlist__mmap_read_backward(struct perf_evlist *evlist,
>  						  int idx);
>  void perf_evlist__mmap_read_catchup(struct perf_evlist *evlist, int idx);
>  
> +void perf_evlist__mmap_consume_ex(struct perf_evlist *evlist,
> +				  int channel, int idx);
>  void perf_evlist__mmap_consume(struct perf_evlist *evlist, int idx);
> +int perf_evlist__mmap_nr(struct perf_evlist *evlist);
> +
> +int perf_evlist__channel_nr(struct perf_evlist *evlist);
> +void perf_evlist__channel_reset(struct perf_evlist *evlist);
> +int perf_evlist__channel_add(struct perf_evlist *evlist,
> +			     unsigned long flag,
> +			     bool is_default);
> +
> +static inline bool
> +__perf_evlist__channel_check(struct perf_evlist *evlist, int channel,
> +			     enum perf_evlist_mmap_flag bits)
> +{
> +	if (channel >= PERF_EVLIST__NR_CHANNELS)
> +		return false;
> +
> +	return (evlist->channel_flags[channel] & bits) ? true : false;
> +}
> +#define perf_evlist__channel_check(e, c, b) \
> +		__perf_evlist__channel_check(e, c, PERF_EVLIST__CHANNEL_##b)
> +
> +static inline bool
> +perf_evlist__channel_is_enabled(struct perf_evlist *evlist, int channel)
> +{
> +	return perf_evlist__channel_check(evlist, channel, ENABLED);
> +}
> +
> +static inline int
> +perf_evlist__idx_channel(struct perf_evlist *evlist, int idx)
> +{
> +	int channel = idx / evlist->nr_mmaps;
> +
> +	if (channel >= PERF_EVLIST__NR_CHANNELS)
> +		return -E2BIG;
> +	return channel;
> +}
> +
> +int perf_evlist__channel_idx(struct perf_evlist *evlist,
> +			     int *p_channel, int *p_idx);
> +
> +static inline struct perf_mmap *
> +perf_evlist__get_mmap(struct perf_evlist *evlist,
> +		      int channel, int idx)
> +{
> +	if (perf_evlist__channel_idx(evlist, &channel, &idx))
> +		return NULL;
> +
> +	return &evlist->mmap[idx];
> +}
>  
>  int perf_evlist__open(struct perf_evlist *evlist);
>  void perf_evlist__close(struct perf_evlist *evlist);
> -- 
> 1.8.3.4

  reply	other threads:[~2016-05-13 13:05 UTC|newest]

Thread overview: 28+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-05-13  7:55 [PATCH 00/17] perf tools: Support overwritable ring buffer Wang Nan
2016-05-13  7:55 ` [PATCH 01/17] perf tools: Extract __perf_evlist__mmap_read() Wang Nan
2016-05-13 13:03   ` Arnaldo Carvalho de Melo
2016-05-13  7:55 ` [PATCH 02/17] perf tools: Add evlist channel helpers Wang Nan
2016-05-13 13:05   ` Arnaldo Carvalho de Melo [this message]
2016-05-18  3:27     ` Wangnan (F)
2016-05-18 13:23       ` Arnaldo Carvalho de Melo
2016-05-13  7:56 ` [PATCH 03/17] perf tools: Automatically add new channel according to evlist Wang Nan
2016-05-13  7:56 ` [PATCH 04/17] perf tools: Operate multiple channels Wang Nan
2016-05-13  7:56 ` [PATCH 05/17] perf record: Prevent reading invalid data in record__mmap_read Wang Nan
2016-05-13  7:56 ` [PATCH 06/17] perf tools: Squash overwrite setting into channel Wang Nan
2016-05-13  7:56 ` [PATCH 07/17] perf record: Don't read from and poll overwrite channel Wang Nan
2016-05-13  7:56 ` [PATCH 08/17] perf record: Don't poll on " Wang Nan
2016-05-13 13:12   ` Arnaldo Carvalho de Melo
2016-05-16  3:18     ` Wangnan (F)
2016-05-13  7:56 ` [PATCH 09/17] perf tools: Detect avalibility of write_backward Wang Nan
2016-05-13 13:08   ` Arnaldo Carvalho de Melo
2016-05-20 15:31     ` Wangnan (F)
2016-05-20 15:39       ` Arnaldo Carvalho de Melo
2016-05-13  7:56 ` [PATCH 10/17] perf tools: Enable overwrite settings Wang Nan
2016-05-16 13:38   ` Arnaldo Carvalho de Melo
2016-05-13  7:56 ` [PATCH 11/17] perf tools: Set write_backward attribut bit for overwrite events Wang Nan
2016-05-13  7:56 ` [PATCH 12/17] perf tools: Record fd into perf_mmap Wang Nan
2016-05-13  7:56 ` [PATCH 13/17] perf tools: Add API to pause a channel Wang Nan
2016-05-13  7:56 ` [PATCH 14/17] perf record: Rename variable to make code clear Wang Nan
2016-05-13  7:56 ` [PATCH 15/17] perf record: Read from backward ring buffer Wang Nan
2016-05-13  7:56 ` [PATCH 16/17] perf record: Toggle overwrite ring buffer for reading Wang Nan
2016-05-13  7:56 ` [PATCH 17/17] perf tools: Don't warn about out of order event if write_backward is used Wang Nan

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=20160513130516.GH11346@kernel.org \
    --to=acme@kernel.org \
    --cc=acme@redhat.com \
    --cc=arnaldo.melo@gmail.com \
    --cc=hekuang@huawei.com \
    --cc=jolsa@kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=lizefan@huawei.com \
    --cc=masami.hiramatsu.pt@hitachi.com \
    --cc=namhyung@kernel.org \
    --cc=pi3orama@163.com \
    --cc=wangnan0@huawei.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