linux-perf-users.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH] libperf: Add API for allocating new thread map
@ 2022-02-10  8:52 Tzvetomir Stoyanov (VMware)
  2022-02-15  4:53 ` Tzvetomir Stoyanov
  2022-02-15 12:18 ` Jiri Olsa
  0 siblings, 2 replies; 5+ messages in thread
From: Tzvetomir Stoyanov (VMware) @ 2022-02-10  8:52 UTC (permalink / raw)
  To: acme, jolsa; +Cc: linux-perf-users, linux-kernel

The existing API perf_thread_map__new_dummy() allocates new thread map
for one thread. I couldn't find a way to reallocate the map with more
threads, or to allocate a new map for more than one thread. Having
multiple threads in a thread map is essential for some use cases.
That's why a new API is proposed, which allocates a new thread map
for given number of threads:
 perf_thread_map__new()

Signed-off-by: Tzvetomir Stoyanov (VMware) <tz.stoyanov@gmail.com>
---
 tools/lib/perf/Documentation/libperf.txt |  1 +
 tools/lib/perf/include/perf/threadmap.h  |  1 +
 tools/lib/perf/libperf.map               |  1 +
 tools/lib/perf/tests/test-threadmap.c    | 27 ++++++++++++++++++++++++
 tools/lib/perf/threadmap.c               | 15 +++++++++----
 5 files changed, 41 insertions(+), 4 deletions(-)

diff --git a/tools/lib/perf/Documentation/libperf.txt b/tools/lib/perf/Documentation/libperf.txt
index 32c5051c24eb..9cbd41c29bff 100644
--- a/tools/lib/perf/Documentation/libperf.txt
+++ b/tools/lib/perf/Documentation/libperf.txt
@@ -62,6 +62,7 @@ SYNOPSIS
   struct perf_thread_map;
 
   struct perf_thread_map *perf_thread_map__new_dummy(void);
+  struct perf_thread_map *perf_thread_map__new(int nr);
 
   void perf_thread_map__set_pid(struct perf_thread_map *map, int thread, pid_t pid);
   char *perf_thread_map__comm(struct perf_thread_map *map, int thread);
diff --git a/tools/lib/perf/include/perf/threadmap.h b/tools/lib/perf/include/perf/threadmap.h
index a7c50de8d010..47d433416040 100644
--- a/tools/lib/perf/include/perf/threadmap.h
+++ b/tools/lib/perf/include/perf/threadmap.h
@@ -8,6 +8,7 @@
 struct perf_thread_map;
 
 LIBPERF_API struct perf_thread_map *perf_thread_map__new_dummy(void);
+LIBPERF_API struct perf_thread_map *perf_thread_map__new(int nr);
 
 LIBPERF_API void perf_thread_map__set_pid(struct perf_thread_map *map, int thread, pid_t pid);
 LIBPERF_API char *perf_thread_map__comm(struct perf_thread_map *map, int thread);
diff --git a/tools/lib/perf/libperf.map b/tools/lib/perf/libperf.map
index 93696affda2e..240a2f087b70 100644
--- a/tools/lib/perf/libperf.map
+++ b/tools/lib/perf/libperf.map
@@ -11,6 +11,7 @@ LIBPERF_0.0.1 {
 		perf_cpu_map__empty;
 		perf_cpu_map__max;
 		perf_cpu_map__has;
+		perf_thread_map__new;
 		perf_thread_map__new_dummy;
 		perf_thread_map__set_pid;
 		perf_thread_map__comm;
diff --git a/tools/lib/perf/tests/test-threadmap.c b/tools/lib/perf/tests/test-threadmap.c
index 5e2a0291e94c..3388bf36dfc0 100644
--- a/tools/lib/perf/tests/test-threadmap.c
+++ b/tools/lib/perf/tests/test-threadmap.c
@@ -11,9 +11,12 @@ static int libperf_print(enum libperf_print_level level,
 	return vfprintf(stderr, fmt, ap);
 }
 
+#define THREADS_NR	5
+
 int test_threadmap(int argc, char **argv)
 {
 	struct perf_thread_map *threads;
+	int i;
 
 	__T_START;
 
@@ -27,6 +30,30 @@ int test_threadmap(int argc, char **argv)
 	perf_thread_map__put(threads);
 	perf_thread_map__put(threads);
 
+	threads = perf_thread_map__new(THREADS_NR);
+	if (!threads)
+		tests_failed++;
+
+	if (perf_thread_map__nr(threads) != THREADS_NR)
+		tests_failed++;
+
+	for (i = 0; i < THREADS_NR; i++) {
+		if (perf_thread_map__pid(threads, i) != -1)
+			tests_failed++;
+	}
+
+	for (i = 1; i < THREADS_NR; i++)
+		perf_thread_map__set_pid(threads, i, i * 100);
+
+	if (perf_thread_map__pid(threads, 0) != -1)
+		tests_failed++;
+
+	for (i = 1; i < THREADS_NR; i++) {
+		if (perf_thread_map__pid(threads, i) != i * 100)
+			tests_failed++;
+	}
+	perf_thread_map__put(threads);
+
 	__T_END;
 	return tests_failed == 0 ? 0 : -1;
 }
diff --git a/tools/lib/perf/threadmap.c b/tools/lib/perf/threadmap.c
index e92c368b0a6c..843fe1070cc9 100644
--- a/tools/lib/perf/threadmap.c
+++ b/tools/lib/perf/threadmap.c
@@ -42,18 +42,25 @@ char *perf_thread_map__comm(struct perf_thread_map *map, int thread)
 	return map->map[thread].comm;
 }
 
