2015-09-04 04:58:31 -04:00
# include <string.h>
# include <stdlib.h>
# include <stdio.h>
# include "tests.h"
# include "util.h"
# include "session.h"
# include "evlist.h"
# include "debug.h"
# define TEMPL " / tmp / perf-test-XXXXXX"
# define DATA_SIZE 10
static int get_temp ( char * path )
{
int fd ;
strcpy ( path , TEMPL ) ;
fd = mkstemp ( path ) ;
if ( fd < 0 ) {
perror ( " mkstemp failed " ) ;
return - 1 ;
}
close ( fd ) ;
return 0 ;
}
static int session_write_header ( char * path )
{
struct perf_session * session ;
struct perf_data_file file = {
. path = path ,
. mode = PERF_DATA_MODE_WRITE ,
} ;
session = perf_session__new ( & file , false , NULL ) ;
TEST_ASSERT_VAL ( " can't get session " , session ) ;
session - > evlist = perf_evlist__new_default ( ) ;
TEST_ASSERT_VAL ( " can't get evlist " , session - > evlist ) ;
perf_header__set_feat ( & session - > header , HEADER_CPU_TOPOLOGY ) ;
perf_header__set_feat ( & session - > header , HEADER_NRCPUS ) ;
session - > header . data_size + = DATA_SIZE ;
TEST_ASSERT_VAL ( " failed to write header " ,
! perf_session__write_header ( session , session - > evlist , file . fd , true ) ) ;
perf_session__delete ( session ) ;
return 0 ;
}
static int check_cpu_topology ( char * path , struct cpu_map * map )
{
struct perf_session * session ;
struct perf_data_file file = {
. path = path ,
. mode = PERF_DATA_MODE_READ ,
} ;
int i ;
session = perf_session__new ( & file , false , NULL ) ;
TEST_ASSERT_VAL ( " can't get session " , session ) ;
perf tools: Replace _SC_NPROCESSORS_CONF with max_present_cpu in cpu_topology_map
There are 2 problems wrt. cpu_topology_map on systems with sparse CPUs:
1. offline/absent CPUs will have their socket_id and core_id set to -1
which triggers:
"socket_id number is too big.You may need to upgrade the perf tool."
2. size of cpu_topology_map (perf_env.cpu[]) is allocated based on
_SC_NPROCESSORS_CONF, but can be indexed with CPU ids going above.
Users of perf_env.cpu[] are using CPU id as index. This can lead
to read beyond what was allocated:
==19991== Invalid read of size 4
==19991== at 0x490CEB: check_cpu_topology (topology.c:69)
==19991== by 0x490CEB: test_session_topology (topology.c:106)
...
For example:
_SC_NPROCESSORS_CONF == 16
available: 2 nodes (0-1)
node 0 cpus: 0 6 8 10 16 22 24 26
node 0 size: 12004 MB
node 0 free: 9470 MB
node 1 cpus: 1 7 9 11 23 25 27
node 1 size: 12093 MB
node 1 free: 9406 MB
node distances:
node 0 1
0: 10 20
1: 20 10
This patch changes HEADER_NRCPUS.nr_cpus_available from _SC_NPROCESSORS_CONF
to max_present_cpu and updates any user of cpu_topology_map to iterate
with nr_cpus_avail.
As a consequence HEADER_CPU_TOPOLOGY core_id and socket_id lists get longer,
but maintain compatibility with pre-patch state - index to cpu_topology_map is
CPU id.
perf test 36 -v
36: Session topology :
--- start ---
test child forked, pid 22211
templ file: /tmp/perf-test-gmdX5i
CPU 0, core 0, socket 0
CPU 1, core 0, socket 1
CPU 6, core 10, socket 0
CPU 7, core 10, socket 1
CPU 8, core 1, socket 0
CPU 9, core 1, socket 1
CPU 10, core 9, socket 0
CPU 11, core 9, socket 1
CPU 16, core 0, socket 0
CPU 22, core 10, socket 0
CPU 23, core 10, socket 1
CPU 24, core 1, socket 0
CPU 25, core 1, socket 1
CPU 26, core 9, socket 0
CPU 27, core 9, socket 1
test child finished with 0
---- end ----
Session topology: Ok
Signed-off-by: Jan Stancek <jstancek@redhat.com>
Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Masami Hiramatsu <mhiramat@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Link: http://lkml.kernel.org/r/d7c05c6445fca74a8442c2c73cfffd349c52c44f.1487146877.git.jstancek@redhat.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2017-02-17 12:10:26 +01:00
for ( i = 0 ; i < session - > header . env . nr_cpus_avail ; i + + ) {
if ( ! cpu_map__has ( map , i ) )
continue ;
2015-09-04 04:58:31 -04:00
pr_debug ( " CPU %d, core %d, socket %d \n " , i ,
session - > header . env . cpu [ i ] . core_id ,
session - > header . env . cpu [ i ] . socket_id ) ;
}
for ( i = 0 ; i < map - > nr ; i + + ) {
TEST_ASSERT_VAL ( " Core ID doesn't match " ,
2015-10-16 12:41:15 +02:00
( session - > header . env . cpu [ map - > map [ i ] ] . core_id = = ( cpu_map__get_core ( map , i , NULL ) & 0xffff ) ) ) ;
2015-09-04 04:58:31 -04:00
TEST_ASSERT_VAL ( " Socket ID doesn't match " ,
2015-10-16 12:41:15 +02:00
( session - > header . env . cpu [ map - > map [ i ] ] . socket_id = = cpu_map__get_socket ( map , i , NULL ) ) ) ;
2015-09-04 04:58:31 -04:00
}
perf_session__delete ( session ) ;
return 0 ;
}
2017-08-03 15:16:31 -03:00
int test__session_topology ( struct test * test __maybe_unused , int subtest __maybe_unused )
2015-09-04 04:58:31 -04:00
{
char path [ PATH_MAX ] ;
struct cpu_map * map ;
int ret = - 1 ;
TEST_ASSERT_VAL ( " can't get templ file " , ! get_temp ( path ) ) ;
pr_debug ( " templ file: %s \n " , path ) ;
if ( session_write_header ( path ) )
goto free_path ;
map = cpu_map__new ( NULL ) ;
if ( map = = NULL ) {
pr_debug ( " failed to get system cpumap \n " ) ;
goto free_path ;
}
if ( check_cpu_topology ( path , map ) )
goto free_map ;
ret = 0 ;
free_map :
cpu_map__put ( map ) ;
free_path :
unlink ( path ) ;
return ret ;
}