2019-07-21 13:24:21 +02:00
// SPDX-License-Identifier: GPL-2.0
# include <perf/evlist.h>
2019-07-21 13:24:55 +02:00
# include <perf/evsel.h>
2019-09-03 11:01:04 +02:00
# include <linux/bitops.h>
2019-07-21 13:24:21 +02:00
# include <linux/list.h>
2019-09-03 11:01:04 +02:00
# include <linux/hash.h>
2019-07-21 13:24:21 +02:00
# include <internal/evlist.h>
2019-07-21 13:24:26 +02:00
# include <internal/evsel.h>
2019-09-03 11:01:04 +02:00
# include <internal/xyarray.h>
2019-07-21 13:24:32 +02:00
# include <linux/zalloc.h>
2019-07-21 13:24:35 +02:00
# include <stdlib.h>
2019-07-21 13:24:43 +02:00
# include <perf/cpumap.h>
# include <perf/threadmap.h>
libperf: Add perf_evlist__init() function
Add the perf_evlist__init() function to initialize a perf_evlist struct.
Committer testing:
Fix a change in init ordering that was causing this backtrace:
(gdb) run stat sleep 1
Starting program: /root/bin/perf stat sleep 1
Program received signal SIGSEGV, Segmentation fault.
0x00000000004f6b55 in __perf_evlist__propagate_maps (evlist=0xbb34c0, evsel=0x0) at util/evlist.c:161
161 if (!evsel->own_cpus || evlist->has_user_cpus) {
Missing separate debuginfos, use: dnf debuginfo-install bzip2-libs-1.0.6-29.fc30.x86_64 elfutils-libelf-0.176-3.fc30.x86_64 elfutils-libs-0.176-3.fc30.x86_64 glib2-2.60.4-1.fc30.x86_64 libbabeltrace-1.5.6-2.fc30.x86_64 libgcc-9.1.1-1.fc30.x86_64 libunwind-1.3.1-2.fc30.x86_64 libuuid-2.33.2-1.fc30.x86_64 libxcrypt-4.4.6-2.fc30.x86_64 libzstd-1.4.0-1.fc30.x86_64 numactl-libs-2.0.12-2.fc30.x86_64 pcre-8.43-2.fc30.x86_64 perl-libs-5.28.2-436.fc30.x86_64 popt-1.16-17.fc30.x86_64 python2-libs-2.7.16-2.fc30.x86_64 slang-2.3.2-5.fc30.x86_64 xz-libs-5.2.4-5.fc30.x86_64 zlib-1.2.11-15.fc30.x86_64
(gdb) bt
#0 0x00000000004f6b55 in __perf_evlist__propagate_maps (evlist=0xbb34c0, evsel=0x0) at util/evlist.c:161
#1 0x00000000004f6c7a in perf_evlist__propagate_maps (evlist=0xbb34c0) at util/evlist.c:178
#2 0x00000000004f955e in perf_evlist__set_maps (evlist=0xbb34c0, cpus=0x0, threads=0x0) at util/evlist.c:1128
#3 0x00000000004f66f8 in evlist__init (evlist=0xbb34c0, cpus=0x0, threads=0x0) at util/evlist.c:52
#4 0x00000000004f6790 in evlist__new () at util/evlist.c:64
#5 0x0000000000456071 in cmd_stat (argc=3, argv=0x7fffffffd670) at builtin-stat.c:1705
#6 0x00000000004dd0fa in run_builtin (p=0xa21e00 <commands+288>, argc=3, argv=0x7fffffffd670) at perf.c:304
#7 0x00000000004dd367 in handle_internal_command (argc=3, argv=0x7fffffffd670) at perf.c:356
#8 0x00000000004dd4ae in run_argv (argcp=0x7fffffffd4cc, argv=0x7fffffffd4c0) at perf.c:400
#9 0x00000000004dd81a in main (argc=3, argv=0x7fffffffd670) at perf.c:522
(gdb) bt
So move the initialization of the core evlist (calling
perf_evlist__init()) to before perf_evlist__set_maps() in
evlist__init().
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
Tested-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Cc: Alexey Budankov <alexey.budankov@linux.intel.com>
Cc: Andi Kleen <ak@linux.intel.com>
Cc: Michael Petlan <mpetlan@redhat.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Link: http://lkml.kernel.org/r/20190721112506.12306-39-jolsa@kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2019-07-21 13:24:25 +02:00
void perf_evlist__init ( struct perf_evlist * evlist )
{
2019-09-02 22:20:12 +02:00
int i ;
for ( i = 0 ; i < PERF_EVLIST__HLIST_SIZE ; + + i )
INIT_HLIST_HEAD ( & evlist - > heads [ i ] ) ;
libperf: Add perf_evlist__init() function
Add the perf_evlist__init() function to initialize a perf_evlist struct.
Committer testing:
Fix a change in init ordering that was causing this backtrace:
(gdb) run stat sleep 1
Starting program: /root/bin/perf stat sleep 1
Program received signal SIGSEGV, Segmentation fault.
0x00000000004f6b55 in __perf_evlist__propagate_maps (evlist=0xbb34c0, evsel=0x0) at util/evlist.c:161
161 if (!evsel->own_cpus || evlist->has_user_cpus) {
Missing separate debuginfos, use: dnf debuginfo-install bzip2-libs-1.0.6-29.fc30.x86_64 elfutils-libelf-0.176-3.fc30.x86_64 elfutils-libs-0.176-3.fc30.x86_64 glib2-2.60.4-1.fc30.x86_64 libbabeltrace-1.5.6-2.fc30.x86_64 libgcc-9.1.1-1.fc30.x86_64 libunwind-1.3.1-2.fc30.x86_64 libuuid-2.33.2-1.fc30.x86_64 libxcrypt-4.4.6-2.fc30.x86_64 libzstd-1.4.0-1.fc30.x86_64 numactl-libs-2.0.12-2.fc30.x86_64 pcre-8.43-2.fc30.x86_64 perl-libs-5.28.2-436.fc30.x86_64 popt-1.16-17.fc30.x86_64 python2-libs-2.7.16-2.fc30.x86_64 slang-2.3.2-5.fc30.x86_64 xz-libs-5.2.4-5.fc30.x86_64 zlib-1.2.11-15.fc30.x86_64
(gdb) bt
#0 0x00000000004f6b55 in __perf_evlist__propagate_maps (evlist=0xbb34c0, evsel=0x0) at util/evlist.c:161
#1 0x00000000004f6c7a in perf_evlist__propagate_maps (evlist=0xbb34c0) at util/evlist.c:178
#2 0x00000000004f955e in perf_evlist__set_maps (evlist=0xbb34c0, cpus=0x0, threads=0x0) at util/evlist.c:1128
#3 0x00000000004f66f8 in evlist__init (evlist=0xbb34c0, cpus=0x0, threads=0x0) at util/evlist.c:52
#4 0x00000000004f6790 in evlist__new () at util/evlist.c:64
#5 0x0000000000456071 in cmd_stat (argc=3, argv=0x7fffffffd670) at builtin-stat.c:1705
#6 0x00000000004dd0fa in run_builtin (p=0xa21e00 <commands+288>, argc=3, argv=0x7fffffffd670) at perf.c:304
#7 0x00000000004dd367 in handle_internal_command (argc=3, argv=0x7fffffffd670) at perf.c:356
#8 0x00000000004dd4ae in run_argv (argcp=0x7fffffffd4cc, argv=0x7fffffffd4c0) at perf.c:400
#9 0x00000000004dd81a in main (argc=3, argv=0x7fffffffd670) at perf.c:522
(gdb) bt
So move the initialization of the core evlist (calling
perf_evlist__init()) to before perf_evlist__set_maps() in
evlist__init().
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
Tested-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Cc: Alexey Budankov <alexey.budankov@linux.intel.com>
Cc: Andi Kleen <ak@linux.intel.com>
Cc: Michael Petlan <mpetlan@redhat.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Link: http://lkml.kernel.org/r/20190721112506.12306-39-jolsa@kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2019-07-21 13:24:25 +02:00
INIT_LIST_HEAD ( & evlist - > entries ) ;
2019-07-21 13:24:28 +02:00
evlist - > nr_entries = 0 ;
libperf: Add perf_evlist__init() function
Add the perf_evlist__init() function to initialize a perf_evlist struct.
Committer testing:
Fix a change in init ordering that was causing this backtrace:
(gdb) run stat sleep 1
Starting program: /root/bin/perf stat sleep 1
Program received signal SIGSEGV, Segmentation fault.
0x00000000004f6b55 in __perf_evlist__propagate_maps (evlist=0xbb34c0, evsel=0x0) at util/evlist.c:161
161 if (!evsel->own_cpus || evlist->has_user_cpus) {
Missing separate debuginfos, use: dnf debuginfo-install bzip2-libs-1.0.6-29.fc30.x86_64 elfutils-libelf-0.176-3.fc30.x86_64 elfutils-libs-0.176-3.fc30.x86_64 glib2-2.60.4-1.fc30.x86_64 libbabeltrace-1.5.6-2.fc30.x86_64 libgcc-9.1.1-1.fc30.x86_64 libunwind-1.3.1-2.fc30.x86_64 libuuid-2.33.2-1.fc30.x86_64 libxcrypt-4.4.6-2.fc30.x86_64 libzstd-1.4.0-1.fc30.x86_64 numactl-libs-2.0.12-2.fc30.x86_64 pcre-8.43-2.fc30.x86_64 perl-libs-5.28.2-436.fc30.x86_64 popt-1.16-17.fc30.x86_64 python2-libs-2.7.16-2.fc30.x86_64 slang-2.3.2-5.fc30.x86_64 xz-libs-5.2.4-5.fc30.x86_64 zlib-1.2.11-15.fc30.x86_64
(gdb) bt
#0 0x00000000004f6b55 in __perf_evlist__propagate_maps (evlist=0xbb34c0, evsel=0x0) at util/evlist.c:161
#1 0x00000000004f6c7a in perf_evlist__propagate_maps (evlist=0xbb34c0) at util/evlist.c:178
#2 0x00000000004f955e in perf_evlist__set_maps (evlist=0xbb34c0, cpus=0x0, threads=0x0) at util/evlist.c:1128
#3 0x00000000004f66f8 in evlist__init (evlist=0xbb34c0, cpus=0x0, threads=0x0) at util/evlist.c:52
#4 0x00000000004f6790 in evlist__new () at util/evlist.c:64
#5 0x0000000000456071 in cmd_stat (argc=3, argv=0x7fffffffd670) at builtin-stat.c:1705
#6 0x00000000004dd0fa in run_builtin (p=0xa21e00 <commands+288>, argc=3, argv=0x7fffffffd670) at perf.c:304
#7 0x00000000004dd367 in handle_internal_command (argc=3, argv=0x7fffffffd670) at perf.c:356
#8 0x00000000004dd4ae in run_argv (argcp=0x7fffffffd4cc, argv=0x7fffffffd4c0) at perf.c:400
#9 0x00000000004dd81a in main (argc=3, argv=0x7fffffffd670) at perf.c:522
(gdb) bt
So move the initialization of the core evlist (calling
perf_evlist__init()) to before perf_evlist__set_maps() in
evlist__init().
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
Tested-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Cc: Alexey Budankov <alexey.budankov@linux.intel.com>
Cc: Andi Kleen <ak@linux.intel.com>
Cc: Michael Petlan <mpetlan@redhat.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Link: http://lkml.kernel.org/r/20190721112506.12306-39-jolsa@kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2019-07-21 13:24:25 +02:00
}
2019-07-21 13:24:26 +02:00
2019-07-21 13:24:43 +02:00
static void __perf_evlist__propagate_maps ( struct perf_evlist * evlist ,
struct perf_evsel * evsel )
{
/*
* 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 - > cpus ) ;
} else if ( evsel - > cpus ! = evsel - > own_cpus ) {
perf_cpu_map__put ( evsel - > cpus ) ;
evsel - > cpus = perf_cpu_map__get ( evsel - > own_cpus ) ;
}
perf_thread_map__put ( evsel - > threads ) ;
evsel - > threads = perf_thread_map__get ( evlist - > threads ) ;
}
static void perf_evlist__propagate_maps ( struct perf_evlist * evlist )
{
struct perf_evsel * evsel ;
perf_evlist__for_each_evsel ( evlist , evsel )
__perf_evlist__propagate_maps ( evlist , evsel ) ;
}
2019-07-21 13:24:26 +02:00
void perf_evlist__add ( struct perf_evlist * evlist ,
struct perf_evsel * evsel )
{
list_add_tail ( & evsel - > node , & evlist - > entries ) ;
2019-07-21 13:24:28 +02:00
evlist - > nr_entries + = 1 ;
2019-07-21 13:24:43 +02:00
__perf_evlist__propagate_maps ( evlist , evsel ) ;
2019-07-21 13:24:26 +02:00
}
2019-07-21 13:24:27 +02:00
void perf_evlist__remove ( struct perf_evlist * evlist ,
struct perf_evsel * evsel )
{
list_del_init ( & evsel - > node ) ;
2019-07-21 13:24:28 +02:00
evlist - > nr_entries - = 1 ;
2019-07-21 13:24:27 +02:00
}
2019-07-21 13:24:32 +02:00
struct perf_evlist * perf_evlist__new ( void )
{
struct perf_evlist * evlist = zalloc ( sizeof ( * evlist ) ) ;
if ( evlist ! = NULL )
perf_evlist__init ( evlist ) ;
return evlist ;
}
2019-07-21 13:24:34 +02:00
struct perf_evsel *
perf_evlist__next ( struct perf_evlist * evlist , struct perf_evsel * prev )
{
struct perf_evsel * next ;
if ( ! prev ) {
next = list_first_entry ( & evlist - > entries ,
struct perf_evsel ,
node ) ;
} else {
next = list_next_entry ( prev , node ) ;
}
/* Empty list is noticed here so don't need checking on entry. */
if ( & next - > node = = & evlist - > entries )
return NULL ;
return next ;
}
2019-07-21 13:24:35 +02:00
void perf_evlist__delete ( struct perf_evlist * evlist )
{
free ( evlist ) ;
}
2019-07-21 13:24:43 +02:00
void perf_evlist__set_maps ( struct perf_evlist * evlist ,
struct perf_cpu_map * cpus ,
struct perf_thread_map * threads )
{
/*
* Allow for the possibility that one or another of the maps isn ' t being
* changed i . e . don ' t put it . Note we are assuming the maps that are
* being applied are brand new and evlist is taking ownership of the
* original reference count of 1. If that is not the case it is up to
* the caller to increase the reference count .
*/
if ( cpus ! = evlist - > cpus ) {
perf_cpu_map__put ( evlist - > cpus ) ;
evlist - > cpus = perf_cpu_map__get ( cpus ) ;
}
if ( threads ! = evlist - > threads ) {
perf_thread_map__put ( evlist - > threads ) ;
evlist - > threads = perf_thread_map__get ( threads ) ;
}
perf_evlist__propagate_maps ( evlist ) ;
}
2019-07-21 13:24:55 +02:00
int perf_evlist__open ( struct perf_evlist * evlist )
{
struct perf_evsel * evsel ;
int err ;
perf_evlist__for_each_entry ( evlist , evsel ) {
err = perf_evsel__open ( evsel , evsel - > cpus , evsel - > threads ) ;
if ( err < 0 )
goto out_err ;
}
return 0 ;
out_err :
perf_evlist__close ( evlist ) ;
return err ;
}
void perf_evlist__close ( struct perf_evlist * evlist )
{
struct perf_evsel * evsel ;
perf_evlist__for_each_entry_reverse ( evlist , evsel )
perf_evsel__close ( evsel ) ;
}
2019-07-21 13:24:56 +02:00
void perf_evlist__enable ( struct perf_evlist * evlist )
{
struct perf_evsel * evsel ;
perf_evlist__for_each_entry ( evlist , evsel )
perf_evsel__enable ( evsel ) ;
}
void perf_evlist__disable ( struct perf_evlist * evlist )
{
struct perf_evsel * evsel ;
perf_evlist__for_each_entry ( evlist , evsel )
perf_evsel__disable ( evsel ) ;
}
2019-09-03 10:54:48 +02:00
u64 perf_evlist__read_format ( struct perf_evlist * evlist )
{
struct perf_evsel * first = perf_evlist__first ( evlist ) ;
return first - > attr . read_format ;
}
2019-09-03 11:01:04 +02:00
# define SID(e, x, y) xyarray__entry(e->sample_id, x, y)
static void perf_evlist__id_hash ( struct perf_evlist * evlist ,
struct perf_evsel * evsel ,
int cpu , int thread , u64 id )
{
int hash ;
struct perf_sample_id * sid = SID ( evsel , cpu , thread ) ;
sid - > id = id ;
sid - > evsel = evsel ;
hash = hash_64 ( sid - > id , PERF_EVLIST__HLIST_BITS ) ;
hlist_add_head ( & sid - > node , & evlist - > heads [ hash ] ) ;
}
void perf_evlist__id_add ( struct perf_evlist * evlist ,
struct perf_evsel * evsel ,
int cpu , int thread , u64 id )
{
perf_evlist__id_hash ( evlist , evsel , cpu , thread , id ) ;
evsel - > id [ evsel - > ids + + ] = id ;
}