2013-03-18 11:41:47 +09:00
# include <unistd.h>
# include <stdlib.h>
# include <signal.h>
# include <sys/mman.h>
# include "tests.h"
# include "util/evsel.h"
# include "util/evlist.h"
# include "util/cpumap.h"
# include "util/thread_map.h"
2013-11-12 11:45:21 -03:00
# define NR_LOOPS 10000000
2013-03-18 11:41:47 +09:00
/*
* This test will open software clock events ( cpu - clock , task - clock )
* then check their frequency - > period conversion has no artifact of
* setting period to 1 forcefully .
*/
static int __test__sw_clock_freq ( enum perf_sw_ids clock_id )
{
int i , err = - 1 ;
volatile int tmp = 0 ;
u64 total_periods = 0 ;
int nr_samples = 0 ;
2014-08-14 02:22:45 +00:00
char sbuf [ STRERR_BUFSIZE ] ;
2013-03-18 11:41:47 +09:00
union perf_event * event ;
struct perf_evsel * evsel ;
struct perf_evlist * evlist ;
struct perf_event_attr attr = {
. type = PERF_TYPE_SOFTWARE ,
. config = clock_id ,
. sample_type = PERF_SAMPLE_PERIOD ,
. exclude_kernel = 1 ,
. disabled = 1 ,
. freq = 1 ,
} ;
2013-11-11 16:33:18 -03:00
attr . sample_freq = 500 ;
2013-03-18 11:41:47 +09:00
evlist = perf_evlist__new ( ) ;
if ( evlist = = NULL ) {
pr_debug ( " perf_evlist__new \n " ) ;
return - 1 ;
}
2013-11-07 16:41:19 -03:00
evsel = perf_evsel__new ( & attr ) ;
2013-03-18 11:41:47 +09:00
if ( evsel = = NULL ) {
pr_debug ( " perf_evsel__new \n " ) ;
2014-01-03 15:56:06 -03:00
goto out_delete_evlist ;
2013-03-18 11:41:47 +09:00
}
perf_evlist__add ( evlist , evsel ) ;
evlist - > cpus = cpu_map__dummy_new ( ) ;
evlist - > threads = thread_map__new_by_tid ( getpid ( ) ) ;
if ( ! evlist - > cpus | | ! evlist - > threads ) {
err = - ENOMEM ;
pr_debug ( " Not enough memory to create thread/cpu maps \n " ) ;
2014-01-03 15:56:06 -03:00
goto out_delete_evlist ;
2013-03-18 11:41:47 +09:00
}
2013-11-11 16:28:42 -03:00
if ( perf_evlist__open ( evlist ) ) {
2013-11-11 16:33:18 -03:00
const char * knob = " /proc/sys/kernel/perf_event_max_sample_rate " ;
2013-11-11 16:28:42 -03:00
err = - errno ;
2013-11-11 16:33:18 -03:00
pr_debug ( " Couldn't open evlist: %s \n Hint: check %s, using % " PRIu64 " in this test. \n " ,
2014-08-14 02:22:45 +00:00
strerror_r ( errno , sbuf , sizeof ( sbuf ) ) ,
knob , ( u64 ) attr . sample_freq ) ;
2014-01-03 15:56:06 -03:00
goto out_delete_evlist ;
2013-11-11 16:28:42 -03:00
}
2013-03-18 11:41:47 +09:00
err = perf_evlist__mmap ( evlist , 128 , true ) ;
if ( err < 0 ) {
pr_debug ( " failed to mmap event: %d (%s) \n " , errno ,
2014-08-14 02:22:45 +00:00
strerror_r ( errno , sbuf , sizeof ( sbuf ) ) ) ;
2014-01-03 16:54:12 -03:00
goto out_delete_evlist ;
2013-03-18 11:41:47 +09:00
}
perf_evlist__enable ( evlist ) ;
/* collect samples */
for ( i = 0 ; i < NR_LOOPS ; i + + )
tmp + + ;
perf_evlist__disable ( evlist ) ;
while ( ( event = perf_evlist__mmap_read ( evlist , 0 ) ) ! = NULL ) {
struct perf_sample sample ;
if ( event - > header . type ! = PERF_RECORD_SAMPLE )
2013-10-24 15:43:33 +08:00
goto next_event ;
2013-03-18 11:41:47 +09:00
err = perf_evlist__parse_sample ( evlist , event , & sample ) ;
if ( err < 0 ) {
pr_debug ( " Error during parse sample \n " ) ;
2014-01-03 17:25:49 -03:00
goto out_delete_evlist ;
2013-03-18 11:41:47 +09:00
}
total_periods + = sample . period ;
nr_samples + + ;
2013-10-24 15:43:33 +08:00
next_event :
perf_evlist__mmap_consume ( evlist , 0 ) ;
2013-03-18 11:41:47 +09:00
}
if ( ( u64 ) nr_samples = = total_periods ) {
pr_debug ( " All (%d) samples have period value of 1! \n " ,
nr_samples ) ;
err = - 1 ;
}
2014-01-03 15:56:06 -03:00
out_delete_evlist :
2013-03-18 11:41:47 +09:00
perf_evlist__delete ( evlist ) ;
return err ;
}
int test__sw_clock_freq ( void )
{
int ret ;
ret = __test__sw_clock_freq ( PERF_COUNT_SW_CPU_CLOCK ) ;
if ( ! ret )
ret = __test__sw_clock_freq ( PERF_COUNT_SW_TASK_CLOCK ) ;
return ret ;
}