-struct perf_thread_map *perf_thread_map__new_dummy(void)
+struct perf_thread_map *perf_thread_map__new(int nr)
 {
-	struct perf_thread_map *threads = thread_map__alloc(1);
+	struct perf_thread_map *threads = thread_map__alloc(nr);
+	int i;
 
 	if (threads != NULL) {
-		perf_thread_map__set_pid(threads, 0, -1);
-		threads->nr = 1;
+		for (i = 0; i < nr; i++)
+			perf_thread_map__set_pid(threads, i, -1);
+		threads->nr = nr;
 		refcount_set(&threads->refcnt, 1);
 	}
 	return threads;
 }
 
+struct perf_thread_map *perf_thread_map__new_dummy(void)
+{
+	return perf_thread_map__new(1);
+}
+
 static void perf_thread_map__delete(struct perf_thread_map *threads)
 {
 	if (threads) {
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* Re: [PATCH] libperf: Add API for allocating new thread map
  2022-02-10  8:52 [PATCH] libperf: Add API for allocating new thread map Tzvetomir Stoyanov (VMware)
@ 2022-02-15  4:53 ` Tzvetomir Stoyanov
  2022-02-15 12:18 ` Jiri Olsa
  1 sibling, 0 replies; 5+ messages in thread
From: Tzvetomir Stoyanov @ 2022-02-15  4:53 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo, Jiri Olsa, Ian Rogers
  Cc: linux-perf-users, linux-kernel

A gentle ping.
I'll be glad for any comments or suggestions for a possible workaround
of this problem.
Thanks!

On Thu, Feb 10, 2022 at 10:52 AM Tzvetomir Stoyanov (VMware)
<tz.stoyanov@gmail.com> wrote:
>
> The existing API perf_thread_map__new_dummy() allocates new thread map
> for one thread. I couldn't find a way to reallocate the map with more
> threads, or to allocate a new map for more than one thread. Having
> multiple threads in a thread map is essential for some use cases.
> That's why a new API is proposed, which allocates a new thread map
> for given number of threads:
>  perf_thread_map__new()
>
> Signed-off-by: Tzvetomir Stoyanov (VMware) <tz.stoyanov@gmail.com>
> ---
>  tools/lib/perf/Documentation/libperf.txt |  1 +
>  tools/lib/perf/include/perf/threadmap.h  |  1 +
>  tools/lib/perf/libperf.map               |  1 +
>  tools/lib/perf/tests/test-threadmap.c    | 27 ++++++++++++++++++++++++
>  tools/lib/perf/threadmap.c               | 15 +++++++++----
>  5 files changed, 41 insertions(+), 4 deletions(-)
>
> diff --git a/tools/lib/perf/Documentation/libperf.txt b/tools/lib/perf/Documentation/libperf.txt
> index 32c5051c24eb..9cbd41c29bff 100644
> --- a/tools/lib/perf/Documentation/libperf.txt
> +++ b/tools/lib/perf/Documentation/libperf.txt
> @@ -62,6 +62,7 @@ SYNOPSIS
>    struct perf_thread_map;
>
>    struct perf_thread_map *perf_thread_map__new_dummy(void);
> +  struct perf_thread_map *perf_thread_map__new(int nr);
>
>    void perf_thread_map__set_pid(struct perf_thread_map *map, int thread, pid_t pid);
>    char *perf_thread_map__comm(struct perf_thread_map *map, int thread);
> diff --git a/tools/lib/perf/include/perf/threadmap.h b/tools/lib/perf/include/perf/threadmap.h
> index a7c50de8d010..47d433416040 100644
> --- a/tools/lib/perf/include/perf/threadmap.h
> +++ b/tools/lib/perf/include/perf/threadmap.h
> @@ -8,6 +8,7 @@
>  struct perf_thread_map;
>
>  LIBPERF_API struct perf_thread_map *perf_thread_map__new_dummy(void);
> +LIBPERF_API struct perf_thread_map *perf_thread_map__new(int nr);
>
>  LIBPERF_API void perf_thread_map__set_pid(struct perf_thread_map *map, int thread, pid_t pid);
>  LIBPERF_API char *perf_thread_map__comm(struct perf_thread_map *map, int thread);
> diff --git a/tools/lib/perf/libperf.map b/tools/lib/perf/libperf.map
> index 93696affda2e..240a2f087b70 100644
> --- a/tools/lib/perf/libperf.map
> +++ b/tools/lib/perf/libperf.map
> @@ -11,6 +11,7 @@ LIBPERF_0.0.1 {
>                 perf_cpu_map__empty;
>                 perf_cpu_map__max;
>                 perf_cpu_map__has;
> +               perf_thread_map__new;
>                 perf_thread_map__new_dummy;
>                 perf_thread_map__set_pid;
>                 perf_thread_map__comm;
> diff --git a/tools/lib/perf/tests/test-threadmap.c b/tools/lib/perf/tests/test-threadmap.c
> index 5e2a0291e94c..3388bf36dfc0 100644
> --- a/tools/lib/perf/tests/test-threadmap.c
> +++ b/tools/lib/perf/tests/test-threadmap.c
> @@ -11,9 +11,12 @@ static int libperf_print(enum libperf_print_level level,
>         return vfprintf(stderr, fmt, ap);
>  }
>
> +#define THREADS_NR     5
> +
>  int test_threadmap(int argc, char **argv)
>  {
>         struct perf_thread_map *threads;
> +       int i;
>
>         __T_START;
>
> @@ -27,6 +30,30 @@ int test_threadmap(int argc, char **argv)
>         perf_thread_map__put(threads);
>         perf_thread_map__put(threads);
>
> +       threads = perf_thread_map__new(THREADS_NR);
> +       if (!threads)
> +               tests_failed++;
> +
> +       if (perf_thread_map__nr(threads) != THREADS_NR)
> +               tests_failed++;
> +
> +       for (i = 0; i < THREADS_NR; i++) {
> +               if (perf_thread_map__pid(threads, i) != -1)
> +                       tests_failed++;
> +       }
> +
> +       for (i = 1; i < THREADS_NR; i++)
> +               perf_thread_map__set_pid(threads, i, i * 100);
> +
> +       if (perf_thread_map__pid(threads, 0) != -1)
> +               tests_failed++;
> +
> +       for (i = 1; i < THREADS_NR; i++) {
> +               if (perf_thread_map__pid(threads, i) != i * 100)
> +                       tests_failed++;
> +       }
> +       perf_thread_map__put(threads);
> +
>         __T_END;
>         return tests_failed == 0 ? 0 : -1;
>  }
> diff --git a/tools/lib/perf/threadmap.c b/tools/lib/perf/threadmap.c
> index e92c368b0a6c..843fe1070cc9 100644
> --- a/tools/lib/perf/threadmap.c
> +++ b/tools/lib/perf/threadmap.c
> @@ -42,18 +42,25 @@ char *perf_thread_map__comm(struct perf_thread_map *map, int thread)
>         return map->map[thread].comm;
>  }
>
> -struct perf_thread_map *perf_thread_map__new_dummy(void)
> +struct perf_thread_map *perf_thread_map__new(int nr)
>  {
> -       struct perf_thread_map *threads = thread_map__alloc(1);
> +       struct perf_thread_map *threads = thread_map__alloc(nr);
> +       int i;
>
>         if (threads != NULL) {
> -               perf_thread_map__set_pid(threads, 0, -1);
> -               threads->nr = 1;
> +               for (i = 0; i < nr; i++)
> +                       perf_thread_map__set_pid(threads, i, -1);
> +               threads->nr = nr;
>                 refcount_set(&threads->refcnt, 1);
>         }
>         return threads;
>  }
>
> +struct perf_thread_map *perf_thread_map__new_dummy(void)
> +{
> +       return perf_thread_map__new(1);
> +}
> +
>  static void perf_thread_map__delete(struct perf_thread_map *threads)
>  {
>         if (threads) {
> --
> 2.34.1
>


-- 
Tzvetomir (Ceco) Stoyanov
VMware Open Source Technology Center

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH] libperf: Add API for allocating new thread map
  2022-02-10  8:52 [PATCH] libperf: Add API for allocating new thread map Tzvetomir Stoyanov (VMware)
  2022-02-15  4:53 ` Tzvetomir Stoyanov
@ 2022-02-15 12:18 ` Jiri Olsa
  2022-02-16 13:54   ` Arnaldo Carvalho de Melo
  1 sibling, 1 reply; 5+ messages in thread
From: Jiri Olsa @ 2022-02-15 12:18 UTC (permalink / raw)
  To: Tzvetomir Stoyanov (VMware); +Cc: acme, jolsa, linux-perf-users, linux-kernel

On Thu, Feb 10, 2022 at 10:52:25AM +0200, Tzvetomir Stoyanov (VMware) wrote:
> The existing API perf_thread_map__new_dummy() allocates new thread map
> for one thread. I couldn't find a way to reallocate the map with more
> threads, or to allocate a new map for more than one thread. Having
> multiple threads in a thread map is essential for some use cases.
> That's why a new API is proposed, which allocates a new thread map
> for given number of threads:
>  perf_thread_map__new()

I'm ok with that, just wondering if we should call it 'perf_thread_map__new_nr'
because we already have perf_cpu_map__new(const char *cpu_list) so
it might be better to keep perf_cpu_map and perf_thread_map in sync

Arnaldo, thoughts on this?

jirka

> 
> Signed-off-by: Tzvetomir Stoyanov (VMware) <tz.stoyanov@gmail.com>
> ---
>  tools/lib/perf/Documentation/libperf.txt |  1 +
>  tools/lib/perf/include/perf/threadmap.h  |  1 +
>  tools/lib/perf/libperf.map               |  1 +
>  tools/lib/perf/tests/test-threadmap.c    | 27 ++++++++++++++++++++++++
>  tools/lib/perf/threadmap.c               | 15 +++++++++----
>  5 files changed, 41 insertions(+), 4 deletions(-)
> 
> diff --git a/tools/lib/perf/Documentation/libperf.txt b/tools/lib/perf/Documentation/libperf.txt
> index 32c5051c24eb..9cbd41c29bff 100644
> --- a/tools/lib/perf/Documentation/libperf.txt
> +++ b/tools/lib/perf/Documentation/libperf.txt
> @@ -62,6 +62,7 @@ SYNOPSIS
>    struct perf_thread_map;
>  
>    struct perf_thread_map *perf_thread_map__new_dummy(void);
> +  struct perf_thread_map *perf_thread_map__new(int nr);
>  
>    void perf_thread_map__set_pid(struct perf_thread_map *map, int thread, pid_t pid);
>    char *perf_thread_map__comm(struct perf_thread_map *map, int thread);
> diff --git a/tools/lib/perf/include/perf/threadmap.h b/tools/lib/perf/include/perf/threadmap.h
> index a7c50de8d010..47d433416040 100644
> --- a/tools/lib/perf/include/perf/threadmap.h
> +++ b/tools/lib/perf/include/perf/threadmap.h
> @@ -8,6 +8,7 @@
>  struct perf_thread_map;
>  
>  LIBPERF_API struct perf_thread_map *perf_thread_map__new_dummy(void);
> +LIBPERF_API struct perf_thread_map *perf_thread_map__new(int nr);
>  
>  LIBPERF_API void perf_thread_map__set_pid(struct perf_thread_map *map, int thread, pid_t pid);
>  LIBPERF_API char *perf_thread_map__comm(struct perf_thread_map *map, int thread);
> diff --git a/tools/lib/perf/libperf.map b/tools/lib/perf/libperf.map
> index 93696affda2e..240a2f087b70 100644
> --- a/tools/lib/perf/libperf.map
> +++ b/tools/lib/perf/libperf.map
> @@ -11,6 +11,7 @@ LIBPERF_0.0.1 {
>  		perf_cpu_map__empty;
>  		perf_cpu_map__max;
>  		perf_cpu_map__has;
> +		perf_thread_map__new;
>  		perf_thread_map__new_dummy;
>  		perf_thread_map__set_pid;
>  		perf_thread_map__comm;
> diff --git a/tools/lib/perf/tests/test-threadmap.c b/tools/lib/perf/tests/test-threadmap.c
> index 5e2a0291e94c..3388bf36dfc0 100644
> --- a/tools/lib/perf/tests/test-threadmap.c
> +++ b/tools/lib/perf/tests/test-threadmap.c
> @@ -11,9 +11,12 @@ static int libperf_print(enum libperf_print_level level,
>  	return vfprintf(stderr, fmt, ap);
>  }
>  
> +#define THREADS_NR	5
> +
>  int test_threadmap(int argc, char **argv)
>  {
>  	struct perf_thread_map *threads;
> +	int i;
>  
>  	__T_START;
>  
> @@ -27,6 +30,30 @@ int test_threadmap(int argc, char **argv)
>  	perf_thread_map__put(threads);
>  	perf_thread_map__put(threads);
>  
> +	threads = perf_thread_map__new(THREADS_NR);
> +	if (!threads)
> +		tests_failed++;
> +
> +	if (perf_thread_map__nr(threads) != THREADS_NR)
> +		tests_failed++;
> +
> +	for (i = 0; i < THREADS_NR; i++) {
> +		if (perf_thread_map__pid(threads, i) != -1)
> +			tests_failed++;
> +	}
> +
> +	for (i = 1; i < THREADS_NR; i++)
> +		perf_thread_map__set_pid(threads, i, i * 100);
> +
> +	if (perf_thread_map__pid(threads, 0) != -1)
> +		tests_failed++;
> +
> +	for (i = 1; i < THREADS_NR; i++) {
> +		if (perf_thread_map__pid(threads, i) != i * 100)
> +			tests_failed++;
> +	}
> +	perf_thread_map__put(threads);
> +
>  	__T_END;
>  	return tests_failed == 0 ? 0 : -1;
>  }
> diff --git a/tools/lib/perf/threadmap.c b/tools/lib/perf/threadmap.c
> index e92c368b0a6c..843fe1070cc9 100644
> --- a/tools/lib/perf/threadmap.c
> +++ b/tools/lib/perf/threadmap.c
> @@ -42,18 +42,25 @@ char *perf_thread_map__comm(struct perf_thread_map *map, int thread)
>  	return map->map[thread].comm;
>  }
>  
> -struct perf_thread_map *perf_thread_map__new_dummy(void)
> +struct perf_thread_map *perf_thread_map__new(int nr)
>  {
> -	struct perf_thread_map *threads = thread_map__alloc(1);
> +	struct perf_thread_map *threads = thread_map__alloc(nr);
> +	int i;
>  
>  	if (threads != NULL) {
> -		perf_thread_map__set_pid(threads, 0, -1);
> -		threads->nr = 1;
> +		for (i = 0; i < nr; i++)
> +			perf_thread_map__set_pid(threads, i, -1);
> +		threads->nr = nr;
>  		refcount_set(&threads->refcnt, 1);
>  	}
>  	return threads;
>  }
>  
> +struct perf_thread_map *perf_thread_map__new_dummy(void)
> +{
> +	return perf_thread_map__new(1);
> +}
> +
>  static void perf_thread_map__delete(struct perf_thread_map *threads)
>  {
>  	if (threads) {
> -- 
> 2.34.1
> 

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH] libperf: Add API for allocating new thread map
  2022-02-15 12:18 ` Jiri Olsa
@ 2022-02-16 13:54   ` Arnaldo Carvalho de Melo
  2022-02-16 14:44     ` Tzvetomir Stoyanov
  0 siblings, 1 reply; 5+ messages in thread
From: Arnaldo Carvalho de Melo @ 2022-02-16 13:54 UTC (permalink / raw)
  To: Jiri Olsa
  Cc: Tzvetomir Stoyanov (VMware), Jiri Olsa, Ian Rogers, Namhyung Kim,
	linux-perf-users, linux-kernel

Em Tue, Feb 15, 2022 at 01:18:31PM +0100, Jiri Olsa escreveu:
> On Thu, Feb 10, 2022 at 10:52:25AM +0200, Tzvetomir Stoyanov (VMware) wrote:
> > The existing API perf_thread_map__new_dummy() allocates new thread map
> > for one thread. I couldn't find a way to reallocate the map with more
> > threads, or to allocate a new map for more than one thread. Having
> > multiple threads in a thread map is essential for some use cases.
> > That's why a new API is proposed, which allocates a new thread map
> > for given number of threads:
> >  perf_thread_map__new()
> 
> I'm ok with that, just wondering if we should call it 'perf_thread_map__new_nr'
> because we already have perf_cpu_map__new(const char *cpu_list) so
> it might be better to keep perf_cpu_map and perf_thread_map in sync
 
> Arnaldo, thoughts on this?

Agreed on trying to have similar semantics for the default, main
constructor, so we probably need perf_thread_map__new(const char *thread_list).

In tools/perf/util/thread_map.c, from where tools/lib/threadmap.c came
from we have many alternative constructors:

⬢[acme@toolbox perf]$ grep 'struct perf_thread_map \*thread_map__new' tools/perf/util/thread_map.c
struct perf_thread_map *thread_map__new_by_pid(pid_t pid)
struct perf_thread_map *thread_map__new_by_tid(pid_t tid)
struct perf_thread_map *thread_map__new_all_cpus(void)
struct perf_thread_map *thread_map__new_by_uid(uid_t uid)
struct perf_thread_map *thread_map__new(pid_t pid, pid_t tid, uid_t uid)
static struct perf_thread_map *thread_map__new_by_pid_str(const char *pid_str)
struct perf_thread_map *thread_map__new_by_tid_str(const char *tid_str)
struct perf_thread_map *thread_map__new_str(const char *pid, const char *tid,
struct perf_thread_map *thread_map__new_event(struct perf_record_thread_map *event)
⬢[acme@toolbox perf]$

The one you want is almost:

	thread_map__new_by_tid_str(const char *tid_str)

but perhaps it would be better to have:

struct perf_thread_map *thread_map__new_array(int nr_threads, pid_t *array);

But yeah, if your logic needs to first allocate space for the thread_map
and then populate it, make it so that array == NULL is supported for
that case, then thread_map__new_array() will not touch it and set
everything to -1, to be populated later using perf_thread_map__set_pid().

With that thread_map__new_by_tid_str() could be reimplemented as a
wrapper around thread_map__new_array(). :-)

While we're on this, shouldn't we rename 'thread' in
tools/lib/perf/include/perf/threadmap.h and threadmap.c to be 'idx' to
avoid confusion?

- Arnaldo
 
> jirka
> 
> > 
> > Signed-off-by: Tzvetomir Stoyanov (VMware) <tz.stoyanov@gmail.com>
> > ---
> >  tools/lib/perf/Documentation/libperf.txt |  1 +
> >  tools/lib/perf/include/perf/threadmap.h  |  1 +
> >  tools/lib/perf/libperf.map               |  1 +
> >  tools/lib/perf/tests/test-threadmap.c    | 27 ++++++++++++++++++++++++
> >  tools/lib/perf/threadmap.c               | 15 +++++++++----
> >  5 files changed, 41 insertions(+), 4 deletions(-)
> > 
> > diff --git a/tools/lib/perf/Documentation/libperf.txt b/tools/lib/perf/Documentation/libperf.txt
> > index 32c5051c24eb..9cbd41c29bff 100644
> > --- a/tools/lib/perf/Documentation/libperf.txt
> > +++ b/tools/lib/perf/Documentation/libperf.txt
> > @@ -62,6 +62,7 @@ SYNOPSIS
> >    struct perf_thread_map;
> >  
> >    struct perf_thread_map *perf_thread_map__new_dummy(void);
> > +  struct perf_thread_map *perf_thread_map__new(int nr);
> >  
> >    void perf_thread_map__set_pid(struct perf_thread_map *map, int thread, pid_t pid);
> >    char *perf_thread_map__comm(struct perf_thread_map *map, int thread);
> > diff --git a/tools/lib/perf/include/perf/threadmap.h b/tools/lib/perf/include/perf/threadmap.h
> > index a7c50de8d010..47d433416040 100644
> > --- a/tools/lib/perf/include/perf/threadmap.h
> > +++ b/tools/lib/perf/include/perf/threadmap.h
> > @@ -8,6 +8,7 @@
> >  struct perf_thread_map;
> >  
> >  LIBPERF_API struct perf_thread_map *perf_thread_map__new_dummy(void);
> > +LIBPERF_API struct perf_thread_map *perf_thread_map__new(int nr);
> >  
> >  LIBPERF_API void perf_thread_map__set_pid(struct perf_thread_map *map, int thread, pid_t pid);
> >  LIBPERF_API char *perf_thread_map__comm(struct perf_thread_map *map, int thread);
> > diff --git a/tools/lib/perf/libperf.map b/tools/lib/perf/libperf.map
> > index 93696affda2e..240a2f087b70 100644
> > --- a/tools/lib/perf/libperf.map
> > +++ b/tools/lib/perf/libperf.map
> > @@ -11,6 +11,7 @@ LIBPERF_0.0.1 {
> >  		perf_cpu_map__empty;
> >  		perf_cpu_map__max;
> >  		perf_cpu_map__has;
> > +		perf_thread_map__new;
> >  		perf_thread_map__new_dummy;
> >  		perf_thread_map__set_pid;
> >  		perf_thread_map__comm;
> > diff --git a/tools/lib/perf/tests/test-threadmap.c b/tools/lib/perf/tests/test-threadmap.c
> > index 5e2a0291e94c..3388bf36dfc0 100644
> > --- a/tools/lib/perf/tests/test-threadmap.c
> > +++ b/tools/lib/perf/tests/test-threadmap.c
> > @@ -11,9 +11,12 @@ static int libperf_print(enum libperf_print_level level,
> >  	return vfprintf(stderr, fmt, ap);
> >  }
> >  
> > +#define THREADS_NR	5
> > +
> >  int test_threadmap(int argc, char **argv)
> >  {
> >  	struct perf_thread_map *threads;
> > +	int i;
> >  
> >  	__T_START;
> >  
> > @@ -27,6 +30,30 @@ int test_threadmap(int argc, char **argv)
> >  	perf_thread_map__put(threads);
> >  	perf_thread_map__put(threads);
> >  
> > +	threads = perf_thread_map__new(THREADS_NR);
> > +	if (!threads)
> > +		tests_failed++;
> > +
> > +	if (perf_thread_map__nr(threads) != THREADS_NR)
> > +		tests_failed++;
> > +
> > +	for (i = 0; i < THREADS_NR; i++) {
> > +		if (perf_thread_map__pid(threads, i) != -1)
> > +			tests_failed++;
> > +	}
> > +
> > +	for (i = 1; i < THREADS_NR; i++)
> > +		perf_thread_map__set_pid(threads, i, i * 100);
> > +
> > +	if (perf_thread_map__pid(threads, 0) != -1)
> > +		tests_failed++;
> > +
> > +	for (i = 1; i < THREADS_NR; i++) {
> > +		if (perf_thread_map__pid(threads, i) != i * 100)
> > +			tests_failed++;
> > +	}
> > +	perf_thread_map__put(threads);
> > +
> >  	__T_END;
> >  	return tests_failed == 0 ? 0 : -1;
> >  }
> > diff --git a/tools/lib/perf/threadmap.c b/tools/lib/perf/threadmap.c
> > index e92c368b0a6c..843fe1070cc9 100644
> > --- a/tools/lib/perf/threadmap.c
> > +++ b/tools/lib/perf/threadmap.c
> > @@ -42,18 +42,25 @@ char *perf_thread_map__comm(struct perf_thread_map *map, int thread)
> >  	return map->map[thread].comm;
> >  }
> >  
> > -struct perf_thread_map *perf_thread_map__new_dummy(void)
> > +struct perf_thread_map *perf_thread_map__new(int nr)
> >  {
> > -	struct perf_thread_map *threads = thread_map__alloc(1);
> > +	struct perf_thread_map *threads = thread_map__alloc(nr);
> > +	int i;
> >  
> >  	if (threads != NULL) {
> > -		perf_thread_map__set_pid(threads, 0, -1);
> > -		threads->nr = 1;
> > +		for (i = 0; i < nr; i++)
> > +			perf_thread_map__set_pid(threads, i, -1);
> > +		threads->nr = nr;
> >  		refcount_set(&threads->refcnt, 1);
> >  	}
> >  	return threads;
> >  }
> >  
> > +struct perf_thread_map *perf_thread_map__new_dummy(void)
> > +{
> > +	return perf_thread_map__new(1);
> > +}
> > +
> >  static void perf_thread_map__delete(struct perf_thread_map *threads)
> >  {
> >  	if (threads) {
> > -- 
> > 2.34.1
> > 

-- 

- Arnaldo

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH] libperf: Add API for allocating new thread map
  2022-02-16 13:54   ` Arnaldo Carvalho de Melo
@ 2022-02-16 14:44     ` Tzvetomir Stoyanov
  0 siblings, 0 replies; 5+ messages in thread
From: Tzvetomir Stoyanov @ 2022-02-16 14:44 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: Jiri Olsa, Jiri Olsa, Ian Rogers, Namhyung Kim, linux-perf-users,
	linux-kernel

On Wed, Feb 16, 2022 at 3:54 PM Arnaldo Carvalho de Melo
<arnaldo.melo@gmail.com> wrote:
>
> Em Tue, Feb 15, 2022 at 01:18:31PM +0100, Jiri Olsa escreveu:
> > On Thu, Feb 10, 2022 at 10:52:25AM +0200, Tzvetomir Stoyanov (VMware) wrote:
> > > The existing API perf_thread_map__new_dummy() allocates new thread map
> > > for one thread. I couldn't find a way to reallocate the map with more
> > > threads, or to allocate a new map for more than one thread. Having
> > > multiple threads in a thread map is essential for some use cases.
> > > That's why a new API is proposed, which allocates a new thread map
> > > for given number of threads:
> > >  perf_thread_map__new()
> >
> > I'm ok with that, just wondering if we should call it 'perf_thread_map__new_nr'
> > because we already have perf_cpu_map__new(const char *cpu_list) so
> > it might be better to keep perf_cpu_map and perf_thread_map in sync
>
> > Arnaldo, thoughts on this?
>
> Agreed on trying to have similar semantics for the default, main
> constructor, so we probably need perf_thread_map__new(const char *thread_list).
>
> In tools/perf/util/thread_map.c, from where tools/lib/threadmap.c came
> from we have many alternative constructors:
>
> ⬢[acme@toolbox perf]$ grep 'struct perf_thread_map \*thread_map__new' tools/perf/util/thread_map.c
> struct perf_thread_map *thread_map__new_by_pid(pid_t pid)
> struct perf_thread_map *thread_map__new_by_tid(pid_t tid)
> struct perf_thread_map *thread_map__new_all_cpus(void)
> struct perf_thread_map *thread_map__new_by_uid(uid_t uid)
> struct perf_thread_map *thread_map__new(pid_t pid, pid_t tid, uid_t uid)
> static struct perf_thread_map *thread_map__new_by_pid_str(const char *pid_str)
> struct perf_thread_map *thread_map__new_by_tid_str(const char *tid_str)
> struct perf_thread_map *thread_map__new_str(const char *pid, const char *tid,
> struct perf_thread_map *thread_map__new_event(struct perf_record_thread_map *event)
> ⬢[acme@toolbox perf]$
>
> The one you want is almost:
>
>         thread_map__new_by_tid_str(const char *tid_str)
>
> but perhaps it would be better to have:
>
> struct perf_thread_map *thread_map__new_array(int nr_threads, pid_t *array);

I like the idea, this API is flexible enough for most of the use
cases. I'll submit the next version of the patch with this
implementation.

>
> But yeah, if your logic needs to first allocate space for the thread_map
> and then populate it, make it so that array == NULL is supported for
> that case, then thread_map__new_array() will not touch it and set
> everything to -1, to be populated later using perf_thread_map__set_pid().
>
> With that thread_map__new_by_tid_str() could be reimplemented as a
> wrapper around thread_map__new_array(). :-)
>
> While we're on this, shouldn't we rename 'thread' in
> tools/lib/perf/include/perf/threadmap.h and threadmap.c to be 'idx' to
> avoid confusion?

You mean the input parameter "int thread", in these APIs ?
  perf_thread_map__set_pid()
  perf_thread_map__comm()
  perf_thread_map__pid()
It makes sense to me, as this is the index in the thread map. I can
submit a separate patch with this renaming.

>
> - Arnaldo
>
> > jirka

Thanks!

[ ... ]


-- 
Tzvetomir (Ceco) Stoyanov
VMware Open Source Technology Center

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2022-02-16 14:45 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2022-02-10  8:52 [PATCH] libperf: Add API for allocating new thread map Tzvetomir Stoyanov (VMware)
2022-02-15  4:53 ` Tzvetomir Stoyanov
2022-02-15 12:18 ` Jiri Olsa
2022-02-16 13:54   ` Arnaldo Carvalho de Melo
2022-02-16 14:44     ` Tzvetomir Stoyanov

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).