summaryrefslogtreecommitdiffstats
path: root/tools/perf/util
diff options
context:
space:
mode:
Diffstat (limited to 'tools/perf/util')
-rwxr-xr-xtools/perf/util/PERF-VERSION-GEN6
-rw-r--r--tools/perf/util/color.c53
-rw-r--r--tools/perf/util/color.h4
-rw-r--r--tools/perf/util/debug.h16
-rw-r--r--tools/perf/util/event.c9
-rw-r--r--tools/perf/util/hist.c66
-rw-r--r--tools/perf/util/hist.h9
-rw-r--r--tools/perf/util/map.c196
-rw-r--r--tools/perf/util/map.h34
-rw-r--r--tools/perf/util/newt.c298
-rw-r--r--tools/perf/util/session.c22
-rw-r--r--tools/perf/util/session.h19
-rw-r--r--tools/perf/util/sort.c93
-rw-r--r--tools/perf/util/sort.h6
-rw-r--r--tools/perf/util/string.h16
-rw-r--r--tools/perf/util/thread.c169
-rw-r--r--tools/perf/util/util.h12
17 files changed, 614 insertions, 414 deletions
diff --git a/tools/perf/util/PERF-VERSION-GEN b/tools/perf/util/PERF-VERSION-GEN
index 54552a00a11..49ece792191 100755
--- a/tools/perf/util/PERF-VERSION-GEN
+++ b/tools/perf/util/PERF-VERSION-GEN
@@ -1,6 +1,10 @@
#!/bin/sh
-GVF=PERF-VERSION-FILE
+if [ $# -eq 1 ] ; then
+ OUTPUT=$1
+fi
+
+GVF=${OUTPUT}PERF-VERSION-FILE
DEF_VER=v0.0.2.PERF
LF='
diff --git a/tools/perf/util/color.c b/tools/perf/util/color.c
index 9da01914e0a..e191eb9a667 100644
--- a/tools/perf/util/color.c
+++ b/tools/perf/util/color.c
@@ -166,6 +166,31 @@ int perf_color_default_config(const char *var, const char *value, void *cb)
return perf_default_config(var, value, cb);
}
+static int __color_vsnprintf(char *bf, size_t size, const char *color,
+ const char *fmt, va_list args, const char *trail)
+{
+ int r = 0;
+
+ /*
+ * Auto-detect:
+ */
+ if (perf_use_color_default < 0) {
+ if (isatty(1) || pager_in_use())
+ perf_use_color_default = 1;
+ else
+ perf_use_color_default = 0;
+ }
+
+ if (perf_use_color_default && *color)
+ r += snprintf(bf, size, "%s", color);
+ r += vsnprintf(bf + r, size - r, fmt, args);
+ if (perf_use_color_default && *color)
+ r += snprintf(bf + r, size - r, "%s", PERF_COLOR_RESET);
+ if (trail)
+ r += snprintf(bf + r, size - r, "%s", trail);
+ return r;
+}
+
static int __color_vfprintf(FILE *fp, const char *color, const char *fmt,
va_list args, const char *trail)
{
@@ -191,11 +216,28 @@ static int __color_vfprintf(FILE *fp, const char *color, const char *fmt,
return r;
}
+int color_vsnprintf(char *bf, size_t size, const char *color,
+ const char *fmt, va_list args)
+{
+ return __color_vsnprintf(bf, size, color, fmt, args, NULL);
+}
+
int color_vfprintf(FILE *fp, const char *color, const char *fmt, va_list args)
{
return __color_vfprintf(fp, color, fmt, args, NULL);
}
+int color_snprintf(char *bf, size_t size, const char *color,
+ const char *fmt, ...)
+{
+ va_list args;
+ int r;
+
+ va_start(args, fmt);
+ r = color_vsnprintf(bf, size, color, fmt, args);
+ va_end(args);
+ return r;
+}
int color_fprintf(FILE *fp, const char *color, const char *fmt, ...)
{
@@ -203,10 +245,7 @@ int color_fprintf(FILE *fp, const char *color, const char *fmt, ...)
int r;
va_start(args, fmt);
- if (use_browser)
- r = vfprintf(fp, fmt, args);
- else
- r = color_vfprintf(fp, color, fmt, args);
+ r = color_vfprintf(fp, color, fmt, args);
va_end(args);
return r;
}
@@ -277,3 +316,9 @@ int percent_color_fprintf(FILE *fp, const char *fmt, double percent)
return r;
}
+
+int percent_color_snprintf(char *bf, size_t size, const char *fmt, double percent)
+{
+ const char *color = get_percent_color(percent);
+ return color_snprintf(bf, size, color, fmt, percent);
+}
diff --git a/tools/perf/util/color.h b/tools/perf/util/color.h
index 24e8809210b..dea082b7960 100644
--- a/tools/perf/util/color.h
+++ b/tools/perf/util/color.h
@@ -32,10 +32,14 @@ int perf_color_default_config(const char *var, const char *value, void *cb);
int perf_config_colorbool(const char *var, const char *value, int stdout_is_tty);
void color_parse(const char *value, const char *var, char *dst);
void color_parse_mem(const char *value, int len, const char *var, char *dst);
+int color_vsnprintf(char *bf, size_t size, const char *color,
+ const char *fmt, va_list args);
int color_vfprintf(FILE *fp, const char *color, const char *fmt, va_list args);
int color_fprintf(FILE *fp, const char *color, const char *fmt, ...);
+int color_snprintf(char *bf, size_t size, const char *color, const char *fmt, ...);
int color_fprintf_ln(FILE *fp, const char *color, const char *fmt, ...);
int color_fwrite_lines(FILE *fp, const char *color, size_t count, const char *buf);
+int percent_color_snprintf(char *bf, size_t size, const char *fmt, double percent);
int percent_color_fprintf(FILE *fp, const char *fmt, double percent);
const char *get_percent_color(double percent);
diff --git a/tools/perf/util/debug.h b/tools/perf/util/debug.h
index 0172edf3f15..5cb0a1b1401 100644
--- a/tools/perf/util/debug.h
+++ b/tools/perf/util/debug.h
@@ -10,13 +10,29 @@ extern int dump_trace;
int dump_printf(const char *fmt, ...) __attribute__((format(printf, 1, 2)));
void trace_event(event_t *event);
+struct ui_progress;
+
#ifdef NO_NEWT_SUPPORT
static inline int browser__show_help(const char *format __used, va_list ap __used)
{
return 0;
}
+
+static inline struct ui_progress *ui_progress__new(const char *title __used,
+ u64 total __used)
+{
+ return (struct ui_progress *)1;
+}
+
+static inline void ui_progress__update(struct ui_progress *self __used,
+ u64 curr __used) {}
+
+static inline void ui_progress__delete(struct ui_progress *self __used) {}
#else
int browser__show_help(const char *format, va_list ap);
+struct ui_progress *ui_progress__new(const char *title, u64 total);
+void ui_progress__update(struct ui_progress *self, u64 curr);
+void ui_progress__delete(struct ui_progress *self);
#endif
#endif /* __PERF_DEBUG_H */
diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c
index 052eaeccc20..571fb25f7eb 100644
--- a/tools/perf/util/event.c
+++ b/tools/perf/util/event.c
@@ -130,6 +130,7 @@ static int event__synthesize_mmap_events(pid_t pid, pid_t tgid,
continue;
pbf += n + 3;
if (*pbf == 'x') { /* vm_exec */
+ u64 vm_pgoff;
char *execname = strchr(bf, '/');
/* Catch VDSO */
@@ -139,6 +140,14 @@ static int event__synthesize_mmap_events(pid_t pid, pid_t tgid,
if (execname == NULL)
continue;
+ pbf += 3;
+ n = hex2u64(pbf, &vm_pgoff);
+ /* pgoff is in bytes, not pages */
+ if (n >= 0)
+ ev.mmap.pgoff = vm_pgoff << getpagesize();
+ else
+ ev.mmap.pgoff = 0;
+
size = strlen(execname);
execname[size - 1] = '\0'; /* Remove \n */
memcpy(ev.mmap.filename, execname, size);
diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c
index 09e09e78cb6..18cf8b32160 100644
--- a/tools/perf/util/hist.c
+++ b/tools/perf/util/hist.c
@@ -50,7 +50,8 @@ struct hist_entry *__perf_session__add_hist_entry(struct rb_root *hists,
p = &(*p)->rb_right;
}
- he = malloc(sizeof(*he));
+ he = malloc(sizeof(*he) + (symbol_conf.use_callchain ?
+ sizeof(struct callchain_node) : 0));
if (!he)
return NULL;
*he = entry;
@@ -168,7 +169,7 @@ static void perf_session__insert_output_hist_entry(struct rb_root *root,
struct hist_entry *iter;
if (symbol_conf.use_callchain)
- callchain_param.sort(&he->sorted_chain, &he->callchain,
+ callchain_param.sort(&he->sorted_chain, he->callchain,
min_callchain_hits, &callchain_param);
while (*p != NULL) {
@@ -185,12 +186,13 @@ static void perf_session__insert_output_hist_entry(struct rb_root *root,
rb_insert_color(&he->rb_node, root);
}
-void perf_session__output_resort(struct rb_root *hists, u64 total_samples)
+u64 perf_session__output_resort(struct rb_root *hists, u64 total_samples)
{
struct rb_root tmp;
struct rb_node *next;
struct hist_entry *n;
u64 min_callchain_hits;
+ u64 nr_hists = 0;
min_callchain_hits =
total_samples * (callchain_param.min_percent / 100);
@@ -205,9 +207,11 @@ void perf_session__output_resort(struct rb_root *hists, u64 total_samples)
rb_erase(&n->rb_node, hists);
perf_session__insert_output_hist_entry(&tmp, n,
min_callchain_hits);
+ ++nr_hists;
}
*hists = tmp;
+ return nr_hists;
}
static size_t callchain__fprintf_left_margin(FILE *fp, int left_margin)
@@ -452,16 +456,17 @@ static size_t hist_entry_callchain__fprintf(FILE *fp, struct hist_entry *self,
return ret;
}
-size_t hist_entry__fprintf(struct hist_entry *self,
+int hist_entry__snprintf(struct hist_entry *self,
+ char *s, size_t size,
struct perf_session *pair_session,
bool show_displacement,
- long displacement, FILE *fp,
+ long displacement, bool color,
u64 session_total)
{
struct sort_entry *se;
u64 count, total;
const char *sep = symbol_conf.field_sep;
- size_t ret;
+ int ret;
if (symbol_conf.exclude_other && !self->parent)
return 0;
@@ -474,17 +479,22 @@ size_t hist_entry__fprintf(struct hist_entry *self,
total = session_total;
}
- if (total)
- ret = percent_color_fprintf(fp, sep ? "%.2f" : " %6.2f%%",
- (count * 100.0) / total);
- else
- ret = fprintf(fp, sep ? "%lld" : "%12lld ", count);
+ if (total) {
+ if (color)
+ ret = percent_color_snprintf(s, size,
+ sep ? "%.2f" : " %6.2f%%",
+ (count * 100.0) / total);
+ else
+ ret = snprintf(s, size, sep ? "%.2f" : " %6.2f%%",
+ (count * 100.0) / total);
+ } else
+ ret = snprintf(s, size, sep ? "%lld" : "%12lld ", count);
if (symbol_conf.show_nr_samples) {
if (sep)
- ret += fprintf(fp, "%c%lld", *sep, count);
+ ret += snprintf(s + ret, size - ret, "%c%lld", *sep, count);
else
- ret += fprintf(fp, "%11lld", count);
+ ret += snprintf(s + ret, size - ret, "%11lld", count);
}
if (pair_session) {
@@ -504,9 +514,9 @@ size_t hist_entry__fprintf(struct hist_entry *self,
snprintf(bf, sizeof(bf), " ");
if (sep)
- ret += fprintf(fp, "%c%s", *sep, bf);
+ ret += snprintf(s + ret, size - ret, "%c%s", *sep, bf);
else
- ret += fprintf(fp, "%11.11s", bf);
+ ret += snprintf(s + ret, size - ret, "%11.11s", bf);
if (show_displacement) {
if (displacement)
@@ -515,9 +525,9 @@ size_t hist_entry__fprintf(struct hist_entry *self,
snprintf(bf, sizeof(bf), " ");
if (sep)
- ret += fprintf(fp, "%c%s", *sep, bf);
+ ret += snprintf(s + ret, size - ret, "%c%s", *sep, bf);
else
- ret += fprintf(fp, "%6.6s", bf);
+ ret += snprintf(s + ret, size - ret, "%6.6s", bf);
}
}
@@ -525,11 +535,25 @@ size_t hist_entry__fprintf(struct hist_entry *self,
if (se->elide)
continue;
- ret += fprintf(fp, "%s", sep ?: " ");
- ret += se->print(fp, self, se->width ? *se->width : 0);
+ ret += snprintf(s + ret, size - ret, "%s", sep ?: " ");
+ ret += se->snprintf(self, s + ret, size - ret,
+ se->width ? *se->width : 0);
}
- return ret + fprintf(fp, "\n");
+ return ret;
+}
+
+int hist_entry__fprintf(struct hist_entry *self,
+ struct perf_session *pair_session,
+ bool show_displacement,
+ long displacement, FILE *fp,
+ u64 session_total)
+{
+ char bf[512];
+ hist_entry__snprintf(self, bf, sizeof(bf), pair_session,
+ show_displacement, displacement,
+ true, session_total);
+ return fprintf(fp, "%s\n", bf);
}
static size_t hist_entry__fprintf_callchain(struct hist_entry *self, FILE *fp,
@@ -658,7 +682,7 @@ print_entries:
if (h->ms.map == NULL && verbose > 1) {
__map_groups__fprintf_maps(&h->thread->mg,
- MAP__FUNCTION, fp);
+ MAP__FUNCTION, verbose, fp);
fprintf(fp, "%.10s end\n", graph_dotted_line);
}
}
diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h
index fe366ce5db4..ad17f0ad798 100644
--- a/tools/perf/util/hist.h
+++ b/tools/perf/util/hist.h
@@ -18,14 +18,19 @@ struct hist_entry *__perf_session__add_hist_entry(struct rb_root *hists,
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 *);
-size_t hist_entry__fprintf(struct hist_entry *self,
+int hist_entry__fprintf(struct hist_entry *self,
struct perf_session *pair_session,
bool show_displacement,
long displacement, FILE *fp,
u64 session_total);
+int hist_entry__snprintf(struct hist_entry *self,
+ char *bf, size_t size,
+ struct perf_session *pair_session,
+ bool show_displacement, long displacement,
+ bool color, u64 session_total);
void hist_entry__free(struct hist_entry *);
-void perf_session__output_resort(struct rb_root *hists, u64 total_samples);
+u64 perf_session__output_resort(struct rb_root *hists, u64 total_samples);
void perf_session__collapse_resort(struct rb_root *hists);
size_t perf_session__fprintf_hists(struct rb_root *hists,
struct perf_session *pair,
diff --git a/tools/perf/util/map.c b/tools/perf/util/map.c
index 9f2963f9ee9..37913b241bd 100644
--- a/tools/perf/util/map.c
+++ b/tools/perf/util/map.c
@@ -1,4 +1,5 @@
#include "symbol.h"
+#include <errno.h>
#include <limits.h>
#include <stdlib.h>
#include <string.h>
@@ -234,18 +235,211 @@ u64 map__objdump_2ip(struct map *map, u64 addr)
return ip;
}
+void map_groups__init(struct map_groups *self)
+{
+ int i;
+ for (i = 0; i < MAP__NR_TYPES; ++i) {
+ self->maps[i] = RB_ROOT;
+ INIT_LIST_HEAD(&self->removed_maps[i]);
+ }
+}
+
+void map_groups__flush(struct map_groups *self)
+{
+ int type;
+
+ for (type = 0; type < MAP__NR_TYPES; type++) {
+ struct rb_root *root = &self->maps[type];
+ struct rb_node *next = rb_first(root);
+
+ while (next) {
+ struct map *pos = rb_entry(next, struct map, rb_node);
+ next = rb_next(&pos->rb_node);
+ rb_erase(&pos->rb_node, root);
+ /*
+ * We may have references to this map, for
+ * instance in some hist_entry instances, so
+ * just move them to a separate list.
+ */
+ list_add_tail(&pos->node, &self->removed_maps[pos->type]);
+ }
+ }
+}
+
struct symbol *map_groups__find_symbol(struct map_groups *self,
enum map_type type, u64 addr,
+ struct map **mapp,
symbol_filter_t filter)
{
struct map *map = map_groups__find(self, type, addr);
- if (map != NULL)
+ if (map != NULL) {
+ if (mapp != NULL)
+ *mapp = map;
return map__find_symbol(map, map->map_ip(map, addr), filter);
+ }
return NULL;
}
+struct symbol *map_groups__find_symbol_by_name(struct map_groups *self,
+ enum map_type type,
+ const char *name,
+ struct map **mapp,
+ symbol_filter_t filter)
+{
+ struct rb_node *nd;
+
+ for (nd = rb_first(&self->maps[type]); nd; nd = rb_next(nd)) {
+ struct map *pos = rb_entry(nd, struct map, rb_node);
+ struct symbol *sym = map__find_symbol_by_name(pos, name, filter);
+
+ if (sym == NULL)
+ continue;
+ if (mapp != NULL)
+ *mapp = pos;
+ return sym;
+ }
+
+ return NULL;
+}
+
+size_t __map_groups__fprintf_maps(struct map_groups *self,
+ enum map_type type, int verbose, FILE *fp)
+{
+ size_t printed = fprintf(fp, "%s:\n", map_type__name[type]);
+ struct rb_node *nd;
+
+ for (nd = rb_first(&self->maps[type]); nd; nd = rb_next(nd)) {
+ struct map *pos = rb_entry(nd, struct map, rb_node);
+ printed += fprintf(fp, "Map:");
+ printed += map__fprintf(pos, fp);
+ if (verbose > 2) {
+ printed += dso__fprintf(pos->dso, type, fp);
+ printed += fprintf(fp, "--\n");
+ }
+ }
+
+ return printed;
+}
+
+size_t map_groups__fprintf_maps(struct map_groups *self, int verbose, FILE *fp)
+{
+ size_t printed = 0, i;
+ for (i = 0; i < MAP__NR_TYPES; ++i)
+ printed += __map_groups__fprintf_maps(self, i, verbose, fp);
+ return printed;
+}
+
+static size_t __map_groups__fprintf_removed_maps(struct map_groups *self,
+ enum map_type type,
+ int verbose, FILE *fp)
+{
+ struct map *pos;
+ size_t printed = 0;
+
+ list_for_each_entry(pos, &self->removed_maps[type], node) {
+ printed += fprintf(fp, "Map:");
+ printed += map__fprintf(pos, fp);
+ if (verbose > 1) {
+ printed += dso__fprintf(pos->dso, type, fp);
+ printed += fprintf(fp, "--\n");
+ }
+ }
+ return printed;
+}
+
+static size_t map_groups__fprintf_removed_maps(struct map_groups *self,
+ int verbose, FILE *fp)
+{
+ size_t printed = 0, i;
+ for (i = 0; i < MAP__NR_TYPES; ++i)
+ printed += __map_groups__fprintf_removed_maps(self, i, verbose, fp);
+ return printed;
+}
+
+size_t map_groups__fprintf(struct map_groups *self, int verbose, FILE *fp)
+{
+ size_t printed = map_groups__fprintf_maps(self, verbose, fp);
+ printed += fprintf(fp, "Removed maps:\n");
+ return printed + map_groups__fprintf_removed_maps(self, verbose, fp);
+}
+
+int map_groups__fixup_overlappings(struct map_groups *self, struct map *map,
+ int verbose, FILE *fp)
+{
+ struct rb_root *root = &self->maps[map->type];
+ struct rb_node *next = rb_first(root);
+
+ while (next) {
+ struct map *pos = rb_entry(next, struct map, rb_node);
+ next = rb_next(&pos->rb_node);
+
+ if (!map__overlap(pos, map))
+ continue;
+
+ if (verbose >= 2) {
+ fputs("overlapping maps:\n", fp);
+ map__fprintf(map, fp);
+ map__fprintf(pos, fp);
+ }
+
+ rb_erase(&pos->rb_node, root);
+ /*
+ * We may have references to this map, for instance in some
+ * hist_entry instances, so just move them to a separate
+ * list.
+ */
+ list_add_tail(&pos->node, &self->removed_maps[map->type]);
+ /*
+ * Now check if we need to create new maps for areas not
+ * overlapped by the new map:
+ */
+ if (map->start > pos->start) {
+ struct map *before = map__clone(pos);
+
+ if (before == NULL)
+ return -ENOMEM;
+
+ before->end = map->start - 1;
+ map_groups__insert(self, before);
+ if (verbose >= 2)
+ map__fprintf(before, fp);
+ }
+
+ if (map->end < pos->end) {
+ struct map *after = map__clone(pos);
+
+ if (after == NULL)
+ return -ENOMEM;
+
+ after->start = map->end + 1;
+ map_groups__insert(self, after);
+ if (verbose >= 2)
+ map__fprintf(after, fp);
+ }
+ }
+
+ return 0;
+}
+
+/*
+ * XXX This should not really _copy_ te maps, but refcount them.
+ */
+int map_groups__clone(struct map_groups *self,
+ struct map_groups *parent, enum map_type type)
+{
+ struct rb_node *nd;
+ for (nd = rb_first(&parent->maps[type]); nd; nd = rb_next(nd)) {
+ struct map *map = rb_entry(nd, struct map, rb_node);
+ struct map *new = map__clone(map);
+ if (new == NULL)
+ return -ENOMEM;
+ map_groups__insert(self, new);
+ }
+ return 0;
+}
+
static u64 map__reloc_map_ip(struct map *map, u64 ip)
{
return ip + (s64)map->pgoff;
diff --git a/tools/perf/util/map.h b/tools/perf/util/map.h
index 6a703fa7470..2031278cc06 100644
--- a/tools/perf/util/map.h
+++ b/tools/perf/util/map.h
@@ -97,11 +97,14 @@ struct map_groups {
};
size_t __map_groups__fprintf_maps(struct map_groups *self,
- enum map_type type, FILE *fp);
+ enum map_type type, int verbose, FILE *fp);
void maps__insert(struct rb_root *maps, struct map *map);
struct map *maps__find(struct rb_root *maps, u64 addr);
void map_groups__init(struct map_groups *self);
-size_t map_groups__fprintf_maps(struct map_groups *self, FILE *fp);
+int map_groups__clone(struct map_groups *self,
+ struct map_groups *parent, enum map_type type);
+size_t map_groups__fprintf(struct map_groups *self, int verbose, FILE *fp);
+size_t map_groups__fprintf_maps(struct map_groups *self, int verbose, FILE *fp);
static inline void map_groups__insert(struct map_groups *self, struct map *map)
{
@@ -116,15 +119,33 @@ static inline struct map *map_groups__find(struct map_groups *self,
struct symbol *map_groups__find_symbol(struct map_groups *self,
enum map_type type, u64 addr,
+ struct map **mapp,
symbol_filter_t filter);
-static inline struct symbol *map_groups__find_function(struct map_groups *self,
- u64 addr,
- symbol_filter_t filter)
+struct symbol *map_groups__find_symbol_by_name(struct map_groups *self,
+ enum map_type type,
+ const char *name,
+ struct map **mapp,
+ symbol_filter_t filter);
+
+static inline
+struct symbol *map_groups__find_function(struct map_groups *self, u64 addr,
+ struct map **mapp, symbol_filter_t filter)
{
- return map_groups__find_symbol(self, MAP__FUNCTION, addr, filter);
+ return map_groups__find_symbol(self, MAP__FUNCTION, addr, mapp, filter);
}
+static inline
+struct symbol *map_groups__find_function_by_name(struct map_groups *self,
+ const char *name, struct map **mapp,
+ symbol_filter_t filter)
+{
+ return map_groups__find_symbol_by_name(self, MAP__FUNCTION, name, mapp, filter);
+}
+
+int map_groups__fixup_overlappings(struct map_groups *self, struct map *map,
+ int verbose, FILE *fp);
+
struct map *map_groups__find_by_name(struct map_groups *self,
enum map_type type, const char *name);
int __map_groups__create_kernel_maps(struct map_groups *self,
@@ -134,5 +155,6 @@ int map_groups__create_kernel_maps(struct map_groups *self,
struct map *vmlinux_maps[MAP__NR_TYPES]);
struct map *map_groups__new_module(struct map_groups *self, u64 start,
const char *filename);
+void map_groups__flush(struct map_groups *self);
#endif /* __PERF_MAP_H */
diff --git a/tools/perf/util/newt.c b/tools/perf/util/newt.c
index e99bcc8d193..c93bc2a2d13 100644
--- a/tools/perf/util/newt.c
+++ b/tools/perf/util/newt.c
@@ -12,6 +12,72 @@
#include "sort.h"
#include "symbol.h"
+struct ui_progress {
+ newtComponent form, scale;
+};
+
+struct ui_progress *ui_progress__new(const char *title, u64 total)
+{
+ struct ui_progress *self = malloc(sizeof(*self));
+
+ if (self != NULL) {
+ int cols;
+ newtGetScreenSize(&cols, NULL);
+ cols -= 4;
+ newtCenteredWindow(cols, 1, title);
+ self->form = newtForm(NULL, NULL, 0);
+ if (self->form == NULL)
+ goto out_free_self;
+ self->scale = newtScale(0, 0, cols, total);
+ if (self->scale == NULL)
+ goto out_free_form;
+ newtFormAddComponents(self->form, self->scale, NULL);
+ newtRefresh();
+ }
+
+ return self;
+
+out_free_form:
+ newtFormDestroy(self->form);
+out_free_self:
+ free(self);
+ return NULL;
+}
+
+void ui_progress__update(struct ui_progress *self, u64 curr)
+{
+ newtScaleSet(self->scale, curr);
+ newtRefresh();
+}
+
+void ui_progress__delete(struct ui_progress *self)
+{
+ newtFormDestroy(self->form);
+ newtPopWindow();
+ free(self);
+}
+
+static char browser__last_msg[1024];
+
+int browser__show_help(const char *format, va_list ap)
+{
+ int ret;
+ static int backlog;
+
+ ret = vsnprintf(browser__last_msg + backlog,
+ sizeof(browser__last_msg) - backlog, format, ap);
+ backlog += ret;
+
+ if (browser__last_msg[backlog - 1] == '\n') {
+ newtPopHelpLine();
+ newtPushHelpLine(browser__last_msg);
+ newtRefresh();
+ backlog = 0;
+ }
+
+ return ret;
+}
+
static void newt_form__set_exit_keys(newtComponent self)
{
newtFormAddHotKey(self, NEWT_KEY_ESCAPE);
@@ -228,60 +294,17 @@ static void hist_entry__append_callchain_browser(struct hist_entry *self,
}
}
-/*
- * FIXME: get lib/string.c linked with perf somehow
- */
-static char *skip_spaces(const char *str)
-{
- while (isspace(*str))
- ++str;
- return (char *)str;
-}
-
-static char *strim(char *s)
-{
- size_t size;
- char *end;
-
- s = skip_spaces(s);
- size = strlen(s);
- if (!size)
- return s;
-
- end = s + size - 1;
- while (end >= s && isspace(*end))
- end--;
- *(end + 1) = '\0';
-
- return s;
-}
-
static size_t hist_entry__append_browser(struct hist_entry *self,
newtComponent tree, u64 total)
{
- char bf[1024], *s;
- FILE *fp;
+ char s[256];
+ size_t ret;
if (symbol_conf.exclude_other && !self->parent)
return 0;
- fp = fmemopen(bf, sizeof(bf), "w");
- if (fp == NULL)
- return 0;
-
- hist_entry__fprintf(self, NULL, false, 0, fp, total);
- fclose(fp);
-
- /*
- * FIXME: We shouldn't need to trim, as the printing routines shouldn't
- * add spaces it in the first place, the stdio output routines should
- * call a __snprintf method instead of the current __print (that
- * actually is a __fprintf) one, but get the raw string and _then_ add
- * the newline, as this is a detail of stdio printing, not needed in
- * other UIs, e.g. newt.
- */
- s = strim(bf);
-
+ ret = hist_entry__snprintf(self, s, sizeof(s), NULL,
+ false, 0, false, total);
if (symbol_conf.use_callchain) {
int indexes[2];
@@ -291,10 +314,11 @@ static size_t hist_entry__append_browser(struct hist_entry *self,
} else
newtListboxAppendEntry(tree, s, &self->ms);
- return strlen(s);
+ return ret;
}
-static void map_symbol__annotate_browser(const struct map_symbol *self)
+static void map_symbol__annotate_browser(const struct map_symbol *self,
+ const char *input_name)
{
FILE *fp;
int cols, rows;
@@ -308,8 +332,8 @@ static void map_symbol__annotate_browser(const struct map_symbol *self)
if (self->sym == NULL)
return;
- if (asprintf(&str, "perf annotate -d \"%s\" %s 2>&1 | expand",
- self->map->dso->name, self->sym->name) < 0)
+ if (asprintf(&str, "perf annotate -i \"%s\" -d \"%s\" %s 2>&1 | expand",
+ input_name, self->map->dso->name, self->sym->name) < 0)
return;
fp = popen(str, "r");
@@ -358,90 +382,121 @@ static const void *newt__symbol_tree_get_current(newtComponent self)
return newtListboxGetCurrent(self);
}
-static void perf_session__selection(newtComponent self, void *data)
+static void hist_browser__selection(newtComponent self, void *data)
{
const struct map_symbol **symbol_ptr = data;
*symbol_ptr = newt__symbol_tree_get_current(self);
}
-void perf_session__browse_hists(struct rb_root *hists, u64 session_total,
- const char *helpline)
-{
- struct sort_entry *se;
- struct rb_node *nd;
- char seq[] = ".";
- unsigned int width;
- char *col_width = symbol_conf.col_width_list_str;
- int rows, cols, idx;
- int max_len = 0;
- char str[1024];
- newtComponent form, tree;
- struct newtExitStruct es;
+struct hist_browser {
+ newtComponent form, tree;
const struct map_symbol *selection;
+};
- snprintf(str, sizeof(str), "Samples: %Ld", session_total);
- newtDrawRootText(0, 0, str);
- newtPushHelpLine(helpline);
-
- newtGetScreenSize(&cols, &rows);
+static struct hist_browser *hist_browser__new(void)
+{
+ struct hist_browser *self = malloc(sizeof(*self));
- if (symbol_conf.use_callchain)
- tree = newtCheckboxTreeMulti(0, 0, rows - 5, seq,
- NEWT_FLAG_SCROLL);
- else
- tree = newtListbox(0, 0, rows - 5, (NEWT_FLAG_SCROLL |
- NEWT_FLAG_RETURNEXIT));
+ if (self != NULL) {
+ char seq[] = ".";
+ int rows;
- newtComponentAddCallback(tree, perf_session__selection, &selection);
+ newtGetScreenSize(NULL, &rows);
- list_for_each_entry(se, &hist_entry__sort_list, list) {
- if (se->elide)
- continue;
- width = strlen(se->header);
- if (se->width) {
- if (symbol_conf.col_width_list_str) {
- if (col_width) {
- *se->width = atoi(col_width);
- col_width = strchr(col_width, ',');
- if (col_width)
- ++col_width;
- }
- }
- *se->width = max(*se->width, width);
- }
+ if (symbol_conf.use_callchain)
+ self->tree = newtCheckboxTreeMulti(0, 0, rows - 5, seq,
+ NEWT_FLAG_SCROLL);
+ else
+ self->tree = newtListbox(0, 0, rows - 5,
+ (NEWT_FLAG_SCROLL |
+ NEWT_FLAG_RETURNEXIT));
+ newtComponentAddCallback(self->tree, hist_browser__selection,
+ &self->selection);
}
+ return self;
+}
+
+static void hist_browser__delete(struct hist_browser *self)
+{
+ newtFormDestroy(self->form);
+ newtPopWindow();
+ free(self);
+}
+
+static int hist_browser__populate(struct hist_browser *self, struct rb_root *hists,
+ u64 nr_hists, u64 session_total)
+{
+ int max_len = 0, idx, cols, rows;
+ struct ui_progress *progress;
+ struct rb_node *nd;
+ u64 curr_hist = 0;
+
+ progress = ui_progress__new("Adding entries to the browser...", nr_hists);
+ if (progress == NULL)
+ return -1;
+
idx = 0;
for (nd = rb_first(hists); nd; nd = rb_next(nd)) {
struct hist_entry *h = rb_entry(nd, struct hist_entry, rb_node);
- int len = hist_entry__append_browser(h, tree, session_total);
+ int len = hist_entry__append_browser(h, self->tree, session_total);
if (len > max_len)
max_len = len;
if (symbol_conf.use_callchain)
- hist_entry__append_callchain_browser(h, tree, session_total, idx++);
+ hist_entry__append_callchain_browser(h, self->tree,
+ session_total, idx++);
+ ++curr_hist;
+ if (curr_hist % 5)
+ ui_progress__update(progress, curr_hist);
}
+ ui_progress__delete(progress);
+
+ newtGetScreenSize(&cols, &rows);
+
if (max_len > cols)
max_len = cols - 3;
if (!symbol_conf.use_callchain)
- newtListboxSetWidth(tree, max_len);
+ newtListboxSetWidth(self->tree, max_len);
newtCenteredWindow(max_len + (symbol_conf.use_callchain ? 5 : 0),
rows - 5, "Report");
- form = newt_form__new();
- newtFormAddHotKey(form, 'A');
- newtFormAddHotKey(form, 'a');
- newtFormAddHotKey(form, NEWT_KEY_RIGHT);
- newtFormAddComponents(form, tree, NULL);
- selection = newt__symbol_tree_get_current(tree);
+ self->form = newt_form__new();
+ newtFormAddHotKey(self->form, 'A');
+ newtFormAddHotKey(self->form, 'a');
+ newtFormAddHotKey(self->form, NEWT_KEY_RIGHT);
+ newtFormAddComponents(self->form, self->tree, NULL);
+ self->selection = newt__symbol_tree_get_current(self->tree);
+
+ return 0;
+}
+
+int perf_session__browse_hists(struct rb_root *hists, u64 nr_hists,
+ u64 session_total, const char *helpline,
+ const char *input_name)
+{
+ struct newtExitStruct es;
+ char str[1024];
+ int err = -1;
+ struct hist_browser *browser = hist_browser__new();
+
+ if (browser == NULL)
+ return -1;
+
+ snprintf(str, sizeof(str), "Samples: %Ld", session_total);
+ newtDrawRootText(0, 0, str);
+ newtPushHelpLine(helpline);
+
+ if (hist_browser__populate(browser, hists, nr_hists, session_total) < 0)
+ goto out;
while (1) {
char annotate[512];
const char *options[2];
int nr_options = 0, choice = 0;
- newtFormRun(form, &es);
+ newtFormRun(browser->form, &es);
if (es.reason == NEWT_EXIT_HOTKEY) {
if (toupper(es.u.key) == 'A')
goto do_annotate;
@@ -455,9 +510,9 @@ void perf_session__browse_hists(struct rb_root *hists, u64 session_total,
}
}
- if (selection->sym != NULL) {
+ if (browser->selection->sym != NULL) {
snprintf(annotate, sizeof(annotate),
- "Annotate %s", selection->sym->name);
+ "Annotate %s", browser->selection->sym->name);
options[nr_options++] = annotate;
}
@@ -466,41 +521,22 @@ void perf_session__browse_hists(struct rb_root *hists, u64 session_total,
if (choice == nr_options - 1)
break;
do_annotate:
- if (selection->sym != NULL && choice >= 0) {
- if (selection->map->dso->origin == DSO__ORIG_KERNEL) {
+ if (browser->selection->sym != NULL && choice >= 0) {
+ if (browser->selection->map->dso->origin == DSO__ORIG_KERNEL) {
newtPopHelpLine();
newtPushHelpLine("No vmlinux file found, can't "
"annotate with just a "
"kallsyms file");
continue;
}
- map_symbol__annotate_browser(selection);
+ map_symbol__annotate_browser(browser->selection,
+ input_name);
}
}
-
- newtFormDestroy(form);
- newtPopWindow();
-}
-
-static char browser__last_msg[1024];
-
-int browser__show_help(const char *format, va_list ap)
-{
- int ret;
- static int backlog;
-
- ret = vsnprintf(browser__last_msg + backlog,
- sizeof(browser__last_msg) - backlog, format, ap);
- backlog += ret;
-
- if (browser__last_msg[backlog - 1] == '\n') {
- newtPopHelpLine();
- newtPushHelpLine(browser__last_msg);
- newtRefresh();
- backlog = 0;
- }
-
- return ret;
+ err = 0;
+out:
+ hist_browser__delete(browser);
+ return err;
}
void setup_browser(void)
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
index 76b4ac689df..ddf288fca3e 100644
--- a/tools/perf/util/session.c
+++ b/tools/perf/util/session.c
@@ -52,11 +52,6 @@ out_close:
return -1;
}
-static inline int perf_session__create_kernel_maps(struct perf_session *self)
-{
- return map_groups__create_kernel_maps(&self->kmaps, self->vmlinux_maps);
-}
-
struct perf_session *perf_session__new(const char *filename, int mode, bool force)
{
size_t len = filename ? strlen(filename) + 1 : 0;
@@ -123,16 +118,11 @@ struct map_symbol *perf_session__resolve_callchain(struct perf_session *self,
struct symbol **parent)
{
u8 cpumode = PERF_RECORD_MISC_USER;
- struct map_symbol *syms = NULL;
unsigned int i;
+ struct map_symbol *syms = calloc(chain->nr, sizeof(*syms));
- if (symbol_conf.use_callchain) {
- syms = calloc(chain->nr, sizeof(*syms));
- if (!syms) {
- fprintf(stderr, "Can't allocate memory for symbols\n");
- exit(-1);
- }
- }
+ if (!syms)
+ return NULL;
for (i = 0; i < chain->nr; i++) {
u64 ip = chain->ips[i];
@@ -397,6 +387,10 @@ int __perf_session__process_events(struct perf_session *self,
event_t *event;
uint32_t size;
char *buf;
+ struct ui_progress *progress = ui_progress__new("Processing events...",
+ self->size);
+ if (progress == NULL)
+ return -1;
perf_event_ops__fill_defaults(ops);
@@ -425,6 +419,7 @@ remap:
more:
event = (event_t *)(buf + head);
+ ui_progress__update(progress, offset);
if (self->header.needs_swap)
perf_event_header__bswap(&event->header);
@@ -475,6 +470,7 @@ more:
done:
err = 0;
out_err:
+ ui_progress__delete(progress);
return err;
}
diff --git a/tools/perf/util/session.h b/tools/perf/util/session.h
index 631f8157fc1..27f4c2dc715 100644
--- a/tools/perf/util/session.h
+++ b/tools/perf/util/session.h
@@ -80,6 +80,11 @@ static inline int __perf_session__create_kernel_maps(struct perf_session *self,
self->vmlinux_maps, kernel);
}
+static inline int perf_session__create_kernel_maps(struct perf_session *self)
+{
+ return map_groups__create_kernel_maps(&self->kmaps, self->vmlinux_maps);
+}
+
static inline struct map *
perf_session__new_module_map(struct perf_session *self,
u64 start, const char *filename)
@@ -88,11 +93,17 @@ static inline struct map *
}
#ifdef NO_NEWT_SUPPORT
-static inline void perf_session__browse_hists(struct rb_root *hists __used,
+static inline int perf_session__browse_hists(struct rb_root *hists __used,
+ u64 nr_hists __used,
u64 session_total __used,
- const char *helpline __used) {}
+ const char *helpline __used,
+ const char *input_name __used)
+{
+ return 0;
+}
#else
-void perf_session__browse_hists(struct rb_root *hists, u64 session_total,
- const char *helpline);
+int perf_session__browse_hists(struct rb_root *hists, u64 nr_hists,
+ u64 session_total, const char *helpline,
+ const char *input_name);
#endif
#endif /* __PERF_SESSION_H */
diff --git a/tools/perf/util/sort.c b/tools/perf/util/sort.c
index 9b80c13cae4..9d24d4b2c8f 100644
--- a/tools/perf/util/sort.c
+++ b/tools/perf/util/sort.c
@@ -18,10 +18,21 @@ char * field_sep;
LIST_HEAD(hist_entry__sort_list);
+static int hist_entry__thread_snprintf(struct hist_entry *self, char *bf,
+ size_t size, unsigned int width);
+static int hist_entry__comm_snprintf(struct hist_entry *self, char *bf,
+ size_t size, unsigned int width);
+static int hist_entry__dso_snprintf(struct hist_entry *self, char *bf,
+ size_t size, unsigned int width);
+static int hist_entry__sym_snprintf(struct hist_entry *self, char *bf,
+ size_t size, unsigned int width);
+static int hist_entry__parent_snprintf(struct hist_entry *self, char *bf,
+ size_t size, unsigned int width);
+
struct sort_entry sort_thread = {
.header = "Command: Pid",
.cmp = sort__thread_cmp,
- .print = sort__thread_print,
+ .snprintf = hist_entry__thread_snprintf,
.width = &threads__col_width,
};
@@ -29,27 +40,27 @@ struct sort_entry sort_comm = {
.header = "Command",
.cmp = sort__comm_cmp,
.collapse = sort__comm_collapse,
- .print = sort__comm_print,
+ .snprintf = hist_entry__comm_snprintf,
.width = &comms__col_width,
};
struct sort_entry sort_dso = {
.header = "Shared Object",
.cmp = sort__dso_cmp,
- .print = sort__dso_print,
+ .snprintf = hist_entry__dso_snprintf,
.width = &dsos__col_width,
};
struct sort_entry sort_sym = {
.header = "Symbol",
.cmp = sort__sym_cmp,
- .print = sort__sym_print,
+ .snprintf = hist_entry__sym_snprintf,
};
struct sort_entry sort_parent = {
.header = "Parent symbol",
.cmp = sort__parent_cmp,
- .print = sort__parent_print,
+ .snprintf = hist_entry__parent_snprintf,
.width = &parent_symbol__col_width,
};
@@ -85,45 +96,38 @@ sort__thread_cmp(struct hist_entry *left, struct hist_entry *right)
return right->thread->pid - left->thread->pid;
}
-int repsep_fprintf(FILE *fp, const char *fmt, ...)
+static int repsep_snprintf(char *bf, size_t size, const char *fmt, ...)
{
int n;
va_list ap;
va_start(ap, fmt);
- if (!field_sep)
- n = vfprintf(fp, fmt, ap);
- else {
- char *bf = NULL;
- n = vasprintf(&bf, fmt, ap);
- if (n > 0) {
- char *sep = bf;
-
- while (1) {
- sep = strchr(sep, *field_sep);
- if (sep == NULL)
- break;
- *sep = '.';
- }
+ n = vsnprintf(bf, size, fmt, ap);
+ if (field_sep && n > 0) {
+ char *sep = bf;
+
+ while (1) {
+ sep = strchr(sep, *field_sep);
+ if (sep == NULL)
+ break;
+ *sep = '.';
}
- fputs(bf, fp);
- free(bf);
}
va_end(ap);
return n;
}
-size_t
-sort__thread_print(FILE *fp, struct hist_entry *self, unsigned int width)
+static int hist_entry__thread_snprintf(struct hist_entry *self, char *bf,
+ size_t size, unsigned int width)
{
- return repsep_fprintf(fp, "%*s:%5d", width - 6,
+ return repsep_snprintf(bf, size, "%*s:%5d", width,
self->thread->comm ?: "", self->thread->pid);
}
-size_t
-sort__comm_print(FILE *fp, struct hist_entry *self, unsigned int width)
+static int hist_entry__comm_snprintf(struct hist_entry *self, char *bf,
+ size_t size, unsigned int width)
{
- return repsep_fprintf(fp, "%*s", width, self->thread->comm);
+ return repsep_snprintf(bf, size, "%*s", width, self->thread->comm);
}
/* --sort dso */
@@ -149,16 +153,16 @@ sort__dso_cmp(struct hist_entry *left, struct hist_entry *right)
return strcmp(dso_name_l, dso_name_r);
}
-size_t
-sort__dso_print(FILE *fp, struct hist_entry *self, unsigned int width)
+static int hist_entry__dso_snprintf(struct hist_entry *self, char *bf,
+ size_t size, unsigned int width)
{
if (self->ms.map && self->ms.map->dso) {
const char *dso_name = !verbose ? self->ms.map->dso->short_name :
self->ms.map->dso->long_name;
- return repsep_fprintf(fp, "%-*s", width, dso_name);
+ return repsep_snprintf(bf, size, "%-*s", width, dso_name);
}
- return repsep_fprintf(fp, "%*llx", width, (u64)self->ip);
+ return repsep_snprintf(bf, size, "%*Lx", width, self->ip);
}
/* --sort symbol */
@@ -177,22 +181,22 @@ sort__sym_cmp(struct hist_entry *left, struct hist_entry *right)
return (int64_t)(ip_r - ip_l);
}
-
-size_t
-sort__sym_print(FILE *fp, struct hist_entry *self, unsigned int width __used)
+static int hist_entry__sym_snprintf(struct hist_entry *self, char *bf,
+ size_t size, unsigned int width __used)
{
size_t ret = 0;
if (verbose) {
char o = self->ms.map ? dso__symtab_origin(self->ms.map->dso) : '!';
- ret += repsep_fprintf(fp, "%#018llx %c ", (u64)self->ip, o);
+ ret += repsep_snprintf(bf, size, "%#018llx %c ", self->ip, o);
}
- ret += repsep_fprintf(fp, "[%c] ", self->level);
+ ret += repsep_snprintf(bf + ret, size - ret, "[%c] ", self->level);
if (self->ms.sym)
- ret += repsep_fprintf(fp, "%s", self->ms.sym->name);
+ ret += repsep_snprintf(bf + ret, size - ret, "%s",
+ self->ms.sym->name);
else
- ret += repsep_fprintf(fp, "%#016llx", (u64)self->ip);
+ ret += repsep_snprintf(bf + ret, size - ret, "%#016llx", self->ip);
return ret;
}
@@ -231,10 +235,10 @@ sort__parent_cmp(struct hist_entry *left, struct hist_entry *right)
return strcmp(sym_l->name, sym_r->name);
}
-size_t
-sort__parent_print(FILE *fp, struct hist_entry *self, unsigned int width)
+static int hist_entry__parent_snprintf(struct hist_entry *self, char *bf,
+ size_t size, unsigned int width)
{
- return repsep_fprintf(fp, "%-*s", width,
+ return repsep_snprintf(bf, size, "%-*s", width,
self->parent ? self->parent->name : "[other]");
}
@@ -260,9 +264,8 @@ int sort_dimension__add(const char *tok)
char err[BUFSIZ];
regerror(ret, &parent_regex, err, sizeof(err));
- fprintf(stderr, "Invalid regex: %s\n%s",
- parent_pattern, err);
- exit(-1);
+ pr_err("Invalid regex: %s\n%s", parent_pattern, err);
+ return -EINVAL;
}
sort__has_parent = 1;
}
diff --git a/tools/perf/util/sort.h b/tools/perf/util/sort.h
index 598568696f9..5bf2b744e7b 100644
--- a/tools/perf/util/sort.h
+++ b/tools/perf/util/sort.h
@@ -49,12 +49,12 @@ struct hist_entry {
u64 ip;
char level;
struct symbol *parent;
- struct callchain_node callchain;
union {
unsigned long position;
struct hist_entry *pair;
struct rb_root sorted_chain;
};
+ struct callchain_node callchain[0];
};
enum sort_type {
@@ -76,7 +76,8 @@ struct sort_entry {
int64_t (*cmp)(struct hist_entry *, struct hist_entry *);
int64_t (*collapse)(struct hist_entry *, struct hist_entry *);
- size_t (*print)(FILE *fp, struct hist_entry *, unsigned int width);
+ int (*snprintf)(struct hist_entry *self, char *bf, size_t size,
+ unsigned int width);
unsigned int *width;
bool elide;
};
@@ -86,7 +87,6 @@ extern struct list_head hist_entry__sort_list;
void setup_sorting(const char * const usagestr[], const struct option *opts);
-extern int repsep_fprintf(FILE *fp, const char *fmt, ...);
extern size_t sort__thread_print(FILE *, struct hist_entry *, unsigned int);
extern size_t sort__comm_print(FILE *, struct hist_entry *, unsigned int);
extern size_t sort__dso_print(FILE *, struct hist_entry *, unsigned int);
diff --git a/tools/perf/util/string.h b/tools/perf/util/string.h
deleted file mode 100644
index 70058241666..00000000000
--- a/tools/perf/util/string.h
+++ /dev/null
@@ -1,16 +0,0 @@
-#ifndef __PERF_STRING_H_
-#define __PERF_STRING_H_
-
-#include <stdbool.h>
-#include "types.h"
-
-s64 perf_atoll(const char *str);
-char **argv_split(const char *str, int *argcp);
-void argv_free(char **argv);
-bool strglobmatch(const char *str, const char *pat);
-bool strlazymatch(const char *str, const char *pat);
-
-#define _STR(x) #x
-#define STR(x) _STR(x)
-
-#endif /* __PERF_STRING_H */
diff --git a/tools/perf/util/thread.c b/tools/perf/util/thread.c
index 9bbe27d7530..1f7ecd47f49 100644
--- a/tools/perf/util/thread.c
+++ b/tools/perf/util/thread.c
@@ -38,15 +38,6 @@ failure:
return ret;
}
-void map_groups__init(struct map_groups *self)
-{
- int i;
- for (i = 0; i < MAP__NR_TYPES; ++i) {
- self->maps[i] = RB_ROOT;
- INIT_LIST_HEAD(&self->removed_maps[i]);
- }
-}
-
static struct thread *thread__new(pid_t pid)
{
struct thread *self = zalloc(sizeof(*self));
@@ -62,28 +53,6 @@ static struct thread *thread__new(pid_t pid)
return self;
}
-static void map_groups__flush(struct map_groups *self)
-{
- int type;
-
- for (type = 0; type < MAP__NR_TYPES; type++) {
- struct rb_root *root = &self->maps[type];
- struct rb_node *next = rb_first(root);
-
- while (next) {
- struct map *pos = rb_entry(next, struct map, rb_node);
- next = rb_next(&pos->rb_node);
- rb_erase(&pos->rb_node, root);
- /*
- * We may have references to this map, for
- * instance in some hist_entry instances, so
- * just move them to a separate list.
- */
- list_add_tail(&pos->node, &self->removed_maps[pos->type]);
- }
- }
-}
-
int thread__set_comm(struct thread *self, const char *comm)
{
int err;
@@ -110,69 +79,10 @@ int thread__comm_len(struct thread *self)
return self->comm_len;
}
-size_t __map_groups__fprintf_maps(struct map_groups *self,
- enum map_type type, FILE *fp)
-{
- size_t printed = fprintf(fp, "%s:\n", map_type__name[type]);
- struct rb_node *nd;
-
- for (nd = rb_first(&self->maps[type]); nd; nd = rb_next(nd)) {
- struct map *pos = rb_entry(nd, struct map, rb_node);
- printed += fprintf(fp, "Map:");
- printed += map__fprintf(pos, fp);
- if (verbose > 2) {
- printed += dso__fprintf(pos->dso, type, fp);
- printed += fprintf(fp, "--\n");
- }
- }
-
- return printed;
-}
-
-size_t map_groups__fprintf_maps(struct map_groups *self, FILE *fp)
-{
- size_t printed = 0, i;
- for (i = 0; i < MAP__NR_TYPES; ++i)
- printed += __map_groups__fprintf_maps(self, i, fp);
- return printed;
-}
-
-static size_t __map_groups__fprintf_removed_maps(struct map_groups *self,
- enum map_type type, FILE *fp)
-{
- struct map *pos;
- size_t printed = 0;
-
- list_for_each_entry(pos, &self->removed_maps[type], node) {
- printed += fprintf(fp, "Map:");
- printed += map__fprintf(pos, fp);
- if (verbose > 1) {
- printed += dso__fprintf(pos->dso, type, fp);
- printed += fprintf(fp, "--\n");
- }
- }
- return printed;
-}
-
-static size_t map_groups__fprintf_removed_maps(struct map_groups *self, FILE *fp)
-{
- size_t printed = 0, i;
- for (i = 0; i < MAP__NR_TYPES; ++i)
- printed += __map_groups__fprintf_removed_maps(self, i, fp);
- return printed;
-}
-
-static size_t map_groups__fprintf(struct map_groups *self, FILE *fp)
-{
- size_t printed = map_groups__fprintf_maps(self, fp);
- printed += fprintf(fp, "Removed maps:\n");
- return printed + map_groups__fprintf_removed_maps(self, fp);
-}
-
static size_t thread__fprintf(struct thread *self, FILE *fp)
{
return fprintf(fp, "Thread %d %s\n", self->pid, self->comm) +
- map_groups__fprintf(&self->mg, fp);
+ map_groups__fprintf(&self->mg, verbose, fp);
}
struct thread *perf_session__findnew(struct perf_session *self, pid_t pid)
@@ -214,87 +124,12 @@ struct thread *perf_session__findnew(struct perf_session *self, pid_t pid)
return th;
}
-static int map_groups__fixup_overlappings(struct map_groups *self,
- struct map *map)
-{
- struct rb_root *root = &self->maps[map->type];
- struct rb_node *next = rb_first(root);
-
- while (next) {
- struct map *pos = rb_entry(next, struct map, rb_node);
- next = rb_next(&pos->rb_node);
-
- if (!map__overlap(pos, map))
- continue;
-
- if (verbose >= 2) {
- fputs("overlapping maps:\n", stderr);
- map__fprintf(map, stderr);
- map__fprintf(pos, stderr);
- }
-
- rb_erase(&pos->rb_node, root);
- /*
- * We may have references to this map, for instance in some
- * hist_entry instances, so just move them to a separate
- * list.
- */
- list_add_tail(&pos->node, &self->removed_maps[map->type]);
- /*
- * Now check if we need to create new maps for areas not
- * overlapped by the new map:
- */
- if (map->start > pos->start) {
- struct map *before = map__clone(pos);
-
- if (before == NULL)
- return -ENOMEM;
-
- before->end = map->start - 1;
- map_groups__insert(self, before);
- if (verbose >= 2)
- map__fprintf(before, stderr);
- }
-
- if (map->end < pos->end) {
- struct map *after = map__clone(pos);
-
- if (after == NULL)
- return -ENOMEM;
-
- after->start = map->end + 1;
- map_groups__insert(self, after);
- if (verbose >= 2)
- map__fprintf(after, stderr);
- }
- }
-
- return 0;
-}
-
void thread__insert_map(struct thread *self, struct map *map)
{
- map_groups__fixup_overlappings(&self->mg, map);
+ map_groups__fixup_overlappings(&self->mg, map, verbose, stderr);
map_groups__insert(&self->mg, map);
}
-/*
- * XXX This should not really _copy_ te maps, but refcount them.
- */
-static int map_groups__clone(struct map_groups *self,
- struct map_groups *parent, enum map_type type)
-{
- struct rb_node *nd;
- for (nd = rb_first(&parent->maps[type]); nd; nd = rb_next(nd)) {
- struct map *map = rb_entry(nd, struct map, rb_node);
- struct map *new = map__clone(map);
- if (new == NULL)
- return -ENOMEM;
- map_groups__insert(self, new);
- }
- return 0;
-}
-
int thread__fork(struct thread *self, struct thread *parent)
{
int i;
diff --git a/tools/perf/util/util.h b/tools/perf/util/util.h
index 52701087ce0..fbf45d1b26f 100644
--- a/tools/perf/util/util.h
+++ b/tools/perf/util/util.h
@@ -42,12 +42,14 @@
#define _ALL_SOURCE 1
#define _GNU_SOURCE 1
#define _BSD_SOURCE 1
+#define HAS_BOOL
#include <unistd.h>
#include <stdio.h>
#include <sys/stat.h>
#include <sys/statfs.h>
#include <fcntl.h>
+#include <stdbool.h>
#include <stddef.h>
#include <stdlib.h>
#include <stdarg.h>
@@ -78,6 +80,7 @@
#include <pwd.h>
#include <inttypes.h>
#include "../../../include/linux/magic.h"
+#include "types.h"
#ifndef NO_ICONV
@@ -415,4 +418,13 @@ void git_qsort(void *base, size_t nmemb, size_t size,
int mkdir_p(char *path, mode_t mode);
int copyfile(const char *from, const char *to);
+s64 perf_atoll(const char *str);
+char **argv_split(const char *str, int *argcp);
+void argv_free(char **argv);
+bool strglobmatch(const char *str, const char *pat);
+bool strlazymatch(const char *str, const char *pat);
+
+#define _STR(x) #x
+#define STR(x) _STR(x)
+
#endif