提交 bac2e4a9 编写于 作者: I Ingo Molnar

Merge tag 'perf-core-for-mingo' of...

Merge tag 'perf-core-for-mingo' of git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux into perf/core

Pull perf/core improvement and fixes from Arnaldo Carvalho de Melo:

User visible changes:

  - Add new compaction-times python script. (Tony Jones)

  - Make the --[no-]-demangle/--[no-]-demangle-kernel command line
    options available in 'perf script' too. (Mark Drayton)

  - Allow for negative numbers in libtraceevent's print format,
    fixing up misformatting in some tracepoints. (Steven Rostedt)

Infrastructure changes:

  - perf_env/perf_evlist changes to allow accessing the data
    structure with the environment where some perf data was
    collected in functions not necessarily related to perf.data
    file processing. (Kan Liang)

  - Cleanups for the tracepoint definition location paths routines. (Jiri Olsa)

  - Introduce sysfs/filename__sprintf_build_id, removing code
    duplication. (Masami Hiramatsu)
Signed-off-by: NArnaldo Carvalho de Melo <acme@redhat.com>
Signed-off-by: NIngo Molnar <mingo@kernel.org>
...@@ -4828,6 +4828,7 @@ static void pretty_print(struct trace_seq *s, void *data, int size, struct event ...@@ -4828,6 +4828,7 @@ static void pretty_print(struct trace_seq *s, void *data, int size, struct event
case 'z': case 'z':
case 'Z': case 'Z':
case '0' ... '9': case '0' ... '9':
case '-':
goto cont_process; goto cont_process;
case 'p': case 'p':
if (pevent->long_size == 4) if (pevent->long_size == 4)
......
...@@ -226,6 +226,13 @@ OPTIONS ...@@ -226,6 +226,13 @@ OPTIONS
Display context switch events i.e. events of type PERF_RECORD_SWITCH or Display context switch events i.e. events of type PERF_RECORD_SWITCH or
PERF_RECORD_SWITCH_CPU_WIDE. PERF_RECORD_SWITCH_CPU_WIDE.
--demangle::
Demangle symbol names to human readable form. It's enabled by default,
disable with --no-demangle.
--demangle-kernel::
Demangle kernel symbol names to human readable form (for C++ kernels).
--header --header
Show perf.data header. Show perf.data header.
......
...@@ -128,7 +128,7 @@ static const char *normalize_arch(char *arch) ...@@ -128,7 +128,7 @@ static const char *normalize_arch(char *arch)
return arch; return arch;
} }
static int perf_session_env__lookup_binutils_path(struct perf_session_env *env, static int perf_session_env__lookup_binutils_path(struct perf_env *env,
const char *name, const char *name,
const char **path) const char **path)
{ {
...@@ -206,7 +206,7 @@ static int perf_session_env__lookup_binutils_path(struct perf_session_env *env, ...@@ -206,7 +206,7 @@ static int perf_session_env__lookup_binutils_path(struct perf_session_env *env,
return -1; return -1;
} }
int perf_session_env__lookup_objdump(struct perf_session_env *env) int perf_session_env__lookup_objdump(struct perf_env *env)
{ {
/* /*
* For live mode, env->arch will be NULL and we can use * For live mode, env->arch will be NULL and we can use
......
...@@ -5,6 +5,6 @@ ...@@ -5,6 +5,6 @@
extern const char *objdump_path; extern const char *objdump_path;
int perf_session_env__lookup_objdump(struct perf_session_env *env); int perf_session_env__lookup_objdump(struct perf_env *env);
#endif /* ARCH_PERF_COMMON_H */ #endif /* ARCH_PERF_COMMON_H */
...@@ -25,8 +25,6 @@ ...@@ -25,8 +25,6 @@
static int build_id_cache__kcore_buildid(const char *proc_dir, char *sbuildid) static int build_id_cache__kcore_buildid(const char *proc_dir, char *sbuildid)
{ {
char root_dir[PATH_MAX]; char root_dir[PATH_MAX];
char notes[PATH_MAX];
u8 build_id[BUILD_ID_SIZE];
char *p; char *p;
strlcpy(root_dir, proc_dir, sizeof(root_dir)); strlcpy(root_dir, proc_dir, sizeof(root_dir));
...@@ -35,15 +33,7 @@ static int build_id_cache__kcore_buildid(const char *proc_dir, char *sbuildid) ...@@ -35,15 +33,7 @@ static int build_id_cache__kcore_buildid(const char *proc_dir, char *sbuildid)
if (!p) if (!p)
return -1; return -1;
*p = '\0'; *p = '\0';
return sysfs__sprintf_build_id(root_dir, sbuildid);
scnprintf(notes, sizeof(notes), "%s/sys/kernel/notes", root_dir);
if (sysfs__read_build_id(notes, build_id, sizeof(build_id)))
return -1;
build_id__sprintf(build_id, sizeof(build_id), sbuildid);
return 0;
} }
static int build_id_cache__kcore_dir(char *dir, size_t sz) static int build_id_cache__kcore_dir(char *dir, size_t sz)
...@@ -138,7 +128,7 @@ static int build_id_cache__add_kcore(const char *filename, bool force) ...@@ -138,7 +128,7 @@ static int build_id_cache__add_kcore(const char *filename, bool force)
return -1; return -1;
*p = '\0'; *p = '\0';
if (build_id_cache__kcore_buildid(from_dir, sbuildid)) if (build_id_cache__kcore_buildid(from_dir, sbuildid) < 0)
return -1; return -1;
scnprintf(to_dir, sizeof(to_dir), "%s/[kernel.kcore]/%s", scnprintf(to_dir, sizeof(to_dir), "%s/[kernel.kcore]/%s",
......
...@@ -19,29 +19,25 @@ ...@@ -19,29 +19,25 @@
static int sysfs__fprintf_build_id(FILE *fp) static int sysfs__fprintf_build_id(FILE *fp)
{ {
u8 kallsyms_build_id[BUILD_ID_SIZE];
char sbuild_id[SBUILD_ID_SIZE]; char sbuild_id[SBUILD_ID_SIZE];
int ret;
if (sysfs__read_build_id("/sys/kernel/notes", kallsyms_build_id, ret = sysfs__sprintf_build_id("/", sbuild_id);
sizeof(kallsyms_build_id)) != 0) if (ret != sizeof(sbuild_id))
return -1; return ret < 0 ? ret : -EINVAL;
build_id__sprintf(kallsyms_build_id, sizeof(kallsyms_build_id), return fprintf(fp, "%s\n", sbuild_id);
sbuild_id);
fprintf(fp, "%s\n", sbuild_id);
return 0;
} }
static int filename__fprintf_build_id(const char *name, FILE *fp) static int filename__fprintf_build_id(const char *name, FILE *fp)
{ {
u8 build_id[BUILD_ID_SIZE];
char sbuild_id[SBUILD_ID_SIZE]; char sbuild_id[SBUILD_ID_SIZE];
int ret;
if (filename__read_build_id(name, build_id, ret = filename__sprintf_build_id(name, sbuild_id);
sizeof(build_id)) != sizeof(build_id)) if (ret != sizeof(sbuild_id))
return 0; return ret < 0 ? ret : -EINVAL;
build_id__sprintf(build_id, sizeof(build_id), sbuild_id);
return fprintf(fp, "%s\n", sbuild_id); return fprintf(fp, "%s\n", sbuild_id);
} }
...@@ -63,7 +59,7 @@ static int perf_session__list_build_ids(bool force, bool with_hits) ...@@ -63,7 +59,7 @@ static int perf_session__list_build_ids(bool force, bool with_hits)
/* /*
* See if this is an ELF file first: * See if this is an ELF file first:
*/ */
if (filename__fprintf_build_id(input_name, stdout)) if (filename__fprintf_build_id(input_name, stdout) > 0)
goto out; goto out;
session = perf_session__new(&file, false, &build_id__mark_dso_hit_ops); session = perf_session__new(&file, false, &build_id__mark_dso_hit_ops);
......
...@@ -1671,6 +1671,11 @@ int cmd_script(int argc, const char **argv, const char *prefix __maybe_unused) ...@@ -1671,6 +1671,11 @@ int cmd_script(int argc, const char **argv, const char *prefix __maybe_unused)
itrace_parse_synth_opts), itrace_parse_synth_opts),
OPT_BOOLEAN(0, "full-source-path", &srcline_full_filename, OPT_BOOLEAN(0, "full-source-path", &srcline_full_filename,
"Show full source file name path for source lines"), "Show full source file name path for source lines"),
OPT_BOOLEAN(0, "demangle", &symbol_conf.demangle,
"Enable symbol demangling"),
OPT_BOOLEAN(0, "demangle-kernel", &symbol_conf.demangle_kernel,
"Enable kernel symbol demangling"),
OPT_END() OPT_END()
}; };
const char * const script_subcommands[] = { "record", "report", NULL }; const char * const script_subcommands[] = { "record", "report", NULL };
......
/*
* builtin-trace.c
*
* Builtin 'trace' command:
*
* Display a continuously updated trace of any workload, CPU, specific PID,
* system wide, etc. Default format is loosely strace like, but any other
* event may be specified using --event.
*
* Copyright (C) 2012, 2013, 2014, 2015 Red Hat Inc, Arnaldo Carvalho de Melo <acme@redhat.com>
*
* Initially based on the 'trace' prototype by Thomas Gleixner:
*
* http://lwn.net/Articles/415728/ ("Announcing a new utility: 'trace'")
*
* Released under the GPL v2. (and only v2, not any later version)
*/
#include <traceevent/event-parse.h> #include <traceevent/event-parse.h>
#include "builtin.h" #include "builtin.h"
#include "util/color.h" #include "util/color.h"
...@@ -27,6 +45,7 @@ ...@@ -27,6 +45,7 @@
#ifndef MADV_HWPOISON #ifndef MADV_HWPOISON
# define MADV_HWPOISON 100 # define MADV_HWPOISON 100
#endif #endif
#ifndef MADV_MERGEABLE #ifndef MADV_MERGEABLE
......
...@@ -231,7 +231,7 @@ static int handle_options(const char ***argv, int *argc, int *envchanged) ...@@ -231,7 +231,7 @@ static int handle_options(const char ***argv, int *argc, int *envchanged)
(*argc)--; (*argc)--;
} else if (!prefixcmp(cmd, CMD_DEBUGFS_DIR)) { } else if (!prefixcmp(cmd, CMD_DEBUGFS_DIR)) {
perf_debugfs_set_path(cmd + strlen(CMD_DEBUGFS_DIR)); perf_debugfs_set_path(cmd + strlen(CMD_DEBUGFS_DIR));
fprintf(stderr, "dir: %s\n", debugfs_mountpoint); fprintf(stderr, "dir: %s\n", tracing_path);
if (envchanged) if (envchanged)
*envchanged = 1; *envchanged = 1;
} else if (!strcmp(cmd, "--list-cmds")) { } else if (!strcmp(cmd, "--list-cmds")) {
......
#!/bin/bash
perf record -e compaction:mm_compaction_begin -e compaction:mm_compaction_end -e compaction:mm_compaction_migratepages -e compaction:mm_compaction_isolate_migratepages -e compaction:mm_compaction_isolate_freepages $@
#!/bin/bash
#description: display time taken by mm compaction
#args: [-h] [-u] [-p|-pv] [-t | [-m] [-fs] [-ms]] [pid|pid-range|comm-regex]
perf script -s "$PERF_EXEC_PATH"/scripts/python/compaction-times.py $@
# report time spent in compaction
# Licensed under the terms of the GNU GPL License version 2
# testing:
# 'echo 1 > /proc/sys/vm/compact_memory' to force compaction of all zones
import os
import sys
import re
import signal
signal.signal(signal.SIGPIPE, signal.SIG_DFL)
usage = "usage: perf script report compaction-times.py -- [-h] [-u] [-p|-pv] [-t | [-m] [-fs] [-ms]] [pid|pid-range|comm-regex]\n"
class popt:
DISP_DFL = 0
DISP_PROC = 1
DISP_PROC_VERBOSE=2
class topt:
DISP_TIME = 0
DISP_MIG = 1
DISP_ISOLFREE = 2
DISP_ISOLMIG = 4
DISP_ALL = 7
class comm_filter:
def __init__(self, re):
self.re = re
def filter(self, pid, comm):
m = self.re.search(comm)
return m == None or m.group() == ""
class pid_filter:
def __init__(self, low, high):
self.low = (0 if low == "" else int(low))
self.high = (0 if high == "" else int(high))
def filter(self, pid, comm):
return not (pid >= self.low and (self.high == 0 or pid <= self.high))
def set_type(t):
global opt_disp
opt_disp = (t if opt_disp == topt.DISP_ALL else opt_disp|t)
def ns(sec, nsec):
return (sec * 1000000000) + nsec
def time(ns):
return "%dns" % ns if opt_ns else "%dus" % (round(ns, -3) / 1000)
class pair:
def __init__(self, aval, bval, alabel = None, blabel = None):
self.alabel = alabel
self.blabel = blabel
self.aval = aval
self.bval = bval
def __add__(self, rhs):
self.aval += rhs.aval
self.bval += rhs.bval
return self
def __str__(self):
return "%s=%d %s=%d" % (self.alabel, self.aval, self.blabel, self.bval)
class cnode:
def __init__(self, ns):
self.ns = ns
self.migrated = pair(0, 0, "moved", "failed")
self.fscan = pair(0,0, "scanned", "isolated")
self.mscan = pair(0,0, "scanned", "isolated")
def __add__(self, rhs):
self.ns += rhs.ns
self.migrated += rhs.migrated
self.fscan += rhs.fscan
self.mscan += rhs.mscan
return self
def __str__(self):
prev = 0
s = "%s " % time(self.ns)
if (opt_disp & topt.DISP_MIG):
s += "migration: %s" % self.migrated
prev = 1
if (opt_disp & topt.DISP_ISOLFREE):
s += "%sfree_scanner: %s" % (" " if prev else "", self.fscan)
prev = 1
if (opt_disp & topt.DISP_ISOLMIG):
s += "%smigration_scanner: %s" % (" " if prev else "", self.mscan)
return s
def complete(self, secs, nsecs):
self.ns = ns(secs, nsecs) - self.ns
def increment(self, migrated, fscan, mscan):
if (migrated != None):
self.migrated += migrated
if (fscan != None):
self.fscan += fscan
if (mscan != None):
self.mscan += mscan
class chead:
heads = {}
val = cnode(0);
fobj = None
@classmethod
def add_filter(cls, filter):
cls.fobj = filter
@classmethod
def create_pending(cls, pid, comm, start_secs, start_nsecs):
filtered = 0
try:
head = cls.heads[pid]
filtered = head.is_filtered()
except KeyError:
if cls.fobj != None:
filtered = cls.fobj.filter(pid, comm)
head = cls.heads[pid] = chead(comm, pid, filtered)
if not filtered:
head.mark_pending(start_secs, start_nsecs)
@classmethod
def increment_pending(cls, pid, migrated, fscan, mscan):
head = cls.heads[pid]
if not head.is_filtered():
if head.is_pending():
head.do_increment(migrated, fscan, mscan)
else:
sys.stderr.write("missing start compaction event for pid %d\n" % pid)
@classmethod
def complete_pending(cls, pid, secs, nsecs):
head = cls.heads[pid]
if not head.is_filtered():
if head.is_pending():
head.make_complete(secs, nsecs)
else:
sys.stderr.write("missing start compaction event for pid %d\n" % pid)
@classmethod
def gen(cls):
if opt_proc != popt.DISP_DFL:
for i in cls.heads:
yield cls.heads[i]
@classmethod
def str(cls):
return cls.val
def __init__(self, comm, pid, filtered):
self.comm = comm
self.pid = pid
self.val = cnode(0)
self.pending = None
self.filtered = filtered
self.list = []
def __add__(self, rhs):
self.ns += rhs.ns
self.val += rhs.val
return self
def mark_pending(self, secs, nsecs):
self.pending = cnode(ns(secs, nsecs))
def do_increment(self, migrated, fscan, mscan):
self.pending.increment(migrated, fscan, mscan)
def make_complete(self, secs, nsecs):
self.pending.complete(secs, nsecs)
chead.val += self.pending
if opt_proc != popt.DISP_DFL:
self.val += self.pending
if opt_proc == popt.DISP_PROC_VERBOSE:
self.list.append(self.pending)
self.pending = None
def enumerate(self):
if opt_proc == popt.DISP_PROC_VERBOSE and not self.is_filtered():
for i, pelem in enumerate(self.list):
sys.stdout.write("%d[%s].%d: %s\n" % (self.pid, self.comm, i+1, pelem))
def is_pending(self):
return self.pending != None
def is_filtered(self):
return self.filtered
def display(self):
if not self.is_filtered():
sys.stdout.write("%d[%s]: %s\n" % (self.pid, self.comm, self.val))
def trace_end():
sys.stdout.write("total: %s\n" % chead.str())
for i in chead.gen():
i.display(),
i.enumerate()
def compaction__mm_compaction_migratepages(event_name, context, common_cpu,
common_secs, common_nsecs, common_pid, common_comm,
common_callchain, nr_migrated, nr_failed):
chead.increment_pending(common_pid,
pair(nr_migrated, nr_failed), None, None)
def compaction__mm_compaction_isolate_freepages(event_name, context, common_cpu,
common_secs, common_nsecs, common_pid, common_comm,
common_callchain, start_pfn, end_pfn, nr_scanned, nr_taken):
chead.increment_pending(common_pid,
None, pair(nr_scanned, nr_taken), None)
def compaction__mm_compaction_isolate_migratepages(event_name, context, common_cpu,
common_secs, common_nsecs, common_pid, common_comm,
common_callchain, start_pfn, end_pfn, nr_scanned, nr_taken):
chead.increment_pending(common_pid,
None, None, pair(nr_scanned, nr_taken))
def compaction__mm_compaction_end(event_name, context, common_cpu,
common_secs, common_nsecs, common_pid, common_comm,
common_callchain, zone_start, migrate_start, free_start, zone_end,
sync, status):
chead.complete_pending(common_pid, common_secs, common_nsecs)
def compaction__mm_compaction_begin(event_name, context, common_cpu,
common_secs, common_nsecs, common_pid, common_comm,
common_callchain, zone_start, migrate_start, free_start, zone_end,
sync):
chead.create_pending(common_pid, common_comm, common_secs, common_nsecs)
def pr_help():
global usage
sys.stdout.write(usage)
sys.stdout.write("\n")
sys.stdout.write("-h display this help\n")
sys.stdout.write("-p display by process\n")
sys.stdout.write("-pv display by process (verbose)\n")
sys.stdout.write("-t display stall times only\n")
sys.stdout.write("-m display stats for migration\n")
sys.stdout.write("-fs display stats for free scanner\n")
sys.stdout.write("-ms display stats for migration scanner\n")
sys.stdout.write("-u display results in microseconds (default nanoseconds)\n")
comm_re = None
pid_re = None
pid_regex = "^(\d*)-(\d*)$|^(\d*)$"
opt_proc = popt.DISP_DFL
opt_disp = topt.DISP_ALL
opt_ns = True
argc = len(sys.argv) - 1
if argc >= 1:
pid_re = re.compile(pid_regex)
for i, opt in enumerate(sys.argv[1:]):
if opt[0] == "-":
if opt == "-h":
pr_help()
exit(0);
elif opt == "-p":
opt_proc = popt.DISP_PROC
elif opt == "-pv":
opt_proc = popt.DISP_PROC_VERBOSE
elif opt == '-u':
opt_ns = False
elif opt == "-t":
set_type(topt.DISP_TIME)
elif opt == "-m":
set_type(topt.DISP_MIG)
elif opt == "-fs":
set_type(topt.DISP_ISOLFREE)
elif opt == "-ms":
set_type(topt.DISP_ISOLMIG)
else:
sys.exit(usage)
elif i == argc - 1:
m = pid_re.search(opt)
if m != None and m.group() != "":
if m.group(3) != None:
f = pid_filter(m.group(3), m.group(3))
else:
f = pid_filter(m.group(1), m.group(2))
else:
try:
comm_re=re.compile(opt)
except:
sys.stderr.write("invalid regex '%s'" % opt)
sys.exit(usage)
f = comm_filter(comm_re)
chead.add_filter(f)
...@@ -61,8 +61,8 @@ int ui_browser__help_window(struct ui_browser *browser, const char *text); ...@@ -61,8 +61,8 @@ int ui_browser__help_window(struct ui_browser *browser, const char *text);
bool ui_browser__dialog_yesno(struct ui_browser *browser, const char *text); bool ui_browser__dialog_yesno(struct ui_browser *browser, const char *text);
int ui_browser__input_window(const char *title, const char *text, char *input, int ui_browser__input_window(const char *title, const char *text, char *input,
const char *exit_msg, int delay_sec); const char *exit_msg, int delay_sec);
struct perf_session_env; struct perf_env;
int tui__header_window(struct perf_session_env *env); int tui__header_window(struct perf_env *env);
void ui_browser__argv_seek(struct ui_browser *browser, off_t offset, int whence); void ui_browser__argv_seek(struct ui_browser *browser, off_t offset, int whence);
unsigned int ui_browser__argv_refresh(struct ui_browser *browser); unsigned int ui_browser__argv_refresh(struct ui_browser *browser);
......
...@@ -91,7 +91,7 @@ static int ui__list_menu(int argc, char * const argv[]) ...@@ -91,7 +91,7 @@ static int ui__list_menu(int argc, char * const argv[])
return list_menu__run(&menu); return list_menu__run(&menu);
} }
int tui__header_window(struct perf_session_env *env) int tui__header_window(struct perf_env *env)
{ {
int i, argc = 0; int i, argc = 0;
char **argv; char **argv;
......
...@@ -26,7 +26,7 @@ struct hist_browser { ...@@ -26,7 +26,7 @@ struct hist_browser {
struct map_symbol *selection; struct map_symbol *selection;
struct hist_browser_timer *hbt; struct hist_browser_timer *hbt;
struct pstack *pstack; struct pstack *pstack;
struct perf_session_env *env; struct perf_env *env;
int print_seq; int print_seq;
bool show_dso; bool show_dso;
bool show_headers; bool show_headers;
...@@ -1214,7 +1214,7 @@ static int hist_browser__dump(struct hist_browser *browser) ...@@ -1214,7 +1214,7 @@ static int hist_browser__dump(struct hist_browser *browser)
static struct hist_browser *hist_browser__new(struct hists *hists, static struct hist_browser *hist_browser__new(struct hists *hists,
struct hist_browser_timer *hbt, struct hist_browser_timer *hbt,
struct perf_session_env *env) struct perf_env *env)
{ {
struct hist_browser *browser = zalloc(sizeof(*browser)); struct hist_browser *browser = zalloc(sizeof(*browser));
...@@ -1695,7 +1695,7 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events, ...@@ -1695,7 +1695,7 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events,
bool left_exits, bool left_exits,
struct hist_browser_timer *hbt, struct hist_browser_timer *hbt,
float min_pcnt, float min_pcnt,
struct perf_session_env *env) struct perf_env *env)
{ {
struct hists *hists = evsel__hists(evsel); struct hists *hists = evsel__hists(evsel);
struct hist_browser *browser = hist_browser__new(hists, hbt, env); struct hist_browser *browser = hist_browser__new(hists, hbt, env);
...@@ -2016,7 +2016,7 @@ struct perf_evsel_menu { ...@@ -2016,7 +2016,7 @@ struct perf_evsel_menu {
struct perf_evsel *selection; struct perf_evsel *selection;
bool lost_events, lost_events_warned; bool lost_events, lost_events_warned;
float min_pcnt; float min_pcnt;
struct perf_session_env *env; struct perf_env *env;
}; };
static void perf_evsel_menu__write(struct ui_browser *browser, static void perf_evsel_menu__write(struct ui_browser *browser,
...@@ -2169,7 +2169,7 @@ static int __perf_evlist__tui_browse_hists(struct perf_evlist *evlist, ...@@ -2169,7 +2169,7 @@ static int __perf_evlist__tui_browse_hists(struct perf_evlist *evlist,
int nr_entries, const char *help, int nr_entries, const char *help,
struct hist_browser_timer *hbt, struct hist_browser_timer *hbt,
float min_pcnt, float min_pcnt,
struct perf_session_env *env) struct perf_env *env)
{ {
struct perf_evsel *pos; struct perf_evsel *pos;
struct perf_evsel_menu menu = { struct perf_evsel_menu menu = {
...@@ -2202,7 +2202,7 @@ static int __perf_evlist__tui_browse_hists(struct perf_evlist *evlist, ...@@ -2202,7 +2202,7 @@ static int __perf_evlist__tui_browse_hists(struct perf_evlist *evlist,
int perf_evlist__tui_browse_hists(struct perf_evlist *evlist, const char *help, int perf_evlist__tui_browse_hists(struct perf_evlist *evlist, const char *help,
struct hist_browser_timer *hbt, struct hist_browser_timer *hbt,
float min_pcnt, float min_pcnt,
struct perf_session_env *env) struct perf_env *env)
{ {
int nr_entries = evlist->nr_entries; int nr_entries = evlist->nr_entries;
......
...@@ -93,6 +93,38 @@ int build_id__sprintf(const u8 *build_id, int len, char *bf) ...@@ -93,6 +93,38 @@ int build_id__sprintf(const u8 *build_id, int len, char *bf)
return raw - build_id; return raw - build_id;
} }
int sysfs__sprintf_build_id(const char *root_dir, char *sbuild_id)
{
char notes[PATH_MAX];
u8 build_id[BUILD_ID_SIZE];
int ret;
if (!root_dir)
root_dir = "";
scnprintf(notes, sizeof(notes), "%s/sys/kernel/notes", root_dir);
ret = sysfs__read_build_id(notes, build_id, sizeof(build_id));
if (ret < 0)
return ret;
return build_id__sprintf(build_id, sizeof(build_id), sbuild_id);
}
int filename__sprintf_build_id(const char *pathname, char *sbuild_id)
{
u8 build_id[BUILD_ID_SIZE];
int ret;
ret = filename__read_build_id(pathname, build_id, sizeof(build_id));
if (ret < 0)
return ret;
else if (ret != sizeof(build_id))
return -EINVAL;
return build_id__sprintf(build_id, sizeof(build_id), sbuild_id);
}
/* asnprintf consolidates asprintf and snprintf */ /* asnprintf consolidates asprintf and snprintf */
static int asnprintf(char **strp, size_t size, const char *fmt, ...) static int asnprintf(char **strp, size_t size, const char *fmt, ...)
{ {
......
...@@ -12,6 +12,9 @@ extern struct perf_tool build_id__mark_dso_hit_ops; ...@@ -12,6 +12,9 @@ extern struct perf_tool build_id__mark_dso_hit_ops;
struct dso; struct dso;
int build_id__sprintf(const u8 *build_id, int len, char *bf); int build_id__sprintf(const u8 *build_id, int len, char *bf);
int sysfs__sprintf_build_id(const char *root_dir, char *sbuild_id);
int filename__sprintf_build_id(const char *pathname, char *sbuild_id);
char *dso__build_id_filename(const struct dso *dso, char *bf, size_t size); char *dso__build_id_filename(const struct dso *dso, char *bf, size_t size);
int build_id__mark_dso_hit(struct perf_tool *tool, union perf_event *event, int build_id__mark_dso_hit(struct perf_tool *tool, union perf_event *event,
......
...@@ -98,6 +98,7 @@ static void perf_evlist__purge(struct perf_evlist *evlist) ...@@ -98,6 +98,7 @@ static void perf_evlist__purge(struct perf_evlist *evlist)
evlist__for_each_safe(evlist, n, pos) { evlist__for_each_safe(evlist, n, pos) {
list_del_init(&pos->node); list_del_init(&pos->node);
pos->evlist = NULL;
perf_evsel__delete(pos); perf_evsel__delete(pos);
} }
...@@ -125,6 +126,7 @@ void perf_evlist__delete(struct perf_evlist *evlist) ...@@ -125,6 +126,7 @@ void perf_evlist__delete(struct perf_evlist *evlist)
void perf_evlist__add(struct perf_evlist *evlist, struct perf_evsel *entry) void perf_evlist__add(struct perf_evlist *evlist, struct perf_evsel *entry)
{ {
entry->evlist = evlist;
list_add_tail(&entry->node, &evlist->entries); list_add_tail(&entry->node, &evlist->entries);
entry->idx = evlist->nr_entries; entry->idx = evlist->nr_entries;
entry->tracking = !entry->idx; entry->tracking = !entry->idx;
......
...@@ -56,6 +56,7 @@ struct perf_evlist { ...@@ -56,6 +56,7 @@ struct perf_evlist {
struct cpu_map *cpus; struct cpu_map *cpus;
struct perf_evsel *selected; struct perf_evsel *selected;
struct events_stats stats; struct events_stats stats;
struct perf_env *env;
}; };
struct perf_evsel_str_handler { struct perf_evsel_str_handler {
......
...@@ -206,6 +206,7 @@ void perf_evsel__init(struct perf_evsel *evsel, ...@@ -206,6 +206,7 @@ void perf_evsel__init(struct perf_evsel *evsel,
evsel->leader = evsel; evsel->leader = evsel;
evsel->unit = ""; evsel->unit = "";
evsel->scale = 1.0; evsel->scale = 1.0;
evsel->evlist = NULL;
INIT_LIST_HEAD(&evsel->node); INIT_LIST_HEAD(&evsel->node);
INIT_LIST_HEAD(&evsel->config_terms); INIT_LIST_HEAD(&evsel->config_terms);
perf_evsel__object.init(evsel); perf_evsel__object.init(evsel);
...@@ -1026,6 +1027,7 @@ void perf_evsel__close_fd(struct perf_evsel *evsel, int ncpus, int nthreads) ...@@ -1026,6 +1027,7 @@ void perf_evsel__close_fd(struct perf_evsel *evsel, int ncpus, int nthreads)
void perf_evsel__exit(struct perf_evsel *evsel) void perf_evsel__exit(struct perf_evsel *evsel)
{ {
assert(list_empty(&evsel->node)); assert(list_empty(&evsel->node));
assert(evsel->evlist == NULL);
perf_evsel__free_fd(evsel); perf_evsel__free_fd(evsel);
perf_evsel__free_id(evsel); perf_evsel__free_id(evsel);
perf_evsel__free_config_terms(evsel); perf_evsel__free_config_terms(evsel);
......
...@@ -60,6 +60,9 @@ struct perf_evsel_config_term { ...@@ -60,6 +60,9 @@ struct perf_evsel_config_term {
/** struct perf_evsel - event selector /** struct perf_evsel - event selector
* *
* @evlist - evlist this evsel is in, if it is in one.
* @node - To insert it into evlist->entries or in other list_heads, say in
* the event parsing routines.
* @name - Can be set to retain the original event name passed by the user, * @name - Can be set to retain the original event name passed by the user,
* so that when showing results in tools such as 'perf stat', we * so that when showing results in tools such as 'perf stat', we
* show the name used, not some alias. * show the name used, not some alias.
...@@ -73,6 +76,7 @@ struct perf_evsel_config_term { ...@@ -73,6 +76,7 @@ struct perf_evsel_config_term {
*/ */
struct perf_evsel { struct perf_evsel {
struct list_head node; struct list_head node;
struct perf_evlist *evlist;
struct perf_event_attr attr; struct perf_event_attr attr;
char *filter; char *filter;
struct xyarray *fd; struct xyarray *fd;
......
...@@ -2514,6 +2514,7 @@ int perf_session__read_header(struct perf_session *session) ...@@ -2514,6 +2514,7 @@ int perf_session__read_header(struct perf_session *session)
if (session->evlist == NULL) if (session->evlist == NULL)
return -ENOMEM; return -ENOMEM;
session->evlist->env = &header->env;
if (perf_data_file__is_pipe(file)) if (perf_data_file__is_pipe(file))
return perf_header__read_pipe(session); return perf_header__read_pipe(session);
......
...@@ -66,7 +66,7 @@ struct perf_header; ...@@ -66,7 +66,7 @@ struct perf_header;
int perf_file_header__read(struct perf_file_header *header, int perf_file_header__read(struct perf_file_header *header,
struct perf_header *ph, int fd); struct perf_header *ph, int fd);
struct perf_session_env { struct perf_env {
char *hostname; char *hostname;
char *os_release; char *os_release;
char *version; char *version;
...@@ -98,7 +98,7 @@ struct perf_header { ...@@ -98,7 +98,7 @@ struct perf_header {
u64 data_size; u64 data_size;
u64 feat_offset; u64 feat_offset;
DECLARE_BITMAP(adds_features, HEADER_FEAT_BITS); DECLARE_BITMAP(adds_features, HEADER_FEAT_BITS);
struct perf_session_env env; struct perf_env env;
}; };
struct perf_evlist; struct perf_evlist;
......
...@@ -313,7 +313,7 @@ int hist_entry__tui_annotate(struct hist_entry *he, struct perf_evsel *evsel, ...@@ -313,7 +313,7 @@ int hist_entry__tui_annotate(struct hist_entry *he, struct perf_evsel *evsel,
int perf_evlist__tui_browse_hists(struct perf_evlist *evlist, const char *help, int perf_evlist__tui_browse_hists(struct perf_evlist *evlist, const char *help,
struct hist_browser_timer *hbt, struct hist_browser_timer *hbt,
float min_pcnt, float min_pcnt,
struct perf_session_env *env); struct perf_env *env);
int script_browse(const char *script_opt); int script_browse(const char *script_opt);
#else #else
static inline static inline
...@@ -321,7 +321,7 @@ int perf_evlist__tui_browse_hists(struct perf_evlist *evlist __maybe_unused, ...@@ -321,7 +321,7 @@ int perf_evlist__tui_browse_hists(struct perf_evlist *evlist __maybe_unused,
const char *help __maybe_unused, const char *help __maybe_unused,
struct hist_browser_timer *hbt __maybe_unused, struct hist_browser_timer *hbt __maybe_unused,
float min_pcnt __maybe_unused, float min_pcnt __maybe_unused,
struct perf_session_env *env __maybe_unused) struct perf_env *env __maybe_unused)
{ {
return 0; return 0;
} }
......
...@@ -170,7 +170,7 @@ static void perf_session__delete_threads(struct perf_session *session) ...@@ -170,7 +170,7 @@ static void perf_session__delete_threads(struct perf_session *session)
machine__delete_threads(&session->machines.host); machine__delete_threads(&session->machines.host);
} }
static void perf_session_env__exit(struct perf_session_env *env) static void perf_session_env__exit(struct perf_env *env)
{ {
zfree(&env->hostname); zfree(&env->hostname);
zfree(&env->os_release); zfree(&env->os_release);
......
...@@ -1853,7 +1853,7 @@ static void vmlinux_path__exit(void) ...@@ -1853,7 +1853,7 @@ static void vmlinux_path__exit(void)
zfree(&vmlinux_path); zfree(&vmlinux_path);
} }
static int vmlinux_path__init(struct perf_session_env *env) static int vmlinux_path__init(struct perf_env *env)
{ {
struct utsname uts; struct utsname uts;
char bf[PATH_MAX]; char bf[PATH_MAX];
...@@ -1964,7 +1964,7 @@ static bool symbol__read_kptr_restrict(void) ...@@ -1964,7 +1964,7 @@ static bool symbol__read_kptr_restrict(void)
return value; return value;
} }
int symbol__init(struct perf_session_env *env) int symbol__init(struct perf_env *env)
{ {
const char *symfs; const char *symfs;
......
...@@ -252,8 +252,8 @@ int modules__parse(const char *filename, void *arg, ...@@ -252,8 +252,8 @@ int modules__parse(const char *filename, void *arg,
int filename__read_debuglink(const char *filename, char *debuglink, int filename__read_debuglink(const char *filename, char *debuglink,
size_t size); size_t size);
struct perf_session_env; struct perf_env;
int symbol__init(struct perf_session_env *env); int symbol__init(struct perf_env *env);
void symbol__exit(void); void symbol__exit(void);
void symbol__elf_init(void); void symbol__elf_init(void);
struct symbol *symbol__new(u64 start, u64 len, u8 binding, const char *name); struct symbol *symbol__new(u64 start, u64 len, u8 binding, const char *name);
......
...@@ -34,6 +34,7 @@ bool test_attr__enabled; ...@@ -34,6 +34,7 @@ bool test_attr__enabled;
bool perf_host = true; bool perf_host = true;
bool perf_guest = false; bool perf_guest = false;
char tracing_path[PATH_MAX + 1] = "/sys/kernel/debug/tracing";
char tracing_events_path[PATH_MAX + 1] = "/sys/kernel/debug/tracing/events"; char tracing_events_path[PATH_MAX + 1] = "/sys/kernel/debug/tracing/events";
void event_attr_init(struct perf_event_attr *attr) void event_attr_init(struct perf_event_attr *attr)
...@@ -391,6 +392,8 @@ void set_term_quiet_input(struct termios *old) ...@@ -391,6 +392,8 @@ void set_term_quiet_input(struct termios *old)
static void set_tracing_events_path(const char *tracing, const char *mountpoint) static void set_tracing_events_path(const char *tracing, const char *mountpoint)
{ {
snprintf(tracing_path, sizeof(tracing_path), "%s/%s",
mountpoint, tracing);
snprintf(tracing_events_path, sizeof(tracing_events_path), "%s/%s%s", snprintf(tracing_events_path, sizeof(tracing_events_path), "%s/%s%s",
mountpoint, tracing, "events"); mountpoint, tracing, "events");
} }
...@@ -436,66 +439,14 @@ const char *perf_debugfs_mount(const char *mountpoint) ...@@ -436,66 +439,14 @@ const char *perf_debugfs_mount(const char *mountpoint)
void perf_debugfs_set_path(const char *mntpt) void perf_debugfs_set_path(const char *mntpt)
{ {
snprintf(debugfs_mountpoint, strlen(debugfs_mountpoint), "%s", mntpt);
set_tracing_events_path("tracing/", mntpt); set_tracing_events_path("tracing/", mntpt);
} }
static const char *find_tracefs(void)
{
const char *path = __perf_tracefs_mount(NULL);
return path;
}
static const char *find_debugfs(void)
{
const char *path = __perf_debugfs_mount(NULL);
if (!path)
fprintf(stderr, "Your kernel does not support the debugfs filesystem");
return path;
}
/*
* Finds the path to the debugfs/tracing
* Allocates the string and stores it.
*/
const char *find_tracing_dir(void)
{
const char *tracing_dir = "";
static char *tracing;
static int tracing_found;
const char *debugfs;
if (tracing_found)
return tracing;
debugfs = find_tracefs();
if (!debugfs) {
tracing_dir = "/tracing";
debugfs = find_debugfs();
if (!debugfs)
return NULL;
}
if (asprintf(&tracing, "%s%s", debugfs, tracing_dir) < 0)
return NULL;
tracing_found = 1;
return tracing;
}
char *get_tracing_file(const char *name) char *get_tracing_file(const char *name)
{ {
const char *tracing;
char *file; char *file;
tracing = find_tracing_dir(); if (asprintf(&file, "%s/%s", tracing_path, name) < 0)
if (!tracing)
return NULL;
if (asprintf(&file, "%s/%s", tracing, name) < 0)
return NULL; return NULL;
return file; return file;
......
...@@ -83,10 +83,10 @@ ...@@ -83,10 +83,10 @@
extern const char *graph_line; extern const char *graph_line;
extern const char *graph_dotted_line; extern const char *graph_dotted_line;
extern char buildid_dir[]; extern char buildid_dir[];
extern char tracing_path[];
extern char tracing_events_path[]; extern char tracing_events_path[];
extern void perf_debugfs_set_path(const char *mountpoint); extern void perf_debugfs_set_path(const char *mountpoint);
const char *perf_debugfs_mount(const char *mountpoint); const char *perf_debugfs_mount(const char *mountpoint);
const char *find_tracing_dir(void);
char *get_tracing_file(const char *name); char *get_tracing_file(const char *name);
void put_tracing_file(char *file); void put_tracing_file(char *file);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册