diff options
Diffstat (limited to 'tools/lib/perf/tests/test-evlist.c')
| -rw-r--r-- | tools/lib/perf/tests/test-evlist.c | 162 | 
1 files changed, 160 insertions, 2 deletions
| diff --git a/tools/lib/perf/tests/test-evlist.c b/tools/lib/perf/tests/test-evlist.c index ce91a582f0e4..b3479dfa9a1c 100644 --- a/tools/lib/perf/tests/test-evlist.c +++ b/tools/lib/perf/tests/test-evlist.c @@ -21,6 +21,9 @@  #include "tests.h"  #include <internal/evsel.h> +#define EVENT_NUM 15 +#define WAIT_COUNT 100000000UL +  static int libperf_print(enum libperf_print_level level,  			 const char *fmt, va_list ap)  { @@ -331,7 +334,8 @@ static int test_mmap_cpus(void)  	};  	cpu_set_t saved_mask;  	char path[PATH_MAX]; -	int id, err, cpu, tmp; +	int id, err, tmp; +	struct perf_cpu cpu;  	union perf_event *event;  	int count = 0; @@ -374,7 +378,7 @@ static int test_mmap_cpus(void)  		cpu_set_t mask;  		CPU_ZERO(&mask); -		CPU_SET(cpu, &mask); +		CPU_SET(cpu.cpu, &mask);  		err = sched_setaffinity(0, sizeof(mask), &mask);  		__T("sched_setaffinity failed", err == 0); @@ -413,6 +417,159 @@ static int test_mmap_cpus(void)  	return 0;  } +static double display_error(long long average, +			    long long high, +			    long long low, +			    long long expected) +{ +	double error; + +	error = (((double)average - expected) / expected) * 100.0; + +	__T_VERBOSE("   Expected: %lld\n", expected); +	__T_VERBOSE("   High: %lld   Low:  %lld   Average:  %lld\n", +		    high, low, average); + +	__T_VERBOSE("   Average Error = %.2f%%\n", error); + +	return error; +} + +static int test_stat_multiplexing(void) +{ +	struct perf_counts_values expected_counts = { .val = 0 }; +	struct perf_counts_values counts[EVENT_NUM] = {{ .val = 0 },}; +	struct perf_thread_map *threads; +	struct perf_evlist *evlist; +	struct perf_evsel *evsel; +	struct perf_event_attr attr = { +		.type	     = PERF_TYPE_HARDWARE, +		.config	     = PERF_COUNT_HW_INSTRUCTIONS, +		.read_format = PERF_FORMAT_TOTAL_TIME_ENABLED | +			       PERF_FORMAT_TOTAL_TIME_RUNNING, +		.disabled    = 1, +	}; +	int err, i, nonzero = 0; +	unsigned long count; +	long long max = 0, min = 0, avg = 0; +	double error = 0.0; +	s8 scaled = 0; + +	/* read for non-multiplexing event count */ +	threads = perf_thread_map__new_dummy(); +	__T("failed to create threads", threads); + +	perf_thread_map__set_pid(threads, 0, 0); + +	evsel = perf_evsel__new(&attr); +	__T("failed to create evsel", evsel); + +	err = perf_evsel__open(evsel, NULL, threads); +	__T("failed to open evsel", err == 0); + +	err = perf_evsel__enable(evsel); +	__T("failed to enable evsel", err == 0); + +	/* wait loop */ +	count = WAIT_COUNT; +	while (count--) +		; + +	perf_evsel__read(evsel, 0, 0, &expected_counts); +	__T("failed to read value for evsel", expected_counts.val != 0); +	__T("failed to read non-multiplexing event count", +	    expected_counts.ena == expected_counts.run); + +	err = perf_evsel__disable(evsel); +	__T("failed to enable evsel", err == 0); + +	perf_evsel__close(evsel); +	perf_evsel__delete(evsel); + +	perf_thread_map__put(threads); + +	/* read for multiplexing event count */ +	threads = perf_thread_map__new_dummy(); +	__T("failed to create threads", threads); + +	perf_thread_map__set_pid(threads, 0, 0); + +	evlist = perf_evlist__new(); +	__T("failed to create evlist", evlist); + +	for (i = 0; i < EVENT_NUM; i++) { +		evsel = perf_evsel__new(&attr); +		__T("failed to create evsel", evsel); + +		perf_evlist__add(evlist, evsel); +	} +	perf_evlist__set_maps(evlist, NULL, threads); + +	err = perf_evlist__open(evlist); +	__T("failed to open evsel", err == 0); + +	perf_evlist__enable(evlist); + +	/* wait loop */ +	count = WAIT_COUNT; +	while (count--) +		; + +	i = 0; +	perf_evlist__for_each_evsel(evlist, evsel) { +		perf_evsel__read(evsel, 0, 0, &counts[i]); +		__T("failed to read value for evsel", counts[i].val != 0); +		i++; +	} + +	perf_evlist__disable(evlist); + +	min = counts[0].val; +	for (i = 0; i < EVENT_NUM; i++) { +		__T_VERBOSE("Event %2d -- Raw count = %lu, run = %lu, enable = %lu\n", +			    i, counts[i].val, counts[i].run, counts[i].ena); + +		perf_counts_values__scale(&counts[i], true, &scaled); +		if (scaled == 1) { +			__T_VERBOSE("\t Scaled count = %lu (%.2lf%%, %lu/%lu)\n", +				    counts[i].val, +				    (double)counts[i].run / (double)counts[i].ena * 100.0, +				    counts[i].run, counts[i].ena); +		} else if (scaled == -1) { +			__T_VERBOSE("\t Not Running\n"); +		} else { +			__T_VERBOSE("\t Not Scaling\n"); +		} + +		if (counts[i].val > max) +			max = counts[i].val; + +		if (counts[i].val < min) +			min = counts[i].val; + +		avg += counts[i].val; + +		if (counts[i].val != 0) +			nonzero++; +	} + +	if (nonzero != 0) +		avg = avg / nonzero; +	else +		avg = 0; + +	error = display_error(avg, max, min, expected_counts.val); + +	__T("Error out of range!", ((error <= 1.0) && (error >= -1.0))); + +	perf_evlist__close(evlist); +	perf_evlist__delete(evlist); + +	perf_thread_map__put(threads); + +	return 0; +} +  int test_evlist(int argc, char **argv)  {  	__T_START; @@ -424,6 +581,7 @@ int test_evlist(int argc, char **argv)  	test_stat_thread_enable();  	test_mmap_thread();  	test_mmap_cpus(); +	test_stat_multiplexing();  	__T_END;  	return tests_failed == 0 ? 0 : -1; |