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
c73a3cb3
Commit
c73a3cb3
authored
Oct 15, 2011
by
Ingo Molnar
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'perf/core' of
git://github.com/acmel/linux
into perf/core
parents
910e94dd
6c3c5b26
Changes
13
Hide whitespace changes
Inline
Side-by-side
Showing
13 changed files
with
375 additions
and
165 deletions
+375
-165
tools/perf/builtin-top.c
tools/perf/builtin-top.c
+20
-5
tools/perf/perf.c
tools/perf/perf.c
+24
-0
tools/perf/perf.h
tools/perf/perf.h
+2
-0
tools/perf/util/header.c
tools/perf/util/header.c
+1
-1
tools/perf/util/hist.c
tools/perf/util/hist.c
+20
-4
tools/perf/util/hist.h
tools/perf/util/hist.h
+8
-3
tools/perf/util/sort.h
tools/perf/util/sort.h
+1
-0
tools/perf/util/ui/browser.c
tools/perf/util/ui/browser.c
+155
-73
tools/perf/util/ui/browser.h
tools/perf/util/ui/browser.h
+5
-5
tools/perf/util/ui/browsers/annotate.c
tools/perf/util/ui/browsers/annotate.c
+78
-17
tools/perf/util/ui/browsers/hists.c
tools/perf/util/ui/browsers/hists.c
+57
-53
tools/perf/util/ui/browsers/map.c
tools/perf/util/ui/browsers/map.c
+2
-4
tools/perf/util/ui/helpline.h
tools/perf/util/ui/helpline.h
+2
-0
No files found.
tools/perf/builtin-top.c
View file @
c73a3cb3
...
...
@@ -304,7 +304,7 @@ static void print_sym_table(void)
hists__collapse_resort_threaded
(
&
top
.
sym_evsel
->
hists
);
hists__output_resort_threaded
(
&
top
.
sym_evsel
->
hists
);
hists__decay_entries
(
&
top
.
sym_evsel
->
hists
);
hists__decay_entries
_threaded
(
&
top
.
sym_evsel
->
hists
);
hists__output_recalc_col_len
(
&
top
.
sym_evsel
->
hists
,
winsize
.
ws_row
-
3
);
putchar
(
'\n'
);
hists__fprintf
(
&
top
.
sym_evsel
->
hists
,
NULL
,
false
,
false
,
...
...
@@ -555,7 +555,7 @@ static void perf_top__sort_new_samples(void *arg)
hists__collapse_resort_threaded
(
&
t
->
sym_evsel
->
hists
);
hists__output_resort_threaded
(
&
t
->
sym_evsel
->
hists
);
hists__decay_entries
(
&
t
->
sym_evsel
->
hists
);
hists__decay_entries
_threaded
(
&
t
->
sym_evsel
->
hists
);
hists__output_recalc_col_len
(
&
t
->
sym_evsel
->
hists
,
winsize
.
ws_row
-
3
);
}
...
...
@@ -585,16 +585,31 @@ static void *display_thread(void *arg __used)
tc
.
c_cc
[
VMIN
]
=
0
;
tc
.
c_cc
[
VTIME
]
=
0
;
pthread__unblock_sigwinch
();
repeat:
delay_msecs
=
top
.
delay_secs
*
1000
;
tcsetattr
(
0
,
TCSANOW
,
&
tc
);
/* trash return*/
getc
(
stdin
);
do
{
while
(
1
)
{
print_sym_table
();
}
while
(
!
poll
(
&
stdin_poll
,
1
,
delay_msecs
)
==
1
);
/*
* Either timeout expired or we got an EINTR due to SIGWINCH,
* refresh screen in both cases.
*/
switch
(
poll
(
&
stdin_poll
,
1
,
delay_msecs
))
{
case
0
:
continue
;
case
-
1
:
if
(
errno
==
EINTR
)
continue
;
/* Fall trhu */
default:
goto
process_hotkey
;
}
}
process_hotkey:
c
=
getc
(
stdin
);
tcsetattr
(
0
,
TCSAFLUSH
,
&
save
);
...
...
tools/perf/perf.c
View file @
c73a3cb3
...
...
@@ -427,6 +427,24 @@ static void get_debugfs_mntpt(void)
debugfs_mntpt
[
0
]
=
'\0'
;
}
static
void
pthread__block_sigwinch
(
void
)
{
sigset_t
set
;
sigemptyset
(
&
set
);
sigaddset
(
&
set
,
SIGWINCH
);
pthread_sigmask
(
SIG_BLOCK
,
&
set
,
NULL
);
}
void
pthread__unblock_sigwinch
(
void
)
{
sigset_t
set
;
sigemptyset
(
&
set
);
sigaddset
(
&
set
,
SIGWINCH
);
pthread_sigmask
(
SIG_UNBLOCK
,
&
set
,
NULL
);
}
int
main
(
int
argc
,
const
char
**
argv
)
{
const
char
*
cmd
;
...
...
@@ -480,6 +498,12 @@ int main(int argc, const char **argv)
* time.
*/
setup_path
();
/*
* Block SIGWINCH notifications so that the thread that wants it can
* unblock and get syscalls like select interrupted instead of waiting
* forever while the signal goes to some other non interested thread.
*/
pthread__block_sigwinch
();
while
(
1
)
{
static
int
done_help
;
...
...
tools/perf/perf.h
View file @
c73a3cb3
...
...
@@ -183,4 +183,6 @@ struct ip_callchain {
extern
bool
perf_host
,
perf_guest
;
extern
const
char
perf_version_string
[];
void
pthread__unblock_sigwinch
(
void
);
#endif
tools/perf/util/header.c
View file @
c73a3cb3
...
...
@@ -1289,7 +1289,7 @@ int build_id_cache__remove_s(const char *sbuild_id, const char *debugdir)
if
(
access
(
linkname
,
F_OK
))
goto
out_free
;
if
(
readlink
(
linkname
,
filename
,
size
)
<
0
)
if
(
readlink
(
linkname
,
filename
,
size
-
1
)
<
0
)
goto
out_free
;
if
(
unlink
(
linkname
))
...
...
tools/perf/util/hist.c
View file @
c73a3cb3
...
...
@@ -100,13 +100,15 @@ static void hist_entry__decay(struct hist_entry *he)
static
bool
hists__decay_entry
(
struct
hists
*
hists
,
struct
hist_entry
*
he
)
{
if
(
he
->
period
==
0
)
return
true
;
hists
->
stats
.
total_period
-=
he
->
period
;
hist_entry__decay
(
he
);
hists
->
stats
.
total_period
+=
he
->
period
;
return
he
->
period
==
0
;
}
void
hists__decay_entries
(
struct
hists
*
hists
)
static
void
__hists__decay_entries
(
struct
hists
*
hists
,
bool
threaded
)
{
struct
rb_node
*
next
=
rb_first
(
&
hists
->
entries
);
struct
hist_entry
*
n
;
...
...
@@ -114,11 +116,15 @@ void hists__decay_entries(struct hists *hists)
while
(
next
)
{
n
=
rb_entry
(
next
,
struct
hist_entry
,
rb_node
);
next
=
rb_next
(
&
n
->
rb_node
);
if
(
hists__decay_entry
(
hists
,
n
))
{
/*
* We may be annotating this, for instance, so keep it here in
* case some it gets new samples, we'll eventually free it when
* the user stops browsing and it agains gets fully decayed.
*/
if
(
hists__decay_entry
(
hists
,
n
)
&&
!
n
->
used
)
{
rb_erase
(
&
n
->
rb_node
,
&
hists
->
entries
);
if
(
sort__need_collapse
)
if
(
sort__need_collapse
||
threaded
)
rb_erase
(
&
n
->
rb_node_in
,
&
hists
->
entries_collapsed
);
hist_entry__free
(
n
);
...
...
@@ -127,6 +133,16 @@ void hists__decay_entries(struct hists *hists)
}
}
void
hists__decay_entries
(
struct
hists
*
hists
)
{
return
__hists__decay_entries
(
hists
,
false
);
}
void
hists__decay_entries_threaded
(
struct
hists
*
hists
)
{
return
__hists__decay_entries
(
hists
,
true
);
}
/*
* histogram, sorted on item, collects periods
*/
...
...
tools/perf/util/hist.h
View file @
c73a3cb3
...
...
@@ -79,6 +79,7 @@ void hists__collapse_resort(struct hists *self);
void
hists__collapse_resort_threaded
(
struct
hists
*
hists
);
void
hists__decay_entries
(
struct
hists
*
hists
);
void
hists__decay_entries_threaded
(
struct
hists
*
hists
);
void
hists__output_recalc_col_len
(
struct
hists
*
hists
,
int
max_rows
);
void
hists__inc_nr_events
(
struct
hists
*
self
,
u32
type
);
...
...
@@ -103,16 +104,20 @@ struct perf_evlist;
#ifdef NO_NEWT_SUPPORT
static
inline
int
perf_evlist__tui_browse_hists
(
struct
perf_evlist
*
evlist
__used
,
const
char
*
help
__used
,
void
(
*
timer
)(
void
*
arg
)
__used
,
void
*
arg
,
const
char
*
help
__used
,
void
(
*
timer
)(
void
*
arg
)
__used
,
void
*
arg
__used
,
int
refresh
__used
)
{
return
0
;
}
static
inline
int
hist_entry__tui_annotate
(
struct
hist_entry
*
self
__used
,
int
evidx
__used
,
int
nr_events
__used
,
int
evidx
__used
,
int
nr_events
__used
,
void
(
*
timer
)(
void
*
arg
)
__used
,
void
*
arg
__used
,
int
delay_secs
__used
);
void
*
arg
__used
,
int
delay_secs
__used
)
{
return
0
;
}
...
...
tools/perf/util/sort.h
View file @
c73a3cb3
...
...
@@ -64,6 +64,7 @@ struct hist_entry {
bool
init_have_children
;
char
level
;
bool
used
;
u8
filtered
;
struct
symbol
*
parent
;
union
{
...
...
tools/perf/util/ui/browser.c
View file @
c73a3cb3
#include "../util.h"
#include "../../perf.h"
#include "libslang.h"
#include <newt.h>
#include "ui.h"
#include <linux/compiler.h>
#include <linux/list.h>
...
...
@@ -8,8 +11,8 @@
#include "browser.h"
#include "helpline.h"
#include "../color.h"
#include "../util.h"
#include <stdio.h>
int
newtGetKey
(
void
);
static
int
ui_browser__percent_color
(
double
percent
,
bool
current
)
{
...
...
@@ -39,31 +42,62 @@ void ui_browser__gotorc(struct ui_browser *self, int y, int x)
SLsmg_gotorc
(
self
->
y
+
y
,
self
->
x
+
x
);
}
static
struct
list_head
*
ui_browser__list_head_filter_entries
(
struct
ui_browser
*
browser
,
struct
list_head
*
pos
)
{
do
{
if
(
!
browser
->
filter
||
!
browser
->
filter
(
browser
,
pos
))
return
pos
;
pos
=
pos
->
next
;
}
while
(
pos
!=
browser
->
entries
);
return
NULL
;
}
static
struct
list_head
*
ui_browser__list_head_filter_prev_entries
(
struct
ui_browser
*
browser
,
struct
list_head
*
pos
)
{
do
{
if
(
!
browser
->
filter
||
!
browser
->
filter
(
browser
,
pos
))
return
pos
;
pos
=
pos
->
prev
;
}
while
(
pos
!=
browser
->
entries
);
return
NULL
;
}
void
ui_browser__list_head_seek
(
struct
ui_browser
*
self
,
off_t
offset
,
int
whence
)
{
struct
list_head
*
head
=
self
->
entries
;
struct
list_head
*
pos
;
if
(
self
->
nr_entries
==
0
)
return
;
switch
(
whence
)
{
case
SEEK_SET
:
pos
=
head
->
next
;
pos
=
ui_browser__list_head_filter_entries
(
self
,
head
->
next
)
;
break
;
case
SEEK_CUR
:
pos
=
self
->
top
;
break
;
case
SEEK_END
:
pos
=
head
->
prev
;
pos
=
ui_browser__list_head_filter_prev_entries
(
self
,
head
->
prev
)
;
break
;
default:
return
;
}
assert
(
pos
!=
NULL
);
if
(
offset
>
0
)
{
while
(
offset
--
!=
0
)
pos
=
pos
->
next
;
pos
=
ui_browser__list_head_filter_entries
(
self
,
pos
->
next
)
;
}
else
{
while
(
offset
++
!=
0
)
pos
=
pos
->
prev
;
pos
=
ui_browser__list_head_filter_prev_entries
(
self
,
pos
->
prev
)
;
}
self
->
top
=
pos
;
...
...
@@ -127,11 +161,8 @@ bool ui_browser__is_current_entry(struct ui_browser *self, unsigned row)
void
ui_browser__refresh_dimensions
(
struct
ui_browser
*
self
)
{
int
cols
,
rows
;
newtGetScreenSize
(
&
cols
,
&
rows
);
self
->
width
=
cols
-
1
;
self
->
height
=
rows
-
2
;
self
->
width
=
SLtt_Screen_Cols
-
1
;
self
->
height
=
SLtt_Screen_Rows
-
2
;
self
->
y
=
1
;
self
->
x
=
0
;
}
...
...
@@ -142,26 +173,11 @@ void ui_browser__reset_index(struct ui_browser *self)
self
->
seek
(
self
,
0
,
SEEK_SET
);
}
void
ui_browser__add_exit_key
(
struct
ui_browser
*
self
,
int
key
)
{
newtFormAddHotKey
(
self
->
form
,
key
);
}
void
ui_browser__add_exit_keys
(
struct
ui_browser
*
self
,
int
keys
[])
{
int
i
=
0
;
while
(
keys
[
i
]
&&
i
<
64
)
{
ui_browser__add_exit_key
(
self
,
keys
[
i
]);
++
i
;
}
}
void
__ui_browser__show_title
(
struct
ui_browser
*
browser
,
const
char
*
title
)
{
SLsmg_gotorc
(
0
,
0
);
ui_browser__set_color
(
browser
,
NEWT_COLORSET_ROOT
);
slsmg_write_nstring
(
title
,
browser
->
width
);
slsmg_write_nstring
(
title
,
browser
->
width
+
1
);
}
void
ui_browser__show_title
(
struct
ui_browser
*
browser
,
const
char
*
title
)
...
...
@@ -174,77 +190,143 @@ void ui_browser__show_title(struct ui_browser *browser, const char *title)
int
ui_browser__show
(
struct
ui_browser
*
self
,
const
char
*
title
,
const
char
*
helpline
,
...)
{
int
err
;
va_list
ap
;
int
keys
[]
=
{
NEWT_KEY_UP
,
NEWT_KEY_DOWN
,
NEWT_KEY_PGUP
,
NEWT_KEY_PGDN
,
NEWT_KEY_HOME
,
NEWT_KEY_END
,
' '
,
NEWT_KEY_LEFT
,
NEWT_KEY_ESCAPE
,
'q'
,
CTRL
(
'c'
),
0
};
if
(
self
->
form
!=
NULL
)
newtFormDestroy
(
self
->
form
);
ui_browser__refresh_dimensions
(
self
);
self
->
form
=
newtForm
(
NULL
,
NULL
,
0
);
if
(
self
->
form
==
NULL
)
return
-
1
;
self
->
sb
=
newtVerticalScrollbar
(
self
->
width
,
1
,
self
->
height
,
HE_COLORSET_NORMAL
,
HE_COLORSET_SELECTED
);
if
(
self
->
sb
==
NULL
)
return
-
1
;
pthread_mutex_lock
(
&
ui__lock
);
__ui_browser__show_title
(
self
,
title
);
ui_browser__add_exit_keys
(
self
,
keys
);
newtFormAddComponent
(
self
->
form
,
self
->
sb
);
self
->
title
=
title
;
free
(
self
->
helpline
);
self
->
helpline
=
NULL
;
va_start
(
ap
,
helpline
);
ui_helpline__vpush
(
helpline
,
ap
);
err
=
vasprintf
(
&
self
->
helpline
,
helpline
,
ap
);
va_end
(
ap
);
if
(
err
>
0
)
ui_helpline__push
(
self
->
helpline
);
pthread_mutex_unlock
(
&
ui__lock
);
return
0
;
return
err
?
0
:
-
1
;
}
void
ui_browser__hide
(
struct
ui_browser
*
self
)
void
ui_browser__hide
(
struct
ui_browser
*
browser
__used
)
{
pthread_mutex_lock
(
&
ui__lock
);
newtFormDestroy
(
self
->
form
);
self
->
form
=
NULL
;
ui_helpline__pop
();
pthread_mutex_unlock
(
&
ui__lock
);
}
int
ui_browser__refresh
(
struct
ui_browser
*
self
)
static
void
ui_browser__scrollbar_set
(
struct
ui_browser
*
browser
)
{
int
height
=
browser
->
height
,
h
=
0
,
pct
=
0
,
col
=
browser
->
width
,
row
=
browser
->
y
-
1
;
if
(
browser
->
nr_entries
>
1
)
{
pct
=
((
browser
->
index
*
(
browser
->
height
-
1
))
/
(
browser
->
nr_entries
-
1
));
}
while
(
h
<
height
)
{
ui_browser__gotorc
(
browser
,
row
++
,
col
);
SLsmg_set_char_set
(
1
);
SLsmg_write_char
(
h
==
pct
?
SLSMG_DIAMOND_CHAR
:
SLSMG_BOARD_CHAR
);
SLsmg_set_char_set
(
0
);
++
h
;
}
}
static
int
__ui_browser__refresh
(
struct
ui_browser
*
browser
)
{
int
row
;
row
=
browser
->
refresh
(
browser
);
ui_browser__set_color
(
browser
,
HE_COLORSET_NORMAL
);
SLsmg_fill_region
(
browser
->
y
+
row
,
browser
->
x
,
browser
->
height
-
row
,
browser
->
width
,
' '
);
ui_browser__scrollbar_set
(
browser
);
return
0
;
}
int
ui_browser__refresh
(
struct
ui_browser
*
browser
)
{
pthread_mutex_lock
(
&
ui__lock
);
newtScrollbarSet
(
self
->
sb
,
self
->
index
,
self
->
nr_entries
-
1
);
row
=
self
->
refresh
(
self
);
ui_browser__set_color
(
self
,
HE_COLORSET_NORMAL
);
SLsmg_fill_region
(
self
->
y
+
row
,
self
->
x
,
self
->
height
-
row
,
self
->
width
,
' '
);
__ui_browser__refresh
(
browser
);
pthread_mutex_unlock
(
&
ui__lock
);
return
0
;
}
int
ui_browser__run
(
struct
ui_browser
*
self
)
/*
* Here we're updating nr_entries _after_ we started browsing, i.e. we have to
* forget about any reference to any entry in the underlying data structure,
* that is why we do a SEEK_SET. Think about 'perf top' in the hists browser
* after an output_resort and hist decay.
*/
void
ui_browser__update_nr_entries
(
struct
ui_browser
*
browser
,
u32
nr_entries
)
{
off_t
offset
=
nr_entries
-
browser
->
nr_entries
;
browser
->
nr_entries
=
nr_entries
;
if
(
offset
<
0
)
{
if
(
browser
->
top_idx
<
(
u64
)
-
offset
)
offset
=
-
browser
->
top_idx
;
browser
->
index
+=
offset
;
browser
->
top_idx
+=
offset
;
}
browser
->
top
=
NULL
;
browser
->
seek
(
browser
,
browser
->
top_idx
,
SEEK_SET
);
}
int
ui_browser__run
(
struct
ui_browser
*
self
,
int
delay_secs
)
{
struct
newtExitStruct
es
;
int
err
,
key
;
struct
timeval
timeout
,
*
ptimeout
=
delay_secs
?
&
timeout
:
NULL
;
if
(
ui_browser__refresh
(
self
)
<
0
)
return
-
1
;
pthread__unblock_sigwinch
();
while
(
1
)
{
off_t
offset
;
fd_set
read_set
;
newtFormRun
(
self
->
form
,
&
es
);
pthread_mutex_lock
(
&
ui__lock
);
err
=
__ui_browser__refresh
(
self
);
SLsmg_refresh
();
pthread_mutex_unlock
(
&
ui__lock
);
if
(
err
<
0
)
break
;
FD_ZERO
(
&
read_set
);
FD_SET
(
0
,
&
read_set
);
if
(
delay_secs
)
{
timeout
.
tv_sec
=
delay_secs
;
timeout
.
tv_usec
=
0
;
}
if
(
es
.
reason
!=
NEWT_EXIT_HOTKEY
)
err
=
select
(
1
,
&
read_set
,
NULL
,
NULL
,
ptimeout
);
if
(
err
>
0
&&
FD_ISSET
(
0
,
&
read_set
))
key
=
newtGetKey
();
else
if
(
err
==
0
)
break
;
switch
(
es
.
u
.
key
)
{
else
{
pthread_mutex_lock
(
&
ui__lock
);
SLtt_get_screen_size
();
SLsmg_reinit_smg
();
pthread_mutex_unlock
(
&
ui__lock
);
ui_browser__refresh_dimensions
(
self
);
__ui_browser__show_title
(
self
,
self
->
title
);
ui_helpline__puts
(
self
->
helpline
);
continue
;
}
switch
(
key
)
{
case
NEWT_KEY_DOWN
:
if
(
self
->
index
==
self
->
nr_entries
-
1
)
break
;
...
...
@@ -301,10 +383,8 @@ int ui_browser__run(struct ui_browser *self)
self
->
seek
(
self
,
-
offset
,
SEEK_END
);
break
;
default:
return
es
.
u
.
key
;
return
key
;
}
if
(
ui_browser__refresh
(
self
)
<
0
)
return
-
1
;
}
return
-
1
;
}
...
...
@@ -316,27 +396,29 @@ unsigned int ui_browser__list_head_refresh(struct ui_browser *self)
int
row
=
0
;
if
(
self
->
top
==
NULL
||
self
->
top
==
self
->
entries
)
self
->
top
=
head
->
next
;
self
->
top
=
ui_browser__list_head_filter_entries
(
self
,
head
->
next
)
;
pos
=
self
->
top
;
list_for_each_from
(
pos
,
head
)
{
ui_browser__gotorc
(
self
,
row
,
0
);
self
->
write
(
self
,
pos
,
row
);
if
(
++
row
==
self
->
height
)
break
;
if
(
!
self
->
filter
||
!
self
->
filter
(
self
,
pos
))
{
ui_browser__gotorc
(
self
,
row
,
0
);
self
->
write
(
self
,
pos
,
row
);
if
(
++
row
==
self
->
height
)
break
;
}
}
return
row
;
}
static
struct
newtPercentTreeC
olors
{
static
struct
ui_browser__c
olors
{
const
char
*
topColorFg
,
*
topColorBg
;
const
char
*
mediumColorFg
,
*
mediumColorBg
;
const
char
*
normalColorFg
,
*
normalColorBg
;
const
char
*
selColorFg
,
*
selColorBg
;
const
char
*
codeColorFg
,
*
codeColorBg
;
}
defaultPercentTreeC
olors
=
{
}
ui_browser__default_c
olors
=
{
"red"
,
"lightgray"
,
"green"
,
"lightgray"
,
"black"
,
"lightgray"
,
...
...
@@ -346,7 +428,7 @@ static struct newtPercentTreeColors {
void
ui_browser__init
(
void
)
{
struct
newtPercentTreeColors
*
c
=
&
defaultPercentTreeC
olors
;
struct
ui_browser__colors
*
c
=
&
ui_browser__default_c
olors
;
sltt_set_color
(
HE_COLORSET_TOP
,
NULL
,
c
->
topColorFg
,
c
->
topColorBg
);
sltt_set_color
(
HE_COLORSET_MEDIUM
,
NULL
,
c
->
mediumColorFg
,
c
->
mediumColorBg
);
...
...
tools/perf/util/ui/browser.h
View file @
c73a3cb3
...
...
@@ -2,7 +2,6 @@
#define _PERF_UI_BROWSER_H_ 1
#include <stdbool.h>
#include <newt.h>
#include <sys/types.h>
#include "../types.h"
...
...
@@ -13,14 +12,16 @@
#define HE_COLORSET_CODE 54
struct
ui_browser
{
newtComponent
form
,
sb
;
u64
index
,
top_idx
;
void
*
top
,
*
entries
;
u16
y
,
x
,
width
,
height
;
void
*
priv
;
const
char
*
title
;
char
*
helpline
;
unsigned
int
(
*
refresh
)(
struct
ui_browser
*
self
);
void
(
*
write
)(
struct
ui_browser
*
self
,
void
*
entry
,
int
row
);
void
(
*
seek
)(
struct
ui_browser
*
self
,
off_t
offset
,
int
whence
);
bool
(
*
filter
)(
struct
ui_browser
*
self
,
void
*
entry
);
u32
nr_entries
;
};
...
...
@@ -32,15 +33,14 @@ void ui_browser__refresh_dimensions(struct ui_browser *self);
void
ui_browser__reset_index
(
struct
ui_browser
*
self
);
void
ui_browser__gotorc
(
struct
ui_browser
*
self
,
int
y
,
int
x
);
void
ui_browser__add_exit_key
(
struct
ui_browser
*
self
,
int
key
);
void
ui_browser__add_exit_keys
(
struct
ui_browser
*
self
,
int
keys
[]);
void
__ui_browser__show_title
(
struct
ui_browser
*
browser
,
const
char
*
title
);
void
ui_browser__show_title
(
struct
ui_browser
*
browser
,
const
char
*
title
);
int
ui_browser__show
(
struct
ui_browser
*
self
,
const
char
*
title
,
const
char
*
helpline
,
...);
void
ui_browser__hide
(
struct
ui_browser
*
self
);
int
ui_browser__refresh
(
struct
ui_browser
*
self
);
int
ui_browser__run
(
struct
ui_browser
*
self
);
int
ui_browser__run
(
struct
ui_browser
*
browser
,
int
delay_secs
);
void
ui_browser__update_nr_entries
(
struct
ui_browser
*
browser
,
u32
nr_entries
);
void
ui_browser__rb_tree_seek
(
struct
ui_browser
*
self
,
off_t
offset
,
int
whence
);
unsigned
int
ui_browser__rb_tree_refresh
(
struct
ui_browser
*
self
);
...
...
tools/perf/util/ui/browsers/annotate.c
View file @
c73a3cb3
...
...
@@ -21,12 +21,16 @@ struct annotate_browser {
struct
rb_root
entries
;
struct
rb_node
*
curr_hot
;
struct
objdump_line
*
selection
;
int
nr_asm_entries
;
int
nr_entries
;
bool
hide_src_code
;
};
struct
objdump_line_rb_node
{
struct
rb_node
rb_node
;
double
percent
;
u32
idx
;
int
idx_asm
;
};
static
inline
...
...
@@ -35,10 +39,22 @@ struct objdump_line_rb_node *objdump_line__rb(struct objdump_line *self)
return
(
struct
objdump_line_rb_node
*
)(
self
+
1
);
}
static
bool
objdump_line__filter
(
struct
ui_browser
*
browser
,
void
*
entry
)
{
struct
annotate_browser
*
ab
=
container_of
(
browser
,
struct
annotate_browser
,
b
);
if
(
ab
->
hide_src_code
)
{
struct
objdump_line
*
ol
=
list_entry
(
entry
,
struct
objdump_line
,
node
);
return
ol
->
offset
==
-
1
;
}
return
false
;
}
static
void
annotate_browser__write
(
struct
ui_browser
*
self
,
void
*
entry
,
int
row
)
{
struct
annotate_browser
*
ab
=
container_of
(
self
,
struct
annotate_browser
,
b
);
struct
objdump_line
*
ol
=
rb
_entry
(
entry
,
struct
objdump_line
,
node
);
struct
objdump_line
*
ol
=
list
_entry
(
entry
,
struct
objdump_line
,
node
);
bool
current_entry
=
ui_browser__is_current_entry
(
self
,
row
);
int
width
=
self
->
width
;
...
...
@@ -168,6 +184,45 @@ static void annotate_browser__calc_percent(struct annotate_browser *browser,
browser
->
curr_hot
=
rb_last
(
&
browser
->
entries
);
}
static
bool
annotate_browser__toggle_source
(
struct
annotate_browser
*
browser
)
{
struct
objdump_line
*
ol
;
struct
objdump_line_rb_node
*
olrb
;
off_t
offset
=
browser
->
b
.
index
-
browser
->
b
.
top_idx
;
browser
->
b
.
seek
(
&
browser
->
b
,
offset
,
SEEK_CUR
);
ol
=
list_entry
(
browser
->
b
.
top
,
struct
objdump_line
,
node
);
olrb
=
objdump_line__rb
(
ol
);
if
(
browser
->
hide_src_code
)
{
if
(
olrb
->
idx_asm
<
offset
)
offset
=
olrb
->
idx
;
browser
->
b
.
nr_entries
=
browser
->
nr_entries
;
browser
->
hide_src_code
=
false
;
browser
->
b
.
seek
(
&
browser
->
b
,
-
offset
,
SEEK_CUR
);
browser
->
b
.
top_idx
=
olrb
->
idx
-
offset
;
browser
->
b
.
index
=
olrb
->
idx
;
}
else
{
if
(
olrb
->
idx_asm
<
0
)
{
ui_helpline__puts
(
"Only available for assembly lines."
);
browser
->
b
.
seek
(
&
browser
->
b
,
-
offset
,
SEEK_CUR
);
return
false
;
}
if
(
olrb
->
idx_asm
<
offset
)
offset
=
olrb
->
idx_asm
;
browser
->
b
.
nr_entries
=
browser
->
nr_asm_entries
;
browser
->
hide_src_code
=
true
;
browser
->
b
.
seek
(
&
browser
->
b
,
-
offset
,
SEEK_CUR
);
browser
->
b
.
top_idx
=
olrb
->
idx_asm
-
offset
;
browser
->
b
.
index
=
olrb
->
idx_asm
;
}
return
true
;
}
static
int
annotate_browser__run
(
struct
annotate_browser
*
self
,
int
evidx
,
int
nr_events
,
void
(
*
timer
)(
void
*
arg
),
void
*
arg
,
int
delay_secs
)
...
...
@@ -175,20 +230,14 @@ static int annotate_browser__run(struct annotate_browser *self, int evidx,
struct
rb_node
*
nd
=
NULL
;
struct
map_symbol
*
ms
=
self
->
b
.
priv
;
struct
symbol
*
sym
=
ms
->
sym
;
/*
* RIGHT To allow builtin-annotate to cycle thru multiple symbols by
* examining the exit key for this function.
*/
int
exit_keys
[]
=
{
'H'
,
NEWT_KEY_TAB
,
NEWT_KEY_UNTAB
,
NEWT_KEY_RIGHT
,
NEWT_KEY_ENTER
,
0
};
const
char
*
help
=
"<-, ESC: exit, TAB/shift+TAB: cycle hottest lines, "
"H: Hottest, -> Line action, S -> Toggle source "
"code view"
;
int
key
;
if
(
ui_browser__show
(
&
self
->
b
,
sym
->
name
,
"<- or ESC: exit, TAB/shift+TAB: "
"cycle hottest lines, H: Hottest, -> Line action"
)
<
0
)
if
(
ui_browser__show
(
&
self
->
b
,
sym
->
name
,
help
)
<
0
)
return
-
1
;
ui_browser__add_exit_keys
(
&
self
->
b
,
exit_keys
);
annotate_browser__calc_percent
(
self
,
evidx
);
if
(
self
->
curr_hot
)
...
...
@@ -196,11 +245,8 @@ static int annotate_browser__run(struct annotate_browser *self, int evidx,
nd
=
self
->
curr_hot
;
if
(
delay_secs
!=
0
)
newtFormSetTimer
(
self
->
b
.
form
,
delay_secs
*
1000
);
while
(
1
)
{
key
=
ui_browser__run
(
&
self
->
b
);
key
=
ui_browser__run
(
&
self
->
b
,
delay_secs
);
if
(
delay_secs
!=
0
)
{
annotate_browser__calc_percent
(
self
,
evidx
);
...
...
@@ -244,6 +290,10 @@ static int annotate_browser__run(struct annotate_browser *self, int evidx,
case
'H'
:
nd
=
self
->
curr_hot
;
break
;
case
'S'
:
if
(
annotate_browser__toggle_source
(
self
))
ui_helpline__puts
(
help
);
continue
;
case
NEWT_KEY_ENTER
:
case
NEWT_KEY_RIGHT
:
if
(
self
->
selection
==
NULL
)
{
...
...
@@ -295,8 +345,13 @@ static int annotate_browser__run(struct annotate_browser *self, int evidx,
timer
,
arg
,
delay_secs
);
}
break
;
default:
case
NEWT_KEY_LEFT
:
case
NEWT_KEY_ESCAPE
:
case
'q'
:
case
CTRL
(
'c'
):
goto
out
;
default:
continue
;
}
if
(
nd
!=
NULL
)
...
...
@@ -329,6 +384,7 @@ int symbol__tui_annotate(struct symbol *sym, struct map *map, int evidx,
.
refresh
=
ui_browser__list_head_refresh
,
.
seek
=
ui_browser__list_head_seek
,
.
write
=
annotate_browser__write
,
.
filter
=
objdump_line__filter
,
.
priv
=
&
ms
,
},
};
...
...
@@ -356,9 +412,14 @@ int symbol__tui_annotate(struct symbol *sym, struct map *map, int evidx,
if
(
browser
.
b
.
width
<
line_len
)
browser
.
b
.
width
=
line_len
;
rbpos
=
objdump_line__rb
(
pos
);
rbpos
->
idx
=
browser
.
b
.
nr_entries
++
;
rbpos
->
idx
=
browser
.
nr_entries
++
;
if
(
pos
->
offset
!=
-
1
)
rbpos
->
idx_asm
=
browser
.
nr_asm_entries
++
;
else
rbpos
->
idx_asm
=
-
1
;
}
browser
.
b
.
nr_entries
=
browser
.
nr_entries
;
browser
.
b
.
entries
=
&
notes
->
src
->
source
,
browser
.
b
.
width
+=
18
;
/* Percentage */
ret
=
annotate_browser__run
(
&
browser
,
evidx
,
nr_events
,
...
...
tools/perf/util/ui/browsers/hists.c
View file @
c73a3cb3
...
...
@@ -301,11 +301,7 @@ static int hist_browser__run(struct hist_browser *self, const char *ev_name,
void
(
*
timer
)(
void
*
arg
),
void
*
arg
,
int
delay_secs
)
{
int
key
;
int
delay_msecs
=
delay_secs
*
1000
;
char
title
[
160
];
int
sym_exit_keys
[]
=
{
'a'
,
'h'
,
'C'
,
'd'
,
'E'
,
't'
,
0
,
};
int
exit_keys
[]
=
{
'?'
,
'h'
,
'D'
,
NEWT_KEY_LEFT
,
NEWT_KEY_RIGHT
,
NEWT_KEY_TAB
,
NEWT_KEY_UNTAB
,
NEWT_KEY_ENTER
,
0
,
};
self
->
b
.
entries
=
&
self
->
hists
->
entries
;
self
->
b
.
nr_entries
=
self
->
hists
->
nr_entries
;
...
...
@@ -318,27 +314,14 @@ static int hist_browser__run(struct hist_browser *self, const char *ev_name,
"Press '?' for help on key bindings"
)
<
0
)
return
-
1
;
if
(
timer
!=
NULL
)
newtFormSetTimer
(
self
->
b
.
form
,
delay_msecs
);
ui_browser__add_exit_keys
(
&
self
->
b
,
exit_keys
);
if
(
self
->
has_symbols
)
ui_browser__add_exit_keys
(
&
self
->
b
,
sym_exit_keys
);
while
(
1
)
{
key
=
ui_browser__run
(
&
self
->
b
);
key
=
ui_browser__run
(
&
self
->
b
,
delay_secs
);
switch
(
key
)
{
case
-
1
:
/* FIXME we need to check if it was es.reason == NEWT_EXIT_TIMER */
timer
(
arg
);
/*
* The timer may have changed the number of entries.
* XXX: Find better way to keep this in synch, probably
* removing this timer function altogether and just sync
* using the hists->lock...
*/
self
->
b
.
nr_entries
=
self
->
hists
->
nr_entries
;
ui_browser__update_nr_entries
(
&
self
->
b
,
self
->
hists
->
nr_entries
);
hists__browser_title
(
self
->
hists
,
title
,
sizeof
(
title
),
ev_name
,
self
->
dso_filter
,
self
->
thread_filter
);
...
...
@@ -617,14 +600,23 @@ static int hist_browser__show_entry(struct hist_browser *self,
return
printed
;
}
static
void
ui_browser__hists_init_top
(
struct
ui_browser
*
browser
)
{
if
(
browser
->
top
==
NULL
)
{
struct
hist_browser
*
hb
;
hb
=
container_of
(
browser
,
struct
hist_browser
,
b
);
browser
->
top
=
rb_first
(
&
hb
->
hists
->
entries
);
}
}
static
unsigned
int
hist_browser__refresh
(
struct
ui_browser
*
self
)
{
unsigned
row
=
0
;
struct
rb_node
*
nd
;
struct
hist_browser
*
hb
=
container_of
(
self
,
struct
hist_browser
,
b
);
if
(
self
->
top
==
NULL
)
self
->
top
=
rb_first
(
&
hb
->
hists
->
entries
);
ui_browser__hists_init_top
(
self
);
for
(
nd
=
self
->
top
;
nd
;
nd
=
rb_next
(
nd
))
{
struct
hist_entry
*
h
=
rb_entry
(
nd
,
struct
hist_entry
,
rb_node
);
...
...
@@ -676,6 +668,8 @@ static void ui_browser__hists_seek(struct ui_browser *self,
if
(
self
->
nr_entries
==
0
)
return
;
ui_browser__hists_init_top
(
self
);
switch
(
whence
)
{
case
SEEK_SET
:
nd
=
hists__filter_entries
(
rb_first
(
self
->
entries
));
...
...
@@ -931,8 +925,11 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events,
!
ui__dialog_yesno
(
"Do you really want to exit?"
))
continue
;
/* Fall thru */
default:
case
'q'
:
case
CTRL
(
'c'
):
goto
out_free_stack
;
default:
continue
;
}
if
(
!
browser
->
has_symbols
)
...
...
@@ -982,9 +979,14 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events,
he
=
hist_browser__selected_entry
(
browser
);
if
(
he
==
NULL
)
continue
;
/*
* Don't let this be freed, say, by hists__decay_entry.
*/
he
->
used
=
true
;
hist_entry__tui_annotate
(
he
,
evsel
->
idx
,
nr_events
,
timer
,
arg
,
delay_secs
);
he
->
used
=
false
;
ui_browser__update_nr_entries
(
&
browser
->
b
,
browser
->
hists
->
nr_entries
);
}
else
if
(
choice
==
browse_map
)
map__browse
(
browser
->
selection
->
map
);
else
if
(
choice
==
zoom_dso
)
{
...
...
@@ -1061,8 +1063,6 @@ static int perf_evsel_menu__run(struct perf_evsel_menu *menu,
int
nr_events
,
const
char
*
help
,
void
(
*
timer
)(
void
*
arg
),
void
*
arg
,
int
delay_secs
)
{
int
exit_keys
[]
=
{
NEWT_KEY_ENTER
,
NEWT_KEY_RIGHT
,
0
,
};
int
delay_msecs
=
delay_secs
*
1000
;
struct
perf_evlist
*
evlist
=
menu
->
b
.
priv
;
struct
perf_evsel
*
pos
;
const
char
*
ev_name
,
*
title
=
"Available samples"
;
...
...
@@ -1072,13 +1072,8 @@ static int perf_evsel_menu__run(struct perf_evsel_menu *menu,
"ESC: exit, ENTER|->: Browse histograms"
)
<
0
)
return
-
1
;
if
(
timer
!=
NULL
)
newtFormSetTimer
(
menu
->
b
.
form
,
delay_msecs
);
ui_browser__add_exit_keys
(
&
menu
->
b
,
exit_keys
);
while
(
1
)
{
key
=
ui_browser__run
(
&
menu
->
b
);
key
=
ui_browser__run
(
&
menu
->
b
,
delay_secs
);
switch
(
key
)
{
case
-
1
:
...
...
@@ -1090,44 +1085,53 @@ static int perf_evsel_menu__run(struct perf_evsel_menu *menu,
if
(
!
menu
->
selection
)
continue
;
pos
=
menu
->
selection
;
perf_evlist__set_selected
(
evlist
,
pos
);
browse_hists:
perf_evlist__set_selected
(
evlist
,
pos
);
/*
* Give the calling tool a chance to populate the non
* default evsel resorted hists tree.
*/
if
(
timer
)
timer
(
arg
);
ev_name
=
event_name
(
pos
);
key
=
perf_evsel__hists_browse
(
pos
,
nr_events
,
help
,
ev_name
,
true
,
timer
,
arg
,
delay_secs
);
ui_browser__show_title
(
&
menu
->
b
,
title
);
break
;
switch
(
key
)
{
case
NEWT_KEY_TAB
:
if
(
pos
->
node
.
next
==
&
evlist
->
entries
)
pos
=
list_entry
(
evlist
->
entries
.
next
,
struct
perf_evsel
,
node
);
else
pos
=
list_entry
(
pos
->
node
.
next
,
struct
perf_evsel
,
node
);
goto
browse_hists
;
case
NEWT_KEY_UNTAB
:
if
(
pos
->
node
.
prev
==
&
evlist
->
entries
)
pos
=
list_entry
(
evlist
->
entries
.
prev
,
struct
perf_evsel
,
node
);
else
pos
=
list_entry
(
pos
->
node
.
prev
,
struct
perf_evsel
,
node
);
goto
browse_hists
;
case
NEWT_KEY_ESCAPE
:
if
(
!
ui__dialog_yesno
(
"Do you really want to exit?"
))
continue
;
/* Fall thru */
case
'q'
:
case
CTRL
(
'c'
):
goto
out
;
default:
continue
;
}
case
NEWT_KEY_LEFT
:
continue
;
case
NEWT_KEY_ESCAPE
:
if
(
!
ui__dialog_yesno
(
"Do you really want to exit?"
))
continue
;
/* Fall thru */
default:
goto
out
;
}
switch
(
key
)
{
case
NEWT_KEY_TAB
:
if
(
pos
->
node
.
next
==
&
evlist
->
entries
)
pos
=
list_entry
(
evlist
->
entries
.
next
,
struct
perf_evsel
,
node
);
else
pos
=
list_entry
(
pos
->
node
.
next
,
struct
perf_evsel
,
node
);
perf_evlist__set_selected
(
evlist
,
pos
);
goto
browse_hists
;
case
NEWT_KEY_UNTAB
:
if
(
pos
->
node
.
prev
==
&
evlist
->
entries
)
pos
=
list_entry
(
evlist
->
entries
.
prev
,
struct
perf_evsel
,
node
);
else
pos
=
list_entry
(
pos
->
node
.
prev
,
struct
perf_evsel
,
node
);
perf_evlist__set_selected
(
evlist
,
pos
);
goto
browse_hists
;
case
'q'
:
case
CTRL
(
'c'
):
goto
out
;
default:
break
;
continue
;
}
}
...
...
tools/perf/util/ui/browsers/map.c
View file @
c73a3cb3
#include "../libslang.h"
#include <elf.h>
#include <newt.h>
#include <inttypes.h>
#include <sys/ttydefaults.h>
#include <ctype.h>
...
...
@@ -108,11 +109,8 @@ static int map_browser__run(struct map_browser *self)
verbose
?
""
:
"restart with -v to use"
)
<
0
)
return
-
1
;
if
(
verbose
)
ui_browser__add_exit_key
(
&
self
->
b
,
'/'
);
while
(
1
)
{
key
=
ui_browser__run
(
&
self
->
b
);
key
=
ui_browser__run
(
&
self
->
b
,
0
);
if
(
verbose
&&
key
==
'/'
)
map_browser__search
(
self
);
...
...
tools/perf/util/ui/helpline.h
View file @
c73a3cb3
#ifndef _PERF_UI_HELPLINE_H_
#define _PERF_UI_HELPLINE_H_ 1
#include <stdio.h>
void
ui_helpline__init
(
void
);
void
ui_helpline__pop
(
void
);
void
ui_helpline__push
(
const
char
*
msg
);
...
...
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