Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 7e2ed097 authored by Arnaldo Carvalho de Melo's avatar Arnaldo Carvalho de Melo
Browse files

perf evlist: Store pointer to the cpu and thread maps



So that we don't have to pass it around to the several methods that
needs it, simplifying usage.

There is one case where we don't have the thread/cpu map in advance,
which is in the parsing routines used by top, stat, record, that we have
to wait till all options are parsed to know if a cpu or thread list was
passed to then create those maps.

For that case consolidate the cpu and thread map creation via
perf_evlist__create_maps() out of the code in top and record, while also
providing a perf_evlist__set_maps() for cases where multiple evlists
share maps or for when maps that represent CPU sockets, for instance,
get crafted out of topology information or subsets of threads in a
particular application are to be monitored, providing more granularity
in specifying which cpus and threads to monitor.

Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Ingo Molnar <mingo@elte.hu>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Stephane Eranian <eranian@google.com>
Cc: Tom Zanussi <tzanussi@gmail.com>
LKML-Reference: <new-submission>
Signed-off-by: default avatarArnaldo Carvalho de Melo <acme@redhat.com>
parent f8a95309
Loading
Loading
Loading
Loading
+16 −28
Original line number Diff line number Diff line
@@ -42,7 +42,6 @@ static u64 user_interval = ULLONG_MAX;
static u64			default_interval		=      0;
static u64			sample_type;

