Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
openeuler
raspberrypi-kernel
提交
70a7c127
R
raspberrypi-kernel
项目概览
openeuler
/
raspberrypi-kernel
通知
13
Star
1
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
R
raspberrypi-kernel
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
提交
70a7c127
编写于
4月 03, 2010
作者:
I
Ingo Molnar
浏览文件
操作
浏览文件
下载
差异文件
Merge branch 'perf' of
git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux-2.6
into perf/core
上级
40b91cd1
533c46c3
变更
25
展开全部
隐藏空白更改
内联
并排
Showing
25 changed file
with
806 addition
and
587 deletion
+806
-587
tools/perf/Makefile
tools/perf/Makefile
+168
-157
tools/perf/bench/mem-memcpy.c
tools/perf/bench/mem-memcpy.c
+0
-1
tools/perf/builtin-annotate.c
tools/perf/builtin-annotate.c
+0
-1
tools/perf/builtin-kmem.c
tools/perf/builtin-kmem.c
+7
-2
tools/perf/builtin-record.c
tools/perf/builtin-record.c
+3
-1
tools/perf/builtin-report.c
tools/perf/builtin-report.c
+14
-9
tools/perf/builtin-timechart.c
tools/perf/builtin-timechart.c
+0
-1
tools/perf/perf.c
tools/perf/perf.c
+0
-1
tools/perf/util/PERF-VERSION-GEN
tools/perf/util/PERF-VERSION-GEN
+5
-1
tools/perf/util/color.c
tools/perf/util/color.c
+49
-4
tools/perf/util/color.h
tools/perf/util/color.h
+4
-0
tools/perf/util/debug.h
tools/perf/util/debug.h
+16
-0
tools/perf/util/event.c
tools/perf/util/event.c
+9
-0
tools/perf/util/hist.c
tools/perf/util/hist.c
+45
-21
tools/perf/util/hist.h
tools/perf/util/hist.h
+7
-2
tools/perf/util/map.c
tools/perf/util/map.c
+195
-1
tools/perf/util/map.h
tools/perf/util/map.h
+28
-6
tools/perf/util/newt.c
tools/perf/util/newt.c
+167
-131
tools/perf/util/session.c
tools/perf/util/session.c
+9
-13
tools/perf/util/session.h
tools/perf/util/session.h
+15
-4
tools/perf/util/sort.c
tools/perf/util/sort.c
+48
-45
tools/perf/util/sort.h
tools/perf/util/sort.h
+3
-3
tools/perf/util/string.h
tools/perf/util/string.h
+0
-16
tools/perf/util/thread.c
tools/perf/util/thread.c
+2
-167
tools/perf/util/util.h
tools/perf/util/util.h
+12
-0
未找到文件。
tools/perf/Makefile
浏览文件 @
70a7c127
此差异已折叠。
点击以展开。
tools/perf/bench/mem-memcpy.c
浏览文件 @
70a7c127
...
...
@@ -10,7 +10,6 @@
#include "../perf.h"
#include "../util/util.h"
#include "../util/parse-options.h"
#include "../util/string.h"
#include "../util/header.h"
#include "bench.h"
...
...
tools/perf/builtin-annotate.c
浏览文件 @
70a7c127
...
...
@@ -14,7 +14,6 @@
#include "util/cache.h"
#include <linux/rbtree.h>
#include "util/symbol.h"
#include "util/string.h"
#include "perf.h"
#include "util/debug.h"
...
...
tools/perf/builtin-kmem.c
浏览文件 @
70a7c127
...
...
@@ -363,19 +363,21 @@ static void __print_result(struct rb_root *root, struct perf_session *session,
struct
alloc_stat
*
data
=
rb_entry
(
next
,
struct
alloc_stat
,
node
);
struct
symbol
*
sym
=
NULL
;
struct
map
*
map
;
char
buf
[
BUFSIZ
];
u64
addr
;
if
(
is_caller
)
{
addr
=
data
->
call_site
;
if
(
!
raw_ip
)
sym
=
map_groups__find_function
(
&
session
->
kmaps
,
addr
,
NULL
);
sym
=
map_groups__find_function
(
&
session
->
kmaps
,
addr
,
&
map
,
NULL
);
}
else
addr
=
data
->
ptr
;
if
(
sym
!=
NULL
)
snprintf
(
buf
,
sizeof
(
buf
),
"%s+%Lx"
,
sym
->
name
,
addr
-
sym
->
start
);
addr
-
map
->
unmap_ip
(
map
,
sym
->
start
)
);
else
snprintf
(
buf
,
sizeof
(
buf
),
"%#Lx"
,
addr
);
printf
(
" %-34s |"
,
buf
);
...
...
@@ -488,6 +490,9 @@ static int __cmd_kmem(void)
if
(
session
==
NULL
)
return
-
ENOMEM
;
if
(
perf_session__create_kernel_maps
(
session
)
<
0
)
goto
out_delete
;
if
(
!
perf_session__has_traces
(
session
,
"kmem record"
))
goto
out_delete
;
...
...
tools/perf/builtin-record.c
浏览文件 @
70a7c127
...
...
@@ -15,7 +15,6 @@
#include "util/util.h"
#include "util/parse-options.h"
#include "util/parse-events.h"
#include "util/string.h"
#include "util/header.h"
#include "util/event.h"
...
...
@@ -575,6 +574,9 @@ static int __cmd_record(int argc, const char **argv)
err
=
event__synthesize_kernel_mmap
(
process_synthesized_event
,
session
,
"_text"
);
if
(
err
<
0
)
err
=
event__synthesize_kernel_mmap
(
process_synthesized_event
,
session
,
"_stext"
);
if
(
err
<
0
)
{
pr_err
(
"Couldn't record kernel reference relocation symbol.
\n
"
);
return
err
;
...
...
tools/perf/builtin-report.c
浏览文件 @
70a7c127
...
...
@@ -14,7 +14,6 @@
#include "util/cache.h"
#include <linux/rbtree.h>
#include "util/symbol.h"
#include "util/string.h"
#include "util/callchain.h"
#include "util/strlist.h"
#include "util/values.h"
...
...
@@ -89,9 +88,12 @@ static int perf_session__add_hist_entry(struct perf_session *self,
struct
event_stat_id
*
stats
;
struct
perf_event_attr
*
attr
;
if
((
sort__has_parent
||
symbol_conf
.
use_callchain
)
&&
data
->
callchain
)
if
((
sort__has_parent
||
symbol_conf
.
use_callchain
)
&&
data
->
callchain
)
{
syms
=
perf_session__resolve_callchain
(
self
,
al
->
thread
,
data
->
callchain
,
&
parent
);
if
(
syms
==
NULL
)
return
-
ENOMEM
;
}
attr
=
perf_header__find_attr
(
data
->
id
,
&
self
->
header
);
if
(
attr
)
...
...
@@ -110,8 +112,8 @@ static int perf_session__add_hist_entry(struct perf_session *self,
if
(
symbol_conf
.
use_callchain
)
{
if
(
!
hit
)
callchain_init
(
&
he
->
callchain
);
err
=
append_chain
(
&
he
->
callchain
,
data
->
callchain
,
syms
);
callchain_init
(
he
->
callchain
);
err
=
append_chain
(
he
->
callchain
,
data
->
callchain
,
syms
);
free
(
syms
);
if
(
err
)
...
...
@@ -303,14 +305,16 @@ static int __cmd_report(void)
next
=
rb_first
(
&
session
->
stats_by_id
);
while
(
next
)
{
struct
event_stat_id
*
stats
;
u64
nr_hists
;
stats
=
rb_entry
(
next
,
struct
event_stat_id
,
rb_node
);
perf_session__collapse_resort
(
&
stats
->
hists
);
perf_session__output_resort
(
&
stats
->
hists
,
stats
->
stats
.
total
);
nr_hists
=
perf_session__output_resort
(
&
stats
->
hists
,
stats
->
stats
.
total
);
if
(
use_browser
)
perf_session__browse_hists
(
&
stats
->
hists
,
stats
->
stats
.
total
,
help
);
perf_session__browse_hists
(
&
stats
->
hists
,
nr_hists
,
stats
->
stats
.
total
,
help
,
input_name
);
else
{
if
(
rb_first
(
&
session
->
stats_by_id
)
==
rb_last
(
&
session
->
stats_by_id
))
...
...
@@ -469,7 +473,8 @@ int cmd_report(int argc, const char **argv, const char *prefix __used)
setup_sorting
(
report_usage
,
options
);
if
(
parent_pattern
!=
default_parent_pattern
)
{
sort_dimension__add
(
"parent"
);
if
(
sort_dimension__add
(
"parent"
)
<
0
)
return
-
1
;
sort_parent
.
elide
=
1
;
}
else
symbol_conf
.
exclude_other
=
false
;
...
...
tools/perf/builtin-timechart.c
浏览文件 @
70a7c127
...
...
@@ -21,7 +21,6 @@
#include "util/cache.h"
#include <linux/rbtree.h>
#include "util/symbol.h"
#include "util/string.h"
#include "util/callchain.h"
#include "util/strlist.h"
...
...
tools/perf/perf.c
浏览文件 @
70a7c127
...
...
@@ -13,7 +13,6 @@
#include "util/quote.h"
#include "util/run-command.h"
#include "util/parse-events.h"
#include "util/string.h"
#include "util/debugfs.h"
bool
use_browser
;
...
...
tools/perf/util/PERF-VERSION-GEN
浏览文件 @
70a7c127
#!/bin/sh
GVF
=
PERF-VERSION-FILE
if
[
$#
-eq
1
]
;
then
OUTPUT
=
$1
fi
GVF
=
${
OUTPUT
}
PERF-VERSION-FILE
DEF_VER
=
v0.0.2.PERF
LF
=
'
...
...
tools/perf/util/color.c
浏览文件 @
70a7c127
...
...
@@ -166,6 +166,31 @@ int perf_color_default_config(const char *var, const char *value, void *cb)
return
perf_default_config
(
var
,
value
,
cb
);
}
static
int
__color_vsnprintf
(
char
*
bf
,
size_t
size
,
const
char
*
color
,
const
char
*
fmt
,
va_list
args
,
const
char
*
trail
)
{
int
r
=
0
;
/*
* Auto-detect:
*/
if
(
perf_use_color_default
<
0
)
{
if
(
isatty
(
1
)
||
pager_in_use
())
perf_use_color_default
=
1
;
else
perf_use_color_default
=
0
;
}
if
(
perf_use_color_default
&&
*
color
)
r
+=
snprintf
(
bf
,
size
,
"%s"
,
color
);
r
+=
vsnprintf
(
bf
+
r
,
size
-
r
,
fmt
,
args
);
if
(
perf_use_color_default
&&
*
color
)
r
+=
snprintf
(
bf
+
r
,
size
-
r
,
"%s"
,
PERF_COLOR_RESET
);
if
(
trail
)
r
+=
snprintf
(
bf
+
r
,
size
-
r
,
"%s"
,
trail
);
return
r
;
}
static
int
__color_vfprintf
(
FILE
*
fp
,
const
char
*
color
,
const
char
*
fmt
,
va_list
args
,
const
char
*
trail
)
{
...
...
@@ -191,11 +216,28 @@ static int __color_vfprintf(FILE *fp, const char *color, const char *fmt,
return
r
;
}
int
color_vsnprintf
(
char
*
bf
,
size_t
size
,
const
char
*
color
,
const
char
*
fmt
,
va_list
args
)
{
return
__color_vsnprintf
(
bf
,
size
,
color
,
fmt
,
args
,
NULL
);
}
int
color_vfprintf
(
FILE
*
fp
,
const
char
*
color
,
const
char
*
fmt
,
va_list
args
)
{
return
__color_vfprintf
(
fp
,
color
,
fmt
,
args
,
NULL
);
}
int
color_snprintf
(
char
*
bf
,
size_t
size
,
const
char
*
color
,
const
char
*
fmt
,
...)
{
va_list
args
;
int
r
;
va_start
(
args
,
fmt
);
r
=
color_vsnprintf
(
bf
,
size
,
color
,
fmt
,
args
);
va_end
(
args
);
return
r
;
}
int
color_fprintf
(
FILE
*
fp
,
const
char
*
color
,
const
char
*
fmt
,
...)
{
...
...
@@ -203,10 +245,7 @@ int color_fprintf(FILE *fp, const char *color, const char *fmt, ...)
int
r
;
va_start
(
args
,
fmt
);
if
(
use_browser
)
r
=
vfprintf
(
fp
,
fmt
,
args
);
else
r
=
color_vfprintf
(
fp
,
color
,
fmt
,
args
);
r
=
color_vfprintf
(
fp
,
color
,
fmt
,
args
);
va_end
(
args
);
return
r
;
}
...
...
@@ -277,3 +316,9 @@ int percent_color_fprintf(FILE *fp, const char *fmt, double percent)
return
r
;
}
int
percent_color_snprintf
(
char
*
bf
,
size_t
size
,
const
char
*
fmt
,
double
percent
)
{
const
char
*
color
=
get_percent_color
(
percent
);
return
color_snprintf
(
bf
,
size
,
color
,
fmt
,
percent
);
}
tools/perf/util/color.h
浏览文件 @
70a7c127
...
...
@@ -32,10 +32,14 @@ int perf_color_default_config(const char *var, const char *value, void *cb);
int
perf_config_colorbool
(
const
char
*
var
,
const
char
*
value
,
int
stdout_is_tty
);
void
color_parse
(
const
char
*
value
,
const
char
*
var
,
char
*
dst
);
void
color_parse_mem
(
const
char
*
value
,
int
len
,
const
char
*
var
,
char
*
dst
);
int
color_vsnprintf
(
char
*
bf
,
size_t
size
,
const
char
*
color
,
const
char
*
fmt
,
va_list
args
);
int
color_vfprintf
(
FILE
*
fp
,
const
char
*
color
,
const
char
*
fmt
,
va_list
args
);
int
color_fprintf
(
FILE
*
fp
,
const
char
*
color
,
const
char
*
fmt
,
...);
int
color_snprintf
(
char
*
bf
,
size_t
size
,
const
char
*
color
,
const
char
*
fmt
,
...);
int
color_fprintf_ln
(
FILE
*
fp
,
const
char
*
color
,
const
char
*
fmt
,
...);
int
color_fwrite_lines
(
FILE
*
fp
,
const
char
*
color
,
size_t
count
,
const
char
*
buf
);
int
percent_color_snprintf
(
char
*
bf
,
size_t
size
,
const
char
*
fmt
,
double
percent
);
int
percent_color_fprintf
(
FILE
*
fp
,
const
char
*
fmt
,
double
percent
);
const
char
*
get_percent_color
(
double
percent
);
...
...
tools/perf/util/debug.h
浏览文件 @
70a7c127
...
...
@@ -10,13 +10,29 @@ extern int dump_trace;
int
dump_printf
(
const
char
*
fmt
,
...)
__attribute__
((
format
(
printf
,
1
,
2
)));
void
trace_event
(
event_t
*
event
);
struct
ui_progress
;
#ifdef NO_NEWT_SUPPORT
static
inline
int
browser__show_help
(
const
char
*
format
__used
,
va_list
ap
__used
)
{
return
0
;
}
static
inline
struct
ui_progress
*
ui_progress__new
(
const
char
*
title
__used
,
u64
total
__used
)
{
return
(
struct
ui_progress
*
)
1
;
}
static
inline
void
ui_progress__update
(
struct
ui_progress
*
self
__used
,
u64
curr
__used
)
{}
static
inline
void
ui_progress__delete
(
struct
ui_progress
*
self
__used
)
{}
#else
int
browser__show_help
(
const
char
*
format
,
va_list
ap
);
struct
ui_progress
*
ui_progress__new
(
const
char
*
title
,
u64
total
);
void
ui_progress__update
(
struct
ui_progress
*
self
,
u64
curr
);
void
ui_progress__delete
(
struct
ui_progress
*
self
);
#endif
#endif
/* __PERF_DEBUG_H */
tools/perf/util/event.c
浏览文件 @
70a7c127
...
...
@@ -130,6 +130,7 @@ static int event__synthesize_mmap_events(pid_t pid, pid_t tgid,
continue
;
pbf
+=
n
+
3
;
if
(
*
pbf
==
'x'
)
{
/* vm_exec */
u64
vm_pgoff
;
char
*
execname
=
strchr
(
bf
,
'/'
);
/* Catch VDSO */
...
...
@@ -139,6 +140,14 @@ static int event__synthesize_mmap_events(pid_t pid, pid_t tgid,
if
(
execname
==
NULL
)
continue
;
pbf
+=
3
;
n
=
hex2u64
(
pbf
,
&
vm_pgoff
);
/* pgoff is in bytes, not pages */
if
(
n
>=
0
)
ev
.
mmap
.
pgoff
=
vm_pgoff
<<
getpagesize
();
else
ev
.
mmap
.
pgoff
=
0
;
size
=
strlen
(
execname
);
execname
[
size
-
1
]
=
'\0'
;
/* Remove \n */
memcpy
(
ev
.
mmap
.
filename
,
execname
,
size
);
...
...
tools/perf/util/hist.c
浏览文件 @
70a7c127
...
...
@@ -50,7 +50,8 @@ struct hist_entry *__perf_session__add_hist_entry(struct rb_root *hists,
p
=
&
(
*
p
)
->
rb_right
;
}
he
=
malloc
(
sizeof
(
*
he
));
he
=
malloc
(
sizeof
(
*
he
)
+
(
symbol_conf
.
use_callchain
?
sizeof
(
struct
callchain_node
)
:
0
));
if
(
!
he
)
return
NULL
;
*
he
=
entry
;
...
...
@@ -168,7 +169,7 @@ static void perf_session__insert_output_hist_entry(struct rb_root *root,
struct
hist_entry
*
iter
;
if
(
symbol_conf
.
use_callchain
)
callchain_param
.
sort
(
&
he
->
sorted_chain
,
&
he
->
callchain
,
callchain_param
.
sort
(
&
he
->
sorted_chain
,
he
->
callchain
,
min_callchain_hits
,
&
callchain_param
);
while
(
*
p
!=
NULL
)
{
...
...
@@ -185,12 +186,13 @@ static void perf_session__insert_output_hist_entry(struct rb_root *root,
rb_insert_color
(
&
he
->
rb_node
,
root
);
}
void
perf_session__output_resort
(
struct
rb_root
*
hists
,
u64
total_samples
)
u64
perf_session__output_resort
(
struct
rb_root
*
hists
,
u64
total_samples
)
{
struct
rb_root
tmp
;
struct
rb_node
*
next
;
struct
hist_entry
*
n
;
u64
min_callchain_hits
;
u64
nr_hists
=
0
;
min_callchain_hits
=
total_samples
*
(
callchain_param
.
min_percent
/
100
);
...
...
@@ -205,9 +207,11 @@ void perf_session__output_resort(struct rb_root *hists, u64 total_samples)
rb_erase
(
&
n
->
rb_node
,
hists
);
perf_session__insert_output_hist_entry
(
&
tmp
,
n
,
min_callchain_hits
);
++
nr_hists
;
}
*
hists
=
tmp
;
return
nr_hists
;
}
static
size_t
callchain__fprintf_left_margin
(
FILE
*
fp
,
int
left_margin
)
...
...
@@ -452,16 +456,17 @@ static size_t hist_entry_callchain__fprintf(FILE *fp, struct hist_entry *self,
return
ret
;
}
size_t
hist_entry__fprintf
(
struct
hist_entry
*
self
,
int
hist_entry__snprintf
(
struct
hist_entry
*
self
,
char
*
s
,
size_t
size
,
struct
perf_session
*
pair_session
,
bool
show_displacement
,
long
displacement
,
FILE
*
fp
,
long
displacement
,
bool
color
,
u64
session_total
)
{
struct
sort_entry
*
se
;
u64
count
,
total
;
const
char
*
sep
=
symbol_conf
.
field_sep
;
size_
t
ret
;
in
t
ret
;
if
(
symbol_conf
.
exclude_other
&&
!
self
->
parent
)
return
0
;
...
...
@@ -474,17 +479,22 @@ size_t hist_entry__fprintf(struct hist_entry *self,
total
=
session_total
;
}
if
(
total
)
ret
=
percent_color_fprintf
(
fp
,
sep
?
"%.2f"
:
" %6.2f%%"
,
(
count
*
100
.
0
)
/
total
);
else
ret
=
fprintf
(
fp
,
sep
?
"%lld"
:
"%12lld "
,
count
);
if
(
total
)
{
if
(
color
)
ret
=
percent_color_snprintf
(
s
,
size
,
sep
?
"%.2f"
:
" %6.2f%%"
,
(
count
*
100
.
0
)
/
total
);
else
ret
=
snprintf
(
s
,
size
,
sep
?
"%.2f"
:
" %6.2f%%"
,
(
count
*
100
.
0
)
/
total
);
}
else
ret
=
snprintf
(
s
,
size
,
sep
?
"%lld"
:
"%12lld "
,
count
);
if
(
symbol_conf
.
show_nr_samples
)
{
if
(
sep
)
ret
+=
fprintf
(
fp
,
"%c%lld"
,
*
sep
,
count
);
ret
+=
snprintf
(
s
+
ret
,
size
-
ret
,
"%c%lld"
,
*
sep
,
count
);
else
ret
+=
fprintf
(
fp
,
"%11lld"
,
count
);
ret
+=
snprintf
(
s
+
ret
,
size
-
ret
,
"%11lld"
,
count
);
}
if
(
pair_session
)
{
...
...
@@ -504,9 +514,9 @@ size_t hist_entry__fprintf(struct hist_entry *self,
snprintf
(
bf
,
sizeof
(
bf
),
" "
);
if
(
sep
)
ret
+=
fprintf
(
fp
,
"%c%s"
,
*
sep
,
bf
);
ret
+=
snprintf
(
s
+
ret
,
size
-
ret
,
"%c%s"
,
*
sep
,
bf
);
else
ret
+=
fprintf
(
fp
,
"%11.11s"
,
bf
);
ret
+=
snprintf
(
s
+
ret
,
size
-
ret
,
"%11.11s"
,
bf
);
if
(
show_displacement
)
{
if
(
displacement
)
...
...
@@ -515,9 +525,9 @@ size_t hist_entry__fprintf(struct hist_entry *self,
snprintf
(
bf
,
sizeof
(
bf
),
" "
);
if
(
sep
)
ret
+=
fprintf
(
fp
,
"%c%s"
,
*
sep
,
bf
);
ret
+=
snprintf
(
s
+
ret
,
size
-
ret
,
"%c%s"
,
*
sep
,
bf
);
else
ret
+=
fprintf
(
fp
,
"%6.6s"
,
bf
);
ret
+=
snprintf
(
s
+
ret
,
size
-
ret
,
"%6.6s"
,
bf
);
}
}
...
...
@@ -525,11 +535,25 @@ size_t hist_entry__fprintf(struct hist_entry *self,
if
(
se
->
elide
)
continue
;
ret
+=
fprintf
(
fp
,
"%s"
,
sep
?:
" "
);
ret
+=
se
->
print
(
fp
,
self
,
se
->
width
?
*
se
->
width
:
0
);
ret
+=
snprintf
(
s
+
ret
,
size
-
ret
,
"%s"
,
sep
?:
" "
);
ret
+=
se
->
snprintf
(
self
,
s
+
ret
,
size
-
ret
,
se
->
width
?
*
se
->
width
:
0
);
}
return
ret
+
fprintf
(
fp
,
"
\n
"
);
return
ret
;
}
int
hist_entry__fprintf
(
struct
hist_entry
*
self
,
struct
perf_session
*
pair_session
,
bool
show_displacement
,
long
displacement
,
FILE
*
fp
,
u64
session_total
)
{
char
bf
[
512
];
hist_entry__snprintf
(
self
,
bf
,
sizeof
(
bf
),
pair_session
,
show_displacement
,
displacement
,
true
,
session_total
);
return
fprintf
(
fp
,
"%s
\n
"
,
bf
);
}
static
size_t
hist_entry__fprintf_callchain
(
struct
hist_entry
*
self
,
FILE
*
fp
,
...
...
@@ -658,7 +682,7 @@ size_t perf_session__fprintf_hists(struct rb_root *hists,
if
(
h
->
ms
.
map
==
NULL
&&
verbose
>
1
)
{
__map_groups__fprintf_maps
(
&
h
->
thread
->
mg
,
MAP__FUNCTION
,
fp
);
MAP__FUNCTION
,
verbose
,
fp
);
fprintf
(
fp
,
"%.10s end
\n
"
,
graph_dotted_line
);
}
}
...
...
tools/perf/util/hist.h
浏览文件 @
70a7c127
...
...
@@ -18,14 +18,19 @@ struct hist_entry *__perf_session__add_hist_entry(struct rb_root *hists,
u64
count
,
bool
*
hit
);
extern
int64_t
hist_entry__cmp
(
struct
hist_entry
*
,
struct
hist_entry
*
);
extern
int64_t
hist_entry__collapse
(
struct
hist_entry
*
,
struct
hist_entry
*
);
size_
t
hist_entry__fprintf
(
struct
hist_entry
*
self
,
in
t
hist_entry__fprintf
(
struct
hist_entry
*
self
,
struct
perf_session
*
pair_session
,
bool
show_displacement
,
long
displacement
,
FILE
*
fp
,
u64
session_total
);
int
hist_entry__snprintf
(
struct
hist_entry
*
self
,
char
*
bf
,
size_t
size
,
struct
perf_session
*
pair_session
,
bool
show_displacement
,
long
displacement
,
bool
color
,
u64
session_total
);
void
hist_entry__free
(
struct
hist_entry
*
);
void
perf_session__output_resort
(
struct
rb_root
*
hists
,
u64
total_samples
);
u64
perf_session__output_resort
(
struct
rb_root
*
hists
,
u64
total_samples
);
void
perf_session__collapse_resort
(
struct
rb_root
*
hists
);
size_t
perf_session__fprintf_hists
(
struct
rb_root
*
hists
,
struct
perf_session
*
pair
,
...
...
tools/perf/util/map.c
浏览文件 @
70a7c127
#include "symbol.h"
#include <errno.h>
#include <limits.h>
#include <stdlib.h>
#include <string.h>
...
...
@@ -234,18 +235,211 @@ u64 map__objdump_2ip(struct map *map, u64 addr)
return
ip
;
}
void
map_groups__init
(
struct
map_groups
*
self
)
{
int
i
;
for
(
i
=
0
;
i
<
MAP__NR_TYPES
;
++
i
)
{
self
->
maps
[
i
]
=
RB_ROOT
;
INIT_LIST_HEAD
(
&
self
->
removed_maps
[
i
]);
}
}
void
map_groups__flush
(
struct
map_groups
*
self
)
{
int
type
;
for
(
type
=
0
;
type
<
MAP__NR_TYPES
;
type
++
)
{
struct
rb_root
*
root
=
&
self
->
maps
[
type
];
struct
rb_node
*
next
=
rb_first
(
root
);
while
(
next
)
{
struct
map
*
pos
=
rb_entry
(
next
,
struct
map
,
rb_node
);
next
=
rb_next
(
&
pos
->
rb_node
);
rb_erase
(
&
pos
->
rb_node
,
root
);
/*
* We may have references to this map, for
* instance in some hist_entry instances, so
* just move them to a separate list.
*/
list_add_tail
(
&
pos
->
node
,
&
self
->
removed_maps
[
pos
->
type
]);
}
}
}
struct
symbol
*
map_groups__find_symbol
(
struct
map_groups
*
self
,
enum
map_type
type
,
u64
addr
,
struct
map
**
mapp
,
symbol_filter_t
filter
)
{
struct
map
*
map
=
map_groups__find
(
self
,
type
,
addr
);
if
(
map
!=
NULL
)
if
(
map
!=
NULL
)
{
if
(
mapp
!=
NULL
)
*
mapp
=
map
;
return
map__find_symbol
(
map
,
map
->
map_ip
(
map
,
addr
),
filter
);
}
return
NULL
;
}
struct
symbol
*
map_groups__find_symbol_by_name
(
struct
map_groups
*
self
,
enum
map_type
type
,
const
char
*
name
,
struct
map
**
mapp
,
symbol_filter_t
filter
)
{
struct
rb_node
*
nd
;
for
(
nd
=
rb_first
(
&
self
->
maps
[
type
]);
nd
;
nd
=
rb_next
(
nd
))
{
struct
map
*
pos
=
rb_entry
(
nd
,
struct
map
,
rb_node
);
struct
symbol
*
sym
=
map__find_symbol_by_name
(
pos
,
name
,
filter
);
if
(
sym
==
NULL
)
continue
;
if
(
mapp
!=
NULL
)
*
mapp
=
pos
;
return
sym
;
}
return
NULL
;
}
size_t
__map_groups__fprintf_maps
(
struct
map_groups
*
self
,
enum
map_type
type
,
int
verbose
,
FILE
*
fp
)
{
size_t
printed
=
fprintf
(
fp
,
"%s:
\n
"
,
map_type__name
[
type
]);
struct
rb_node
*
nd
;
for
(
nd
=
rb_first
(
&
self
->
maps
[
type
]);
nd
;
nd
=
rb_next
(
nd
))
{
struct
map
*
pos
=
rb_entry
(
nd
,
struct
map
,
rb_node
);
printed
+=
fprintf
(
fp
,
"Map:"
);
printed
+=
map__fprintf
(
pos
,
fp
);
if
(
verbose
>
2
)
{
printed
+=
dso__fprintf
(
pos
->
dso
,
type
,
fp
);
printed
+=
fprintf
(
fp
,
"--
\n
"
);
}
}
return
printed
;
}
size_t
map_groups__fprintf_maps
(
struct
map_groups
*
self
,
int
verbose
,
FILE
*
fp
)
{
size_t
printed
=
0
,
i
;
for
(
i
=
0
;
i
<
MAP__NR_TYPES
;
++
i
)
printed
+=
__map_groups__fprintf_maps
(
self
,
i
,
verbose
,
fp
);
return
printed
;
}
static
size_t
__map_groups__fprintf_removed_maps
(
struct
map_groups
*
self
,
enum
map_type
type
,
int
verbose
,
FILE
*
fp
)
{
struct
map
*
pos
;
size_t
printed
=
0
;
list_for_each_entry
(
pos
,
&
self
->
removed_maps
[
type
],
node
)
{
printed
+=
fprintf
(
fp
,
"Map:"
);
printed
+=
map__fprintf
(
pos
,
fp
);
if
(
verbose
>
1
)
{
printed
+=
dso__fprintf
(
pos
->
dso
,
type
,
fp
);
printed
+=
fprintf
(
fp
,
"--
\n
"
);
}
}
return
printed
;
}
static
size_t
map_groups__fprintf_removed_maps
(
struct
map_groups
*
self
,
int
verbose
,
FILE
*
fp
)
{
size_t
printed
=
0
,
i
;
for
(
i
=
0
;
i
<
MAP__NR_TYPES
;
++
i
)
printed
+=
__map_groups__fprintf_removed_maps
(
self
,
i
,
verbose
,
fp
);
return
printed
;
}
size_t
map_groups__fprintf
(
struct
map_groups
*
self
,
int
verbose
,
FILE
*
fp
)
{
size_t
printed
=
map_groups__fprintf_maps
(
self
,
verbose
,
fp
);
printed
+=
fprintf
(
fp
,
"Removed maps:
\n
"
);
return
printed
+
map_groups__fprintf_removed_maps
(
self
,
verbose
,
fp
);
}
int
map_groups__fixup_overlappings
(
struct
map_groups
*
self
,
struct
map
*
map
,
int
verbose
,
FILE
*
fp
)
{
struct
rb_root
*
root
=
&
self
->
maps
[
map
->
type
];
struct
rb_node
*
next
=
rb_first
(
root
);
while
(
next
)
{
struct
map
*
pos
=
rb_entry
(
next
,
struct
map
,
rb_node
);
next
=
rb_next
(
&
pos
->
rb_node
);
if
(
!
map__overlap
(
pos
,
map
))
continue
;
if
(
verbose
>=
2
)
{
fputs
(
"overlapping maps:
\n
"
,
fp
);
map__fprintf
(
map
,
fp
);
map__fprintf
(
pos
,
fp
);
}
rb_erase
(
&
pos
->
rb_node
,
root
);
/*
* We may have references to this map, for instance in some
* hist_entry instances, so just move them to a separate
* list.
*/
list_add_tail
(
&
pos
->
node
,
&
self
->
removed_maps
[
map
->
type
]);
/*
* Now check if we need to create new maps for areas not
* overlapped by the new map:
*/
if
(
map
->
start
>
pos
->
start
)
{
struct
map
*
before
=
map__clone
(
pos
);
if
(
before
==
NULL
)
return
-
ENOMEM
;
before
->
end
=
map
->
start
-
1
;
map_groups__insert
(
self
,
before
);
if
(
verbose
>=
2
)
map__fprintf
(
before
,
fp
);
}
if
(
map
->
end
<
pos
->
end
)
{
struct
map
*
after
=
map__clone
(
pos
);
if
(
after
==
NULL
)
return
-
ENOMEM
;
after
->
start
=
map
->
end
+
1
;
map_groups__insert
(
self
,
after
);
if
(
verbose
>=
2
)
map__fprintf
(
after
,
fp
);
}
}
return
0
;
}
/*
* XXX This should not really _copy_ te maps, but refcount them.
*/
int
map_groups__clone
(
struct
map_groups
*
self
,
struct
map_groups
*
parent
,
enum
map_type
type
)
{
struct
rb_node
*
nd
;
for
(
nd
=
rb_first
(
&
parent
->
maps
[
type
]);
nd
;
nd
=
rb_next
(
nd
))
{
struct
map
*
map
=
rb_entry
(
nd
,
struct
map
,
rb_node
);
struct
map
*
new
=
map__clone
(
map
);
if
(
new
==
NULL
)
return
-
ENOMEM
;
map_groups__insert
(
self
,
new
);
}
return
0
;
}
static
u64
map__reloc_map_ip
(
struct
map
*
map
,
u64
ip
)
{
return
ip
+
(
s64
)
map
->
pgoff
;
...
...
tools/perf/util/map.h
浏览文件 @
70a7c127
...
...
@@ -97,11 +97,14 @@ struct map_groups {
};
size_t
__map_groups__fprintf_maps
(
struct
map_groups
*
self
,
enum
map_type
type
,
FILE
*
fp
);
enum
map_type
type
,
int
verbose
,
FILE
*
fp
);
void
maps__insert
(
struct
rb_root
*
maps
,
struct
map
*
map
);
struct
map
*
maps__find
(
struct
rb_root
*
maps
,
u64
addr
);
void
map_groups__init
(
struct
map_groups
*
self
);
size_t
map_groups__fprintf_maps
(
struct
map_groups
*
self
,
FILE
*
fp
);
int
map_groups__clone
(
struct
map_groups
*
self
,
struct
map_groups
*
parent
,
enum
map_type
type
);
size_t
map_groups__fprintf
(
struct
map_groups
*
self
,
int
verbose
,
FILE
*
fp
);
size_t
map_groups__fprintf_maps
(
struct
map_groups
*
self
,
int
verbose
,
FILE
*
fp
);
static
inline
void
map_groups__insert
(
struct
map_groups
*
self
,
struct
map
*
map
)
{
...
...
@@ -116,15 +119,33 @@ static inline struct map *map_groups__find(struct map_groups *self,
struct
symbol
*
map_groups__find_symbol
(
struct
map_groups
*
self
,
enum
map_type
type
,
u64
addr
,
struct
map
**
mapp
,
symbol_filter_t
filter
);
static
inline
struct
symbol
*
map_groups__find_function
(
struct
map_groups
*
self
,
u64
addr
,
symbol_filter_t
filter
)
struct
symbol
*
map_groups__find_symbol_by_name
(
struct
map_groups
*
self
,
enum
map_type
type
,
const
char
*
name
,
struct
map
**
mapp
,
symbol_filter_t
filter
);
static
inline
struct
symbol
*
map_groups__find_function
(
struct
map_groups
*
self
,
u64
addr
,
struct
map
**
mapp
,
symbol_filter_t
filter
)
{
return
map_groups__find_symbol
(
self
,
MAP__FUNCTION
,
addr
,
filter
);
return
map_groups__find_symbol
(
self
,
MAP__FUNCTION
,
addr
,
mapp
,
filter
);
}
static
inline
struct
symbol
*
map_groups__find_function_by_name
(
struct
map_groups
*
self
,
const
char
*
name
,
struct
map
**
mapp
,
symbol_filter_t
filter
)
{
return
map_groups__find_symbol_by_name
(
self
,
MAP__FUNCTION
,
name
,
mapp
,
filter
);
}
int
map_groups__fixup_overlappings
(
struct
map_groups
*
self
,
struct
map
*
map
,
int
verbose
,
FILE
*
fp
);
struct
map
*
map_groups__find_by_name
(
struct
map_groups
*
self
,
enum
map_type
type
,
const
char
*
name
);
int
__map_groups__create_kernel_maps
(
struct
map_groups
*
self
,
...
...
@@ -134,5 +155,6 @@ int map_groups__create_kernel_maps(struct map_groups *self,
struct
map
*
vmlinux_maps
[
MAP__NR_TYPES
]);
struct
map
*
map_groups__new_module
(
struct
map_groups
*
self
,
u64
start
,
const
char
*
filename
);
void
map_groups__flush
(
struct
map_groups
*
self
);
#endif
/* __PERF_MAP_H */
tools/perf/util/newt.c
浏览文件 @
70a7c127
...
...
@@ -12,6 +12,72 @@
#include "sort.h"
#include "symbol.h"
struct
ui_progress
{
newtComponent
form
,
scale
;
};
struct
ui_progress
*
ui_progress__new
(
const
char
*
title
,
u64
total
)
{
struct
ui_progress
*
self
=
malloc
(
sizeof
(
*
self
));
if
(
self
!=
NULL
)
{
int
cols
;
newtGetScreenSize
(
&
cols
,
NULL
);
cols
-=
4
;
newtCenteredWindow
(
cols
,
1
,
title
);
self
->
form
=
newtForm
(
NULL
,
NULL
,
0
);
if
(
self
->
form
==
NULL
)
goto
out_free_self
;
self
->
scale
=
newtScale
(
0
,
0
,
cols
,
total
);
if
(
self
->
scale
==
NULL
)
goto
out_free_form
;
newtFormAddComponents
(
self
->
form
,
self
->
scale
,
NULL
);
newtRefresh
();
}
return
self
;
out_free_form:
newtFormDestroy
(
self
->
form
);
out_free_self:
free
(
self
);
return
NULL
;
}
void
ui_progress__update
(
struct
ui_progress
*
self
,
u64
curr
)
{
newtScaleSet
(
self
->
scale
,
curr
);
newtRefresh
();
}
void
ui_progress__delete
(
struct
ui_progress
*
self
)
{
newtFormDestroy
(
self
->
form
);
newtPopWindow
();
free
(
self
);
}
static
char
browser__last_msg
[
1024
];
int
browser__show_help
(
const
char
*
format
,
va_list
ap
)
{
int
ret
;
static
int
backlog
;
ret
=
vsnprintf
(
browser__last_msg
+
backlog
,
sizeof
(
browser__last_msg
)
-
backlog
,
format
,
ap
);
backlog
+=
ret
;
if
(
browser__last_msg
[
backlog
-
1
]
==
'\n'
)
{
newtPopHelpLine
();
newtPushHelpLine
(
browser__last_msg
);
newtRefresh
();
backlog
=
0
;
}
return
ret
;
}
static
void
newt_form__set_exit_keys
(
newtComponent
self
)
{
newtFormAddHotKey
(
self
,
NEWT_KEY_ESCAPE
);
...
...
@@ -228,60 +294,17 @@ static void hist_entry__append_callchain_browser(struct hist_entry *self,
}
}
/*
* FIXME: get lib/string.c linked with perf somehow
*/
static
char
*
skip_spaces
(
const
char
*
str
)
{
while
(
isspace
(
*
str
))
++
str
;
return
(
char
*
)
str
;
}
static
char
*
strim
(
char
*
s
)
{
size_t
size
;
char
*
end
;
s
=
skip_spaces
(
s
);
size
=
strlen
(
s
);
if
(
!
size
)
return
s
;
end
=
s
+
size
-
1
;
while
(
end
>=
s
&&
isspace
(
*
end
))
end
--
;
*
(
end
+
1
)
=
'\0'
;
return
s
;
}
static
size_t
hist_entry__append_browser
(
struct
hist_entry
*
self
,
newtComponent
tree
,
u64
total
)
{
char
bf
[
1024
],
*
s
;
FILE
*
fp
;
char
s
[
256
]
;
size_t
ret
;
if
(
symbol_conf
.
exclude_other
&&
!
self
->
parent
)
return
0
;
fp
=
fmemopen
(
bf
,
sizeof
(
bf
),
"w"
);
if
(
fp
==
NULL
)
return
0
;
hist_entry__fprintf
(
self
,
NULL
,
false
,
0
,
fp
,
total
);
fclose
(
fp
);
/*
* FIXME: We shouldn't need to trim, as the printing routines shouldn't
* add spaces it in the first place, the stdio output routines should
* call a __snprintf method instead of the current __print (that
* actually is a __fprintf) one, but get the raw string and _then_ add
* the newline, as this is a detail of stdio printing, not needed in
* other UIs, e.g. newt.
*/
s
=
strim
(
bf
);
ret
=
hist_entry__snprintf
(
self
,
s
,
sizeof
(
s
),
NULL
,
false
,
0
,
false
,
total
);
if
(
symbol_conf
.
use_callchain
)
{
int
indexes
[
2
];
...
...
@@ -291,10 +314,11 @@ static size_t hist_entry__append_browser(struct hist_entry *self,
}
else
newtListboxAppendEntry
(
tree
,
s
,
&
self
->
ms
);
return
strlen
(
s
)
;
return
ret
;
}
static
void
map_symbol__annotate_browser
(
const
struct
map_symbol
*
self
)
static
void
map_symbol__annotate_browser
(
const
struct
map_symbol
*
self
,
const
char
*
input_name
)
{
FILE
*
fp
;
int
cols
,
rows
;
...
...
@@ -308,8 +332,8 @@ static void map_symbol__annotate_browser(const struct map_symbol *self)
if
(
self
->
sym
==
NULL
)
return
;
if
(
asprintf
(
&
str
,
"perf annotate -d
\"
%s
\"
%s 2>&1 | expand"
,
self
->
map
->
dso
->
name
,
self
->
sym
->
name
)
<
0
)
if
(
asprintf
(
&
str
,
"perf annotate -
i
\"
%s
\"
-
d
\"
%s
\"
%s 2>&1 | expand"
,
input_name
,
self
->
map
->
dso
->
name
,
self
->
sym
->
name
)
<
0
)
return
;
fp
=
popen
(
str
,
"r"
);
...
...
@@ -358,90 +382,121 @@ static const void *newt__symbol_tree_get_current(newtComponent self)
return
newtListboxGetCurrent
(
self
);
}
static
void
perf_session
__selection
(
newtComponent
self
,
void
*
data
)
static
void
hist_browser
__selection
(
newtComponent
self
,
void
*
data
)
{
const
struct
map_symbol
**
symbol_ptr
=
data
;
*
symbol_ptr
=
newt__symbol_tree_get_current
(
self
);
}
void
perf_session__browse_hists
(
struct
rb_root
*
hists
,
u64
session_total
,
const
char
*
helpline
)
{
struct
sort_entry
*
se
;
struct
rb_node
*
nd
;
char
seq
[]
=
"."
;
unsigned
int
width
;
char
*
col_width
=
symbol_conf
.
col_width_list_str
;
int
rows
,
cols
,
idx
;
int
max_len
=
0
;
char
str
[
1024
];
newtComponent
form
,
tree
;
struct
newtExitStruct
es
;
struct
hist_browser
{
newtComponent
form
,
tree
;
const
struct
map_symbol
*
selection
;
};
snprintf
(
str
,
sizeof
(
str
),
"Samples: %Ld"
,
session_total
);
newtDrawRootText
(
0
,
0
,
str
);
newtPushHelpLine
(
helpline
);
newtGetScreenSize
(
&
cols
,
&
rows
);
static
struct
hist_browser
*
hist_browser__new
(
void
)
{
struct
hist_browser
*
self
=
malloc
(
sizeof
(
*
self
));
if
(
symbol_conf
.
use_callchain
)
tree
=
newtCheckboxTreeMulti
(
0
,
0
,
rows
-
5
,
seq
,
NEWT_FLAG_SCROLL
);
else
tree
=
newtListbox
(
0
,
0
,
rows
-
5
,
(
NEWT_FLAG_SCROLL
|
NEWT_FLAG_RETURNEXIT
));
if
(
self
!=
NULL
)
{
char
seq
[]
=
"."
;
int
rows
;
newtComponentAddCallback
(
tree
,
perf_session__selection
,
&
selection
);
newtGetScreenSize
(
NULL
,
&
rows
);
list_for_each_entry
(
se
,
&
hist_entry__sort_list
,
list
)
{
if
(
se
->
elide
)
continue
;
width
=
strlen
(
se
->
header
);
if
(
se
->
width
)
{
if
(
symbol_conf
.
col_width_list_str
)
{
if
(
col_width
)
{
*
se
->
width
=
atoi
(
col_width
);
col_width
=
strchr
(
col_width
,
','
);
if
(
col_width
)
++
col_width
;
}
}
*
se
->
width
=
max
(
*
se
->
width
,
width
);
}
if
(
symbol_conf
.
use_callchain
)
self
->
tree
=
newtCheckboxTreeMulti
(
0
,
0
,
rows
-
5
,
seq
,
NEWT_FLAG_SCROLL
);
else
self
->
tree
=
newtListbox
(
0
,
0
,
rows
-
5
,
(
NEWT_FLAG_SCROLL
|
NEWT_FLAG_RETURNEXIT
));
newtComponentAddCallback
(
self
->
tree
,
hist_browser__selection
,
&
self
->
selection
);
}
return
self
;
}
static
void
hist_browser__delete
(
struct
hist_browser
*
self
)
{
newtFormDestroy
(
self
->
form
);
newtPopWindow
();
free
(
self
);
}
static
int
hist_browser__populate
(
struct
hist_browser
*
self
,
struct
rb_root
*
hists
,
u64
nr_hists
,
u64
session_total
)
{
int
max_len
=
0
,
idx
,
cols
,
rows
;
struct
ui_progress
*
progress
;
struct
rb_node
*
nd
;
u64
curr_hist
=
0
;
progress
=
ui_progress__new
(
"Adding entries to the browser..."
,
nr_hists
);
if
(
progress
==
NULL
)
return
-
1
;
idx
=
0
;
for
(
nd
=
rb_first
(
hists
);
nd
;
nd
=
rb_next
(
nd
))
{
struct
hist_entry
*
h
=
rb_entry
(
nd
,
struct
hist_entry
,
rb_node
);
int
len
=
hist_entry__append_browser
(
h
,
tree
,
session_total
);
int
len
=
hist_entry__append_browser
(
h
,
self
->
tree
,
session_total
);
if
(
len
>
max_len
)
max_len
=
len
;
if
(
symbol_conf
.
use_callchain
)
hist_entry__append_callchain_browser
(
h
,
tree
,
session_total
,
idx
++
);
hist_entry__append_callchain_browser
(
h
,
self
->
tree
,
session_total
,
idx
++
);
++
curr_hist
;
if
(
curr_hist
%
5
)
ui_progress__update
(
progress
,
curr_hist
);
}
ui_progress__delete
(
progress
);
newtGetScreenSize
(
&
cols
,
&
rows
);
if
(
max_len
>
cols
)
max_len
=
cols
-
3
;
if
(
!
symbol_conf
.
use_callchain
)
newtListboxSetWidth
(
tree
,
max_len
);
newtListboxSetWidth
(
self
->
tree
,
max_len
);
newtCenteredWindow
(
max_len
+
(
symbol_conf
.
use_callchain
?
5
:
0
),
rows
-
5
,
"Report"
);
form
=
newt_form__new
();
newtFormAddHotKey
(
form
,
'A'
);
newtFormAddHotKey
(
form
,
'a'
);
newtFormAddHotKey
(
form
,
NEWT_KEY_RIGHT
);
newtFormAddComponents
(
form
,
tree
,
NULL
);
selection
=
newt__symbol_tree_get_current
(
tree
);
self
->
form
=
newt_form__new
();
newtFormAddHotKey
(
self
->
form
,
'A'
);
newtFormAddHotKey
(
self
->
form
,
'a'
);
newtFormAddHotKey
(
self
->
form
,
NEWT_KEY_RIGHT
);
newtFormAddComponents
(
self
->
form
,
self
->
tree
,
NULL
);
self
->
selection
=
newt__symbol_tree_get_current
(
self
->
tree
);
return
0
;
}
int
perf_session__browse_hists
(
struct
rb_root
*
hists
,
u64
nr_hists
,
u64
session_total
,
const
char
*
helpline
,
const
char
*
input_name
)
{
struct
newtExitStruct
es
;
char
str
[
1024
];
int
err
=
-
1
;
struct
hist_browser
*
browser
=
hist_browser__new
();
if
(
browser
==
NULL
)
return
-
1
;
snprintf
(
str
,
sizeof
(
str
),
"Samples: %Ld"
,
session_total
);
newtDrawRootText
(
0
,
0
,
str
);
newtPushHelpLine
(
helpline
);
if
(
hist_browser__populate
(
browser
,
hists
,
nr_hists
,
session_total
)
<
0
)
goto
out
;
while
(
1
)
{
char
annotate
[
512
];
const
char
*
options
[
2
];
int
nr_options
=
0
,
choice
=
0
;
newtFormRun
(
form
,
&
es
);
newtFormRun
(
browser
->
form
,
&
es
);
if
(
es
.
reason
==
NEWT_EXIT_HOTKEY
)
{
if
(
toupper
(
es
.
u
.
key
)
==
'A'
)
goto
do_annotate
;
...
...
@@ -455,9 +510,9 @@ void perf_session__browse_hists(struct rb_root *hists, u64 session_total,
}
}
if
(
selection
->
sym
!=
NULL
)
{
if
(
browser
->
selection
->
sym
!=
NULL
)
{
snprintf
(
annotate
,
sizeof
(
annotate
),
"Annotate %s"
,
selection
->
sym
->
name
);
"Annotate %s"
,
browser
->
selection
->
sym
->
name
);
options
[
nr_options
++
]
=
annotate
;
}
...
...
@@ -466,41 +521,22 @@ void perf_session__browse_hists(struct rb_root *hists, u64 session_total,
if
(
choice
==
nr_options
-
1
)
break
;
do_annotate:
if
(
selection
->
sym
!=
NULL
&&
choice
>=
0
)
{
if
(
selection
->
map
->
dso
->
origin
==
DSO__ORIG_KERNEL
)
{
if
(
browser
->
selection
->
sym
!=
NULL
&&
choice
>=
0
)
{
if
(
browser
->
selection
->
map
->
dso
->
origin
==
DSO__ORIG_KERNEL
)
{
newtPopHelpLine
();
newtPushHelpLine
(
"No vmlinux file found, can't "
"annotate with just a "
"kallsyms file"
);
continue
;
}
map_symbol__annotate_browser
(
selection
);
map_symbol__annotate_browser
(
browser
->
selection
,
input_name
);
}
}
newtFormDestroy
(
form
);
newtPopWindow
();
}
static
char
browser__last_msg
[
1024
];
int
browser__show_help
(
const
char
*
format
,
va_list
ap
)
{
int
ret
;
static
int
backlog
;
ret
=
vsnprintf
(
browser__last_msg
+
backlog
,
sizeof
(
browser__last_msg
)
-
backlog
,
format
,
ap
);
backlog
+=
ret
;
if
(
browser__last_msg
[
backlog
-
1
]
==
'\n'
)
{
newtPopHelpLine
();
newtPushHelpLine
(
browser__last_msg
);
newtRefresh
();
backlog
=
0
;
}
return
ret
;
err
=
0
;
out:
hist_browser__delete
(
browser
);
return
err
;
}
void
setup_browser
(
void
)
...
...
tools/perf/util/session.c
浏览文件 @
70a7c127
...
...
@@ -52,11 +52,6 @@ static int perf_session__open(struct perf_session *self, bool force)
return
-
1
;
}
static
inline
int
perf_session__create_kernel_maps
(
struct
perf_session
*
self
)
{
return
map_groups__create_kernel_maps
(
&
self
->
kmaps
,
self
->
vmlinux_maps
);
}
struct
perf_session
*
perf_session__new
(
const
char
*
filename
,
int
mode
,
bool
force
)
{
size_t
len
=
filename
?
strlen
(
filename
)
+
1
:
0
;
...
...
@@ -123,16 +118,11 @@ struct map_symbol *perf_session__resolve_callchain(struct perf_session *self,
struct
symbol
**
parent
)
{
u8
cpumode
=
PERF_RECORD_MISC_USER
;
struct
map_symbol
*
syms
=
NULL
;
unsigned
int
i
;
struct
map_symbol
*
syms
=
calloc
(
chain
->
nr
,
sizeof
(
*
syms
));
if
(
symbol_conf
.
use_callchain
)
{
syms
=
calloc
(
chain
->
nr
,
sizeof
(
*
syms
));
if
(
!
syms
)
{
fprintf
(
stderr
,
"Can't allocate memory for symbols
\n
"
);
exit
(
-
1
);
}
}
if
(
!
syms
)
return
NULL
;
for
(
i
=
0
;
i
<
chain
->
nr
;
i
++
)
{
u64
ip
=
chain
->
ips
[
i
];
...
...
@@ -397,6 +387,10 @@ int __perf_session__process_events(struct perf_session *self,
event_t
*
event
;
uint32_t
size
;
char
*
buf
;
struct
ui_progress
*
progress
=
ui_progress__new
(
"Processing events..."
,
self
->
size
);
if
(
progress
==
NULL
)
return
-
1
;
perf_event_ops__fill_defaults
(
ops
);
...
...
@@ -425,6 +419,7 @@ int __perf_session__process_events(struct perf_session *self,
more:
event
=
(
event_t
*
)(
buf
+
head
);
ui_progress__update
(
progress
,
offset
);
if
(
self
->
header
.
needs_swap
)
perf_event_header__bswap
(
&
event
->
header
);
...
...
@@ -475,6 +470,7 @@ int __perf_session__process_events(struct perf_session *self,
done:
err
=
0
;
out_err:
ui_progress__delete
(
progress
);
return
err
;
}
...
...
tools/perf/util/session.h
浏览文件 @
70a7c127
...
...
@@ -80,6 +80,11 @@ static inline int __perf_session__create_kernel_maps(struct perf_session *self,
self
->
vmlinux_maps
,
kernel
);
}
static
inline
int
perf_session__create_kernel_maps
(
struct
perf_session
*
self
)
{
return
map_groups__create_kernel_maps
(
&
self
->
kmaps
,
self
->
vmlinux_maps
);
}
static
inline
struct
map
*
perf_session__new_module_map
(
struct
perf_session
*
self
,
u64
start
,
const
char
*
filename
)
...
...
@@ -88,11 +93,17 @@ static inline struct map *
}
#ifdef NO_NEWT_SUPPORT
static
inline
void
perf_session__browse_hists
(
struct
rb_root
*
hists
__used
,
static
inline
int
perf_session__browse_hists
(
struct
rb_root
*
hists
__used
,
u64
nr_hists
__used
,
u64
session_total
__used
,
const
char
*
helpline
__used
)
{}
const
char
*
helpline
__used
,
const
char
*
input_name
__used
)
{
return
0
;
}
#else
void
perf_session__browse_hists
(
struct
rb_root
*
hists
,
u64
session_total
,
const
char
*
helpline
);
int
perf_session__browse_hists
(
struct
rb_root
*
hists
,
u64
nr_hists
,
u64
session_total
,
const
char
*
helpline
,
const
char
*
input_name
);
#endif
#endif
/* __PERF_SESSION_H */
tools/perf/util/sort.c
浏览文件 @
70a7c127
...
...
@@ -18,10 +18,21 @@ char * field_sep;
LIST_HEAD
(
hist_entry__sort_list
);
static
int
hist_entry__thread_snprintf
(
struct
hist_entry
*
self
,
char
*
bf
,
size_t
size
,
unsigned
int
width
);
static
int
hist_entry__comm_snprintf
(
struct
hist_entry
*
self
,
char
*
bf
,
size_t
size
,
unsigned
int
width
);
static
int
hist_entry__dso_snprintf
(
struct
hist_entry
*
self
,
char
*
bf
,
size_t
size
,
unsigned
int
width
);
static
int
hist_entry__sym_snprintf
(
struct
hist_entry
*
self
,
char
*
bf
,
size_t
size
,
unsigned
int
width
);
static
int
hist_entry__parent_snprintf
(
struct
hist_entry
*
self
,
char
*
bf
,
size_t
size
,
unsigned
int
width
);
struct
sort_entry
sort_thread
=
{
.
header
=
"Command: Pid"
,
.
cmp
=
sort__thread_cmp
,
.
print
=
sort__thread_print
,
.
snprintf
=
hist_entry__thread_snprintf
,
.
width
=
&
threads__col_width
,
};
...
...
@@ -29,27 +40,27 @@ struct sort_entry sort_comm = {
.
header
=
"Command"
,
.
cmp
=
sort__comm_cmp
,
.
collapse
=
sort__comm_collapse
,
.
print
=
sort__comm_print
,
.
snprintf
=
hist_entry__comm_snprintf
,
.
width
=
&
comms__col_width
,
};
struct
sort_entry
sort_dso
=
{
.
header
=
"Shared Object"
,
.
cmp
=
sort__dso_cmp
,
.
print
=
sort__dso_print
,
.
snprintf
=
hist_entry__dso_snprintf
,
.
width
=
&
dsos__col_width
,
};
struct
sort_entry
sort_sym
=
{
.
header
=
"Symbol"
,
.
cmp
=
sort__sym_cmp
,
.
print
=
sort__sym_print
,
.
snprintf
=
hist_entry__sym_snprintf
,
};
struct
sort_entry
sort_parent
=
{
.
header
=
"Parent symbol"
,
.
cmp
=
sort__parent_cmp
,
.
print
=
sort__parent_print
,
.
snprintf
=
hist_entry__parent_snprintf
,
.
width
=
&
parent_symbol__col_width
,
};
...
...
@@ -85,45 +96,38 @@ sort__thread_cmp(struct hist_entry *left, struct hist_entry *right)
return
right
->
thread
->
pid
-
left
->
thread
->
pid
;
}
int
repsep_fprintf
(
FILE
*
fp
,
const
char
*
fmt
,
...)
static
int
repsep_snprintf
(
char
*
bf
,
size_t
size
,
const
char
*
fmt
,
...)
{
int
n
;
va_list
ap
;
va_start
(
ap
,
fmt
);
if
(
!
field_sep
)
n
=
vfprintf
(
fp
,
fmt
,
ap
);
else
{
char
*
bf
=
NULL
;
n
=
vasprintf
(
&
bf
,
fmt
,
ap
);
if
(
n
>
0
)
{
char
*
sep
=
bf
;
while
(
1
)
{
sep
=
strchr
(
sep
,
*
field_sep
);
if
(
sep
==
NULL
)
break
;
*
sep
=
'.'
;
}
n
=
vsnprintf
(
bf
,
size
,
fmt
,
ap
);
if
(
field_sep
&&
n
>
0
)
{
char
*
sep
=
bf
;
while
(
1
)
{
sep
=
strchr
(
sep
,
*
field_sep
);
if
(
sep
==
NULL
)
break
;
*
sep
=
'.'
;
}
fputs
(
bf
,
fp
);
free
(
bf
);
}
va_end
(
ap
);
return
n
;
}
s
ize_t
sort__thread_print
(
FILE
*
fp
,
struct
hist_entry
*
self
,
unsigned
int
width
)
s
tatic
int
hist_entry__thread_snprintf
(
struct
hist_entry
*
self
,
char
*
bf
,
size_t
size
,
unsigned
int
width
)
{
return
repsep_
fprintf
(
fp
,
"%*s:%5d"
,
width
-
6
,
return
repsep_
snprintf
(
bf
,
size
,
"%*s:%5d"
,
width
,
self
->
thread
->
comm
?:
""
,
self
->
thread
->
pid
);
}
s
ize_t
sort__comm_print
(
FILE
*
fp
,
struct
hist_entry
*
self
,
unsigned
int
width
)
s
tatic
int
hist_entry__comm_snprintf
(
struct
hist_entry
*
self
,
char
*
bf
,
size_t
size
,
unsigned
int
width
)
{
return
repsep_
fprintf
(
fp
,
"%*s"
,
width
,
self
->
thread
->
comm
);
return
repsep_
snprintf
(
bf
,
size
,
"%*s"
,
width
,
self
->
thread
->
comm
);
}
/* --sort dso */
...
...
@@ -149,16 +153,16 @@ sort__dso_cmp(struct hist_entry *left, struct hist_entry *right)
return
strcmp
(
dso_name_l
,
dso_name_r
);
}
s
ize_t
sort__dso_print
(
FILE
*
fp
,
struct
hist_entry
*
self
,
unsigned
int
width
)
s
tatic
int
hist_entry__dso_snprintf
(
struct
hist_entry
*
self
,
char
*
bf
,
size_t
size
,
unsigned
int
width
)
{
if
(
self
->
ms
.
map
&&
self
->
ms
.
map
->
dso
)
{
const
char
*
dso_name
=
!
verbose
?
self
->
ms
.
map
->
dso
->
short_name
:
self
->
ms
.
map
->
dso
->
long_name
;
return
repsep_
fprintf
(
fp
,
"%-*s"
,
width
,
dso_name
);
return
repsep_
snprintf
(
bf
,
size
,
"%-*s"
,
width
,
dso_name
);
}
return
repsep_
fprintf
(
fp
,
"%*llx"
,
width
,
(
u64
)
self
->
ip
);
return
repsep_
snprintf
(
bf
,
size
,
"%*Lx"
,
width
,
self
->
ip
);
}
/* --sort symbol */
...
...
@@ -177,22 +181,22 @@ sort__sym_cmp(struct hist_entry *left, struct hist_entry *right)
return
(
int64_t
)(
ip_r
-
ip_l
);
}
size_t
sort__sym_print
(
FILE
*
fp
,
struct
hist_entry
*
self
,
unsigned
int
width
__used
)
static
int
hist_entry__sym_snprintf
(
struct
hist_entry
*
self
,
char
*
bf
,
size_t
size
,
unsigned
int
width
__used
)
{
size_t
ret
=
0
;
if
(
verbose
)
{
char
o
=
self
->
ms
.
map
?
dso__symtab_origin
(
self
->
ms
.
map
->
dso
)
:
'!'
;
ret
+=
repsep_
fprintf
(
fp
,
"%#018llx %c "
,
(
u64
)
self
->
ip
,
o
);
ret
+=
repsep_
snprintf
(
bf
,
size
,
"%#018llx %c "
,
self
->
ip
,
o
);
}
ret
+=
repsep_
fprintf
(
fp
,
"[%c] "
,
self
->
level
);
ret
+=
repsep_
snprintf
(
bf
+
ret
,
size
-
ret
,
"[%c] "
,
self
->
level
);
if
(
self
->
ms
.
sym
)
ret
+=
repsep_fprintf
(
fp
,
"%s"
,
self
->
ms
.
sym
->
name
);
ret
+=
repsep_snprintf
(
bf
+
ret
,
size
-
ret
,
"%s"
,
self
->
ms
.
sym
->
name
);
else
ret
+=
repsep_
fprintf
(
fp
,
"%#016llx"
,
(
u64
)
self
->
ip
);
ret
+=
repsep_
snprintf
(
bf
+
ret
,
size
-
ret
,
"%#016llx"
,
self
->
ip
);
return
ret
;
}
...
...
@@ -231,10 +235,10 @@ sort__parent_cmp(struct hist_entry *left, struct hist_entry *right)
return
strcmp
(
sym_l
->
name
,
sym_r
->
name
);
}
s
ize_t
sort__parent_print
(
FILE
*
fp
,
struct
hist_entry
*
self
,
unsigned
int
width
)
s
tatic
int
hist_entry__parent_snprintf
(
struct
hist_entry
*
self
,
char
*
bf
,
size_t
size
,
unsigned
int
width
)
{
return
repsep_
fprintf
(
fp
,
"%-*s"
,
width
,
return
repsep_
snprintf
(
bf
,
size
,
"%-*s"
,
width
,
self
->
parent
?
self
->
parent
->
name
:
"[other]"
);
}
...
...
@@ -260,9 +264,8 @@ int sort_dimension__add(const char *tok)
char
err
[
BUFSIZ
];
regerror
(
ret
,
&
parent_regex
,
err
,
sizeof
(
err
));
fprintf
(
stderr
,
"Invalid regex: %s
\n
%s"
,
parent_pattern
,
err
);
exit
(
-
1
);
pr_err
(
"Invalid regex: %s
\n
%s"
,
parent_pattern
,
err
);
return
-
EINVAL
;
}
sort__has_parent
=
1
;
}
...
...
tools/perf/util/sort.h
浏览文件 @
70a7c127
...
...
@@ -49,12 +49,12 @@ struct hist_entry {
u64
ip
;
char
level
;
struct
symbol
*
parent
;
struct
callchain_node
callchain
;
union
{
unsigned
long
position
;
struct
hist_entry
*
pair
;
struct
rb_root
sorted_chain
;
};
struct
callchain_node
callchain
[
0
];
};
enum
sort_type
{
...
...
@@ -76,7 +76,8 @@ struct sort_entry {
int64_t
(
*
cmp
)(
struct
hist_entry
*
,
struct
hist_entry
*
);
int64_t
(
*
collapse
)(
struct
hist_entry
*
,
struct
hist_entry
*
);
size_t
(
*
print
)(
FILE
*
fp
,
struct
hist_entry
*
,
unsigned
int
width
);
int
(
*
snprintf
)(
struct
hist_entry
*
self
,
char
*
bf
,
size_t
size
,
unsigned
int
width
);
unsigned
int
*
width
;
bool
elide
;
};
...
...
@@ -86,7 +87,6 @@ extern struct list_head hist_entry__sort_list;
void
setup_sorting
(
const
char
*
const
usagestr
[],
const
struct
option
*
opts
);
extern
int
repsep_fprintf
(
FILE
*
fp
,
const
char
*
fmt
,
...);
extern
size_t
sort__thread_print
(
FILE
*
,
struct
hist_entry
*
,
unsigned
int
);
extern
size_t
sort__comm_print
(
FILE
*
,
struct
hist_entry
*
,
unsigned
int
);
extern
size_t
sort__dso_print
(
FILE
*
,
struct
hist_entry
*
,
unsigned
int
);
...
...
tools/perf/util/string.h
已删除
100644 → 0
浏览文件 @
40b91cd1
#ifndef __PERF_STRING_H_
#define __PERF_STRING_H_
#include <stdbool.h>
#include "types.h"
s64
perf_atoll
(
const
char
*
str
);
char
**
argv_split
(
const
char
*
str
,
int
*
argcp
);
void
argv_free
(
char
**
argv
);
bool
strglobmatch
(
const
char
*
str
,
const
char
*
pat
);
bool
strlazymatch
(
const
char
*
str
,
const
char
*
pat
);
#define _STR(x) #x
#define STR(x) _STR(x)
#endif
/* __PERF_STRING_H */
tools/perf/util/thread.c
浏览文件 @
70a7c127
...
...
@@ -38,15 +38,6 @@ int find_all_tid(int pid, pid_t ** all_tid)
return
ret
;
}
void
map_groups__init
(
struct
map_groups
*
self
)
{
int
i
;
for
(
i
=
0
;
i
<
MAP__NR_TYPES
;
++
i
)
{
self
->
maps
[
i
]
=
RB_ROOT
;
INIT_LIST_HEAD
(
&
self
->
removed_maps
[
i
]);
}
}
static
struct
thread
*
thread__new
(
pid_t
pid
)
{
struct
thread
*
self
=
zalloc
(
sizeof
(
*
self
));
...
...
@@ -62,28 +53,6 @@ static struct thread *thread__new(pid_t pid)
return
self
;
}
static
void
map_groups__flush
(
struct
map_groups
*
self
)
{
int
type
;
for
(
type
=
0
;
type
<
MAP__NR_TYPES
;
type
++
)
{
struct
rb_root
*
root
=
&
self
->
maps
[
type
];
struct
rb_node
*
next
=
rb_first
(
root
);
while
(
next
)
{
struct
map
*
pos
=
rb_entry
(
next
,
struct
map
,
rb_node
);
next
=
rb_next
(
&
pos
->
rb_node
);
rb_erase
(
&
pos
->
rb_node
,
root
);
/*
* We may have references to this map, for
* instance in some hist_entry instances, so
* just move them to a separate list.
*/
list_add_tail
(
&
pos
->
node
,
&
self
->
removed_maps
[
pos
->
type
]);
}
}
}
int
thread__set_comm
(
struct
thread
*
self
,
const
char
*
comm
)
{
int
err
;
...
...
@@ -110,69 +79,10 @@ int thread__comm_len(struct thread *self)
return
self
->
comm_len
;
}
size_t
__map_groups__fprintf_maps
(
struct
map_groups
*
self
,
enum
map_type
type
,
FILE
*
fp
)
{
size_t
printed
=
fprintf
(
fp
,
"%s:
\n
"
,
map_type__name
[
type
]);
struct
rb_node
*
nd
;
for
(
nd
=
rb_first
(
&
self
->
maps
[
type
]);
nd
;
nd
=
rb_next
(
nd
))
{
struct
map
*
pos
=
rb_entry
(
nd
,
struct
map
,
rb_node
);
printed
+=
fprintf
(
fp
,
"Map:"
);
printed
+=
map__fprintf
(
pos
,
fp
);
if
(
verbose
>
2
)
{
printed
+=
dso__fprintf
(
pos
->
dso
,
type
,
fp
);
printed
+=
fprintf
(
fp
,
"--
\n
"
);
}
}
return
printed
;
}
size_t
map_groups__fprintf_maps
(
struct
map_groups
*
self
,
FILE
*
fp
)
{
size_t
printed
=
0
,
i
;
for
(
i
=
0
;
i
<
MAP__NR_TYPES
;
++
i
)
printed
+=
__map_groups__fprintf_maps
(
self
,
i
,
fp
);
return
printed
;
}
static
size_t
__map_groups__fprintf_removed_maps
(
struct
map_groups
*
self
,
enum
map_type
type
,
FILE
*
fp
)
{
struct
map
*
pos
;
size_t
printed
=
0
;
list_for_each_entry
(
pos
,
&
self
->
removed_maps
[
type
],
node
)
{
printed
+=
fprintf
(
fp
,
"Map:"
);
printed
+=
map__fprintf
(
pos
,
fp
);
if
(
verbose
>
1
)
{
printed
+=
dso__fprintf
(
pos
->
dso
,
type
,
fp
);
printed
+=
fprintf
(
fp
,
"--
\n
"
);
}
}
return
printed
;
}
static
size_t
map_groups__fprintf_removed_maps
(
struct
map_groups
*
self
,
FILE
*
fp
)
{
size_t
printed
=
0
,
i
;
for
(
i
=
0
;
i
<
MAP__NR_TYPES
;
++
i
)
printed
+=
__map_groups__fprintf_removed_maps
(
self
,
i
,
fp
);
return
printed
;
}
static
size_t
map_groups__fprintf
(
struct
map_groups
*
self
,
FILE
*
fp
)
{
size_t
printed
=
map_groups__fprintf_maps
(
self
,
fp
);
printed
+=
fprintf
(
fp
,
"Removed maps:
\n
"
);
return
printed
+
map_groups__fprintf_removed_maps
(
self
,
fp
);
}
static
size_t
thread__fprintf
(
struct
thread
*
self
,
FILE
*
fp
)
{
return
fprintf
(
fp
,
"Thread %d %s
\n
"
,
self
->
pid
,
self
->
comm
)
+
map_groups__fprintf
(
&
self
->
mg
,
fp
);
map_groups__fprintf
(
&
self
->
mg
,
verbose
,
fp
);
}
struct
thread
*
perf_session__findnew
(
struct
perf_session
*
self
,
pid_t
pid
)
...
...
@@ -214,87 +124,12 @@ struct thread *perf_session__findnew(struct perf_session *self, pid_t pid)
return
th
;
}
static
int
map_groups__fixup_overlappings
(
struct
map_groups
*
self
,
struct
map
*
map
)
{
struct
rb_root
*
root
=
&
self
->
maps
[
map
->
type
];
struct
rb_node
*
next
=
rb_first
(
root
);
while
(
next
)
{
struct
map
*
pos
=
rb_entry
(
next
,
struct
map
,
rb_node
);
next
=
rb_next
(
&
pos
->
rb_node
);
if
(
!
map__overlap
(
pos
,
map
))
continue
;
if
(
verbose
>=
2
)
{
fputs
(
"overlapping maps:
\n
"
,
stderr
);
map__fprintf
(
map
,
stderr
);
map__fprintf
(
pos
,
stderr
);
}
rb_erase
(
&
pos
->
rb_node
,
root
);
/*
* We may have references to this map, for instance in some
* hist_entry instances, so just move them to a separate
* list.
*/
list_add_tail
(
&
pos
->
node
,
&
self
->
removed_maps
[
map
->
type
]);
/*
* Now check if we need to create new maps for areas not
* overlapped by the new map:
*/
if
(
map
->
start
>
pos
->
start
)
{
struct
map
*
before
=
map__clone
(
pos
);
if
(
before
==
NULL
)
return
-
ENOMEM
;
before
->
end
=
map
->
start
-
1
;
map_groups__insert
(
self
,
before
);
if
(
verbose
>=
2
)
map__fprintf
(
before
,
stderr
);
}
if
(
map
->
end
<
pos
->
end
)
{
struct
map
*
after
=
map__clone
(
pos
);
if
(
after
==
NULL
)
return
-
ENOMEM
;
after
->
start
=
map
->
end
+
1
;
map_groups__insert
(
self
,
after
);
if
(
verbose
>=
2
)
map__fprintf
(
after
,
stderr
);
}
}
return
0
;
}
void
thread__insert_map
(
struct
thread
*
self
,
struct
map
*
map
)
{
map_groups__fixup_overlappings
(
&
self
->
mg
,
map
);
map_groups__fixup_overlappings
(
&
self
->
mg
,
map
,
verbose
,
stderr
);
map_groups__insert
(
&
self
->
mg
,
map
);
}
/*
* XXX This should not really _copy_ te maps, but refcount them.
*/
static
int
map_groups__clone
(
struct
map_groups
*
self
,
struct
map_groups
*
parent
,
enum
map_type
type
)
{
struct
rb_node
*
nd
;
for
(
nd
=
rb_first
(
&
parent
->
maps
[
type
]);
nd
;
nd
=
rb_next
(
nd
))
{
struct
map
*
map
=
rb_entry
(
nd
,
struct
map
,
rb_node
);
struct
map
*
new
=
map__clone
(
map
);
if
(
new
==
NULL
)
return
-
ENOMEM
;
map_groups__insert
(
self
,
new
);
}
return
0
;
}
int
thread__fork
(
struct
thread
*
self
,
struct
thread
*
parent
)
{
int
i
;
...
...
tools/perf/util/util.h
浏览文件 @
70a7c127
...
...
@@ -42,12 +42,14 @@
#define _ALL_SOURCE 1
#define _GNU_SOURCE 1
#define _BSD_SOURCE 1
#define HAS_BOOL
#include <unistd.h>
#include <stdio.h>
#include <sys/stat.h>
#include <sys/statfs.h>
#include <fcntl.h>
#include <stdbool.h>
#include <stddef.h>
#include <stdlib.h>
#include <stdarg.h>
...
...
@@ -78,6 +80,7 @@
#include <pwd.h>
#include <inttypes.h>
#include "../../../include/linux/magic.h"
#include "types.h"
#ifndef NO_ICONV
...
...
@@ -415,4 +418,13 @@ void git_qsort(void *base, size_t nmemb, size_t size,
int
mkdir_p
(
char
*
path
,
mode_t
mode
);
int
copyfile
(
const
char
*
from
,
const
char
*
to
);
s64
perf_atoll
(
const
char
*
str
);
char
**
argv_split
(
const
char
*
str
,
int
*
argcp
);
void
argv_free
(
char
**
argv
);
bool
strglobmatch
(
const
char
*
str
,
const
char
*
pat
);
bool
strlazymatch
(
const
char
*
str
,
const
char
*
pat
);
#define _STR(x) #x
#define STR(x) _STR(x)
#endif
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录