diff options
author | Thomas Richter <tmricht@linux.ibm.com> | 2020-01-20 16:20:09 +0300 |
---|---|---|
committer | Arnaldo Carvalho de Melo <acme@redhat.com> | 2020-01-30 13:55:02 +0300 |
commit | 0dd1979f7f9981dcc5c497e68390f208580032ae (patch) | |
tree | 3b5d1bc1a5d622f5211f670ff33a62f6e0d8be1e /tools | |
parent | 3220fb8d5e59d7a9b59d02965d4209aef7691e9f (diff) | |
download | linux-0dd1979f7f9981dcc5c497e68390f208580032ae.tar.xz |
perf test: Fix test case Merge cpu map
Commit a2408a70368a ("perf evlist: Maintain evlist->all_cpus")
introduces a test case for cpumap merge operation, see functions
perf_cpu_map__merge() and test__cpu_map_merge().
The test case fails on s390 with this error message:
[root@m35lp76 perf]# ./perf test -Fvvvvv 52
52: Merge cpu map :
--- start ---
cpumask list: 1-2,4-5,7
perf: /root/linux/tools/include/linux/refcount.h:131:\
refcount_sub_and_test: Assertion `!(new > val)' failed.
Aborted (core dumped)
[root@m35lp76 perf]#
The root cause is in the function test__cpu_map_merge():
It creates two cpu_maps named 'a' and 'b':
struct perf_cpu_map *a = perf_cpu_map__new("4,2,1");
struct perf_cpu_map *b = perf_cpu_map__new("4,5,7");
and creates a third map named 'c' which is the result of
the merge of maps a and b:
struct perf_cpu_map *c = perf_cpu_map__merge(a, b);
After some verifaction of the merged cpu_map all three
of them are have their reference count reduced and are
freed:
perf_cpu_map__put(a); (1)
perf_cpu_map__put(b);
perf_cpu_map__put(c);
The release of perf_cpu_map__put(a) is wrong. The map
is already released and free'ed as part of the function
perf_cpu_map__merge(struct perf_cpu_map *orig,
| struct perf_cpu_map *other)
+--> perf_cpu_map__put(orig);
|
+--> cpu_map__delete(orig)
At the end perf_cpu_map_put() is called for map 'orig'
alias 'a' and since the reference count is 1, the map
is deleted, as can be seen by the following gdb trace:
(gdb) where
#0 tcache_put (tc_idx=0, chunk=0x156cc30) at malloc.c:2940
#1 _int_free (av=0x3fffd49ee80 <main_arena>, p=0x156cc30,
have_lock=<optimized out>) at malloc.c:4222
#2 0x00000000012d5e78 in cpu_map__delete (map=0x156cc40) at cpumap.c:31
#3 0x00000000012d5f7a in perf_cpu_map__put (map=0x156cc40) at cpumap.c:45
#4 0x00000000012d723a in perf_cpu_map__merge (orig=0x156cc40,
other=0x156cc60) at cpumap.c:343
#5 0x000000000110cdd0 in test__cpu_map_merge (
test=0x14ea6c8 <generic_tests+2856>, subtest=-1) at tests/cpumap.c:128
Thus the perf_cpu_map__put(a) (see (1) above) frees map 'a'
a second time and causes the failure. Fix this be removing that
function call.
Output after:
[root@m35lp76 perf]# ./perf test -Fvvvvv 52
52: Merge cpu map :
--- start ---
cpumask list: 1-2,4-5,7
---- end ----
Merge cpu map: Ok
[root@m35lp76 perf]#
Signed-off-by: Thomas Richter <tmricht@linux.ibm.com>
Reviewed-by: Andi Kleen <ak@linux.intel.com>
Cc: Heiko Carstens <heiko.carstens@de.ibm.com>
Cc: Vasily Gorbik <gor@linux.ibm.com>
Cc: sumanthk@linux.ibm.com
Link: http://lore.kernel.org/lkml/20200120132011.64698-1-tmricht@linux.ibm.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Diffstat (limited to 'tools')
-rw-r--r-- | tools/perf/tests/cpumap.c | 1 |
1 files changed, 0 insertions, 1 deletions
diff --git a/tools/perf/tests/cpumap.c b/tools/perf/tests/cpumap.c index 4ac56741ac5f..29c793ac7d10 100644 --- a/tools/perf/tests/cpumap.c +++ b/tools/perf/tests/cpumap.c @@ -131,7 +131,6 @@ int test__cpu_map_merge(struct test *test __maybe_unused, int subtest __maybe_un TEST_ASSERT_VAL("failed to merge map: bad nr", c->nr == 5); cpu_map__snprint(c, buf, sizeof(buf)); TEST_ASSERT_VAL("failed to merge map: bad result", !strcmp(buf, "1-2,4-5,7")); - perf_cpu_map__put(a); perf_cpu_map__put(b); perf_cpu_map__put(c); return 0; |