Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
linux
Commits
975fc2d5
Commit
975fc2d5
authored
May 12, 2010
by
Ingo Molnar
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'perf' of
git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux-2.6
into perf/core
parents
8e6d5573
ef7b93a1
Changes
8
Show whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
688 additions
and
355 deletions
+688
-355
tools/perf/Makefile
tools/perf/Makefile
+10
-2
tools/perf/builtin-annotate.c
tools/perf/builtin-annotate.c
+2
-196
tools/perf/builtin-report.c
tools/perf/builtin-report.c
+19
-5
tools/perf/util/hist.c
tools/perf/util/hist.c
+243
-0
tools/perf/util/hist.h
tools/perf/util/hist.h
+44
-0
tools/perf/util/newt.c
tools/perf/util/newt.c
+370
-131
tools/perf/util/session.h
tools/perf/util/session.h
+0
-15
tools/perf/util/sort.h
tools/perf/util/sort.h
+0
-6
No files found.
tools/perf/Makefile
View file @
975fc2d5
...
...
@@ -506,8 +506,8 @@ PERFLIBS = $(LIB_FILE)
-include
config.mak
ifndef
NO_DWARF
ifneq
($(shell sh -c "(echo '\
#include <dwarf.h>'; echo '\#include <libdw.h>'; echo 'int main(void) { Dwarf *dbg; dbg = dwarf_begin(0, DWARF_C_READ); return (long)dbg; }') | $(CC) -x c - $(ALL_CFLAGS) -I/usr/include/elfutils -ldw -lelf -o $(BITBUCKET) $(ALL_LDFLAGS) $(EXTLIBS) "$(QUIET_STDERR)" && echo y"), y)
msg
:=
$(
warning
No libdw.h found or old libdw.h found
, disables dwarf support. Please
install
elfutils-devel/libdw-dev
)
;
ifneq
($(shell sh -c "(echo '\
#include <dwarf.h>'; echo '\#include <libdw.h>'; echo '
\#include <version.h>'; echo '\#ifndef _ELFUTILS_PREREQ'; echo '\#error'; echo '\#endif'; echo '
int main(void) { Dwarf *dbg; dbg = dwarf_begin(0, DWARF_C_READ); return (long)dbg; }') | $(CC) -x c - $(ALL_CFLAGS) -I/usr/include/elfutils -ldw -lelf -o $(BITBUCKET) $(ALL_LDFLAGS) $(EXTLIBS) "$(QUIET_STDERR)" && echo y"), y)
msg
:=
$(
warning
No libdw.h found or old libdw.h found
or elfutils is older than 0.138, disables dwarf support. Please
install
new
elfutils-devel/libdw-dev
)
;
NO_DWARF
:=
1
endif
# Dwarf support
endif
# NO_DWARF
...
...
@@ -560,6 +560,8 @@ ifneq ($(shell sh -c "(echo '\#include <newt.h>'; echo 'int main(void) { newtIni
msg
:=
$(
warning
newt not found, disables TUI support. Please
install
newt-devel or libnewt-dev
)
;
BASIC_CFLAGS
+=
-DNO_NEWT_SUPPORT
else
# Fedora has /usr/include/slang/slang.h, but ubuntu /usr/include/slang.h
BASIC_CFLAGS
+=
-I
/usr/include/slang
EXTLIBS
+=
-lnewt
LIB_OBJS
+=
$(OUTPUT)
util/newt.o
endif
...
...
@@ -592,6 +594,9 @@ endif
ifdef
NO_DEMANGLE
BASIC_CFLAGS
+=
-DNO_DEMANGLE
else
ifdef
HAVE_CPLUS_DEMANGLE
EXTLIBS
+=
-liberty
BASIC_CFLAGS
+=
-DHAVE_CPLUS_DEMANGLE
else
has_bfd
:=
$(
shell
sh
-c
"(echo '
\#
include <bfd.h>'; echo 'int main(void
)
{ bfd_demangle(0, 0, 0
)
; return 0;
}
'
)
|
$(CC)
-x c -
$(ALL_CFLAGS)
-o
$(BITBUCKET)
$(ALL_LDFLAGS)
$(EXTLIBS)
-lbfd "
$(QUIET_STDERR)
" && echo y"
)
...
...
@@ -945,6 +950,9 @@ $(OUTPUT)builtin-init-db.o: builtin-init-db.c $(OUTPUT)PERF-CFLAGS
$(OUTPUT)util/config.o
:
util/config.c $(OUTPUT)PERF-CFLAGS
$(QUIET_CC)$(CC)
-o
$@
-c
$(ALL_CFLAGS)
-DETC_PERFCONFIG
=
'"
$(ETC_PERFCONFIG_SQ)
"'
$<
$(OUTPUT)util/newt.o
:
util/newt.c $(OUTPUT)PERF-CFLAGS
$(QUIET_CC)$(CC)
-o
$@
-c
$(ALL_CFLAGS)
-DENABLE_SLFUTURE_CONST
$<
$(OUTPUT)util/rbtree.o
:
../../lib/rbtree.c $(OUTPUT)PERF-CFLAGS
$(QUIET_CC)$(CC)
-o
$@
-c
$(ALL_CFLAGS)
-DETC_PERFCONFIG
=
'"
$(ETC_PERFCONFIG_SQ)
"'
$<
...
...
tools/perf/builtin-annotate.c
View file @
975fc2d5
...
...
@@ -34,68 +34,8 @@ static bool full_paths;
static
bool
print_line
;
struct
sym_hist
{
u64
sum
;
u64
ip
[
0
];
};
struct
sym_ext
{
struct
rb_node
node
;
double
percent
;
char
*
path
;
};
struct
sym_priv
{
struct
sym_hist
*
hist
;
struct
sym_ext
*
ext
;
};
static
const
char
*
sym_hist_filter
;
static
int
sym__alloc_hist
(
struct
symbol
*
self
)
{
struct
sym_priv
*
priv
=
symbol__priv
(
self
);
const
int
size
=
(
sizeof
(
*
priv
->
hist
)
+
(
self
->
end
-
self
->
start
)
*
sizeof
(
u64
));
priv
->
hist
=
zalloc
(
size
);
return
priv
->
hist
==
NULL
?
-
1
:
0
;
}
/*
* collect histogram counts
*/
static
int
annotate__hist_hit
(
struct
hist_entry
*
he
,
u64
ip
)
{
unsigned
int
sym_size
,
offset
;
struct
symbol
*
sym
=
he
->
ms
.
sym
;
struct
sym_priv
*
priv
;
struct
sym_hist
*
h
;
if
(
!
sym
||
!
he
->
ms
.
map
)
return
0
;
priv
=
symbol__priv
(
sym
);
if
(
priv
->
hist
==
NULL
&&
sym__alloc_hist
(
sym
)
<
0
)
return
-
ENOMEM
;
sym_size
=
sym
->
end
-
sym
->
start
;
offset
=
ip
-
sym
->
start
;
pr_debug3
(
"%s: ip=%#Lx
\n
"
,
__func__
,
he
->
ms
.
map
->
unmap_ip
(
he
->
ms
.
map
,
ip
));
if
(
offset
>=
sym_size
)
return
0
;
h
=
priv
->
hist
;
h
->
sum
++
;
h
->
ip
[
offset
]
++
;
pr_debug3
(
"%#Lx %s: count++ [ip: %#Lx, %#Lx] => %Ld
\n
"
,
he
->
ms
.
sym
->
start
,
he
->
ms
.
sym
->
name
,
ip
,
ip
-
he
->
ms
.
sym
->
start
,
h
->
ip
[
offset
]);
return
0
;
}
static
int
hists__add_entry
(
struct
hists
*
self
,
struct
addr_location
*
al
)
{
struct
hist_entry
*
he
;
...
...
@@ -115,7 +55,7 @@ static int hists__add_entry(struct hists *self, struct addr_location *al)
if
(
he
==
NULL
)
return
-
ENOMEM
;
return
annotate__hist_hit
(
he
,
al
->
addr
);
return
hist_entry__inc_addr_samples
(
he
,
al
->
addr
);
}
static
int
process_sample_event
(
event_t
*
event
,
struct
perf_session
*
session
)
...
...
@@ -140,101 +80,6 @@ static int process_sample_event(event_t *event, struct perf_session *session)
return
0
;
}
struct
objdump_line
{
struct
list_head
node
;
s64
offset
;
char
*
line
;
};
static
struct
objdump_line
*
objdump_line__new
(
s64
offset
,
char
*
line
)
{
struct
objdump_line
*
self
=
malloc
(
sizeof
(
*
self
));
if
(
self
!=
NULL
)
{
self
->
offset
=
offset
;
self
->
line
=
line
;
}
return
self
;
}
static
void
objdump_line__free
(
struct
objdump_line
*
self
)
{
free
(
self
->
line
);
free
(
self
);
}
static
void
objdump__add_line
(
struct
list_head
*
head
,
struct
objdump_line
*
line
)
{
list_add_tail
(
&
line
->
node
,
head
);
}
static
struct
objdump_line
*
objdump__get_next_ip_line
(
struct
list_head
*
head
,
struct
objdump_line
*
pos
)
{
list_for_each_entry_continue
(
pos
,
head
,
node
)
if
(
pos
->
offset
>=
0
)
return
pos
;
return
NULL
;
}
static
int
parse_line
(
FILE
*
file
,
struct
hist_entry
*
he
,
struct
list_head
*
head
)
{
struct
symbol
*
sym
=
he
->
ms
.
sym
;
struct
objdump_line
*
objdump_line
;
char
*
line
=
NULL
,
*
tmp
,
*
tmp2
;
size_t
line_len
;
s64
line_ip
,
offset
=
-
1
;
char
*
c
;
if
(
getline
(
&
line
,
&
line_len
,
file
)
<
0
)
return
-
1
;
if
(
!
line
)
return
-
1
;
c
=
strchr
(
line
,
'\n'
);
if
(
c
)
*
c
=
0
;
line_ip
=
-
1
;
/*
* Strip leading spaces:
*/
tmp
=
line
;
while
(
*
tmp
)
{
if
(
*
tmp
!=
' '
)
break
;
tmp
++
;
}
if
(
*
tmp
)
{
/*
* Parse hexa addresses followed by ':'
*/
line_ip
=
strtoull
(
tmp
,
&
tmp2
,
16
);
if
(
*
tmp2
!=
':'
)
line_ip
=
-
1
;
}
if
(
line_ip
!=
-
1
)
{
u64
start
=
map__rip_2objdump
(
he
->
ms
.
map
,
sym
->
start
);
offset
=
line_ip
-
start
;
}
objdump_line
=
objdump_line__new
(
offset
,
line
);
if
(
objdump_line
==
NULL
)
{
free
(
line
);
return
-
1
;
}
objdump__add_line
(
head
,
objdump_line
);
return
0
;
}
static
int
objdump_line__print
(
struct
objdump_line
*
self
,
struct
list_head
*
head
,
struct
hist_entry
*
he
,
u64
len
)
...
...
@@ -439,28 +284,12 @@ static void annotate_sym(struct hist_entry *he)
struct
symbol
*
sym
=
he
->
ms
.
sym
;
const
char
*
filename
=
dso
->
long_name
,
*
d_filename
;
u64
len
;
char
command
[
PATH_MAX
*
2
];
FILE
*
file
;
LIST_HEAD
(
head
);
struct
objdump_line
*
pos
,
*
n
;
if
(
!
filename
)
if
(
hist_entry__annotate
(
he
,
&
head
)
<
0
)
return
;
if
(
dso
->
origin
==
DSO__ORIG_KERNEL
)
{
if
(
dso
->
annotate_warned
)
return
;
dso
->
annotate_warned
=
1
;
pr_err
(
"Can't annotate %s: No vmlinux file was found in the "
"path:
\n
"
,
sym
->
name
);
vmlinux_path__fprintf
(
stderr
);
return
;
}
pr_debug
(
"%s: filename=%s, sym=%s, start=%#Lx, end=%#Lx
\n
"
,
__func__
,
filename
,
sym
->
name
,
map
->
unmap_ip
(
map
,
sym
->
start
),
map
->
unmap_ip
(
map
,
sym
->
end
));
if
(
full_paths
)
d_filename
=
filename
;
else
...
...
@@ -477,29 +306,6 @@ static void annotate_sym(struct hist_entry *he)
printf
(
" Percent | Source code & Disassembly of %s
\n
"
,
d_filename
);
printf
(
"------------------------------------------------
\n
"
);
if
(
verbose
>=
2
)
printf
(
"annotating [%p] %30s : [%p] %30s
\n
"
,
dso
,
dso
->
long_name
,
sym
,
sym
->
name
);
sprintf
(
command
,
"objdump --start-address=0x%016Lx --stop-address=0x%016Lx -dS %s|grep -v %s"
,
map__rip_2objdump
(
map
,
sym
->
start
),
map__rip_2objdump
(
map
,
sym
->
end
),
filename
,
filename
);
if
(
verbose
>=
3
)
printf
(
"doing: %s
\n
"
,
command
);
file
=
popen
(
command
,
"r"
);
if
(
!
file
)
return
;
while
(
!
feof
(
file
))
{
if
(
parse_line
(
file
,
he
,
&
head
)
<
0
)
break
;
}
pclose
(
file
);
if
(
verbose
)
hist_entry__print_hits
(
he
);
...
...
tools/perf/builtin-report.c
View file @
975fc2d5
...
...
@@ -106,8 +106,18 @@ static int perf_session__add_hist_entry(struct perf_session *self,
if
(
he
==
NULL
)
goto
out_free_syms
;
err
=
0
;
if
(
symbol_conf
.
use_callchain
)
if
(
symbol_conf
.
use_callchain
)
{
err
=
append_chain
(
he
->
callchain
,
data
->
callchain
,
syms
);
if
(
err
)
goto
out_free_syms
;
}
/*
* Only in the newt browser we are doing integrated annotation,
* so we don't allocated the extra space needed because the stdio
* code will not use it.
*/
if
(
use_browser
)
err
=
hist_entry__inc_addr_samples
(
he
,
al
->
addr
);
out_free_syms:
free
(
syms
);
return
err
;
...
...
@@ -301,10 +311,7 @@ static int __cmd_report(void)
hists__collapse_resort
(
hists
);
hists__output_resort
(
hists
);
if
(
use_browser
)
perf_session__browse_hists
(
&
hists
->
entries
,
hists
->
nr_entries
,
hists
->
stats
.
total
,
help
,
input_name
);
hists__browse
(
hists
,
help
,
input_name
);
else
{
if
(
rb_first
(
&
session
->
hists
.
entries
)
==
rb_last
(
&
session
->
hists
.
entries
))
...
...
@@ -461,6 +468,13 @@ int cmd_report(int argc, const char **argv, const char *prefix __used)
if
(
strcmp
(
input_name
,
"-"
)
!=
0
)
setup_browser
();
/*
* Only in the newt browser we are doing integrated annotation,
* so don't allocate extra space that won't be used in the stdio
* implementation.
*/
if
(
use_browser
)
symbol_conf
.
priv_size
=
sizeof
(
struct
sym_priv
);
if
(
symbol__init
()
<
0
)
return
-
1
;
...
...
tools/perf/util/hist.c
View file @
975fc2d5
...
...
@@ -784,3 +784,246 @@ size_t hists__fprintf(struct hists *self, struct hists *pair,
return
ret
;
}
enum
hist_filter
{
HIST_FILTER__DSO
,
HIST_FILTER__THREAD
,
};
void
hists__filter_by_dso
(
struct
hists
*
self
,
const
struct
dso
*
dso
)
{
struct
rb_node
*
nd
;
self
->
nr_entries
=
self
->
stats
.
total
=
0
;
self
->
max_sym_namelen
=
0
;
for
(
nd
=
rb_first
(
&
self
->
entries
);
nd
;
nd
=
rb_next
(
nd
))
{
struct
hist_entry
*
h
=
rb_entry
(
nd
,
struct
hist_entry
,
rb_node
);
if
(
symbol_conf
.
exclude_other
&&
!
h
->
parent
)
continue
;
if
(
dso
!=
NULL
&&
(
h
->
ms
.
map
==
NULL
||
h
->
ms
.
map
->
dso
!=
dso
))
{
h
->
filtered
|=
(
1
<<
HIST_FILTER__DSO
);
continue
;
}
h
->
filtered
&=
~
(
1
<<
HIST_FILTER__DSO
);
if
(
!
h
->
filtered
)
{
++
self
->
nr_entries
;
self
->
stats
.
total
+=
h
->
count
;
if
(
h
->
ms
.
sym
&&
self
->
max_sym_namelen
<
h
->
ms
.
sym
->
namelen
)
self
->
max_sym_namelen
=
h
->
ms
.
sym
->
namelen
;
}
}
}
void
hists__filter_by_thread
(
struct
hists
*
self
,
const
struct
thread
*
thread
)
{
struct
rb_node
*
nd
;
self
->
nr_entries
=
self
->
stats
.
total
=
0
;
self
->
max_sym_namelen
=
0
;
for
(
nd
=
rb_first
(
&
self
->
entries
);
nd
;
nd
=
rb_next
(
nd
))
{
struct
hist_entry
*
h
=
rb_entry
(
nd
,
struct
hist_entry
,
rb_node
);
if
(
thread
!=
NULL
&&
h
->
thread
!=
thread
)
{
h
->
filtered
|=
(
1
<<
HIST_FILTER__THREAD
);
continue
;
}
h
->
filtered
&=
~
(
1
<<
HIST_FILTER__THREAD
);
if
(
!
h
->
filtered
)
{
++
self
->
nr_entries
;
self
->
stats
.
total
+=
h
->
count
;
if
(
h
->
ms
.
sym
&&
self
->
max_sym_namelen
<
h
->
ms
.
sym
->
namelen
)
self
->
max_sym_namelen
=
h
->
ms
.
sym
->
namelen
;
}
}
}
static
int
symbol__alloc_hist
(
struct
symbol
*
self
)
{
struct
sym_priv
*
priv
=
symbol__priv
(
self
);
const
int
size
=
(
sizeof
(
*
priv
->
hist
)
+
(
self
->
end
-
self
->
start
)
*
sizeof
(
u64
));
priv
->
hist
=
zalloc
(
size
);
return
priv
->
hist
==
NULL
?
-
1
:
0
;
}
int
hist_entry__inc_addr_samples
(
struct
hist_entry
*
self
,
u64
ip
)
{
unsigned
int
sym_size
,
offset
;
struct
symbol
*
sym
=
self
->
ms
.
sym
;
struct
sym_priv
*
priv
;
struct
sym_hist
*
h
;
if
(
!
sym
||
!
self
->
ms
.
map
)
return
0
;
priv
=
symbol__priv
(
sym
);
if
(
priv
->
hist
==
NULL
&&
symbol__alloc_hist
(
sym
)
<
0
)
return
-
ENOMEM
;
sym_size
=
sym
->
end
-
sym
->
start
;
offset
=
ip
-
sym
->
start
;
pr_debug3
(
"%s: ip=%#Lx
\n
"
,
__func__
,
self
->
ms
.
map
->
unmap_ip
(
self
->
ms
.
map
,
ip
));
if
(
offset
>=
sym_size
)
return
0
;
h
=
priv
->
hist
;
h
->
sum
++
;
h
->
ip
[
offset
]
++
;
pr_debug3
(
"%#Lx %s: count++ [ip: %#Lx, %#Lx] => %Ld
\n
"
,
self
->
ms
.
sym
->
start
,
self
->
ms
.
sym
->
name
,
ip
,
ip
-
self
->
ms
.
sym
->
start
,
h
->
ip
[
offset
]);
return
0
;
}
static
struct
objdump_line
*
objdump_line__new
(
s64
offset
,
char
*
line
)
{
struct
objdump_line
*
self
=
malloc
(
sizeof
(
*
self
));
if
(
self
!=
NULL
)
{
self
->
offset
=
offset
;
self
->
line
=
line
;
}
return
self
;
}
void
objdump_line__free
(
struct
objdump_line
*
self
)
{
free
(
self
->
line
);
free
(
self
);
}
static
void
objdump__add_line
(
struct
list_head
*
head
,
struct
objdump_line
*
line
)
{
list_add_tail
(
&
line
->
node
,
head
);
}
struct
objdump_line
*
objdump__get_next_ip_line
(
struct
list_head
*
head
,
struct
objdump_line
*
pos
)
{
list_for_each_entry_continue
(
pos
,
head
,
node
)
if
(
pos
->
offset
>=
0
)
return
pos
;
return
NULL
;
}
static
int
hist_entry__parse_objdump_line
(
struct
hist_entry
*
self
,
FILE
*
file
,
struct
list_head
*
head
)
{
struct
symbol
*
sym
=
self
->
ms
.
sym
;
struct
objdump_line
*
objdump_line
;
char
*
line
=
NULL
,
*
tmp
,
*
tmp2
,
*
c
;
size_t
line_len
;
s64
line_ip
,
offset
=
-
1
;
if
(
getline
(
&
line
,
&
line_len
,
file
)
<
0
)
return
-
1
;
if
(
!
line
)
return
-
1
;
while
(
line_len
!=
0
&&
isspace
(
line
[
line_len
-
1
]))
line
[
--
line_len
]
=
'\0'
;
c
=
strchr
(
line
,
'\n'
);
if
(
c
)
*
c
=
0
;
line_ip
=
-
1
;
/*
* Strip leading spaces:
*/
tmp
=
line
;
while
(
*
tmp
)
{
if
(
*
tmp
!=
' '
)
break
;
tmp
++
;
}
if
(
*
tmp
)
{
/*
* Parse hexa addresses followed by ':'
*/
line_ip
=
strtoull
(
tmp
,
&
tmp2
,
16
);
if
(
*
tmp2
!=
':'
)
line_ip
=
-
1
;
}
if
(
line_ip
!=
-
1
)
{
u64
start
=
map__rip_2objdump
(
self
->
ms
.
map
,
sym
->
start
);
offset
=
line_ip
-
start
;
}
objdump_line
=
objdump_line__new
(
offset
,
line
);
if
(
objdump_line
==
NULL
)
{
free
(
line
);
return
-
1
;
}
objdump__add_line
(
head
,
objdump_line
);
return
0
;
}
int
hist_entry__annotate
(
struct
hist_entry
*
self
,
struct
list_head
*
head
)
{
struct
symbol
*
sym
=
self
->
ms
.
sym
;
struct
map
*
map
=
self
->
ms
.
map
;
struct
dso
*
dso
=
map
->
dso
;
const
char
*
filename
=
dso
->
long_name
;
char
command
[
PATH_MAX
*
2
];
FILE
*
file
;
u64
len
;
if
(
!
filename
)
return
-
1
;
if
(
dso
->
origin
==
DSO__ORIG_KERNEL
)
{
if
(
dso
->
annotate_warned
)
return
0
;
dso
->
annotate_warned
=
1
;
pr_err
(
"Can't annotate %s: No vmlinux file was found in the "
"path:
\n
"
,
sym
->
name
);
vmlinux_path__fprintf
(
stderr
);
return
-
1
;
}
pr_debug
(
"%s: filename=%s, sym=%s, start=%#Lx, end=%#Lx
\n
"
,
__func__
,
filename
,
sym
->
name
,
map
->
unmap_ip
(
map
,
sym
->
start
),
map
->
unmap_ip
(
map
,
sym
->
end
));
len
=
sym
->
end
-
sym
->
start
;
pr_debug
(
"annotating [%p] %30s : [%p] %30s
\n
"
,
dso
,
dso
->
long_name
,
sym
,
sym
->
name
);
snprintf
(
command
,
sizeof
(
command
),
"objdump --start-address=0x%016Lx --stop-address=0x%016Lx -dS %s|grep -v %s|expand"
,
map__rip_2objdump
(
map
,
sym
->
start
),
map__rip_2objdump
(
map
,
sym
->
end
),
filename
,
filename
);
pr_debug
(
"Executing: %s
\n
"
,
command
);
file
=
popen
(
command
,
"r"
);
if
(
!
file
)
return
-
1
;
while
(
!
feof
(
file
))
if
(
hist_entry__parse_objdump_line
(
self
,
file
,
head
)
<
0
)
break
;
pclose
(
file
);
return
0
;
}
tools/perf/util/hist.h
View file @
975fc2d5
...
...
@@ -11,6 +11,32 @@ struct addr_location;
struct
symbol
;
struct
rb_root
;
struct
objdump_line
{
struct
list_head
node
;
s64
offset
;
char
*
line
;
};
void
objdump_line__free
(
struct
objdump_line
*
self
);
struct
objdump_line
*
objdump__get_next_ip_line
(
struct
list_head
*
head
,
struct
objdump_line
*
pos
);
struct
sym_hist
{
u64
sum
;
u64
ip
[
0
];
};
struct
sym_ext
{
struct
rb_node
node
;
double
percent
;
char
*
path
;
};
struct
sym_priv
{
struct
sym_hist
*
hist
;
struct
sym_ext
*
ext
;
};
struct
events_stats
{
u64
total
;
u64
lost
;
...
...
@@ -44,4 +70,22 @@ void hists__output_resort(struct hists *self);
void
hists__collapse_resort
(
struct
hists
*
self
);
size_t
hists__fprintf
(
struct
hists
*
self
,
struct
hists
*
pair
,
bool
show_displacement
,
FILE
*
fp
);
int
hist_entry__inc_addr_samples
(
struct
hist_entry
*
self
,
u64
ip
);
int
hist_entry__annotate
(
struct
hist_entry
*
self
,
struct
list_head
*
head
);
void
hists__filter_by_dso
(
struct
hists
*
self
,
const
struct
dso
*
dso
);
void
hists__filter_by_thread
(
struct
hists
*
self
,
const
struct
thread
*
thread
);
#ifdef NO_NEWT_SUPPORT
static
inline
int
hists__browse
(
struct
hists
self
__used
,
const
char
*
helpline
__used
,
const
char
*
input_name
__used
)
{
return
0
;
}
#else
int
hists__browse
(
struct
hists
*
self
,
const
char
*
helpline
,
const
char
*
input_name
);
#endif
#endif
/* __PERF_HIST_H */
tools/perf/util/newt.c
View file @
975fc2d5
...
...
@@ -2,6 +2,7 @@
#include <stdio.h>
#undef _GNU_SOURCE
#include <slang.h>
#include <stdlib.h>
#include <newt.h>
#include <sys/ttydefaults.h>
...
...
@@ -57,6 +58,43 @@ void ui_progress__delete(struct ui_progress *self)
free
(
self
);
}
static
void
ui_helpline__pop
(
void
)
{
newtPopHelpLine
();
}
static
void
ui_helpline__push
(
const
char
*
msg
)
{
newtPushHelpLine
(
msg
);
}
static
void
ui_helpline__vpush
(
const
char
*
fmt
,
va_list
ap
)
{
char
*
s
;
if
(
vasprintf
(
&
s
,
fmt
,
ap
)
<
0
)
vfprintf
(
stderr
,
fmt
,
ap
);
else
{
ui_helpline__push
(
s
);
free
(
s
);
}
}
static
void
ui_helpline__fpush
(
const
char
*
fmt
,
...)
{
va_list
ap
;
va_start
(
ap
,
fmt
);
ui_helpline__vpush
(
fmt
,
ap
);
va_end
(
ap
);
}
static
void
ui_helpline__puts
(
const
char
*
msg
)
{
ui_helpline__pop
();
ui_helpline__push
(
msg
);
}
static
char
browser__last_msg
[
1024
];
int
browser__show_help
(
const
char
*
format
,
va_list
ap
)
...
...
@@ -69,8 +107,7 @@ int browser__show_help(const char *format, va_list ap)
backlog
+=
ret
;
if
(
browser__last_msg
[
backlog
-
1
]
==
'\n'
)
{
newtPopHelpLine
();
newtPushHelpLine
(
browser__last_msg
);
ui_helpline__puts
(
browser__last_msg
);
newtRefresh
();
backlog
=
0
;
}
...
...
@@ -135,6 +172,254 @@ static bool dialog_yesno(const char *msg)
return
newtWinChoice
(
NULL
,
yes
,
no
,
(
char
*
)
msg
)
==
1
;
}
#define HE_COLORSET_TOP 50
#define HE_COLORSET_MEDIUM 51
#define HE_COLORSET_NORMAL 52
#define HE_COLORSET_SELECTED 53
#define HE_COLORSET_CODE 54
static
int
ui_browser__percent_color
(
double
percent
,
bool
current
)
{
if
(
current
)
return
HE_COLORSET_SELECTED
;
if
(
percent
>=
MIN_RED
)
return
HE_COLORSET_TOP
;
if
(
percent
>=
MIN_GREEN
)
return
HE_COLORSET_MEDIUM
;
return
HE_COLORSET_NORMAL
;
}
struct
ui_browser
{
newtComponent
form
,
sb
;
u64
index
,
first_visible_entry_idx
;
void
*
first_visible_entry
,
*
entries
;
u16
top
,
left
,
width
,
height
;
void
*
priv
;
u32
nr_entries
;
};
static
void
ui_browser__refresh_dimensions
(
struct
ui_browser
*
self
)
{
int
cols
,
rows
;
newtGetScreenSize
(
&
cols
,
&
rows
);
if
(
self
->
width
>
cols
-
4
)
self
->
width
=
cols
-
4
;
self
->
height
=
rows
-
5
;
if
(
self
->
height
>
self
->
nr_entries
)
self
->
height
=
self
->
nr_entries
;
self
->
top
=
(
rows
-
self
->
height
)
/
2
;
self
->
left
=
(
cols
-
self
->
width
)
/
2
;
}
static
void
ui_browser__reset_index
(
struct
ui_browser
*
self
)
{
self
->
index
=
self
->
first_visible_entry_idx
=
0
;
self
->
first_visible_entry
=
NULL
;
}
static
int
objdump_line__show
(
struct
objdump_line
*
self
,
struct
list_head
*
head
,
int
width
,
struct
hist_entry
*
he
,
int
len
,
bool
current_entry
)
{
if
(
self
->
offset
!=
-
1
)
{
struct
symbol
*
sym
=
he
->
ms
.
sym
;
unsigned
int
hits
=
0
;
double
percent
=
0
.
0
;
int
color
;
struct
sym_priv
*
priv
=
symbol__priv
(
sym
);
struct
sym_ext
*
sym_ext
=
priv
->
ext
;
struct
sym_hist
*
h
=
priv
->
hist
;
s64
offset
=
self
->
offset
;
struct
objdump_line
*
next
=
objdump__get_next_ip_line
(
head
,
self
);
while
(
offset
<
(
s64
)
len
&&
(
next
==
NULL
||
offset
<
next
->
offset
))
{
if
(
sym_ext
)
{
percent
+=
sym_ext
[
offset
].
percent
;
}
else
hits
+=
h
->
ip
[
offset
];
++
offset
;
}
if
(
sym_ext
==
NULL
&&
h
->
sum
)
percent
=
100
.
0
*
hits
/
h
->
sum
;
color
=
ui_browser__percent_color
(
percent
,
current_entry
);
SLsmg_set_color
(
color
);
SLsmg_printf
(
" %7.2f "
,
percent
);
if
(
!
current_entry
)
SLsmg_set_color
(
HE_COLORSET_CODE
);
}
else
{
int
color
=
ui_browser__percent_color
(
0
,
current_entry
);
SLsmg_set_color
(
color
);
SLsmg_write_nstring
(
" "
,
9
);
}
SLsmg_write_char
(
':'
);
SLsmg_write_nstring
(
" "
,
8
);
if
(
!*
self
->
line
)
SLsmg_write_nstring
(
" "
,
width
-
18
);
else
SLsmg_write_nstring
(
self
->
line
,
width
-
18
);
return
0
;
}
static
int
ui_browser__refresh_entries
(
struct
ui_browser
*
self
)
{
struct
objdump_line
*
pos
;
struct
list_head
*
head
=
self
->
entries
;
struct
hist_entry
*
he
=
self
->
priv
;
int
row
=
0
;
int
len
=
he
->
ms
.
sym
->
end
-
he
->
ms
.
sym
->
start
;
if
(
self
->
first_visible_entry
==
NULL
||
self
->
first_visible_entry
==
self
->
entries
)
self
->
first_visible_entry
=
head
->
next
;
pos
=
list_entry
(
self
->
first_visible_entry
,
struct
objdump_line
,
node
);
list_for_each_entry_from
(
pos
,
head
,
node
)
{
bool
current_entry
=
(
self
->
first_visible_entry_idx
+
row
)
==
self
->
index
;
SLsmg_gotorc
(
self
->
top
+
row
,
self
->
left
);
objdump_line__show
(
pos
,
head
,
self
->
width
,
he
,
len
,
current_entry
);
if
(
++
row
==
self
->
height
)
break
;
}
SLsmg_set_color
(
HE_COLORSET_NORMAL
);
SLsmg_fill_region
(
self
->
top
+
row
,
self
->
left
,
self
->
height
-
row
,
self
->
width
,
' '
);
return
0
;
}
static
int
ui_browser__run
(
struct
ui_browser
*
self
,
const
char
*
title
,
struct
newtExitStruct
*
es
)
{
if
(
self
->
form
)
{
newtFormDestroy
(
self
->
form
);
newtPopWindow
();
}
ui_browser__refresh_dimensions
(
self
);
newtCenteredWindow
(
self
->
width
+
2
,
self
->
height
,
title
);
self
->
form
=
newt_form__new
();
if
(
self
->
form
==
NULL
)
return
-
1
;
self
->
sb
=
newtVerticalScrollbar
(
self
->
width
+
1
,
0
,
self
->
height
,
HE_COLORSET_NORMAL
,
HE_COLORSET_SELECTED
);
if
(
self
->
sb
==
NULL
)
return
-
1
;
newtFormAddHotKey
(
self
->
form
,
NEWT_KEY_UP
);
newtFormAddHotKey
(
self
->
form
,
NEWT_KEY_DOWN
);
newtFormAddHotKey
(
self
->
form
,
NEWT_KEY_PGUP
);
newtFormAddHotKey
(
self
->
form
,
NEWT_KEY_PGDN
);
newtFormAddHotKey
(
self
->
form
,
NEWT_KEY_HOME
);
newtFormAddHotKey
(
self
->
form
,
NEWT_KEY_END
);
if
(
ui_browser__refresh_entries
(
self
)
<
0
)
return
-
1
;
newtFormAddComponent
(
self
->
form
,
self
->
sb
);
while
(
1
)
{
unsigned
int
offset
;
newtFormRun
(
self
->
form
,
es
);
if
(
es
->
reason
!=
NEWT_EXIT_HOTKEY
)
break
;
switch
(
es
->
u
.
key
)
{
case
NEWT_KEY_DOWN
:
if
(
self
->
index
==
self
->
nr_entries
-
1
)
break
;
++
self
->
index
;
if
(
self
->
index
==
self
->
first_visible_entry_idx
+
self
->
height
)
{
struct
list_head
*
pos
=
self
->
first_visible_entry
;
++
self
->
first_visible_entry_idx
;
self
->
first_visible_entry
=
pos
->
next
;
}
break
;
case
NEWT_KEY_UP
:
if
(
self
->
index
==
0
)
break
;
--
self
->
index
;
if
(
self
->
index
<
self
->
first_visible_entry_idx
)
{
struct
list_head
*
pos
=
self
->
first_visible_entry
;
--
self
->
first_visible_entry_idx
;
self
->
first_visible_entry
=
pos
->
prev
;
}
break
;
case
NEWT_KEY_PGDN
:
if
(
self
->
first_visible_entry_idx
+
self
->
height
>
self
->
nr_entries
-
1
)
break
;
offset
=
self
->
height
;
if
(
self
->
index
+
offset
>
self
->
nr_entries
-
1
)
offset
=
self
->
nr_entries
-
1
-
self
->
index
;
self
->
index
+=
offset
;
self
->
first_visible_entry_idx
+=
offset
;
while
(
offset
--
)
{
struct
list_head
*
pos
=
self
->
first_visible_entry
;
self
->
first_visible_entry
=
pos
->
next
;
}
break
;
case
NEWT_KEY_PGUP
:
if
(
self
->
first_visible_entry_idx
==
0
)
break
;
if
(
self
->
first_visible_entry_idx
<
self
->
height
)
offset
=
self
->
first_visible_entry_idx
;
else
offset
=
self
->
height
;
self
->
index
-=
offset
;
self
->
first_visible_entry_idx
-=
offset
;
while
(
offset
--
)
{
struct
list_head
*
pos
=
self
->
first_visible_entry
;
self
->
first_visible_entry
=
pos
->
prev
;
}
break
;
case
NEWT_KEY_HOME
:
ui_browser__reset_index
(
self
);
break
;
case
NEWT_KEY_END
:
{
struct
list_head
*
head
=
self
->
entries
;
offset
=
self
->
height
-
1
;
if
(
offset
>
self
->
nr_entries
)
offset
=
self
->
nr_entries
;
self
->
index
=
self
->
first_visible_entry_idx
=
self
->
nr_entries
-
1
-
offset
;
self
->
first_visible_entry
=
head
->
prev
;
while
(
offset
--
!=
0
)
{
struct
list_head
*
pos
=
self
->
first_visible_entry
;
self
->
first_visible_entry
=
pos
->
prev
;
}
}
break
;
case
NEWT_KEY_ESCAPE
:
case
CTRL
(
'c'
):
case
'Q'
:
case
'q'
:
return
0
;
default:
continue
;
}
if
(
ui_browser__refresh_entries
(
self
)
<
0
)
return
-
1
;
}
return
0
;
}
/*
* When debugging newt problems it was useful to be able to "unroll"
* the calls to newtCheckBoxTreeAdd{Array,Item}, so that we can generate
...
...
@@ -317,62 +602,40 @@ static size_t hist_entry__append_browser(struct hist_entry *self,
return
ret
;
}
static
void
map_symbol__annotate_browser
(
const
struct
map_symbol
*
self
,
const
char
*
input_name
)
static
void
hist_entry__annotate_browser
(
struct
hist_entry
*
self
)
{
FILE
*
fp
;
int
cols
,
rows
;
newtComponent
form
,
tree
;
struct
ui_browser
browser
;
struct
newtExitStruct
es
;
char
*
str
;
size_t
line_len
,
max_line_len
=
0
;
size_t
max_usable_width
;
char
*
line
=
NULL
;
struct
objdump_line
*
pos
,
*
n
;
LIST_HEAD
(
head
);
if
(
self
->
sym
==
NULL
)
if
(
self
->
ms
.
sym
==
NULL
)
return
;
if
(
asprintf
(
&
str
,
"perf annotate -i
\"
%s
\"
-d
\"
%s
\"
%s 2>&1 | expand"
,
input_name
,
self
->
map
->
dso
->
name
,
self
->
sym
->
name
)
<
0
)
if
(
hist_entry__annotate
(
self
,
&
head
)
<
0
)
return
;
fp
=
popen
(
str
,
"r"
);
if
(
fp
==
NULL
)
goto
out_free_str
;
newtPushHelpLine
(
"Press ESC to exit"
);
newtGetScreenSize
(
&
cols
,
&
rows
);
tree
=
newtListbox
(
0
,
0
,
rows
-
5
,
NEWT_FLAG_SCROLL
);
while
(
!
feof
(
fp
))
{
if
(
getline
(
&
line
,
&
line_len
,
fp
)
<
0
||
!
line_len
)
break
;
while
(
line_len
!=
0
&&
isspace
(
line
[
line_len
-
1
]))
line
[
--
line_len
]
=
'\0'
;
ui_helpline__push
(
"Press ESC to exit"
);
if
(
line_len
>
max_line_len
)
max_line_len
=
line_len
;
newtListboxAppendEntry
(
tree
,
line
,
NULL
);
memset
(
&
browser
,
0
,
sizeof
(
browser
));
browser
.
entries
=
&
head
;
browser
.
priv
=
self
;
list_for_each_entry
(
pos
,
&
head
,
node
)
{
size_t
line_len
=
strlen
(
pos
->
line
);
if
(
browser
.
width
<
line_len
)
browser
.
width
=
line_len
;
++
browser
.
nr_entries
;
}
fclose
(
fp
);
free
(
line
);
max_usable_width
=
cols
-
22
;
if
(
max_line_len
>
max_usable_width
)
max_line_len
=
max_usable_width
;
newtListboxSetWidth
(
tree
,
max_line_len
);
newtCenteredWindow
(
max_line_len
+
2
,
rows
-
5
,
self
->
sym
->
name
);
form
=
newt_form__new
();
newtFormAddComponent
(
form
,
tree
);
newtFormRun
(
form
,
&
es
);
newtFormDestroy
(
form
);
browser
.
width
+=
18
;
/* Percentage */
ui_browser__run
(
&
browser
,
self
->
ms
.
sym
->
name
,
&
es
);
newtFormDestroy
(
browser
.
form
);
newtPopWindow
();
newtPopHelpLine
();
out_free_str:
free
(
str
);
list_for_each_entry_safe
(
pos
,
n
,
&
head
,
node
)
{
list_del
(
&
pos
->
node
);
objdump_line__free
(
pos
);
}
ui_helpline__pop
();
}
static
const
void
*
newt__symbol_tree_get_current
(
newtComponent
self
)
...
...
@@ -410,8 +673,8 @@ static void hist_browser__delete(struct hist_browser *self)
free
(
self
);
}
static
int
hist_browser__populate
(
struct
hist_browser
*
self
,
struct
rb_root
*
hists
,
u64
nr_hists
,
u64
session_total
,
const
char
*
title
)
static
int
hist_browser__populate
(
struct
hist_browser
*
self
,
struct
hists
*
hists
,
const
char
*
title
)
{
int
max_len
=
0
,
idx
,
cols
,
rows
;
struct
ui_progress
*
progress
;
...
...
@@ -426,7 +689,7 @@ static int hist_browser__populate(struct hist_browser *self, struct rb_root *his
}
snprintf
(
str
,
sizeof
(
str
),
"Samples: %Ld "
,
session_
total
);
hists
->
stats
.
total
);
newtDrawRootText
(
0
,
0
,
str
);
newtGetScreenSize
(
NULL
,
&
rows
);
...
...
@@ -442,24 +705,25 @@ static int hist_browser__populate(struct hist_browser *self, struct rb_root *his
newtComponentAddCallback
(
self
->
tree
,
hist_browser__selection
,
&
self
->
selection
);
progress
=
ui_progress__new
(
"Adding entries to the browser..."
,
nr_hists
);
progress
=
ui_progress__new
(
"Adding entries to the browser..."
,
hists
->
nr_entries
);
if
(
progress
==
NULL
)
return
-
1
;
idx
=
0
;
for
(
nd
=
rb_first
(
hist
s
);
nd
;
nd
=
rb_next
(
nd
))
{
for
(
nd
=
rb_first
(
&
hists
->
entrie
s
);
nd
;
nd
=
rb_next
(
nd
))
{
struct
hist_entry
*
h
=
rb_entry
(
nd
,
struct
hist_entry
,
rb_node
);
int
len
;
if
(
h
->
filtered
)
continue
;
len
=
hist_entry__append_browser
(
h
,
self
->
tree
,
session_
total
);
len
=
hist_entry__append_browser
(
h
,
self
->
tree
,
hists
->
stats
.
total
);
if
(
len
>
max_len
)
max_len
=
len
;
if
(
symbol_conf
.
use_callchain
)
hist_entry__append_callchain_browser
(
h
,
self
->
tree
,
session_
total
,
idx
++
);
hists
->
stats
.
total
,
idx
++
);
++
curr_hist
;
if
(
curr_hist
%
5
)
ui_progress__update
(
progress
,
curr_hist
);
...
...
@@ -490,58 +754,7 @@ static int hist_browser__populate(struct hist_browser *self, struct rb_root *his
return
0
;
}
enum
hist_filter
{
HIST_FILTER__DSO
,
HIST_FILTER__THREAD
,
};
static
u64
hists__filter_by_dso
(
struct
rb_root
*
hists
,
const
struct
dso
*
dso
,
u64
*
session_total
)
{
struct
rb_node
*
nd
;
u64
nr_hists
=
0
;
*
session_total
=
0
;
for
(
nd
=
rb_first
(
hists
);
nd
;
nd
=
rb_next
(
nd
))
{
struct
hist_entry
*
h
=
rb_entry
(
nd
,
struct
hist_entry
,
rb_node
);
if
(
dso
!=
NULL
&&
(
h
->
ms
.
map
==
NULL
||
h
->
ms
.
map
->
dso
!=
dso
))
{
h
->
filtered
|=
(
1
<<
HIST_FILTER__DSO
);
continue
;
}
h
->
filtered
&=
~
(
1
<<
HIST_FILTER__DSO
);
++
nr_hists
;
*
session_total
+=
h
->
count
;
}
return
nr_hists
;
}
static
u64
hists__filter_by_thread
(
struct
rb_root
*
hists
,
const
struct
thread
*
thread
,
u64
*
session_total
)
{
struct
rb_node
*
nd
;
u64
nr_hists
=
0
;
*
session_total
=
0
;
for
(
nd
=
rb_first
(
hists
);
nd
;
nd
=
rb_next
(
nd
))
{
struct
hist_entry
*
h
=
rb_entry
(
nd
,
struct
hist_entry
,
rb_node
);
if
(
thread
!=
NULL
&&
h
->
thread
!=
thread
)
{
h
->
filtered
|=
(
1
<<
HIST_FILTER__THREAD
);
continue
;
}
h
->
filtered
&=
~
(
1
<<
HIST_FILTER__THREAD
);
++
nr_hists
;
*
session_total
+=
h
->
count
;
}
return
nr_hists
;
}
static
struct
thread
*
hist_browser__selected_thread
(
struct
hist_browser
*
self
)
static
struct
hist_entry
*
hist_browser__selected_entry
(
struct
hist_browser
*
self
)
{
int
*
indexes
;
...
...
@@ -557,7 +770,13 @@ static struct thread *hist_browser__selected_thread(struct hist_browser *self)
}
return
NULL
;
out:
return
*
(
struct
thread
**
)(
self
->
selection
+
1
);
return
container_of
(
self
->
selection
,
struct
hist_entry
,
ms
);
}
static
struct
thread
*
hist_browser__selected_thread
(
struct
hist_browser
*
self
)
{
struct
hist_entry
*
he
=
hist_browser__selected_entry
(
self
);
return
he
?
he
->
thread
:
NULL
;
}
static
int
hist_browser__title
(
char
*
bf
,
size_t
size
,
const
char
*
input_name
,
...
...
@@ -577,9 +796,7 @@ static int hist_browser__title(char *bf, size_t size, const char *input_name,
return
printed
?:
snprintf
(
bf
,
size
,
"Report: %s"
,
input_name
);
}
int
perf_session__browse_hists
(
struct
rb_root
*
hists
,
u64
nr_hists
,
u64
session_total
,
const
char
*
helpline
,
const
char
*
input_name
)
int
hists__browse
(
struct
hists
*
self
,
const
char
*
helpline
,
const
char
*
input_name
)
{
struct
hist_browser
*
browser
=
hist_browser__new
();
const
struct
thread
*
thread_filter
=
NULL
;
...
...
@@ -591,11 +808,11 @@ int perf_session__browse_hists(struct rb_root *hists, u64 nr_hists,
if
(
browser
==
NULL
)
return
-
1
;
newtPushHelpLine
(
helpline
);
ui_helpline__push
(
helpline
);
hist_browser__title
(
msg
,
sizeof
(
msg
),
input_name
,
dso_filter
,
thread_filter
);
if
(
hist_browser__populate
(
browser
,
hists
,
nr_hists
,
session_total
,
msg
)
<
0
)
if
(
hist_browser__populate
(
browser
,
self
,
msg
)
<
0
)
goto
out
;
while
(
1
)
{
...
...
@@ -653,46 +870,48 @@ int perf_session__browse_hists(struct rb_root *hists, u64 nr_hists,
continue
;
do_annotate:
if
(
choice
==
annotate
)
{
struct
hist_entry
*
he
;
if
(
browser
->
selection
->
map
->
dso
->
origin
==
DSO__ORIG_KERNEL
)
{
newtPopHelpLine
();
newtPushHelpLine
(
"No vmlinux file found, can't "
ui_helpline__puts
(
"No vmlinux file found, can't "
"annotate with just a "
"kallsyms file"
);
continue
;
}
map_symbol__annotate_browser
(
browser
->
selection
,
input_name
);
he
=
hist_browser__selected_entry
(
browser
);
if
(
he
==
NULL
)
continue
;
hist_entry__annotate_browser
(
he
);
}
else
if
(
choice
==
zoom_dso
)
{
if
(
dso_filter
)
{
newtPopHelpLine
();
ui_helpline__pop
();
dso_filter
=
NULL
;
}
else
{
snprintf
(
msg
,
sizeof
(
msg
),
"To zoom out press -> +
\"
Zoom out of %s DSO
\"
"
,
ui_helpline__fpush
(
"To zoom out press -> +
\"
Zoom out of %s DSO
\"
"
,
dso
->
kernel
?
"the Kernel"
:
dso
->
short_name
);
newtPushHelpLine
(
msg
);
dso_filter
=
dso
;
}
nr_hists
=
hists__filter_by_dso
(
hists
,
dso_filter
,
&
session_total
);
hists__filter_by_dso
(
self
,
dso_filter
);
hist_browser__title
(
msg
,
sizeof
(
msg
),
input_name
,
dso_filter
,
thread_filter
);
if
(
hist_browser__populate
(
browser
,
hists
,
nr_hists
,
session_total
,
msg
)
<
0
)
if
(
hist_browser__populate
(
browser
,
self
,
msg
)
<
0
)
goto
out
;
}
else
if
(
choice
==
zoom_thread
)
{
if
(
thread_filter
)
{
newtPopHelpLine
();
ui_helpline__pop
();
thread_filter
=
NULL
;
}
else
{
snprintf
(
msg
,
sizeof
(
msg
),
"To zoom out press -> +
\"
Zoom out of %s(%d) thread
\"
"
,
(
thread
->
comm_set
?
thread
->
comm
:
""
),
ui_helpline__fpush
(
"To zoom out press -> +
\"
Zoom out of %s(%d) thread
\"
"
,
thread
->
comm_set
?
thread
->
comm
:
""
,
thread
->
pid
);
newtPushHelpLine
(
msg
);
thread_filter
=
thread
;
}
nr_hists
=
hists__filter_by_thread
(
hists
,
thread_filter
,
&
session_total
);
hists__filter_by_thread
(
self
,
thread_filter
);
hist_browser__title
(
msg
,
sizeof
(
msg
),
input_name
,
dso_filter
,
thread_filter
);
if
(
hist_browser__populate
(
browser
,
hists
,
nr_hists
,
session_total
,
msg
)
<
0
)
if
(
hist_browser__populate
(
browser
,
self
,
msg
)
<
0
)
goto
out
;
}
}
...
...
@@ -702,15 +921,35 @@ int perf_session__browse_hists(struct rb_root *hists, u64 nr_hists,
return
err
;
}
static
struct
newtPercentTreeColors
{
const
char
*
topColorFg
,
*
topColorBg
;
const
char
*
mediumColorFg
,
*
mediumColorBg
;
const
char
*
normalColorFg
,
*
normalColorBg
;
const
char
*
selColorFg
,
*
selColorBg
;
const
char
*
codeColorFg
,
*
codeColorBg
;
}
defaultPercentTreeColors
=
{
"red"
,
"lightgray"
,
"green"
,
"lightgray"
,
"black"
,
"lightgray"
,
"lightgray"
,
"magenta"
,
"blue"
,
"lightgray"
,
};
void
setup_browser
(
void
)
{
struct
newtPercentTreeColors
*
c
=
&
defaultPercentTreeColors
;
if
(
!
isatty
(
1
))
return
;
use_browser
=
true
;
newtInit
();
newtCls
();
newtPushHelpLine
(
" "
);
ui_helpline__puts
(
" "
);
SLtt_set_color
(
HE_COLORSET_TOP
,
NULL
,
c
->
topColorFg
,
c
->
topColorBg
);
SLtt_set_color
(
HE_COLORSET_MEDIUM
,
NULL
,
c
->
mediumColorFg
,
c
->
mediumColorBg
);
SLtt_set_color
(
HE_COLORSET_NORMAL
,
NULL
,
c
->
normalColorFg
,
c
->
normalColorBg
);
SLtt_set_color
(
HE_COLORSET_SELECTED
,
NULL
,
c
->
selColorFg
,
c
->
selColorBg
);
SLtt_set_color
(
HE_COLORSET_CODE
,
NULL
,
c
->
codeColorFg
,
c
->
codeColorBg
);
}
void
exit_browser
(
bool
wait_for_ok
)
...
...
tools/perf/util/session.h
View file @
975fc2d5
...
...
@@ -102,21 +102,6 @@ int perf_session__create_kernel_maps(struct perf_session *self);
int
do_read
(
int
fd
,
void
*
buf
,
size_t
size
);
void
perf_session__update_sample_type
(
struct
perf_session
*
self
);
#ifdef NO_NEWT_SUPPORT
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
*
input_name
__used
)
{
return
0
;
}
#else
int
perf_session__browse_hists
(
struct
rb_root
*
hists
,
u64
nr_hists
,
u64
session_total
,
const
char
*
helpline
,
const
char
*
input_name
);
#endif
static
inline
struct
machine
*
perf_session__find_host_machine
(
struct
perf_session
*
self
)
{
...
...
tools/perf/util/sort.h
View file @
975fc2d5
...
...
@@ -48,12 +48,6 @@ struct hist_entry {
u64
count_us
;
u64
count_guest_sys
;
u64
count_guest_us
;
/*
* XXX WARNING!
* thread _has_ to come after ms, see
* hist_browser__selected_thread in util/newt.c
*/
struct
map_symbol
ms
;
struct
thread
*
thread
;
u64
ip
;
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment