diff options
Diffstat (limited to 'tools/perf/tests')
| -rw-r--r-- | tools/perf/tests/attr.c | 9 | ||||
| -rw-r--r-- | tools/perf/tests/attr.py | 5 | ||||
| -rw-r--r-- | tools/perf/tests/attr/base-record | 1 | ||||
| -rw-r--r-- | tools/perf/tests/attr/base-stat | 1 | ||||
| -rw-r--r-- | tools/perf/tests/attr/test-record-C0 | 13 | ||||
| -rw-r--r-- | tools/perf/tests/attr/test-stat-C0 | 9 | ||||
| -rw-r--r-- | tools/perf/tests/bp_signal.c | 186 | ||||
| -rw-r--r-- | tools/perf/tests/bp_signal_overflow.c | 126 | ||||
| -rw-r--r-- | tools/perf/tests/builtin-test.c | 16 | ||||
| -rw-r--r-- | tools/perf/tests/evsel-roundtrip-name.c | 4 | ||||
| -rw-r--r-- | tools/perf/tests/hists_link.c | 6 | ||||
| -rw-r--r-- | tools/perf/tests/mmap-basic.c | 4 | ||||
| -rw-r--r-- | tools/perf/tests/open-syscall-tp-fields.c | 10 | ||||
| -rw-r--r-- | tools/perf/tests/parse-events.c | 4 | ||||
| -rw-r--r-- | tools/perf/tests/perf-record.c | 9 | ||||
| -rw-r--r-- | tools/perf/tests/sw-clock.c | 119 | ||||
| -rw-r--r-- | tools/perf/tests/task-exit.c | 123 | ||||
| -rw-r--r-- | tools/perf/tests/tests.h | 4 | 
18 files changed, 631 insertions, 18 deletions
| diff --git a/tools/perf/tests/attr.c b/tools/perf/tests/attr.c index bdcceb886f7..038de3ecb8c 100644 --- a/tools/perf/tests/attr.c +++ b/tools/perf/tests/attr.c @@ -147,10 +147,15 @@ void test_attr__open(struct perf_event_attr *attr, pid_t pid, int cpu,  static int run_dir(const char *d, const char *perf)  { +	char v[] = "-vvvvv"; +	int vcnt = min(verbose, (int) sizeof(v) - 1);  	char cmd[3*PATH_MAX]; -	snprintf(cmd, 3*PATH_MAX, PYTHON " %s/attr.py -d %s/attr/ -p %s %s", -		 d, d, perf, verbose ? "-v" : ""); +	if (verbose) +		vcnt++; + +	snprintf(cmd, 3*PATH_MAX, PYTHON " %s/attr.py -d %s/attr/ -p %s %.*s", +		 d, d, perf, vcnt, v);  	return system(cmd);  } diff --git a/tools/perf/tests/attr.py b/tools/perf/tests/attr.py index 2f629ca485b..c9b4b6269b5 100644 --- a/tools/perf/tests/attr.py +++ b/tools/perf/tests/attr.py @@ -24,6 +24,7 @@ class Unsup(Exception):  class Event(dict):      terms = [ +        'cpu',          'flags',          'type',          'size', @@ -121,7 +122,7 @@ class Test(object):          parser = ConfigParser.SafeConfigParser()          parser.read(path) -        log.debug("running '%s'" % path) +        log.warning("running '%s'" % path)          self.path     = path          self.test_dir = options.test_dir @@ -172,7 +173,7 @@ class Test(object):                self.perf, self.command, tempdir, self.args)          ret = os.WEXITSTATUS(os.system(cmd)) -        log.warning("  running '%s' ret %d " % (cmd, ret)) +        log.info("  '%s' ret %d " % (cmd, ret))          if ret != int(self.ret):              raise Unsup(self) diff --git a/tools/perf/tests/attr/base-record b/tools/perf/tests/attr/base-record index 5bc3880f7be..b4fc835de60 100644 --- a/tools/perf/tests/attr/base-record +++ b/tools/perf/tests/attr/base-record @@ -2,6 +2,7 @@  fd=1  group_fd=-1  flags=0 +cpu=*  type=0|1  size=96  config=0 diff --git a/tools/perf/tests/attr/base-stat b/tools/perf/tests/attr/base-stat index 4bd79a82784..748ee949a20 100644 --- a/tools/perf/tests/attr/base-stat +++ b/tools/perf/tests/attr/base-stat @@ -2,6 +2,7 @@  fd=1  group_fd=-1  flags=0 +cpu=*  type=0  size=96  config=0 diff --git a/tools/perf/tests/attr/test-record-C0 b/tools/perf/tests/attr/test-record-C0 new file mode 100644 index 00000000000..d6a7e43f61b --- /dev/null +++ b/tools/perf/tests/attr/test-record-C0 @@ -0,0 +1,13 @@ +[config] +command = record +args    = -C 0 kill >/dev/null 2>&1 + +[event:base-record] +cpu=0 + +# no enable on exec for CPU attached +enable_on_exec=0 + +# PERF_SAMPLE_IP | PERF_SAMPLE_TID PERF_SAMPLE_TIME | # PERF_SAMPLE_PERIOD +# + PERF_SAMPLE_CPU added by -C 0 +sample_type=391 diff --git a/tools/perf/tests/attr/test-stat-C0 b/tools/perf/tests/attr/test-stat-C0 new file mode 100644 index 00000000000..aa835950751 --- /dev/null +++ b/tools/perf/tests/attr/test-stat-C0 @@ -0,0 +1,9 @@ +[config] +command = stat +args    = -e cycles -C 0 kill >/dev/null 2>&1 +ret     = 1 + +[event:base-stat] +# events are enabled by default when attached to cpu +disabled=0 +enable_on_exec=0 diff --git a/tools/perf/tests/bp_signal.c b/tools/perf/tests/bp_signal.c new file mode 100644 index 00000000000..68daa289e94 --- /dev/null +++ b/tools/perf/tests/bp_signal.c @@ -0,0 +1,186 @@ +/* + * Inspired by breakpoint overflow test done by + * Vince Weaver <vincent.weaver@maine.edu> for perf_event_tests + * (git://github.com/deater/perf_event_tests) + */ + +#include <stdlib.h> +#include <stdio.h> +#include <unistd.h> +#include <string.h> +#include <sys/ioctl.h> +#include <time.h> +#include <fcntl.h> +#include <signal.h> +#include <sys/mman.h> +#include <linux/compiler.h> +#include <linux/hw_breakpoint.h> + +#include "tests.h" +#include "debug.h" +#include "perf.h" + +static int fd1; +static int fd2; +static int overflows; + +__attribute__ ((noinline)) +static int test_function(void) +{ +	return time(NULL); +} + +static void sig_handler(int signum __maybe_unused, +			siginfo_t *oh __maybe_unused, +			void *uc __maybe_unused) +{ +	overflows++; + +	if (overflows > 10) { +		/* +		 * This should be executed only once during +		 * this test, if we are here for the 10th +		 * time, consider this the recursive issue. +		 * +		 * We can get out of here by disable events, +		 * so no new SIGIO is delivered. +		 */ +		ioctl(fd1, PERF_EVENT_IOC_DISABLE, 0); +		ioctl(fd2, PERF_EVENT_IOC_DISABLE, 0); +	} +} + +static int bp_event(void *fn, int setup_signal) +{ +	struct perf_event_attr pe; +	int fd; + +	memset(&pe, 0, sizeof(struct perf_event_attr)); +	pe.type = PERF_TYPE_BREAKPOINT; +	pe.size = sizeof(struct perf_event_attr); + +	pe.config = 0; +	pe.bp_type = HW_BREAKPOINT_X; +	pe.bp_addr = (unsigned long) fn; +	pe.bp_len = sizeof(long); + +	pe.sample_period = 1; +	pe.sample_type = PERF_SAMPLE_IP; +	pe.wakeup_events = 1; + +	pe.disabled = 1; +	pe.exclude_kernel = 1; +	pe.exclude_hv = 1; + +	fd = sys_perf_event_open(&pe, 0, -1, -1, 0); +	if (fd < 0) { +		pr_debug("failed opening event %llx\n", pe.config); +		return TEST_FAIL; +	} + +	if (setup_signal) { +		fcntl(fd, F_SETFL, O_RDWR|O_NONBLOCK|O_ASYNC); +		fcntl(fd, F_SETSIG, SIGIO); +		fcntl(fd, F_SETOWN, getpid()); +	} + +	ioctl(fd, PERF_EVENT_IOC_RESET, 0); + +	return fd; +} + +static long long bp_count(int fd) +{ +	long long count; +	int ret; + +	ret = read(fd, &count, sizeof(long long)); +	if (ret != sizeof(long long)) { +		pr_debug("failed to read: %d\n", ret); +		return TEST_FAIL; +	} + +	return count; +} + +int test__bp_signal(void) +{ +	struct sigaction sa; +	long long count1, count2; + +	/* setup SIGIO signal handler */ +	memset(&sa, 0, sizeof(struct sigaction)); +	sa.sa_sigaction = (void *) sig_handler; +	sa.sa_flags = SA_SIGINFO; + +	if (sigaction(SIGIO, &sa, NULL) < 0) { +		pr_debug("failed setting up signal handler\n"); +		return TEST_FAIL; +	} + +	/* +	 * We create following events: +	 * +	 * fd1 - breakpoint event on test_function with SIGIO +	 *       signal configured. We should get signal +	 *       notification each time the breakpoint is hit +	 * +	 * fd2 - breakpoint event on sig_handler without SIGIO +	 *       configured. +	 * +	 * Following processing should happen: +	 *   - execute test_function +	 *   - fd1 event breakpoint hit -> count1 == 1 +	 *   - SIGIO is delivered       -> overflows == 1 +	 *   - fd2 event breakpoint hit -> count2 == 1 +	 * +	 * The test case check following error conditions: +	 * - we get stuck in signal handler because of debug +	 *   exception being triggered receursively due to +	 *   the wrong RF EFLAG management +	 * +	 * - we never trigger the sig_handler breakpoint due +	 *   to the rong RF EFLAG management +	 * +	 */ + +	fd1 = bp_event(test_function, 1); +	fd2 = bp_event(sig_handler, 0); + +	ioctl(fd1, PERF_EVENT_IOC_ENABLE, 0); +	ioctl(fd2, PERF_EVENT_IOC_ENABLE, 0); + +	/* +	 * Kick off the test by trigering 'fd1' +	 * breakpoint. +	 */ +	test_function(); + +	ioctl(fd1, PERF_EVENT_IOC_DISABLE, 0); +	ioctl(fd2, PERF_EVENT_IOC_DISABLE, 0); + +	count1 = bp_count(fd1); +	count2 = bp_count(fd2); + +	close(fd1); +	close(fd2); + +	pr_debug("count1 %lld, count2 %lld, overflow %d\n", +		 count1, count2, overflows); + +	if (count1 != 1) { +		if (count1 == 11) +			pr_debug("failed: RF EFLAG recursion issue detected\n"); +		else +			pr_debug("failed: wrong count for bp1%lld\n", count1); +	} + +	if (overflows != 1) +		pr_debug("failed: wrong overflow hit\n"); + +	if (count2 != 1) +		pr_debug("failed: wrong count for bp2\n"); + +	return count1 == 1 && overflows == 1 && count2 == 1 ? +		TEST_OK : TEST_FAIL; +} diff --git a/tools/perf/tests/bp_signal_overflow.c b/tools/perf/tests/bp_signal_overflow.c new file mode 100644 index 00000000000..fe7ed28815f --- /dev/null +++ b/tools/perf/tests/bp_signal_overflow.c @@ -0,0 +1,126 @@ +/* + * Originally done by Vince Weaver <vincent.weaver@maine.edu> for + * perf_event_tests (git://github.com/deater/perf_event_tests) + */ + +#include <stdlib.h> +#include <stdio.h> +#include <unistd.h> +#include <string.h> +#include <sys/ioctl.h> +#include <time.h> +#include <fcntl.h> +#include <signal.h> +#include <sys/mman.h> +#include <linux/compiler.h> +#include <linux/hw_breakpoint.h> + +#include "tests.h" +#include "debug.h" +#include "perf.h" + +static int overflows; + +__attribute__ ((noinline)) +static int test_function(void) +{ +	return time(NULL); +} + +static void sig_handler(int signum __maybe_unused, +			siginfo_t *oh __maybe_unused, +			void *uc __maybe_unused) +{ +	overflows++; +} + +static long long bp_count(int fd) +{ +	long long count; +	int ret; + +	ret = read(fd, &count, sizeof(long long)); +	if (ret != sizeof(long long)) { +		pr_debug("failed to read: %d\n", ret); +		return TEST_FAIL; +	} + +	return count; +} + +#define EXECUTIONS 10000 +#define THRESHOLD  100 + +int test__bp_signal_overflow(void) +{ +	struct perf_event_attr pe; +	struct sigaction sa; +	long long count; +	int fd, i, fails = 0; + +	/* setup SIGIO signal handler */ +	memset(&sa, 0, sizeof(struct sigaction)); +	sa.sa_sigaction = (void *) sig_handler; +	sa.sa_flags = SA_SIGINFO; + +	if (sigaction(SIGIO, &sa, NULL) < 0) { +		pr_debug("failed setting up signal handler\n"); +		return TEST_FAIL; +	} + +	memset(&pe, 0, sizeof(struct perf_event_attr)); +	pe.type = PERF_TYPE_BREAKPOINT; +	pe.size = sizeof(struct perf_event_attr); + +	pe.config = 0; +	pe.bp_type = HW_BREAKPOINT_X; +	pe.bp_addr = (unsigned long) test_function; +	pe.bp_len = sizeof(long); + +	pe.sample_period = THRESHOLD; +	pe.sample_type = PERF_SAMPLE_IP; +	pe.wakeup_events = 1; + +	pe.disabled = 1; +	pe.exclude_kernel = 1; +	pe.exclude_hv = 1; + +	fd = sys_perf_event_open(&pe, 0, -1, -1, 0); +	if (fd < 0) { +		pr_debug("failed opening event %llx\n", pe.config); +		return TEST_FAIL; +	} + +	fcntl(fd, F_SETFL, O_RDWR|O_NONBLOCK|O_ASYNC); +	fcntl(fd, F_SETSIG, SIGIO); +	fcntl(fd, F_SETOWN, getpid()); + +	ioctl(fd, PERF_EVENT_IOC_RESET, 0); +	ioctl(fd, PERF_EVENT_IOC_ENABLE, 0); + +	for (i = 0; i < EXECUTIONS; i++) +		test_function(); + +	ioctl(fd, PERF_EVENT_IOC_DISABLE, 0); + +	count = bp_count(fd); + +	close(fd); + +	pr_debug("count %lld, overflow %d\n", +		 count, overflows); + +	if (count != EXECUTIONS) { +		pr_debug("\tWrong number of executions %lld != %d\n", +		count, EXECUTIONS); +		fails++; +	} + +	if (overflows != EXECUTIONS / THRESHOLD) { +		pr_debug("\tWrong number of overflows %d != %d\n", +		overflows, EXECUTIONS / THRESHOLD); +		fails++; +	} + +	return fails ? TEST_FAIL : TEST_OK; +} diff --git a/tools/perf/tests/builtin-test.c b/tools/perf/tests/builtin-test.c index acb98e0e39f..0918ada4cc4 100644 --- a/tools/perf/tests/builtin-test.c +++ b/tools/perf/tests/builtin-test.c @@ -78,6 +78,22 @@ static struct test {  		.func = test__python_use,  	},  	{ +		.desc = "Test breakpoint overflow signal handler", +		.func = test__bp_signal, +	}, +	{ +		.desc = "Test breakpoint overflow sampling", +		.func = test__bp_signal_overflow, +	}, +	{ +		.desc = "Test number of exit event of a simple workload", +		.func = test__task_exit, +	}, +	{ +		.desc = "Test software clock events have valid period values", +		.func = test__sw_clock_freq, +	}, +	{  		.func = NULL,  	},  }; diff --git a/tools/perf/tests/evsel-roundtrip-name.c b/tools/perf/tests/evsel-roundtrip-name.c index 0fd99a9adb9..0197bda9c46 100644 --- a/tools/perf/tests/evsel-roundtrip-name.c +++ b/tools/perf/tests/evsel-roundtrip-name.c @@ -8,7 +8,7 @@ static int perf_evsel__roundtrip_cache_name_test(void)  	char name[128];  	int type, op, err = 0, ret = 0, i, idx;  	struct perf_evsel *evsel; -        struct perf_evlist *evlist = perf_evlist__new(NULL, NULL); +	struct perf_evlist *evlist = perf_evlist__new();          if (evlist == NULL)                  return -ENOMEM; @@ -64,7 +64,7 @@ static int __perf_evsel__name_array_test(const char *names[], int nr_names)  {  	int i, err;  	struct perf_evsel *evsel; -        struct perf_evlist *evlist = perf_evlist__new(NULL, NULL); +	struct perf_evlist *evlist = perf_evlist__new();          if (evlist == NULL)                  return -ENOMEM; diff --git a/tools/perf/tests/hists_link.c b/tools/perf/tests/hists_link.c index 1be64a6c5da..89085a9615e 100644 --- a/tools/perf/tests/hists_link.c +++ b/tools/perf/tests/hists_link.c @@ -223,7 +223,7 @@ static int add_hist_entries(struct perf_evlist *evlist, struct machine *machine)  							  &sample, 0) < 0)  				goto out; -			he = __hists__add_entry(&evsel->hists, &al, NULL, 1); +			he = __hists__add_entry(&evsel->hists, &al, NULL, 1, 1);  			if (he == NULL)  				goto out; @@ -247,7 +247,7 @@ static int add_hist_entries(struct perf_evlist *evlist, struct machine *machine)  							  &sample, 0) < 0)  				goto out; -			he = __hists__add_entry(&evsel->hists, &al, NULL, 1); +			he = __hists__add_entry(&evsel->hists, &al, NULL, 1, 1);  			if (he == NULL)  				goto out; @@ -436,7 +436,7 @@ int test__hists_link(void)  	struct machines machines;  	struct machine *machine = NULL;  	struct perf_evsel *evsel, *first; -        struct perf_evlist *evlist = perf_evlist__new(NULL, NULL); +	struct perf_evlist *evlist = perf_evlist__new();  	if (evlist == NULL)                  return -ENOMEM; diff --git a/tools/perf/tests/mmap-basic.c b/tools/perf/tests/mmap-basic.c index cdd50755af5..5b1b5aba722 100644 --- a/tools/perf/tests/mmap-basic.c +++ b/tools/perf/tests/mmap-basic.c @@ -53,12 +53,14 @@ int test__basic_mmap(void)  		goto out_free_cpus;  	} -	evlist = perf_evlist__new(cpus, threads); +	evlist = perf_evlist__new();  	if (evlist == NULL) {  		pr_debug("perf_evlist__new\n");  		goto out_free_cpus;  	} +	perf_evlist__set_maps(evlist, cpus, threads); +  	for (i = 0; i < nsyscalls; ++i) {  		char name[64]; diff --git a/tools/perf/tests/open-syscall-tp-fields.c b/tools/perf/tests/open-syscall-tp-fields.c index 1c52fdc1164..fc5b9fca8b4 100644 --- a/tools/perf/tests/open-syscall-tp-fields.c +++ b/tools/perf/tests/open-syscall-tp-fields.c @@ -18,7 +18,7 @@ int test__syscall_open_tp_fields(void)  	};  	const char *filename = "/etc/passwd";  	int flags = O_RDONLY | O_DIRECTORY; -	struct perf_evlist *evlist = perf_evlist__new(NULL, NULL); +	struct perf_evlist *evlist = perf_evlist__new();  	struct perf_evsel *evsel;  	int err = -1, i, nr_events = 0, nr_polls = 0; @@ -48,13 +48,13 @@ int test__syscall_open_tp_fields(void)  	err = perf_evlist__open(evlist);  	if (err < 0) {  		pr_debug("perf_evlist__open: %s\n", strerror(errno)); -		goto out_delete_evlist; +		goto out_delete_maps;  	}  	err = perf_evlist__mmap(evlist, UINT_MAX, false);  	if (err < 0) {  		pr_debug("perf_evlist__mmap: %s\n", strerror(errno)); -		goto out_delete_evlist; +		goto out_close_evlist;  	}  	perf_evlist__enable(evlist); @@ -110,6 +110,10 @@ out_ok:  	err = 0;  out_munmap:  	perf_evlist__munmap(evlist); +out_close_evlist: +	perf_evlist__close(evlist); +out_delete_maps: +	perf_evlist__delete_maps(evlist);  out_delete_evlist:  	perf_evlist__delete(evlist);  out: diff --git a/tools/perf/tests/parse-events.c b/tools/perf/tests/parse-events.c index c5636f36fe3..88e2f44cb15 100644 --- a/tools/perf/tests/parse-events.c +++ b/tools/perf/tests/parse-events.c @@ -3,7 +3,7 @@  #include "evsel.h"  #include "evlist.h"  #include "sysfs.h" -#include "debugfs.h" +#include <lk/debugfs.h>  #include "tests.h"  #include <linux/hw_breakpoint.h> @@ -1218,7 +1218,7 @@ static int test_event(struct evlist_test *e)  	struct perf_evlist *evlist;  	int ret; -	evlist = perf_evlist__new(NULL, NULL); +	evlist = perf_evlist__new();  	if (evlist == NULL)  		return -ENOMEM; diff --git a/tools/perf/tests/perf-record.c b/tools/perf/tests/perf-record.c index 1e8e5128d0d..72d8881873b 100644 --- a/tools/perf/tests/perf-record.c +++ b/tools/perf/tests/perf-record.c @@ -45,7 +45,7 @@ int test__PERF_RECORD(void)  	};  	cpu_set_t cpu_mask;  	size_t cpu_mask_size = sizeof(cpu_mask); -	struct perf_evlist *evlist = perf_evlist__new(NULL, NULL); +	struct perf_evlist *evlist = perf_evlist__new();  	struct perf_evsel *evsel;  	struct perf_sample sample;  	const char *cmd = "sleep"; @@ -93,7 +93,8 @@ int test__PERF_RECORD(void)  	 * so that we have time to open the evlist (calling sys_perf_event_open  	 * on all the fds) and then mmap them.  	 */ -	err = perf_evlist__prepare_workload(evlist, &opts, argv); +	err = perf_evlist__prepare_workload(evlist, &opts.target, argv, +					    false, false);  	if (err < 0) {  		pr_debug("Couldn't run the workload!\n");  		goto out_delete_maps; @@ -142,7 +143,7 @@ int test__PERF_RECORD(void)  	err = perf_evlist__mmap(evlist, opts.mmap_pages, false);  	if (err < 0) {  		pr_debug("perf_evlist__mmap: %s\n", strerror(errno)); -		goto out_delete_maps; +		goto out_close_evlist;  	}  	/* @@ -305,6 +306,8 @@ found_exit:  	}  out_err:  	perf_evlist__munmap(evlist); +out_close_evlist: +	perf_evlist__close(evlist);  out_delete_maps:  	perf_evlist__delete_maps(evlist);  out_delete_evlist: diff --git a/tools/perf/tests/sw-clock.c b/tools/perf/tests/sw-clock.c new file mode 100644 index 00000000000..2e41e2d32cc --- /dev/null +++ b/tools/perf/tests/sw-clock.c @@ -0,0 +1,119 @@ +#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" + +#define NR_LOOPS  1000000 + +/* + * 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; +	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, +	}; + +	attr.sample_freq = 10000; + +	evlist = perf_evlist__new(); +	if (evlist == NULL) { +		pr_debug("perf_evlist__new\n"); +		return -1; +	} + +	evsel = perf_evsel__new(&attr, 0); +	if (evsel == NULL) { +		pr_debug("perf_evsel__new\n"); +		goto out_free_evlist; +	} +	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"); +		goto out_delete_maps; +	} + +	perf_evlist__open(evlist); + +	err = perf_evlist__mmap(evlist, 128, true); +	if (err < 0) { +		pr_debug("failed to mmap event: %d (%s)\n", errno, +			 strerror(errno)); +		goto out_close_evlist; +	} + +	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) +			continue; + +		err = perf_evlist__parse_sample(evlist, event, &sample); +		if (err < 0) { +			pr_debug("Error during parse sample\n"); +			goto out_unmap_evlist; +		} + +		total_periods += sample.period; +		nr_samples++; +	} + +	if ((u64) nr_samples == total_periods) { +		pr_debug("All (%d) samples have period value of 1!\n", +			 nr_samples); +		err = -1; +	} + +out_unmap_evlist: +	perf_evlist__munmap(evlist); +out_close_evlist: +	perf_evlist__close(evlist); +out_delete_maps: +	perf_evlist__delete_maps(evlist); +out_free_evlist: +	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; +} diff --git a/tools/perf/tests/task-exit.c b/tools/perf/tests/task-exit.c new file mode 100644 index 00000000000..28fe5894b06 --- /dev/null +++ b/tools/perf/tests/task-exit.c @@ -0,0 +1,123 @@ +#include "evlist.h" +#include "evsel.h" +#include "thread_map.h" +#include "cpumap.h" +#include "tests.h" + +#include <signal.h> + +static int exited; +static int nr_exit; + +static void sig_handler(int sig) +{ +	exited = 1; + +	if (sig == SIGUSR1) +		nr_exit = -1; +} + +/* + * This test will start a workload that does nothing then it checks + * if the number of exit event reported by the kernel is 1 or not + * in order to check the kernel returns correct number of event. + */ +int test__task_exit(void) +{ +	int err = -1; +	union perf_event *event; +	struct perf_evsel *evsel; +	struct perf_evlist *evlist; +	struct perf_target target = { +		.uid		= UINT_MAX, +		.uses_mmap	= true, +	}; +	const char *argv[] = { "true", NULL }; + +	signal(SIGCHLD, sig_handler); +	signal(SIGUSR1, sig_handler); + +	evlist = perf_evlist__new(); +	if (evlist == NULL) { +		pr_debug("perf_evlist__new\n"); +		return -1; +	} +	/* +	 * We need at least one evsel in the evlist, use the default +	 * one: "cycles". +	 */ +	err = perf_evlist__add_default(evlist); +	if (err < 0) { +		pr_debug("Not enough memory to create evsel\n"); +		goto out_free_evlist; +	} + +	/* +	 * Create maps of threads and cpus to monitor. In this case +	 * we start with all threads and cpus (-1, -1) but then in +	 * perf_evlist__prepare_workload we'll fill in the only thread +	 * we're monitoring, the one forked there. +	 */ +	evlist->cpus = cpu_map__dummy_new(); +	evlist->threads = thread_map__new_by_tid(-1); +	if (!evlist->cpus || !evlist->threads) { +		err = -ENOMEM; +		pr_debug("Not enough memory to create thread/cpu maps\n"); +		goto out_delete_maps; +	} + +	err = perf_evlist__prepare_workload(evlist, &target, argv, false, true); +	if (err < 0) { +		pr_debug("Couldn't run the workload!\n"); +		goto out_delete_maps; +	} + +	evsel = perf_evlist__first(evlist); +	evsel->attr.task = 1; +	evsel->attr.sample_freq = 0; +	evsel->attr.inherit = 0; +	evsel->attr.watermark = 0; +	evsel->attr.wakeup_events = 1; +	evsel->attr.exclude_kernel = 1; + +	err = perf_evlist__open(evlist); +	if (err < 0) { +		pr_debug("Couldn't open the evlist: %s\n", strerror(-err)); +		goto out_delete_maps; +	} + +	if (perf_evlist__mmap(evlist, 128, true) < 0) { +		pr_debug("failed to mmap events: %d (%s)\n", errno, +			 strerror(errno)); +		goto out_close_evlist; +	} + +	perf_evlist__start_workload(evlist); + +retry: +	while ((event = perf_evlist__mmap_read(evlist, 0)) != NULL) { +		if (event->header.type != PERF_RECORD_EXIT) +			continue; + +		nr_exit++; +	} + +	if (!exited || !nr_exit) { +		poll(evlist->pollfd, evlist->nr_fds, -1); +		goto retry; +	} + +	if (nr_exit != 1) { +		pr_debug("received %d EXIT records\n", nr_exit); +		err = -1; +	} + +	perf_evlist__munmap(evlist); +out_close_evlist: +	perf_evlist__close(evlist); +out_delete_maps: +	perf_evlist__delete_maps(evlist); +out_free_evlist: +	perf_evlist__delete(evlist); +	return err; +} diff --git a/tools/perf/tests/tests.h b/tools/perf/tests/tests.h index 5de0be1ff4b..dd7feae2d37 100644 --- a/tools/perf/tests/tests.h +++ b/tools/perf/tests/tests.h @@ -23,5 +23,9 @@ int test__dso_data(void);  int test__parse_events(void);  int test__hists_link(void);  int test__python_use(void); +int test__bp_signal(void); +int test__bp_signal_overflow(void); +int test__task_exit(void); +int test__sw_clock_freq(void);  #endif /* TESTS_H */ |