static struct strlist *dso_list, *comm_list, *sym_list;
static int force;
+static bool use_callchain;
-static int full_paths;
static int show_nr_samples;
static int show_threads;
static char callchain_default_opt[] = "fractal,0.5";
-static u64 sample_type;
-
-struct symbol_conf symbol_conf;
+static struct symbol_conf symbol_conf;
static size_t
return ret;
}
-static size_t
-hist_entry__fprintf(FILE *fp, struct hist_entry *self, u64 total_samples)
+static size_t hist_entry__fprintf(FILE *fp, struct hist_entry *self,
+ struct perf_session *session,
+ u64 total_samples)
{
struct sort_entry *se;
size_t ret;
ret += fprintf(fp, "\n");
- if (callchain) {
+ if (session->use_callchain) {
int left_margin = 0;
if (sort__first_dimension == SORT_COMM) {
return 0;
}
-static int call__match(struct symbol *sym)
-{
- if (sym->name && !regexec(&parent_regex, sym->name, 0, NULL, 0))
- return 1;
-
- return 0;
-}
-
-static struct symbol **resolve_callchain(struct thread *thread,
- struct ip_callchain *chain,
- struct symbol **parent)
-{
- u8 cpumode = PERF_RECORD_MISC_USER;
- struct symbol **syms = NULL;
- unsigned int i;
-
- if (callchain) {
- syms = calloc(chain->nr, sizeof(*syms));
- if (!syms) {
- fprintf(stderr, "Can't allocate memory for symbols\n");
- exit(-1);
- }
- }
-
- for (i = 0; i < chain->nr; i++) {
- u64 ip = chain->ips[i];
- struct addr_location al;
-
- if (ip >= PERF_CONTEXT_MAX) {
- switch (ip) {
- case PERF_CONTEXT_HV:
- cpumode = PERF_RECORD_MISC_HYPERVISOR; break;
- case PERF_CONTEXT_KERNEL:
- cpumode = PERF_RECORD_MISC_KERNEL; break;
- case PERF_CONTEXT_USER:
- cpumode = PERF_RECORD_MISC_USER; break;
- default:
- break;
- }
- continue;
- }
-
- thread__find_addr_location(thread, cpumode, MAP__FUNCTION,
- ip, &al, NULL);
- if (al.sym != NULL) {
- if (sort__has_parent && !*parent &&
- call__match(al.sym))
- *parent = al.sym;
- if (!callchain)
- break;
- syms[i] = al.sym;
- }
- }
-
- return syms;
-}
-
/*
* collect histogram counts
*/
-static int hist_entry__add(struct addr_location *al,
- struct ip_callchain *chain, u64 count)
+static int perf_session__add_hist_entry(struct perf_session *self,
+ struct addr_location *al,
+ struct ip_callchain *chain, u64 count)
{
struct symbol **syms = NULL, *parent = NULL;
bool hit;
struct hist_entry *he;
- if ((sort__has_parent || callchain) && chain)
- syms = resolve_callchain(al->thread, chain, &parent);
-
- he = __hist_entry__add(al, parent, count, &hit);
+ if ((sort__has_parent || self->use_callchain) && chain)
+ syms = perf_session__resolve_callchain(self, al->thread,
+ chain, &parent);
+ he = __perf_session__add_hist_entry(self, al, parent, count, &hit);
if (he == NULL)
return -ENOMEM;
if (hit)
he->count += count;
- if (callchain) {
+ if (self->use_callchain) {
if (!hit)
callchain_init(&he->callchain);
append_chain(&he->callchain, chain, syms);
return 0;
}
-static size_t output__fprintf(FILE *fp, u64 total_samples)
+static size_t perf_session__fprintf_hist_entries(struct perf_session *self,
+ u64 total_samples, FILE *fp)
{
struct hist_entry *pos;
struct sort_entry *se;
fprintf(fp, "#\n");
print_entries:
- for (nd = rb_first(&output_hists); nd; nd = rb_next(nd)) {
+ for (nd = rb_first(&self->hists); nd; nd = rb_next(nd)) {
pos = rb_entry(nd, struct hist_entry, rb_node);
- ret += hist_entry__fprintf(fp, pos, total_samples);
+ ret += hist_entry__fprintf(fp, pos, self, total_samples);
}
if (sort_order == default_sort_order &&
return 0;
}
-static int process_sample_event(event_t *event, struct perf_session *session __used)
+static int process_sample_event(event_t *event, struct perf_session *session)
{
struct sample_data data;
int cpumode;
memset(&data, 0, sizeof(data));
data.period = 1;
- event__parse_sample(event, sample_type, &data);
+ event__parse_sample(event, session->sample_type, &data);
dump_printf("(IP, %d): %d/%d: %p period: %Ld\n",
event->header.misc,
(void *)(long)data.ip,
(long long)data.period);
- if (sample_type & PERF_SAMPLE_CALLCHAIN) {
+ if (session->sample_type & PERF_SAMPLE_CALLCHAIN) {
unsigned int i;
dump_printf("... chain: nr:%Lu\n", data.callchain->nr);
}
}
- thread = threads__findnew(data.pid);
+ thread = perf_session__findnew(session, data.pid);
if (thread == NULL) {
pr_debug("problem processing %d event, skipping it.\n",
event->header.type);
cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK;
- thread__find_addr_location(thread, cpumode,
+ thread__find_addr_location(thread, session, cpumode,
MAP__FUNCTION, data.ip, &al, NULL);
/*
* We have to do this here as we may have a dso with no symbol hit that
if (sym_list && al.sym && !strlist__has_entry(sym_list, al.sym->name))
return 0;
- if (hist_entry__add(&al, data.callchain, data.period)) {
+ if (perf_session__add_hist_entry(session, &al, data.callchain, data.period)) {
pr_debug("problem incrementing symbol count, skipping event\n");
return -1;
}
- event__stats.total += data.period;
-
+ session->events_stats.total += data.period;
return 0;
}
-static int process_comm_event(event_t *event, struct perf_session *session __used)
+static int process_comm_event(event_t *event, struct perf_session *session)
{
- struct thread *thread = threads__findnew(event->comm.pid);
+ struct thread *thread = perf_session__findnew(session, event->comm.pid);
dump_printf(": %s:%d\n", event->comm.comm, event->comm.pid);
return 0;
}
-static int sample_type_check(u64 type)
+static int sample_type_check(struct perf_session *session)
{
- sample_type = type;
-
- if (!(sample_type & PERF_SAMPLE_CALLCHAIN)) {
+ if (!(session->sample_type & PERF_SAMPLE_CALLCHAIN)) {
if (sort__has_parent) {
fprintf(stderr, "selected --sort parent, but no"
" callchain data. Did you call"
" perf record without -g?\n");
return -1;
}
- if (callchain) {
+ if (session->use_callchain) {
fprintf(stderr, "selected -g but no callchain data."
" Did you call perf record without"
" -g?\n");
return -1;
}
- } else if (callchain_param.mode != CHAIN_NONE && !callchain) {
- callchain = 1;
+ } else if (callchain_param.mode != CHAIN_NONE && !session->use_callchain) {
+ session->use_callchain = true;
if (register_callchain_param(&callchain_param) < 0) {
fprintf(stderr, "Can't register callchain"
" params\n");
int ret;
struct perf_session *session;
- session = perf_session__new(input_name, O_RDONLY, force);
+ session = perf_session__new(input_name, O_RDONLY, force, &symbol_conf);
if (session == NULL)
return -ENOMEM;
+ session->use_callchain = use_callchain;
+
if (show_threads)
perf_read_values_init(&show_threads_values);
- ret = perf_session__process_events(session, &event_ops, full_paths,
- &event__cwdlen, &event__cwd);
+ ret = perf_session__process_events(session, &event_ops);
if (ret)
goto out_delete;
}
if (verbose > 3)
- threads__fprintf(stdout);
+ perf_session__fprintf(session, stdout);
if (verbose > 2)
dsos__fprintf(stdout);
- collapse__resort();
- output__resort(event__stats.total);
- output__fprintf(stdout, event__stats.total);
+ perf_session__collapse_resort(session);
+ perf_session__output_resort(session, session->events_stats.total);
+ perf_session__fprintf_hist_entries(session, session->events_stats.total, stdout);
if (show_threads)
perf_read_values_destroy(&show_threads_values);
char *tok;
char *endptr;
- callchain = 1;
+ use_callchain = true;
if (!arg)
return 0;
else if (!strncmp(tok, "none", strlen(arg))) {
callchain_param.mode = CHAIN_NONE;
- callchain = 0;
+ use_callchain = true;
return 0;
}
"pretty printing style key: normal raw"),
OPT_STRING('s', "sort", &sort_order, "key[,key2...]",
"sort by key(s): pid, comm, dso, symbol, parent"),
- OPT_BOOLEAN('P', "full-paths", &full_paths,
+ OPT_BOOLEAN('P', "full-paths", &event_ops.full_paths,
"Don't shorten the pathnames taking into account the cwd"),
OPT_STRING('p', "parent", &parent_pattern, "regex",
"regex filter to identify parent, see: '--sort parent'"),
OPT_END()
};
-static void setup_sorting(void)
-{
- char *tmp, *tok, *str = strdup(sort_order);
-
- for (tok = strtok_r(str, ", ", &tmp);
- tok; tok = strtok_r(NULL, ", ", &tmp)) {
- if (sort_dimension__add(tok) < 0) {
- error("Unknown --sort key: `%s'", tok);
- usage_with_options(report_usage, options);
- }
- }
-
- free(str);
-}
-
static void setup_list(struct strlist **list, const char *list_str,
struct sort_entry *se, const char *list_name,
FILE *fp)
argc = parse_options(argc, argv, options, report_usage, 0);
- setup_sorting();
+ setup_sorting(report_usage, options);
if (parent_pattern != default_parent_pattern) {
sort_dimension__add("parent");