2012-11-10 01:46:44 +01:00
# include "evlist.h"
# include "evsel.h"
# include "thread_map.h"
# include "cpumap.h"
# include "tests.h"
/*
* This test will generate random numbers of calls to some getpid syscalls ,
* then establish an mmap for a group of events that are created to monitor
* the syscalls .
*
* It will receive the events , using mmap , use its PERF_SAMPLE_ID generated
* sample . id field to map back to its respective perf_evsel instance .
*
* Then it checks if the number of syscalls reported as perf events by
* the kernel corresponds to the number of syscalls made .
*/
int test__basic_mmap ( void )
{
int err = - 1 ;
union perf_event * event ;
struct thread_map * threads ;
struct cpu_map * cpus ;
struct perf_evlist * evlist ;
cpu_set_t cpu_set ;
const char * syscall_names [ ] = { " getsid " , " getppid " , " getpgrp " ,
" getpgid " , } ;
pid_t ( * syscalls [ ] ) ( void ) = { ( void * ) getsid , getppid , getpgrp ,
( void * ) getpgid } ;
# define nsyscalls ARRAY_SIZE(syscall_names)
unsigned int nr_events [ nsyscalls ] ,
expected_nr_events [ nsyscalls ] , i , j ;
struct perf_evsel * evsels [ nsyscalls ] , * evsel ;
threads = thread_map__new ( - 1 , getpid ( ) , UINT_MAX ) ;
if ( threads = = NULL ) {
pr_debug ( " thread_map__new \n " ) ;
return - 1 ;
}
cpus = cpu_map__new ( NULL ) ;
if ( cpus = = NULL ) {
pr_debug ( " cpu_map__new \n " ) ;
goto out_free_threads ;
}
CPU_ZERO ( & cpu_set ) ;
CPU_SET ( cpus - > map [ 0 ] , & cpu_set ) ;
sched_setaffinity ( 0 , sizeof ( cpu_set ) , & cpu_set ) ;
if ( sched_setaffinity ( 0 , sizeof ( cpu_set ) , & cpu_set ) < 0 ) {
pr_debug ( " sched_setaffinity() failed on CPU %d: %s " ,
cpus - > map [ 0 ] , strerror ( errno ) ) ;
goto out_free_cpus ;
}
2013-03-11 16:43:12 +09:00
evlist = perf_evlist__new ( ) ;
2012-11-10 01:46:44 +01:00
if ( evlist = = NULL ) {
pr_debug ( " perf_evlist__new \n " ) ;
goto out_free_cpus ;
}
2013-03-11 16:43:12 +09:00
perf_evlist__set_maps ( evlist , cpus , threads ) ;
2012-11-10 01:46:44 +01:00
for ( i = 0 ; i < nsyscalls ; + + i ) {
2012-12-10 15:11:43 -03:00
char name [ 64 ] ;
snprintf ( name , sizeof ( name ) , " sys_enter_%s " , syscall_names [ i ] ) ;
2013-11-07 16:41:19 -03:00
evsels [ i ] = perf_evsel__newtp ( " syscalls " , name ) ;
2012-11-10 01:46:44 +01:00
if ( evsels [ i ] = = NULL ) {
pr_debug ( " perf_evsel__new \n " ) ;
2014-01-03 16:54:12 -03:00
goto out_delete_evlist ;
2012-11-10 01:46:44 +01:00
}
2012-12-10 15:11:43 -03:00
evsels [ i ] - > attr . wakeup_events = 1 ;
2013-08-27 11:23:09 +03:00
perf_evsel__set_sample_id ( evsels [ i ] , false ) ;
2012-12-10 15:11:43 -03:00
2012-11-10 01:46:44 +01:00
perf_evlist__add ( evlist , evsels [ i ] ) ;
if ( perf_evsel__open ( evsels [ i ] , cpus , threads ) < 0 ) {
pr_debug ( " failed to open counter: %s, "
" tweak /proc/sys/kernel/perf_event_paranoid? \n " ,
strerror ( errno ) ) ;
2014-01-03 16:54:12 -03:00
goto out_delete_evlist ;
2012-11-10 01:46:44 +01:00
}
2012-12-10 15:11:43 -03:00
nr_events [ i ] = 0 ;
expected_nr_events [ i ] = 1 + rand ( ) % 127 ;
2012-11-10 01:46:44 +01:00
}
if ( perf_evlist__mmap ( evlist , 128 , true ) < 0 ) {
pr_debug ( " failed to mmap events: %d (%s) \n " , errno ,
strerror ( errno ) ) ;
2014-01-03 16:54:12 -03:00
goto out_delete_evlist ;
2012-11-10 01:46:44 +01:00
}
for ( i = 0 ; i < nsyscalls ; + + i )
for ( j = 0 ; j < expected_nr_events [ i ] ; + + j ) {
int foo = syscalls [ i ] ( ) ;
+ + foo ;
}
while ( ( event = perf_evlist__mmap_read ( evlist , 0 ) ) ! = NULL ) {
struct perf_sample sample ;
if ( event - > header . type ! = PERF_RECORD_SAMPLE ) {
pr_debug ( " unexpected %s event \n " ,
perf_event__name ( event - > header . type ) ) ;
2014-01-03 17:25:49 -03:00
goto out_delete_evlist ;
2012-11-10 01:46:44 +01:00
}
err = perf_evlist__parse_sample ( evlist , event , & sample ) ;
if ( err ) {
pr_err ( " Can't parse sample, err = %d \n " , err ) ;
2014-01-03 17:25:49 -03:00
goto out_delete_evlist ;
2012-11-10 01:46:44 +01:00
}
2012-12-10 14:58:42 -03:00
err = - 1 ;
2012-11-10 01:46:44 +01:00
evsel = perf_evlist__id2evsel ( evlist , sample . id ) ;
if ( evsel = = NULL ) {
pr_debug ( " event with id % " PRIu64
" doesn't map to an evsel \n " , sample . id ) ;
2014-01-03 17:25:49 -03:00
goto out_delete_evlist ;
2012-11-10 01:46:44 +01:00
}
nr_events [ evsel - > idx ] + + ;
2013-10-24 15:43:33 +08:00
perf_evlist__mmap_consume ( evlist , 0 ) ;
2012-11-10 01:46:44 +01:00
}
2012-12-10 14:58:42 -03:00
err = 0 ;
2014-01-10 10:37:27 -03:00
evlist__for_each ( evlist , evsel ) {
2012-11-10 01:46:44 +01:00
if ( nr_events [ evsel - > idx ] ! = expected_nr_events [ evsel - > idx ] ) {
pr_debug ( " expected %d %s events, got %d \n " ,
expected_nr_events [ evsel - > idx ] ,
perf_evsel__name ( evsel ) , nr_events [ evsel - > idx ] ) ;
2012-12-10 14:58:42 -03:00
err = - 1 ;
2014-01-03 17:25:49 -03:00
goto out_delete_evlist ;
2012-11-10 01:46:44 +01:00
}
}
2014-01-03 16:54:12 -03:00
out_delete_evlist :
2012-11-10 01:46:44 +01:00
perf_evlist__delete ( evlist ) ;
2014-01-03 15:56:06 -03:00
cpus = NULL ;
threads = NULL ;
2012-11-10 01:46:44 +01:00
out_free_cpus :
cpu_map__delete ( cpus ) ;
out_free_threads :
thread_map__delete ( threads ) ;
return err ;
}