aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorArnaldo Carvalho de Melo <acme@redhat.com>2011-11-25 08:19:45 -0200
committerArnaldo Carvalho de Melo <acme@redhat.com>2011-11-28 10:38:56 -0200
commitd20deb64e0490ee9442b5181bc08a62d2cadcb90 (patch)
treeafdb3f6fc9abbce9d0a96b7049d1f8121178a356
parent7009cc34b964939815160d7de64cf0215cdbf8bb (diff)
perf tools: Pass tool context in the the perf_event_ops functions
So that we don't need to have that many globals. Next steps will remove the 'session' pointer, that in most cases is not needed. Then we can rename perf_event_ops to 'perf_tool' that better describes this class hierarchy. Cc: David Ahern <dsahern@gmail.com> Cc: Frederic Weisbecker <fweisbec@gmail.com> Cc: Mike Galbraith <efault@gmx.de> Cc: Paul Mackerras <paulus@samba.org> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Stephane Eranian <eranian@google.com> Link: http://lkml.kernel.org/n/tip-wp4djox7x6w1i2bab1pt4xxp@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
-rw-r--r--tools/perf/builtin-annotate.c62
-rw-r--r--tools/perf/builtin-diff.c3
-rw-r--r--tools/perf/builtin-inject.c55
-rw-r--r--tools/perf/builtin-kmem.c3
-rw-r--r--tools/perf/builtin-lock.c3
-rw-r--r--tools/perf/builtin-record.c383
-rw-r--r--tools/perf/builtin-report.c97
-rw-r--r--tools/perf/builtin-sched.c3
-rw-r--r--tools/perf/builtin-script.c3
-rw-r--r--tools/perf/builtin-timechart.c12
-rw-r--r--tools/perf/builtin-top.c6
-rw-r--r--tools/perf/util/build-id.c7
-rw-r--r--tools/perf/util/callchain.h3
-rw-r--r--tools/perf/util/event.c66
-rw-r--r--tools/perf/util/event.h38
-rw-r--r--tools/perf/util/header.c36
-rw-r--r--tools/perf/util/header.h27
-rw-r--r--tools/perf/util/session.c60
-rw-r--r--tools/perf/util/session.h23
-rw-r--r--tools/perf/util/top.h3
20 files changed, 520 insertions, 373 deletions
diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c
index 4f0c3d98352..483cb946644 100644
--- a/tools/perf/builtin-annotate.c
+++ b/tools/perf/builtin-annotate.c
@@ -30,7 +30,8 @@
#include <linux/bitmap.h>
-static struct perf_annotate {
+struct perf_annotate {
+ struct perf_event_ops ops;
char const *input_name;
bool force, use_tui, use_stdio;
bool full_paths;
@@ -38,13 +39,12 @@ static struct perf_annotate {
const char *sym_hist_filter;
const char *cpu_list;
DECLARE_BITMAP(cpu_bitmap, MAX_NR_CPUS);
-} annotate = {
- .input_name = "perf.data",
-}, *ann = &annotate;
+};
static int perf_evsel__add_sample(struct perf_evsel *evsel,
struct perf_sample *sample,
- struct addr_location *al)
+ struct addr_location *al,
+ struct perf_annotate *ann)
{
struct hist_entry *he;
int ret;
@@ -79,11 +79,13 @@ static int perf_evsel__add_sample(struct perf_evsel *evsel,
return ret;
}
-static int process_sample_event(union perf_event *event,
+static int process_sample_event(struct perf_event_ops *ops,
+ union perf_event *event,
struct perf_sample *sample,
struct perf_evsel *evsel,
struct perf_session *session)
{
+ struct perf_annotate *ann = container_of(ops, struct perf_annotate, ops);
struct addr_location al;
if (perf_event__preprocess_sample(event, session, &al, sample,
@@ -96,7 +98,7 @@ static int process_sample_event(union perf_event *event,
if (ann->cpu_list && !test_bit(sample->cpu, ann->cpu_bitmap))
return 0;
- if (!al.filtered && perf_evsel__add_sample(evsel, sample, &al)) {
+ if (!al.filtered && perf_evsel__add_sample(evsel, sample, &al, ann)) {
pr_warning("problem incrementing symbol count, "
"skipping event\n");
return -1;
@@ -105,13 +107,15 @@ static int process_sample_event(union perf_event *event,
return 0;
}
-static int hist_entry__tty_annotate(struct hist_entry *he, int evidx)
+static int hist_entry__tty_annotate(struct hist_entry *he, int evidx,
+ struct perf_annotate *ann)
{
return symbol__tty_annotate(he->ms.sym, he->ms.map, evidx,
ann->print_line, ann->full_paths, 0, 0);
}
-static void hists__find_annotations(struct hists *self, int evidx)
+static void hists__find_annotations(struct hists *self, int evidx,
+ struct perf_annotate *ann)
{
struct rb_node *nd = rb_first(&self->entries), *next;
int key = K_RIGHT;
@@ -149,7 +153,7 @@ find_next:
if (next != NULL)
nd = next;
} else {
- hist_entry__tty_annotate(he, evidx);
+ hist_entry__tty_annotate(he, evidx, ann);
nd = rb_next(nd);
/*
* Since we have a hist_entry per IP for the same
@@ -162,16 +166,7 @@ find_next:
}
}
-static struct perf_event_ops event_ops = {
- .sample = process_sample_event,
- .mmap = perf_event__process_mmap,
- .comm = perf_event__process_comm,
- .fork = perf_event__process_task,
- .ordered_samples = true,
- .ordering_requires_timestamps = true,
-};
-
-static int __cmd_annotate(void)
+static int __cmd_annotate(struct perf_annotate *ann)
{
int ret;
struct perf_session *session;
@@ -179,7 +174,7 @@ static int __cmd_annotate(void)
u64 total_nr_samples;
session = perf_session__new(ann->input_name, O_RDONLY,
- ann->force, false, &event_ops);
+ ann->force, false, &ann->ops);
if (session == NULL)
return -ENOMEM;
@@ -190,7 +185,7 @@ static int __cmd_annotate(void)
goto out_delete;
}
- ret = perf_session__process_events(session, &event_ops);
+ ret = perf_session__process_events(session, &ann->ops);
if (ret)
goto out_delete;
@@ -214,7 +209,7 @@ static int __cmd_annotate(void)
total_nr_samples += nr_samples;
hists__collapse_resort(hists);
hists__output_resort(hists);
- hists__find_annotations(hists, pos->idx);
+ hists__find_annotations(hists, pos->idx, ann);
}
}
@@ -243,7 +238,20 @@ static const char * const annotate_usage[] = {
NULL
};
-static const struct option options[] = {
+int cmd_annotate(int argc, const char **argv, const char *prefix __used)
+{
+ struct perf_annotate annotate = {
+ .ops = {
+ .sample = process_sample_event,
+ .mmap = perf_event__process_mmap,
+ .comm = perf_event__process_comm,
+ .fork = perf_event__process_task,
+ .ordered_samples = true,
+ .ordering_requires_timestamps = true,
+ },
+ .input_name = "perf.data",
+ };
+ const struct option options[] = {
OPT_STRING('i', "input", &annotate.input_name, "file",
"input file name"),
OPT_STRING('d', "dsos", &symbol_conf.dso_list_str, "dso[,dso...]",
@@ -275,10 +283,8 @@ static const struct option options[] = {
OPT_STRING('M', "disassembler-style", &disassembler_style, "disassembler style",
"Specify disassembler style (e.g. -M intel for intel syntax)"),
OPT_END()
-};
+ };
-int cmd_annotate(int argc, const char **argv, const char *prefix __used)
-{
argc = parse_options(argc, argv, options, annotate_usage, 0);
if (annotate.use_stdio)
@@ -312,5 +318,5 @@ int cmd_annotate(int argc, const char **argv, const char *prefix __used)
return -1;
}
- return __cmd_annotate();
+ return __cmd_annotate(&annotate);
}
diff --git a/tools/perf/builtin-diff.c b/tools/perf/builtin-diff.c
index b39f3a1ee7d..9a0872f9e83 100644
--- a/tools/perf/builtin-diff.c
+++ b/tools/perf/builtin-diff.c
@@ -30,7 +30,8 @@ static int hists__add_entry(struct hists *self,
return -ENOMEM;
}
-static int diff__process_sample_event(union perf_event *event,
+static int diff__process_sample_event(struct perf_event_ops *ops __used,
+ union perf_event *event,
struct perf_sample *sample,
struct perf_evsel *evsel __used,
struct perf_session *session)
diff --git a/tools/perf/builtin-inject.c b/tools/perf/builtin-inject.c
index 978751ec64c..6ce6d80b59d 100644
--- a/tools/perf/builtin-inject.c
+++ b/tools/perf/builtin-inject.c
@@ -16,7 +16,8 @@
static char const *input_name = "-";
static bool inject_build_ids;
-static int perf_event__repipe_synth(union perf_event *event,
+static int perf_event__repipe_synth(struct perf_event_ops *ops __used,
+ union perf_event *event,
struct perf_session *session __used)
{
uint32_t size;
@@ -36,47 +37,57 @@ static int perf_event__repipe_synth(union perf_event *event,
return 0;
}
+static int perf_event__repipe_tracing_data_synth(union perf_event *event,
+ struct perf_session *session)
+{
+ return perf_event__repipe_synth(NULL, event, session);
+}
+
static int perf_event__repipe_attr(union perf_event *event,
struct perf_evlist **pevlist __used)
{
- return perf_event__repipe_synth(event, NULL);
+ return perf_event__repipe_synth(NULL, event, NULL);
}
-static int perf_event__repipe(union perf_event *event,
+static int perf_event__repipe(struct perf_event_ops *ops,
+ union perf_event *event,
struct perf_sample *sample __used,
struct perf_session *session)
{
- return perf_event__repipe_synth(event, session);
+ return perf_event__repipe_synth(ops, event, session);
}
-static int perf_event__repipe_sample(union perf_event *event,
+static int perf_event__repipe_sample(struct perf_event_ops *ops,
+ union perf_event *event,
struct perf_sample *sample __used,
struct perf_evsel *evsel __used,
struct perf_session *session)
{
- return perf_event__repipe_synth(event, session);
+ return perf_event__repipe_synth(ops, event, session);
}
-static int perf_event__repipe_mmap(union perf_event *event,
+static int perf_event__repipe_mmap(struct perf_event_ops *ops,
+ union perf_event *event,
struct perf_sample *sample,
struct perf_session *session)
{
int err;
- err = perf_event__process_mmap(event, sample, session);
- perf_event__repipe(event, sample, session);
+ err = perf_event__process_mmap(ops, event, sample, session);
+ perf_event__repipe(ops, event, sample, session);
return err;
}
-static int perf_event__repipe_task(union perf_event *event,
+static int perf_event__repipe_task(struct perf_event_ops *ops,
+ union perf_event *event,
struct perf_sample *sample,
struct perf_session *session)
{
int err;
- err = perf_event__process_task(event, sample, session);
- perf_event__repipe(event, sample, session);
+ err = perf_event__process_task(ops, event, sample, session);
+ perf_event__repipe(ops, event, sample, session);
return err;
}
@@ -86,7 +97,7 @@ static int perf_event__repipe_tracing_data(union perf_event *event,
{
int err;
- perf_event__repipe_synth(event, session);
+ perf_event__repipe_synth(NULL, event, session);
err = perf_event__process_tracing_data(event, session);
return err;
@@ -106,7 +117,8 @@ static int dso__read_build_id(struct dso *self)
return -1;
}
-static int dso__inject_build_id(struct dso *self, struct perf_session *session)
+static int dso__inject_build_id(struct dso *self, struct perf_event_ops *ops,
+ struct perf_session *session)
{
u16 misc = PERF_RECORD_MISC_USER;
struct machine *machine;
@@ -126,7 +138,7 @@ static int dso__inject_build_id(struct dso *self, struct perf_session *session)
if (self->kernel)
misc = PERF_RECORD_MISC_KERNEL;
- err = perf_event__synthesize_build_id(self, misc, perf_event__repipe,
+ err = perf_event__synthesize_build_id(ops, self, misc, perf_event__repipe,
machine, session);
if (err) {
pr_err("Can't synthesize build_id event for %s\n", self->long_name);
@@ -136,7 +148,8 @@ static int dso__inject_build_id(struct dso *self, struct perf_session *session)
return 0;
}
-static int perf_event__inject_buildid(union perf_event *event,
+static int perf_event__inject_buildid(struct perf_event_ops *ops,
+ union perf_event *event,
struct perf_sample *sample,
struct perf_evsel *evsel __used,
struct perf_session *session)
@@ -161,7 +174,7 @@ static int perf_event__inject_buildid(union perf_event *event,
if (!al.map->dso->hit) {
al.map->dso->hit = 1;
if (map__load(al.map, NULL) >= 0) {
- dso__inject_build_id(al.map->dso, session);
+ dso__inject_build_id(al.map->dso, ops, session);
/*
* If this fails, too bad, let the other side
* account this as unresolved.
@@ -174,7 +187,7 @@ static int perf_event__inject_buildid(union perf_event *event,
}
repipe:
- perf_event__repipe(event, sample, session);
+ perf_event__repipe(ops, event, sample, session);
return 0;
}
@@ -189,9 +202,9 @@ struct perf_event_ops inject_ops = {
.throttle = perf_event__repipe,
.unthrottle = perf_event__repipe,
.attr = perf_event__repipe_attr,
- .event_type = perf_event__repipe_synth,
- .tracing_data = perf_event__repipe_synth,
- .build_id = perf_event__repipe_synth,
+ .event_type = perf_event__repipe_synth,
+ .tracing_data = perf_event__repipe_tracing_data_synth,
+ .build_id = perf_event__repipe_synth,
};
extern volatile int session_done;
diff --git a/tools/perf/builtin-kmem.c b/tools/perf/builtin-kmem.c
index 225e963df10..5d01218e50e 100644
--- a/tools/perf/builtin-kmem.c
+++ b/tools/perf/builtin-kmem.c
@@ -303,7 +303,8 @@ static void process_raw_event(union perf_event *raw_event __used, void *data,
}
}
-static int process_sample_event(union perf_event *event,
+static int process_sample_event(struct perf_event_ops *ops __used,
+ union perf_event *event,
struct perf_sample *sample,
struct perf_evsel *evsel __used,
struct perf_session *session)
diff --git a/tools/perf/builtin-lock.c b/tools/perf/builtin-lock.c
index 899080ace26..f06b0a44c7c 100644
--- a/tools/perf/builtin-lock.c
+++ b/tools/perf/builtin-lock.c
@@ -845,7 +845,8 @@ static void dump_info(void)
die("Unknown type of information\n");
}
-static int process_sample_event(union perf_event *event,
+static int process_sample_event(struct perf_event_ops *ops __used,
+ union perf_event *event,
struct perf_sample *sample,
struct perf_evsel *evsel __used,
struct perf_session *s)
diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index ba6777a147c..4642d38b8d1 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -35,43 +35,36 @@ enum write_mode_t {
WRITE_APPEND
};
-struct perf_record_opts record_opts = {
- .target_pid = -1,
- .target_tid = -1,
- .mmap_pages = UINT_MAX,
- .user_freq = UINT_MAX,
- .user_interval = ULLONG_MAX,
- .freq = 1000,
- .sample_id_all_avail = true,
+struct perf_record {
+ struct perf_event_ops ops;
+ struct perf_record_opts opts;
+ u64 bytes_written;
+ const char *output_name;
+ struct perf_evlist *evlist;
+ struct perf_session *session;
+ const char *progname;
+ int output;
+ unsigned int page_size;
+ int realtime_prio;
+ enum write_mode_t write_mode;
+ bool no_buildid;
+ bool no_buildid_cache;
+ bool force;
+ bool file_new;
+ bool append_file;
+ long samples;
+ off_t post_processing_offset;
};
-static unsigned int page_size;
-static int output;
-static const char *output_name = NULL;
-static int realtime_prio = 0;
-static enum write_mode_t write_mode = WRITE_FORCE;
-static bool no_buildid = false;
-static bool no_buildid_cache = false;
-static struct perf_evlist *evsel_list;
-
-static long samples = 0;
-static u64 bytes_written = 0;
-
-static int file_new = 1;
-static off_t post_processing_offset;
-
-static struct perf_session *session;
-static const char *progname;
-
-static void advance_output(size_t size)
+static void advance_output(struct perf_record *rec, size_t size)
{
- bytes_written += size;
+ rec->bytes_written += size;
}
-static void write_output(void *buf, size_t size)
+static void write_output(struct perf_record *rec, void *buf, size_t size)
{
while (size) {
- int ret = write(output, buf, size);
+ int ret = write(rec->output, buf, size);
if (ret < 0)
die("failed to write");
@@ -79,30 +72,33 @@ static void write_output(void *buf, size_t size)
size -= ret;
buf += ret;
- bytes_written += ret;
+ rec->bytes_written += ret;
}
}
-static int process_synthesized_event(union perf_event *event,
+static int process_synthesized_event(struct perf_event_ops *ops,
+ union perf_event *event,
struct perf_sample *sample __used,
struct perf_session *self __used)
{
- write_output(event, event->header.size);
+ struct perf_record *rec = container_of(ops, struct perf_record, ops);
+ write_output(rec, event, event->header.size);
return 0;
}
-static void mmap_read(struct perf_mmap *md)
+static void perf_record__mmap_read(struct perf_record *rec,
+ struct perf_mmap *md)
{
unsigned int head = perf_mmap__read_head(md);
unsigned int old = md->prev;
- unsigned char *data = md->base + page_size;
+ unsigned char *data = md->base + rec->page_size;
unsigned long size;
void *buf;
if (old == head)
return;
- samples++;
+ rec->samples++;
size = head - old;
@@ -111,14 +107,14 @@ static void mmap_read(struct perf_mmap *md)
size = md->mask + 1 - (old & md->mask);
old += size;
- write_output(buf, size);
+ write_output(rec, buf, size);
}
buf = &data[old & md->mask];
size = head - old;
old += size;
- write_output(buf, size);
+ write_output(rec, buf, size);
md->prev = old;
perf_mmap__write_tail(md, old);
@@ -137,17 +133,18 @@ static void sig_handler(int sig)
signr = sig;
}
-static void sig_atexit(void)
+static void perf_record__sig_exit(int exit_status __used, void *arg)
{
+ struct perf_record *rec = arg;
int status;
- if (evsel_list->workload.pid > 0) {
+ if (rec->evlist->workload.pid > 0) {
if (!child_finished)
- kill(evsel_list->workload.pid, SIGTERM);
+ kill(rec->evlist->workload.pid, SIGTERM);
wait(&status);
if (WIFSIGNALED(status))
- psignal(WTERMSIG(status), progname);
+ psignal(WTERMSIG(status), rec->progname);
}
if (signr == -1 || signr == SIGUSR1)
@@ -176,13 +173,16 @@ static bool perf_evlist__equal(struct perf_evlist *evlist,
return true;
}
-static void open_counters(struct perf_evlist *evlist)
+static void perf_record__open(struct perf_record *rec)
{
struct perf_evsel *pos, *first;
+ struct perf_evlist *evlist = rec->evlist;
+ struct perf_session *session = rec->session;
+ struct perf_record_opts *opts = &rec->opts;
first = list_entry(evlist->entries.next, struct perf_evsel, node);
- perf_evlist__config_attrs(evlist, &record_opts);
+ perf_evlist__config_attrs(evlist, opts);
list_for_each_entry(pos, &evlist->entries, node) {
struct perf_event_attr *attr = &pos->attr;
@@ -201,27 +201,27 @@ static void open_counters(struct perf_evlist *evlist)
*/
bool time_needed = attr->sample_type & PERF_SAMPLE_TIME;
- if (record_opts.group && pos != first)
+ if (opts->group && pos != first)
group_fd = first->fd;
retry_sample_id:
- attr->sample_id_all = record_opts.sample_id_all_avail ? 1 : 0;
+ attr->sample_id_all = opts->sample_id_all_avail ? 1 : 0;
try_again:
if (perf_evsel__open(pos, evlist->cpus, evlist->threads,
- record_opts.group, group_fd) < 0) {
+ opts->group, group_fd) < 0) {
int err = errno;
if (err == EPERM || err == EACCES) {
ui__error_paranoid();
exit(EXIT_FAILURE);
- } else if (err == ENODEV && record_opts.cpu_list) {
+ } else if (err == ENODEV && opts->cpu_list) {
die("No such device - did you specify"
" an out-of-range profile CPU?\n");
- } else if (err == EINVAL && record_opts.sample_id_all_avail) {
+ } else if (err == EINVAL && opts->sample_id_all_avail) {
/*
* Old kernel, no attr->sample_id_type_all field
*/
- record_opts.sample_id_all_avail = false;
- if (!record_opts.sample_time && !record_opts.raw_samples && !time_needed)
+ opts->sample_id_all_avail = false;
+ if (!opts->sample_time && !opts->raw_samples && !time_needed)
attr->sample_type &= ~PERF_SAMPLE_TIME;
goto retry_sample_id;
@@ -271,10 +271,10 @@ try_again:
exit(-1);
}
- if (perf_evlist__mmap(evlist, record_opts.mmap_pages, false) < 0)
+ if (perf_evlist__mmap(evlist, opts->mmap_pages, false) < 0)
die("failed to mmap with %d (%s)\n", errno, strerror(errno));
- if (file_new)
+ if (rec->file_new)
session->evlist = evlist;
else {
if (!perf_evlist__equal(session->evlist, evlist)) {
@@ -286,29 +286,32 @@ try_again:
perf_session__update_sample_type(session);
}
-static int process_buildids(void)
+static int process_buildids(struct perf_record *rec)
{
- u64 size = lseek(output, 0, SEEK_CUR);
+ u64 size = lseek(rec->output, 0, SEEK_CUR);
if (size == 0)
return 0;
- session->fd = output;
- return __perf_session__process_events(session, post_processing_offset,
- size - post_processing_offset,
+ rec->session->fd = rec->output;
+ return __perf_session__process_events(rec->session, rec->post_processing_offset,
+ size - rec->post_processing_offset,
size, &build_id__mark_dso_hit_ops);
}
-static void atexit_header(void)
+static void perf_record__exit(int status __used, void *arg)
{
- if (!record_opts.pipe_output) {
- session->header.data_size += bytes_written;
-
- if (!no_buildid)
- process_buildids();
- perf_session__write_header(session, evsel_list, output, true);
- perf_session__delete(session);
- perf_evlist__delete(evsel_list);
+ struct perf_record *rec = arg;
+
+ if (!rec->opts.pipe_output) {
+ rec->session->header.data_size += rec->bytes_written;
+
+ if (!rec->no_buildid)
+ process_buildids(rec);
+ perf_session__write_header(rec->session, rec->evlist,
+ rec->output, true);
+ perf_session__delete(rec->session);
+ perf_evlist__delete(rec->evlist);
symbol__exit();
}
}
@@ -316,7 +319,9 @@ static void atexit_header(void)
static void perf_event__synthesize_guest_os(struct machine *machine, void *data)
{
int err;
- struct perf_session *psession = data;
+ struct perf_event_ops *ops = data;
+ struct perf_record *rec = container_of(ops, struct perf_record, ops);
+ struct perf_session *psession = rec->session;
if (machine__is_host(machine))
return;
@@ -329,7 +334,7 @@ static void perf_event__synthesize_guest_os(struct machine *machine, void *data)
*method is used to avoid symbol missing when the first addr is
*in module instead of in guest kernel.
*/
- err = perf_event__synthesize_modules(process_synthesized_event,
+ err = perf_event__synthesize_modules(ops, process_synthesized_event,
psession, machine);
if (err < 0)
pr_err("Couldn't record guest kernel [%d]'s reference"
@@ -339,10 +344,10 @@ static void perf_event__synthesize_guest_os(struct machine *machine, void *data)
* We use _stext for guest kernel because guest kernel's /proc/kallsyms
* have no _text sometimes.
*/
- err = perf_event__synthesize_kernel_mmap(process_synthesized_event,
+ err = perf_event__synthesize_kernel_mmap(ops, process_synthesized_event,
psession, machine, "_text");
if (err < 0)
- err = perf_event__synthesize_kernel_mmap(process_synthesized_event,
+ err = perf_event__synthesize_kernel_mmap(ops, process_synthesized_event,
psession, machine,
"_stext");
if (err < 0)
@@ -355,66 +360,71 @@ static struct perf_event_header finished_round_event = {
.type = PERF_RECORD_FINISHED_ROUND,
};
-static void mmap_read_all(void)
+static void perf_record__mmap_read_all(struct perf_record *rec)
{
int i;
- for (i = 0; i < evsel_list->nr_mmaps; i++) {
- if (evsel_list->mmap[i].base)
- mmap_read(&evsel_list->mmap[i]);
+ for (i = 0; i < rec->evlist->nr_mmaps; i++) {
+ if (rec->evlist->mmap[i].base)
+ perf_record__mmap_read(rec, &rec->evlist->mmap[i]);
}
- if (perf_header__has_feat(&session->header, HEADER_TRACE_INFO))
- write_output(&finished_round_event, sizeof(finished_round_event));
+ if (perf_header__has_feat(&rec->session->header, HEADER_TRACE_INFO))
+ write_output(rec, &finished_round_event, sizeof(finished_round_event));
}
-static int __cmd_record(int argc, const char **argv)
+static int __cmd_record(struct perf_record *rec, int argc, const char **argv)
{
struct stat st;
int flags;
- int err;
+ int err, output;
unsigned long waking = 0;
const bool forks = argc > 0;
struct machine *machine;
+ struct perf_event_ops *ops = &rec->ops;
+ struct perf_record_opts *opts = &rec->opts;
+ struct perf_evlist *evsel_list = rec->evlist;
+ const char *output_name = rec->output_name;
+ struct perf_session *session;
- progname = argv[0];
+ rec->progname = argv[0];
- page_size = sysconf(_SC_PAGE_SIZE);
+ rec->page_size = sysconf(_SC_PAGE_SIZE);
- atexit(sig_atexit);
+ on_exit(perf_record__sig_exit, rec);
signal(SIGCHLD, sig_handler);
signal(SIGINT, sig_handler);
signal(SIGUSR1, sig_handler);
if (!output_name) {
if (!fstat(STDOUT_FILENO, &st) && S_ISFIFO(st.st_mode))
- record_opts.pipe_output = true;
+ opts->pipe_output = true;
else
- output_name = "perf.data";
+ rec->output_name = output_name = "perf.data";
}
if (output_name) {
if (!strcmp(output_name, "-"))
- record_opts.pipe_output = true;
+ opts->pipe_output = true;
else if (!stat(output_name, &st) && st.st_size) {
- if (write_mode == WRITE_FORCE) {
+ if (rec->write_mode == WRITE_FORCE) {
char oldname[PATH_MAX];
snprintf(oldname, sizeof(oldname), "%s.old",
output_name);
unlink(oldname);
rename(output_name, oldname);
}
- } else if (write_mode == WRITE_APPEND) {
- write_mode = WRITE_FORCE;
+ } else if (rec->write_mode == WRITE_APPEND) {
+ rec->write_mode = WRITE_FORCE;
}
}
flags = O_CREAT|O_RDWR;
- if (write_mode == WRITE_APPEND)
- file_new = 0;
+ if (rec->write_mode == WRITE_APPEND)
+ rec->file_new = 0;
else
flags |= O_TRUNC;
- if (record_opts.pipe_output)
+ if (opts->pipe_output)
output = STDOUT_FILENO;
else
output = open(output_name, flags, S_IRUSR | S_IWUSR);
@@ -423,17 +433,21 @@ static int __cmd_record(int argc, const char **argv)
exit(-1);
}
+ rec->output = output;
+
session = perf_session__new(output_name, O_WRONLY,
- write_mode == WRITE_FORCE, false, NULL);
+ rec->write_mode == WRITE_FORCE, false, NULL);
if (session == NULL) {
pr_err("Not enough memory for reading perf file header\n");
return -1;
}
- if (!no_buildid)
+ rec->session = session;
+
+ if (!rec->no_buildid)
perf_header__set_feat(&session->header, HEADER_BUILD_ID);
- if (!file_new) {
+ if (!rec->file_new) {
err = perf_session__read_header(session, output);
if (err < 0)
goto out_delete_session;
@@ -456,42 +470,42 @@ static int __cmd_record(int argc, const char **argv)
perf_header__set_feat(&session->header, HEADER_CPUID);
if (forks) {
- err = perf_evlist__prepare_workload(evsel_list, &record_opts, argv);
+ err = perf_evlist__prepare_workload(evsel_list, opts, argv);
if (err < 0) {
pr_err("Couldn't run the workload!\n");
goto out_delete_session;
}
}
- open_counters(evsel_list);
+ perf_record__open(rec);
/*
- * perf_session__delete(session) will be called at atexit_header()
+ * perf_session__delete(session) will be called at perf_record__exit()
*/
- atexit(atexit_header);
+ on_exit(perf_record__exit, rec);
- if (record_opts.pipe_output) {
+ if (opts->pipe_output) {
err = perf_header__write_pipe(output);
if (err < 0)
return err;
- } else if (file_new) {
+ } else if (rec->file_new) {
err = perf_session__write_header(session, evsel_list,
output, false);
if (err < 0)
return err;
}
- post_processing_offset = lseek(output, 0, SEEK_CUR);
+ rec->post_processing_offset = lseek(output, 0, SEEK_CUR);
- if (record_opts.pipe_output) {
- err = perf_session__synthesize_attrs(session,
- process_synthesized_event);
+ if (opts->pipe_output) {
+ err = perf_event__synthesize_attrs(ops, session,
+ process_synthesized_event);
if (err < 0) {
pr_err("Couldn't synthesize attrs.\n");
return err;
}
- err = perf_event__synthesize_event_types(process_synthesized_event,
+ err = perf_event__synthesize_event_types(ops, process_synthesized_event,
session);
if (err < 0) {
pr_err("Couldn't synthesize event_types.\n");
@@ -507,14 +521,14 @@ static int __cmd_record(int argc, const char **argv)
* return this more properly and also
* propagate errors that now are calling die()
*/
- err = perf_event__synthesize_tracing_data(output, evsel_list,
+ err = perf_event__synthesize_tracing_data(ops, output, evsel_list,
process_synthesized_event,
session);
if (err <= 0) {
pr_err("Couldn't record tracing data.\n");
return err;
}
- advance_output(err);
+ advance_output(rec, err);
}
}
@@ -524,17 +538,17 @@ static int __cmd_record(int argc, const char **argv)
return -1;
}
- err = perf_event__synthesize_kernel_mmap(process_synthesized_event,
+ err = perf_event__synthesize_kernel_mmap(ops, process_synthesized_event,
session, machine, "_text");
if (err < 0)
- err = perf_event__synthesize_kernel_mmap(process_synthesized_event,
+ err = perf_event__synthesize_kernel_mmap(ops, process_synthesized_event,
session, machine, "_stext");
if (err < 0)
pr_err("Couldn't record kernel reference relocation symbol\n"
"Symbol resolution may be skewed if relocation was used (e.g. kexec).\n"
"Check /proc/kallsyms permission or run as root.\n");
- err = perf_event__synthesize_modules(process_synthesized_event,
+ err = perf_event__synthesize_modules(ops, process_synthesized_event,
session, machine);
if (err < 0)
pr_err("Couldn't record kernel module information.\n"
@@ -542,21 +556,21 @@ static int __cmd_record(int argc, const char **argv)
"Check /proc/modules permission or run as root.\n");
if (perf_guest)
- perf_session__process_machines(session,
+ perf_session__process_machines(session, ops,
perf_event__synthesize_guest_os);
- if (!record_opts.system_wide)
- perf_event__synthesize_thread_map(evsel_list->threads,
+ if (!opts->system_wide)
+ perf_event__synthesize_thread_map(ops, evsel_list->threads,
process_synthesized_event,
session);
else
- perf_event__synthesize_threads(process_synthesized_event,
+ perf_event__synthesize_threads(ops, process_synthesized_event,
session);
- if (realtime_prio) {
+ if (rec->realtime_prio) {
struct sched_param param;
- param.sched_priority = realtime_prio;
+ param.sched_priority = rec->realtime_prio;
if (sched_setscheduler(0, SCHED_FIFO, &param)) {
pr_err("Could not set realtime priority.\n");
exit(-1);
@@ -572,11 +586,11 @@ static int __cmd_record(int argc, const char **argv)
perf_evlist__start_workload(evsel_list);
for (;;) {
- int hits = samples;
+ int hits = rec->samples;
- mmap_read_all();
+ perf_record__mmap_read_all(rec);
- if (hits == samples) {
+ if (hits == rec->samples) {
if (done)
break;
err = poll(evsel_list->pollfd, evsel_list->nr_fds, -1);
@@ -597,9 +611,9 @@ static int __cmd_record(int argc, const char **ar