static struct cpu_map		*cpus;
static unsigned int		page_size;
static unsigned int		mmap_pages			=    128;
static unsigned int		user_freq 			= UINT_MAX;
@@ -58,7 +57,6 @@ static bool sample_id_all_avail = true;
static bool			system_wide			=  false;
static pid_t			target_pid			=     -1;
static pid_t			target_tid			=     -1;
static struct thread_map	*threads;
static pid_t			child_pid			=     -1;
static bool			no_inherit			=  false;
static enum write_mode_t	write_mode			= WRITE_FORCE;
@@ -189,7 +187,7 @@ static void create_counter(struct perf_evsel *evsel, int cpu)
	int thread_index;
	int ret;

	for (thread_index = 0; thread_index < threads->nr; thread_index++) {
	for (thread_index = 0; thread_index < evsel_list->threads->nr; thread_index++) {
		h_attr = get_header_attr(attr, evsel->idx);
		if (h_attr == NULL)
			die("nomem\n");
@@ -317,7 +315,8 @@ static void open_counters(struct perf_evlist *evlist)
retry_sample_id:
		attr->sample_id_all = sample_id_all_avail ? 1 : 0;
try_again:
		if (perf_evsel__open(pos, cpus, threads, group, !no_inherit) < 0) {
		if (perf_evsel__open(pos, evlist->cpus, evlist->threads, group,
				     !no_inherit) < 0) {
			int err = errno;

			if (err == EPERM || err == EACCES)
@@ -368,10 +367,10 @@ try_again:
		}
	}

	if (perf_evlist__mmap(evlist, cpus, threads, mmap_pages, false) < 0)
	if (perf_evlist__mmap(evlist, mmap_pages, false) < 0)
		die("failed to mmap with %d (%s)\n", errno, strerror(errno));

	for (cpu = 0; cpu < cpus->nr; ++cpu) {
	for (cpu = 0; cpu < evsel_list->cpus->nr; ++cpu) {
		list_for_each_entry(pos, &evlist->entries, node)
			create_counter(pos, cpu);
	}
@@ -450,7 +449,7 @@ static void mmap_read_all(void)
{
	int i;

	for (i = 0; i < cpus->nr; i++) {
	for (i = 0; i < evsel_list->cpus->nr; i++) {
		if (evsel_list->mmap[i].base)
			mmap_read(&evsel_list->mmap[i]);
	}
@@ -584,7 +583,7 @@ static int __cmd_record(int argc, const char **argv)
		}

		if (!system_wide && target_tid == -1 && target_pid == -1)
			threads->map[0] = child_pid;
			evsel_list->threads->map[0] = child_pid;

		close(child_ready_pipe[1]);
		close(go_pipe[0]);
@@ -718,12 +717,12 @@ static int __cmd_record(int argc, const char **argv)
		}

		if (done) {
			for (i = 0; i < cpus->nr; i++) {
			for (i = 0; i < evsel_list->cpus->nr; i++) {
				struct perf_evsel *pos;

				list_for_each_entry(pos, &evsel_list->entries, node) {
					for (thread = 0;
						thread < threads->nr;
						thread < evsel_list->threads->nr;
						thread++)
						ioctl(FD(pos, i, thread),
							PERF_EVENT_IOC_DISABLE);
@@ -816,7 +815,7 @@ int cmd_record(int argc, const char **argv, const char *prefix __used)
	int err = -ENOMEM;
	struct perf_evsel *pos;

	evsel_list = perf_evlist__new();
	evsel_list = perf_evlist__new(NULL, NULL);
	if (evsel_list == NULL)
		return -ENOMEM;

@@ -850,28 +849,19 @@ int cmd_record(int argc, const char **argv, const char *prefix __used)
	if (target_pid != -1)
		target_tid = target_pid;

	threads = thread_map__new(target_pid, target_tid);
	if (threads == NULL) {
		pr_err("Problems finding threads of monitor\n");
		usage_with_options(record_usage, record_options);
	}

	if (target_tid != -1)
		cpus = cpu_map__dummy_new();
	else
		cpus = cpu_map__new(cpu_list);

	if (cpus == NULL)
	if (perf_evlist__create_maps(evsel_list, target_pid,
				     target_tid, cpu_list) < 0)
		usage_with_options(record_usage, record_options);

	list_for_each_entry(pos, &evsel_list->entries, node) {
		if (perf_evsel__alloc_fd(pos, cpus->nr, threads->nr) < 0)
		if (perf_evsel__alloc_fd(pos, evsel_list->cpus->nr,
					 evsel_list->threads->nr) < 0)
			goto out_free_fd;
		if (perf_header__push_event(pos->attr.config, event_name(pos)))
			goto out_free_fd;
	}

	if (perf_evlist__alloc_pollfd(evsel_list, cpus->nr, threads->nr) < 0)
	if (perf_evlist__alloc_pollfd(evsel_list) < 0)
		goto out_free_fd;

	if (user_interval != ULLONG_MAX)
@@ -893,10 +883,8 @@ int cmd_record(int argc, const char **argv, const char *prefix __used)
	}

	err = __cmd_record(argc, argv);

out_free_fd:
	thread_map__delete(threads);
	threads = NULL;
	perf_evlist__delete_maps(evsel_list);
out_symbol_exit:
	symbol__exit();
	return err;
+22 −23
Original line number Diff line number Diff line
@@ -76,7 +76,6 @@ static struct perf_event_attr default_attrs[] = {
struct perf_evlist		*evsel_list;

static bool			system_wide			=  false;
static struct cpu_map		*cpus;
static int			run_idx				=  0;

static int			run_count			=  1;
@@ -85,7 +84,6 @@ static bool scale = true;
static bool			no_aggr				= false;
static pid_t			target_pid			= -1;
static pid_t			target_tid			= -1;
static struct thread_map	*threads;
static pid_t			child_pid			= -1;
static bool			null_run			=  false;
static bool			big_num				=  true;
@@ -170,7 +168,7 @@ static int create_perf_stat_counter(struct perf_evsel *evsel)
				    PERF_FORMAT_TOTAL_TIME_RUNNING;

	if (system_wide)
		return perf_evsel__open_per_cpu(evsel, cpus, false, false);
		return perf_evsel__open_per_cpu(evsel, evsel_list->cpus, false, false);

	attr->inherit = !no_inherit;
	if (target_pid == -1 && target_tid == -1) {
@@ -178,7 +176,7 @@ static int create_perf_stat_counter(struct perf_evsel *evsel)
		attr->enable_on_exec = 1;
	}

	return perf_evsel__open_per_thread(evsel, threads, false, false);
	return perf_evsel__open_per_thread(evsel, evsel_list->threads, false, false);
}

/*
@@ -203,7 +201,8 @@ static int read_counter_aggr(struct perf_evsel *counter)
	u64 *count = counter->counts->aggr.values;
	int i;

	if (__perf_evsel__read(counter, cpus->nr, threads->nr, scale) < 0)
	if (__perf_evsel__read(counter, evsel_list->cpus->nr,
			       evsel_list->threads->nr, scale) < 0)
		return -1;

	for (i = 0; i < 3; i++)
@@ -236,7 +235,7 @@ static int read_counter(struct perf_evsel *counter)
	u64 *count;
	int cpu;

	for (cpu = 0; cpu < cpus->nr; cpu++) {
	for (cpu = 0; cpu < evsel_list->cpus->nr; cpu++) {
		if (__perf_evsel__read_on_cpu(counter, cpu, 0, scale) < 0)
			return -1;

@@ -301,7 +300,7 @@ static int run_perf_stat(int argc __used, const char **argv)
		}

		if (target_tid == -1 && target_pid == -1 && !system_wide)
			threads->map[0] = child_pid;
			evsel_list->threads->map[0] = child_pid;

		/*
		 * Wait for the child to be ready to exec.
@@ -353,12 +352,13 @@ static int run_perf_stat(int argc __used, const char **argv)
	if (no_aggr) {
		list_for_each_entry(counter, &evsel_list->entries, node) {
			read_counter(counter);
			perf_evsel__close_fd(counter, cpus->nr, 1);
			perf_evsel__close_fd(counter, evsel_list->cpus->nr, 1);
		}
	} else {
		list_for_each_entry(counter, &evsel_list->entries, node) {
			read_counter_aggr(counter);
			perf_evsel__close_fd(counter, cpus->nr, threads->nr);
			perf_evsel__close_fd(counter, evsel_list->cpus->nr,
					     evsel_list->threads->nr);
		}
	}

@@ -386,7 +386,7 @@ static void nsec_printout(int cpu, struct perf_evsel *evsel, double avg)
	if (no_aggr)
		sprintf(cpustr, "CPU%*d%s",
			csv_output ? 0 : -4,
			cpus->map[cpu], csv_sep);
			evsel_list->cpus->map[cpu], csv_sep);

	fprintf(stderr, fmt, cpustr, msecs, csv_sep, event_name(evsel));

@@ -414,7 +414,7 @@ static void abs_printout(int cpu, struct perf_evsel *evsel, double avg)
	if (no_aggr)
		sprintf(cpustr, "CPU%*d%s",
			csv_output ? 0 : -4,
			cpus->map[cpu], csv_sep);
			evsel_list->cpus->map[cpu], csv_sep);
	else
		cpu = 0;

@@ -500,14 +500,14 @@ static void print_counter(struct perf_evsel *counter)
	u64 ena, run, val;
	int cpu;

	for (cpu = 0; cpu < cpus->nr; cpu++) {
	for (cpu = 0; cpu < evsel_list->cpus->nr; cpu++) {
		val = counter->counts->cpu[cpu].val;
		ena = counter->counts->cpu[cpu].ena;
		run = counter->counts->cpu[cpu].run;
		if (run == 0 || ena == 0) {
			fprintf(stderr, "CPU%*d%s%*s%s%-24s",
				csv_output ? 0 : -4,
				cpus->map[cpu], csv_sep,
				evsel_list->cpus->map[cpu], csv_sep,
				csv_output ? 0 : 18,
				"<not counted>", csv_sep,
				event_name(counter));
@@ -652,7 +652,7 @@ int cmd_stat(int argc, const char **argv, const char *prefix __used)

	setlocale(LC_ALL, "");

	evsel_list = perf_evlist__new();
	evsel_list = perf_evlist__new(NULL, NULL);
	if (evsel_list == NULL)
		return -ENOMEM;

@@ -701,18 +701,18 @@ int cmd_stat(int argc, const char **argv, const char *prefix __used)
	if (target_pid != -1)
		target_tid = target_pid;

	threads = thread_map__new(target_pid, target_tid);
	if (threads == NULL) {
	evsel_list->threads = thread_map__new(target_pid, target_tid);
	if (evsel_list->threads == NULL) {
		pr_err("Problems finding threads of monitor\n");
		usage_with_options(stat_usage, options);
	}

	if (system_wide)
		cpus = cpu_map__new(cpu_list);
		evsel_list->cpus = cpu_map__new(cpu_list);
	else
		cpus = cpu_map__dummy_new();
		evsel_list->cpus = cpu_map__dummy_new();

	if (cpus == NULL) {
	if (evsel_list->cpus == NULL) {
		perror("failed to parse CPUs map");
		usage_with_options(stat_usage, options);
		return -1;
@@ -720,8 +720,8 @@ int cmd_stat(int argc, const char **argv, const char *prefix __used)

	list_for_each_entry(pos, &evsel_list->entries, node) {
		if (perf_evsel__alloc_stat_priv(pos) < 0 ||
		    perf_evsel__alloc_counts(pos, cpus->nr) < 0 ||
		    perf_evsel__alloc_fd(pos, cpus->nr, threads->nr) < 0)
		    perf_evsel__alloc_counts(pos, evsel_list->cpus->nr) < 0 ||
		    perf_evsel__alloc_fd(pos, evsel_list->cpus->nr, evsel_list->threads->nr) < 0)
			goto out_free_fd;
	}

@@ -750,7 +750,6 @@ out_free_fd:
		perf_evsel__free_stat_priv(pos);
	perf_evlist__delete(evsel_list);
out:
	thread_map__delete(threads);
	threads = NULL;
	perf_evlist__delete_maps(evsel_list);
	return status;
}
+3 −3
Original line number Diff line number Diff line
@@ -509,7 +509,7 @@ static int test__basic_mmap(void)
		goto out_free_cpus;
	}

	evlist = perf_evlist__new();
	evlist = perf_evlist__new(cpus, threads);
	if (evlist == NULL) {
		pr_debug("perf_evlist__new\n");
		goto out_free_cpus;
@@ -537,7 +537,7 @@ static int test__basic_mmap(void)
		}
	}

	if (perf_evlist__mmap(evlist, cpus, threads, 128, true) < 0) {
	if (perf_evlist__mmap(evlist, 128, true) < 0) {
		pr_debug("failed to mmap events: %d (%s)\n", errno,
			 strerror(errno));
		goto out_close_fd;
@@ -579,7 +579,7 @@ static int test__basic_mmap(void)

	err = 0;
out_munmap:
	perf_evlist__munmap(evlist, 1);
	perf_evlist__munmap(evlist);
out_close_fd:
	for (i = 0; i < nsyscalls; ++i)
		perf_evsel__close_fd(evsels[i], 1, threads->nr);
+19 −28
Original line number Diff line number Diff line
@@ -73,9 +73,7 @@ static int print_entries;

static int			target_pid			=     -1;
static int			target_tid			=     -1;
static struct thread_map	*threads;
static bool			inherit				=  false;
static struct cpu_map		*cpus;
static int			realtime_prio			=      0;
static bool			group				=  false;
static unsigned int		page_size;
@@ -567,12 +565,13 @@ static void print_sym_table(struct perf_session *session)
		printf(" (all");

	if (cpu_list)
		printf(", CPU%s: %s)\n", cpus->nr > 1 ? "s" : "", cpu_list);
		printf(", CPU%s: %s)\n", evsel_list->cpus->nr > 1 ? "s" : "", cpu_list);
	else {
		if (target_tid != -1)
			printf(")\n");
		else
			printf(", %d CPU%s)\n", cpus->nr, cpus->nr > 1 ? "s" : "");
			printf(", %d CPU%s)\n", evsel_list->cpus->nr,
			       evsel_list->cpus->nr > 1 ? "s" : "");
	}

	printf("%-*.*s\n", win_width, win_width, graph_dotted_line);
@@ -1124,7 +1123,7 @@ static void perf_session__mmap_read(struct perf_session *self)
{
	int i;

	for (i = 0; i < cpus->nr; i++)
	for (i = 0; i < evsel_list->cpus->nr; i++)
		perf_session__mmap_read_cpu(self, i);
}

@@ -1150,7 +1149,8 @@ static void start_counters(struct perf_evlist *evlist)

		attr->mmap = 1;
try_again:
		if (perf_evsel__open(counter, cpus, threads, group, inherit) < 0) {
		if (perf_evsel__open(counter, evsel_list->cpus,
				     evsel_list->threads, group, inherit) < 0) {
			int err = errno;

			if (err == EPERM || err == EACCES)
@@ -1181,7 +1181,7 @@ try_again:
		}
	}

	if (perf_evlist__mmap(evlist, cpus, threads, mmap_pages, false) < 0)
	if (perf_evlist__mmap(evlist, mmap_pages, false) < 0)
		die("failed to mmap with %d (%s)\n", errno, strerror(errno));
}

@@ -1296,7 +1296,7 @@ int cmd_top(int argc, const char **argv, const char *prefix __used)
	struct perf_evsel *pos;
	int status = -ENOMEM;

	evsel_list = perf_evlist__new();
	evsel_list = perf_evlist__new(NULL, NULL);
	if (evsel_list == NULL)
		return -ENOMEM;

@@ -1306,15 +1306,6 @@ int cmd_top(int argc, const char **argv, const char *prefix __used)
	if (argc)
		usage_with_options(top_usage, options);

	if (target_pid != -1)
		target_tid = target_pid;

	threads = thread_map__new(target_pid, target_tid);
	if (threads == NULL) {
		pr_err("Problems finding threads of monitor\n");
		usage_with_options(top_usage, options);
	}

	/* CPU and PID are mutually exclusive */
	if (target_tid > 0 && cpu_list) {
		printf("WARNING: PID switch overriding CPU\n");
@@ -1322,6 +1313,13 @@ int cmd_top(int argc, const char **argv, const char *prefix __used)
		cpu_list = NULL;
	}

	if (target_pid != -1)
		target_tid = target_pid;

	if (perf_evlist__create_maps(evsel_list, target_pid,
				     target_tid, cpu_list) < 0)
		usage_with_options(top_usage, options);

	if (!evsel_list->nr_entries &&
	    perf_evlist__add_default(evsel_list) < 0) {
		pr_err("Not enough memory for event selector list\n");
@@ -1343,16 +1341,9 @@ int cmd_top(int argc, const char **argv, const char *prefix __used)
		exit(EXIT_FAILURE);
	}

	if (target_tid != -1)
		cpus = cpu_map__dummy_new();
	else
		cpus = cpu_map__new(cpu_list);

	if (cpus == NULL)
		usage_with_options(top_usage, options);

	list_for_each_entry(pos, &evsel_list->entries, node) {
		if (perf_evsel__alloc_fd(pos, cpus->nr, threads->nr) < 0)
		if (perf_evsel__alloc_fd(pos, evsel_list->cpus->nr,
					 evsel_list->threads->nr) < 0)
			goto out_free_fd;
		/*
		 * Fill in the ones not specifically initialized via -c:
@@ -1363,8 +1354,8 @@ int cmd_top(int argc, const char **argv, const char *prefix __used)
		pos->attr.sample_period = default_interval;
	}

	if (perf_evlist__alloc_pollfd(evsel_list, cpus->nr, threads->nr) < 0 ||
	    perf_evlist__alloc_mmap(evsel_list, cpus->nr) < 0)
	if (perf_evlist__alloc_pollfd(evsel_list) < 0 ||
	    perf_evlist__alloc_mmap(evsel_list) < 0)
		goto out_free_fd;

	sym_evsel = list_entry(evsel_list->entries.next, struct perf_evsel, node);
+2 −2
Original line number Diff line number Diff line
@@ -23,9 +23,9 @@ def main():
			   sample_id_all = 1,
			   sample_type = perf.SAMPLE_PERIOD | perf.SAMPLE_TID | perf.SAMPLE_CPU | perf.SAMPLE_TID)
	evsel.open(cpus = cpus, threads = threads);
	evlist = perf.evlist()
	evlist = perf.evlist(cpus, threads)
	evlist.add(evsel)
	evlist.mmap(cpus = cpus, threads = threads)
	evlist.mmap()
	while True:
		evlist.poll(timeout = -1)
		for cpu in cpus:
Loading