h->ip[offset]);
}
-static int hist_entry__add(struct addr_location *al, u64 count)
+static int perf_session__add_hist_entry(struct perf_session *self,
+ struct addr_location *al, u64 count)
{
bool hit;
- struct hist_entry *he = __hist_entry__add(al, NULL, count, &hit);
+ struct hist_entry *he = __perf_session__add_hist_entry(self, al, NULL,
+ count, &hit);
if (he == NULL)
return -ENOMEM;
hist_hit(he, al->addr);
return -1;
}
- if (hist_entry__add(&al, 1)) {
+ if (perf_session__add_hist_entry(session, &al, 1)) {
fprintf(stderr, "problem incrementing symbol count, "
"skipping event\n");
return -1;
free_source_line(he, len);
}
-static void find_annotations(void)
+static void perf_session__find_annotations(struct perf_session *self)
{
struct rb_node *nd;
- for (nd = rb_first(&hist); nd; nd = rb_next(nd)) {
+ for (nd = rb_first(&self->hists); nd; nd = rb_next(nd)) {
struct hist_entry *he = rb_entry(nd, struct hist_entry, rb_node);
struct sym_priv *priv;
if (verbose > 2)
dsos__fprintf(stdout);
- collapse__resort();
- output__resort(event__total[0]);
-
- find_annotations();
+ perf_session__collapse_resort(session);
+ perf_session__output_resort(session, event__total[0]);
+ perf_session__find_annotations(session);
out_delete:
perf_session__delete(session);
return 0;
}
-static int sample_type_check(u64 type)
+static int sample_type_check(u64 type, struct perf_session *session __used)
{
sample_type = type;
static struct strlist *dso_list, *comm_list, *sym_list;
static int force;
+static bool use_callchain;
static int show_nr_samples;
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) {
struct symbol **syms = NULL;
unsigned int i;
- if (callchain) {
+ if (session->use_callchain) {
syms = calloc(chain->nr, sizeof(*syms));
if (!syms) {
fprintf(stderr, "Can't allocate memory for symbols\n");
if (sort__has_parent && !*parent &&
call__match(al.sym))
*parent = al.sym;
- if (!callchain)
+ if (!session->use_callchain)
break;
syms[i] = al.sym;
}
* collect histogram counts
*/
-static int hist_entry__add(struct addr_location *al,
- struct perf_session *session,
- 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, session, chain, &parent);
+ if ((sort__has_parent || self->use_callchain) && chain)
+ syms = resolve_callchain(al->thread, self, chain, &parent);
- he = __hist_entry__add(al, parent, count, &hit);
+ 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(&hist); 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 &&
if (sym_list && al.sym && !strlist__has_entry(sym_list, al.sym->name))
return 0;
- if (hist_entry__add(&al, session, 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;
}
return 0;
}
-static int sample_type_check(u64 type)
+static int sample_type_check(u64 type, struct perf_session *session)
{
sample_type = type;
" 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");
if (session == NULL)
return -ENOMEM;
+ session->use_callchain = use_callchain;
+
if (show_threads)
perf_read_values_init(&show_threads_values);
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, event__stats.total);
+ perf_session__fprintf_hist_entries(session, event__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;
}
return 0;
}
-static int sample_type_check(u64 type)
+static int sample_type_check(u64 type, struct perf_session *session __used)
{
sample_type = type;
}
}
-static int sample_type_check(u64 type)
+static int sample_type_check(u64 type, struct perf_session *session __used)
{
sample_type = type;
return 0;
}
-static int sample_type_check(u64 type)
+static int sample_type_check(u64 type, struct perf_session *session __used)
{
sample_type = type;
err = -EINVAL;
if (ops->sample_type_check &&
- ops->sample_type_check(sample_type) < 0)
+ ops->sample_type_check(sample_type, self) < 0)
goto out_err;
if (!ops->full_paths) {
#include "hist.h"
-
-struct rb_root hist;
-int callchain;
+#include "session.h"
+#include "sort.h"
struct callchain_param callchain_param = {
.mode = CHAIN_GRAPH_REL,
* histogram, sorted on item, collects counts
*/
-struct hist_entry *__hist_entry__add(struct addr_location *al,
- struct symbol *sym_parent,
- u64 count, bool *hit)
+struct hist_entry *__perf_session__add_hist_entry(struct perf_session *self,
+ struct addr_location *al,
+ struct symbol *sym_parent,
+ u64 count, bool *hit)
{
- struct rb_node **p = &hist.rb_node;
+ struct rb_node **p = &self->hists.rb_node;
struct rb_node *parent = NULL;
struct hist_entry *he;
struct hist_entry entry = {
return NULL;
*he = entry;
rb_link_node(&he->rb_node, parent, p);
- rb_insert_color(&he->rb_node, &hist);
+ rb_insert_color(&he->rb_node, &self->hists);
*hit = false;
return he;
}
rb_insert_color(&he->rb_node, root);
}
-void collapse__resort(void)
+void perf_session__collapse_resort(struct perf_session *self)
{
struct rb_root tmp;
struct rb_node *next;
return;
tmp = RB_ROOT;
- next = rb_first(&hist);
+ next = rb_first(&self->hists);
while (next) {
n = rb_entry(next, struct hist_entry, rb_node);
next = rb_next(&n->rb_node);
- rb_erase(&n->rb_node, &hist);
+ rb_erase(&n->rb_node, &self->hists);
collapse__insert_entry(&tmp, n);
}
- hist = tmp;
+ self->hists = tmp;
}
/*
* reverse the map, sort on count.
*/
-static void output__insert_entry(struct rb_root *root, struct hist_entry *he,
- u64 min_callchain_hits)
+static void perf_session__insert_output_hist_entry(struct perf_session *self,
+ struct rb_root *root,
+ struct hist_entry *he,
+ u64 min_callchain_hits)
{
struct rb_node **p = &root->rb_node;
struct rb_node *parent = NULL;
struct hist_entry *iter;
- if (callchain)
+ if (self->use_callchain)
callchain_param.sort(&he->sorted_chain, &he->callchain,
min_callchain_hits, &callchain_param);
rb_insert_color(&he->rb_node, root);
}
-void output__resort(u64 total_samples)
+void perf_session__output_resort(struct perf_session *self, u64 total_samples)
{
struct rb_root tmp;
struct rb_node *next;
total_samples * (callchain_param.min_percent / 100);
tmp = RB_ROOT;
- next = rb_first(&hist);
+ next = rb_first(&self->hists);
while (next) {
n = rb_entry(next, struct hist_entry, rb_node);
next = rb_next(&n->rb_node);
- rb_erase(&n->rb_node, &hist);
- output__insert_entry(&tmp, n, min_callchain_hits);
+ rb_erase(&n->rb_node, &self->hists);
+ perf_session__insert_output_hist_entry(self, &tmp, n,
+ min_callchain_hits);
}
- hist = tmp;
+ self->hists = tmp;
}
#ifndef __PERF_HIST_H
#define __PERF_HIST_H
-#include "../builtin.h"
-#include "util.h"
-
-#include "color.h"
-#include <linux/list.h>
-#include "cache.h"
-#include <linux/rbtree.h>
-#include "symbol.h"
-#include "string.h"
+#include <linux/types.h>
#include "callchain.h"
-#include "strlist.h"
-#include "values.h"
-
-#include "../perf.h"
-#include "debug.h"
-#include "header.h"
-
-#include "parse-options.h"
-#include "parse-events.h"
-#include "thread.h"
-#include "sort.h"
-
-extern struct rb_root hist;
-extern int callchain;
extern struct callchain_param callchain_param;
-struct hist_entry *__hist_entry__add(struct addr_location *al,
- struct symbol *parent,
- u64 count, bool *hit);
+struct perf_session;
+struct hist_entry;
+struct addr_location;
+struct symbol;
+
+struct hist_entry *__perf_session__add_hist_entry(struct perf_session *self,
+ struct addr_location *al,
+ struct symbol *parent,
+ u64 count, bool *hit);
extern int64_t hist_entry__cmp(struct hist_entry *, struct hist_entry *);
extern int64_t hist_entry__collapse(struct hist_entry *, struct hist_entry *);
-extern void hist_entry__free(struct hist_entry *);
-extern void collapse__resort(void);
-extern void output__resort(u64);
+void hist_entry__free(struct hist_entry *);
+
+void perf_session__output_resort(struct perf_session *self, u64 total_samples);
+void perf_session__collapse_resort(struct perf_session *self);
#endif /* __PERF_HIST_H */
struct map_groups kmaps;
struct rb_root threads;
struct thread *last_match;
+ struct rb_root hists;
int fd;
int cwdlen;
char *cwd;
bool use_modules;
+ bool use_callchain;
char filename[0];
};
event_op process_read_event;
event_op process_throttle_event;
event_op process_unthrottle_event;
- int (*sample_type_check)(u64 sample_type);
+ int (*sample_type_check)(u64 sample_type,
+ struct perf_session *session);
unsigned long total_unknown;
bool full_paths;
};