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;
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;
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");
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)
}
}
- 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);
}
{
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]);
}
}
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]);
}
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);
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;
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)
}
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;
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;
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;
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) {
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);
}
/*
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++)
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;
}
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.
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);
}
}
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));
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;
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));
setlocale(LC_ALL, "");
- evsel_list = perf_evlist__new();
+ evsel_list = perf_evlist__new(NULL, NULL);
if (evsel_list == NULL)
return -ENOMEM;
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;
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;
}
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;
}
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;
}
}
- 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;
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);
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;
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);
{
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);
}
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)
}
}
- 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));
}
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;
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");
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");
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:
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);
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:
#define FD(e, x, y) (*(int *)xyarray__entry(e->fd, x, y))
#define SID(e, x, y) xyarray__entry(e->id, x, y)
-void perf_evlist__init(struct perf_evlist *evlist)
+void perf_evlist__init(struct perf_evlist *evlist, struct cpu_map *cpus,
+ struct thread_map *threads)
{
int i;
for (i = 0; i < PERF_EVLIST__HLIST_SIZE; ++i)
INIT_HLIST_HEAD(&evlist->heads[i]);
INIT_LIST_HEAD(&evlist->entries);
+ perf_evlist__set_maps(evlist, cpus, threads);
}
-struct perf_evlist *perf_evlist__new(void)
+struct perf_evlist *perf_evlist__new(struct cpu_map *cpus,
+ struct thread_map *threads)
{
struct perf_evlist *evlist = zalloc(sizeof(*evlist));
if (evlist != NULL)
- perf_evlist__init(evlist);
+ perf_evlist__init(evlist, cpus, threads);
return evlist;
}
return 0;
}
-int perf_evlist__alloc_pollfd(struct perf_evlist *evlist, int ncpus, int nthreads)
+int perf_evlist__alloc_pollfd(struct perf_evlist *evlist)
{
- int nfds = ncpus * nthreads * evlist->nr_entries;
+ int nfds = evlist->cpus->nr * evlist->threads->nr * evlist->nr_entries;
evlist->pollfd = malloc(sizeof(struct pollfd) * nfds);
return evlist->pollfd != NULL ? 0 : -ENOMEM;
}
return event;
}
-void perf_evlist__munmap(struct perf_evlist *evlist, int ncpus)
+void perf_evlist__munmap(struct perf_evlist *evlist)
{
int cpu;
- for (cpu = 0; cpu < ncpus; cpu++) {
+ for (cpu = 0; cpu < evlist->cpus->nr; cpu++) {
if (evlist->mmap[cpu].base != NULL) {
munmap(evlist->mmap[cpu].base, evlist->mmap_len);
evlist->mmap[cpu].base = NULL;
}
}
-int perf_evlist__alloc_mmap(struct perf_evlist *evlist, int ncpus)
+int perf_evlist__alloc_mmap(struct perf_evlist *evlist)
{
- evlist->mmap = zalloc(ncpus * sizeof(struct perf_mmap));
+ evlist->mmap = zalloc(evlist->cpus->nr * sizeof(struct perf_mmap));
return evlist->mmap != NULL ? 0 : -ENOMEM;
}
/** perf_evlist__mmap - Create per cpu maps to receive events
*
* @evlist - list of events
- * @cpus - cpu map being monitored
- * @threads - threads map being monitored
* @pages - map length in pages
* @overwrite - overwrite older events?
*
* unsigned int head = perf_mmap__read_head(m);
*
* perf_mmap__write_tail(m, head)
+ *
+ * Using perf_evlist__read_on_cpu does this automatically.
*/
-int perf_evlist__mmap(struct perf_evlist *evlist, struct cpu_map *cpus,
- struct thread_map *threads, int pages, bool overwrite)
+int perf_evlist__mmap(struct perf_evlist *evlist, int pages, bool overwrite)
{
unsigned int page_size = sysconf(_SC_PAGE_SIZE);
int mask = pages * page_size - 1, cpu;
struct perf_evsel *first_evsel, *evsel;
+ const struct cpu_map *cpus = evlist->cpus;
+ const struct thread_map *threads = evlist->threads;
int thread, prot = PROT_READ | (overwrite ? 0 : PROT_WRITE);
- if (evlist->mmap == NULL &&
- perf_evlist__alloc_mmap(evlist, cpus->nr) < 0)
+ if (evlist->mmap == NULL && perf_evlist__alloc_mmap(evlist) < 0)
return -ENOMEM;
- if (evlist->pollfd == NULL &&
- perf_evlist__alloc_pollfd(evlist, cpus->nr, threads->nr) < 0)
+ if (evlist->pollfd == NULL && perf_evlist__alloc_pollfd(evlist) < 0)
return -ENOMEM;
evlist->overwrite = overwrite;
}
return -1;
}
+
+int perf_evlist__create_maps(struct perf_evlist *evlist, pid_t target_pid,
+ pid_t target_tid, const char *cpu_list)
+{
+ evlist->threads = thread_map__new(target_pid, target_tid);
+
+ if (evlist->threads == NULL)
+ return -1;
+
+ if (target_tid != -1)
+ evlist->cpus = cpu_map__dummy_new();
+ else
+ evlist->cpus = cpu_map__new(cpu_list);
+
+ if (evlist->cpus == NULL)
+ goto out_delete_threads;
+
+ return 0;
+
+out_delete_threads:
+ thread_map__delete(evlist->threads);
+ return -1;
+}
+
+void perf_evlist__delete_maps(struct perf_evlist *evlist)
+{
+ cpu_map__delete(evlist->cpus);
+ thread_map__delete(evlist->threads);
+ evlist->cpus = NULL;
+ evlist->threads = NULL;
+}
union perf_event event_copy;
struct perf_mmap *mmap;
struct pollfd *pollfd;
+ struct thread_map *threads;
+ struct cpu_map *cpus;
};
struct perf_evsel;
-struct perf_evlist *perf_evlist__new(void);
-void perf_evlist__init(struct perf_evlist *evlist);
+struct perf_evlist *perf_evlist__new(struct cpu_map *cpus,
+ struct thread_map *threads);
+void perf_evlist__init(struct perf_evlist *evlist, struct cpu_map *cpus,
+ struct thread_map *threads);
void perf_evlist__exit(struct perf_evlist *evlist);
void perf_evlist__delete(struct perf_evlist *evlist);
void perf_evlist__add(struct perf_evlist *evlist, struct perf_evsel *entry);
int perf_evlist__add_default(struct perf_evlist *evlist);
-int perf_evlist__alloc_pollfd(struct perf_evlist *evlist, int ncpus, int nthreads);
+int perf_evlist__alloc_pollfd(struct perf_evlist *evlist);
void perf_evlist__add_pollfd(struct perf_evlist *evlist, int fd);
struct perf_evsel *perf_evlist__id2evsel(struct perf_evlist *evlist, u64 id);
union perf_event *perf_evlist__read_on_cpu(struct perf_evlist *self, int cpu);
-int perf_evlist__alloc_mmap(struct perf_evlist *evlist, int ncpus);
-int perf_evlist__mmap(struct perf_evlist *evlist, struct cpu_map *cpus,
- struct thread_map *threads, int pages, bool overwrite);
-void perf_evlist__munmap(struct perf_evlist *evlist, int ncpus);
+int perf_evlist__alloc_mmap(struct perf_evlist *evlist);
+int perf_evlist__mmap(struct perf_evlist *evlist, int pages, bool overwrite);
+void perf_evlist__munmap(struct perf_evlist *evlist);
+
+static inline void perf_evlist__set_maps(struct perf_evlist *evlist,
+ struct cpu_map *cpus,
+ struct thread_map *threads)
+{
+ evlist->cpus = cpus;
+ evlist->threads = threads;
+}
+
+int perf_evlist__create_maps(struct perf_evlist *evlist, pid_t target_pid,
+ pid_t target_tid, const char *cpu_list);
+void perf_evlist__delete_maps(struct perf_evlist *evlist);
#endif /* __PERF_EVLIST_H */
static int pyrf_evlist__init(struct pyrf_evlist *pevlist,
PyObject *args, PyObject *kwargs)
{
- perf_evlist__init(&pevlist->evlist);
+ PyObject *pcpus = NULL, *pthreads = NULL;
+ struct cpu_map *cpus;
+ struct thread_map *threads;
+
+ if (!PyArg_ParseTuple(args, "OO", &pcpus, &pthreads))
+ return -1;
+
+ threads = ((struct pyrf_thread_map *)pthreads)->threads;
+ cpus = ((struct pyrf_cpu_map *)pcpus)->cpus;
+ perf_evlist__init(&pevlist->evlist, cpus, threads);
return 0;
}
PyObject *args, PyObject *kwargs)
{
struct perf_evlist *evlist = &pevlist->evlist;
- PyObject *pcpus = NULL, *pthreads = NULL;
- struct cpu_map *cpus = NULL;
- struct thread_map *threads = NULL;
- static char *kwlist[] = {"cpus", "threads", "pages", "overwrite",
+ static char *kwlist[] = {"pages", "overwrite",
NULL, NULL};
int pages = 128, overwrite = false;
- if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|ii", kwlist,
- &pcpus, &pthreads, &pages, &overwrite))
+ if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|ii", kwlist,
+ &pages, &overwrite))
return NULL;
- threads = ((struct pyrf_thread_map *)pthreads)->threads;
- cpus = ((struct pyrf_cpu_map *)pcpus)->cpus;
-
- if (perf_evlist__mmap(evlist, cpus, threads, pages, overwrite) < 0) {
+ if (perf_evlist__mmap(evlist, pages, overwrite) < 0) {
PyErr_SetFromErrno(PyExc_OSError);
return NULL;
}