aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf
diff options
context:
space:
mode:
Diffstat (limited to 'tools/perf')
-rw-r--r--tools/perf/builtin-annotate.c2
-rw-r--r--tools/perf/builtin-buildid-list.c4
-rw-r--r--tools/perf/builtin-record.c5
-rw-r--r--tools/perf/builtin-report.c2
-rw-r--r--tools/perf/builtin-sched.c1
-rw-r--r--tools/perf/builtin-top.c2
-rw-r--r--tools/perf/scripts/python/check-perf-trace.py3
-rwxr-xr-xtools/perf/util/PERF-VERSION-GEN17
-rw-r--r--tools/perf/util/callchain.c35
-rw-r--r--tools/perf/util/callchain.h5
-rw-r--r--tools/perf/util/debug.c2
-rw-r--r--tools/perf/util/event.c17
-rw-r--r--tools/perf/util/hist.c2
-rw-r--r--tools/perf/util/newt.c16
-rw-r--r--tools/perf/util/scripting-engines/trace-event-python.c50
-rw-r--r--tools/perf/util/session.c11
-rw-r--r--tools/perf/util/session.h2
-rw-r--r--tools/perf/util/symbol.c35
-rw-r--r--tools/perf/util/symbol.h2
-rw-r--r--tools/perf/util/thread.c11
-rw-r--r--tools/perf/util/thread.h5
21 files changed, 155 insertions, 74 deletions
diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c
index 08278eda31a5..96db5248e995 100644
--- a/tools/perf/builtin-annotate.c
+++ b/tools/perf/builtin-annotate.c
@@ -343,7 +343,7 @@ find_next:
343 continue; 343 continue;
344 } 344 }
345 345
346 if (use_browser) { 346 if (use_browser > 0) {
347 key = hist_entry__tui_annotate(he); 347 key = hist_entry__tui_annotate(he);
348 if (is_exit_key(key)) 348 if (is_exit_key(key))
349 break; 349 break;
diff --git a/tools/perf/builtin-buildid-list.c b/tools/perf/builtin-buildid-list.c
index 44a47e13bd67..99890728409e 100644
--- a/tools/perf/builtin-buildid-list.c
+++ b/tools/perf/builtin-buildid-list.c
@@ -43,8 +43,10 @@ static int __cmd_buildid_list(void)
43 if (session == NULL) 43 if (session == NULL)
44 return -1; 44 return -1;
45 45
46 if (with_hits) 46 if (with_hits) {
47 symbol_conf.full_paths = true;
47 perf_session__process_events(session, &build_id__mark_dso_hit_ops); 48 perf_session__process_events(session, &build_id__mark_dso_hit_ops);
49 }
48 50
49 perf_session__fprintf_dsos_buildid(session, stdout, with_hits); 51 perf_session__fprintf_dsos_buildid(session, stdout, with_hits);
50 52
diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index 9bc89050e6f8..711745f56bba 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -193,7 +193,7 @@ static void sig_handler(int sig)
193 193
194static void sig_atexit(void) 194static void sig_atexit(void)
195{ 195{
196 if (child_pid != -1) 196 if (child_pid > 0)
197 kill(child_pid, SIGTERM); 197 kill(child_pid, SIGTERM);
198 198
199 if (signr == -1) 199 if (signr == -1)
@@ -503,7 +503,6 @@ static int __cmd_record(int argc, const char **argv)
503{ 503{
504 int i, counter; 504 int i, counter;
505 struct stat st; 505 struct stat st;
506 pid_t pid = 0;
507 int flags; 506 int flags;
508 int err; 507 int err;
509 unsigned long waking = 0; 508 unsigned long waking = 0;
@@ -572,7 +571,7 @@ static int __cmd_record(int argc, const char **argv)
572 571
573 if (forks) { 572 if (forks) {
574 child_pid = fork(); 573 child_pid = fork();
575 if (pid < 0) { 574 if (child_pid < 0) {
576 perror("failed to fork"); 575 perror("failed to fork");
577 exit(-1); 576 exit(-1);
578 } 577 }
diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c
index 359205782964..fd7407c7205c 100644
--- a/tools/perf/builtin-report.c
+++ b/tools/perf/builtin-report.c
@@ -107,7 +107,7 @@ static int perf_session__add_hist_entry(struct perf_session *self,
107 goto out_free_syms; 107 goto out_free_syms;
108 err = 0; 108 err = 0;
109 if (symbol_conf.use_callchain) { 109 if (symbol_conf.use_callchain) {
110 err = append_chain(he->callchain, data->callchain, syms); 110 err = append_chain(he->callchain, data->callchain, syms, data->period);
111 if (err) 111 if (err)
112 goto out_free_syms; 112 goto out_free_syms;
113 } 113 }
diff --git a/tools/perf/builtin-sched.c b/tools/perf/builtin-sched.c
index f67bce2a83b4..55f3b5dcc731 100644
--- a/tools/perf/builtin-sched.c
+++ b/tools/perf/builtin-sched.c
@@ -1645,6 +1645,7 @@ static struct perf_event_ops event_ops = {
1645 .sample = process_sample_event, 1645 .sample = process_sample_event,
1646 .comm = event__process_comm, 1646 .comm = event__process_comm,
1647 .lost = event__process_lost, 1647 .lost = event__process_lost,
1648 .fork = event__process_task,
1648 .ordered_samples = true, 1649 .ordered_samples = true,
1649}; 1650};
1650 1651
diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c
index 397290a0a76e..a66f4272b994 100644
--- a/tools/perf/builtin-top.c
+++ b/tools/perf/builtin-top.c
@@ -1060,7 +1060,7 @@ static void event__process_sample(const event_t *self,
1060 pr_err("Can't annotate %s", sym->name); 1060 pr_err("Can't annotate %s", sym->name);
1061 if (sym_filter_entry->map->dso->origin == DSO__ORIG_KERNEL) { 1061 if (sym_filter_entry->map->dso->origin == DSO__ORIG_KERNEL) {
1062 pr_err(": No vmlinux file was found in the path:\n"); 1062 pr_err(": No vmlinux file was found in the path:\n");
1063 vmlinux_path__fprintf(stderr); 1063 machine__fprintf_vmlinux_path(machine, stderr);
1064 } else 1064 } else
1065 pr_err(".\n"); 1065 pr_err(".\n");
1066 exit(1); 1066 exit(1);
diff --git a/tools/perf/scripts/python/check-perf-trace.py b/tools/perf/scripts/python/check-perf-trace.py
index 964d934395ff..d9f7893e315c 100644
--- a/tools/perf/scripts/python/check-perf-trace.py
+++ b/tools/perf/scripts/python/check-perf-trace.py
@@ -51,8 +51,7 @@ def kmem__kmalloc(event_name, context, common_cpu,
51 51
52 flag_str("kmem__kmalloc", "gfp_flags", gfp_flags)), 52 flag_str("kmem__kmalloc", "gfp_flags", gfp_flags)),
53 53
54def trace_unhandled(event_name, context, common_cpu, common_secs, common_nsecs, 54def trace_unhandled(event_name, context, event_fields_dict):
55 common_pid, common_comm):
56 try: 55 try:
57 unhandled[event_name] += 1 56 unhandled[event_name] += 1
58 except TypeError: 57 except TypeError:
diff --git a/tools/perf/util/PERF-VERSION-GEN b/tools/perf/util/PERF-VERSION-GEN
index 49ece7921914..97d76562a1a0 100755
--- a/tools/perf/util/PERF-VERSION-GEN
+++ b/tools/perf/util/PERF-VERSION-GEN
@@ -5,17 +5,13 @@ if [ $# -eq 1 ] ; then
5fi 5fi
6 6
7GVF=${OUTPUT}PERF-VERSION-FILE 7GVF=${OUTPUT}PERF-VERSION-FILE
8DEF_VER=v0.0.2.PERF
9 8
10LF=' 9LF='
11' 10'
12 11
13# First see if there is a version file (included in release tarballs), 12# First check if there is a .git to get the version from git describe
14# then try git-describe, then default. 13# otherwise try to get the version from the kernel makefile
15if test -f version 14if test -d ../../.git -o -f ../../.git &&
16then
17 VN=$(cat version) || VN="$DEF_VER"
18elif test -d .git -o -f .git &&
19 VN=$(git describe --abbrev=4 HEAD 2>/dev/null) && 15 VN=$(git describe --abbrev=4 HEAD 2>/dev/null) &&
20 case "$VN" in 16 case "$VN" in
21 *$LF*) (exit 1) ;; 17 *$LF*) (exit 1) ;;
@@ -27,7 +23,12 @@ elif test -d .git -o -f .git &&
27then 23then
28 VN=$(echo "$VN" | sed -e 's/-/./g'); 24 VN=$(echo "$VN" | sed -e 's/-/./g');
29else 25else
30 VN="$DEF_VER" 26 eval `grep '^VERSION\s*=' ../../Makefile|tr -d ' '`
27 eval `grep '^PATCHLEVEL\s*=' ../../Makefile|tr -d ' '`
28 eval `grep '^SUBLEVEL\s*=' ../../Makefile|tr -d ' '`
29 eval `grep '^EXTRAVERSION\s*=' ../../Makefile|tr -d ' '`
30
31 VN="${VERSION}.${PATCHLEVEL}.${SUBLEVEL}${EXTRAVERSION}"
31fi 32fi
32 33
33VN=$(expr "$VN" : v*'\(.*\)') 34VN=$(expr "$VN" : v*'\(.*\)')
diff --git a/tools/perf/util/callchain.c b/tools/perf/util/callchain.c
index 62b69ad4aa73..52c777e451ed 100644
--- a/tools/perf/util/callchain.c
+++ b/tools/perf/util/callchain.c
@@ -230,7 +230,7 @@ fill_node(struct callchain_node *node, struct resolved_chain *chain, int start)
230 230
231static void 231static void
232add_child(struct callchain_node *parent, struct resolved_chain *chain, 232add_child(struct callchain_node *parent, struct resolved_chain *chain,
233 int start) 233 int start, u64 period)
234{ 234{
235 struct callchain_node *new; 235 struct callchain_node *new;
236 236
@@ -238,7 +238,7 @@ add_child(struct callchain_node *parent, struct resolved_chain *chain,
238 fill_node(new, chain, start); 238 fill_node(new, chain, start);
239 239
240 new->children_hit = 0; 240 new->children_hit = 0;
241 new->hit = 1; 241 new->hit = period;
242} 242}
243 243
244/* 244/*
@@ -248,7 +248,8 @@ add_child(struct callchain_node *parent, struct resolved_chain *chain,
248 */ 248 */
249static void 249static void
250split_add_child(struct callchain_node *parent, struct resolved_chain *chain, 250split_add_child(struct callchain_node *parent, struct resolved_chain *chain,
251 struct callchain_list *to_split, int idx_parents, int idx_local) 251 struct callchain_list *to_split, int idx_parents, int idx_local,
252 u64 period)
252{ 253{
253 struct callchain_node *new; 254 struct callchain_node *new;
254 struct list_head *old_tail; 255 struct list_head *old_tail;
@@ -275,41 +276,41 @@ split_add_child(struct callchain_node *parent, struct resolved_chain *chain,
275 /* create a new child for the new branch if any */ 276 /* create a new child for the new branch if any */
276 if (idx_total < chain->nr) { 277 if (idx_total < chain->nr) {
277 parent->hit = 0; 278 parent->hit = 0;
278 add_child(parent, chain, idx_total); 279 add_child(parent, chain, idx_total, period);
279 parent->children_hit++; 280 parent->children_hit += period;
280 } else { 281 } else {
281 parent->hit = 1; 282 parent->hit = period;
282 } 283 }
283} 284}
284 285
285static int 286static int
286__append_chain(struct callchain_node *root, struct resolved_chain *chain, 287__append_chain(struct callchain_node *root, struct resolved_chain *chain,
287 unsigned int start); 288 unsigned int start, u64 period);
288 289
289static void 290static void
290__append_chain_children(struct callchain_node *root, 291__append_chain_children(struct callchain_node *root,
291 struct resolved_chain *chain, 292 struct resolved_chain *chain,
292 unsigned int start) 293 unsigned int start, u64 period)
293{ 294{
294 struct callchain_node *rnode; 295 struct callchain_node *rnode;
295 296
296 /* lookup in childrens */ 297 /* lookup in childrens */
297 chain_for_each_child(rnode, root) { 298 chain_for_each_child(rnode, root) {
298 unsigned int ret = __append_chain(rnode, chain, start); 299 unsigned int ret = __append_chain(rnode, chain, start, period);
299 300
300 if (!ret) 301 if (!ret)
301 goto inc_children_hit; 302 goto inc_children_hit;
302 } 303 }
303 /* nothing in children, add to the current node */ 304 /* nothing in children, add to the current node */
304 add_child(root, chain, start); 305 add_child(root, chain, start, period);
305 306
306inc_children_hit: 307inc_children_hit:
307 root->children_hit++; 308 root->children_hit += period;
308} 309}
309 310
310static int 311static int
311__append_chain(struct callchain_node *root, struct resolved_chain *chain, 312__append_chain(struct callchain_node *root, struct resolved_chain *chain,
312 unsigned int start) 313 unsigned int start, u64 period)
313{ 314{
314 struct callchain_list *cnode; 315 struct callchain_list *cnode;
315 unsigned int i = start; 316 unsigned int i = start;
@@ -345,18 +346,18 @@ __append_chain(struct callchain_node *root, struct resolved_chain *chain,
345 346
346 /* we match only a part of the node. Split it and add the new chain */ 347 /* we match only a part of the node. Split it and add the new chain */
347 if (i - start < root->val_nr) { 348 if (i - start < root->val_nr) {
348 split_add_child(root, chain, cnode, start, i - start); 349 split_add_child(root, chain, cnode, start, i - start, period);
349 return 0; 350 return 0;
350 } 351 }
351 352
352 /* we match 100% of the path, increment the hit */ 353 /* we match 100% of the path, increment the hit */
353 if (i - start == root->val_nr && i == chain->nr) { 354 if (i - start == root->val_nr && i == chain->nr) {
354 root->hit++; 355 root->hit += period;
355 return 0; 356 return 0;
356 } 357 }
357 358
358 /* We match the node and still have a part remaining */ 359 /* We match the node and still have a part remaining */
359 __append_chain_children(root, chain, i); 360 __append_chain_children(root, chain, i, period);
360 361
361 return 0; 362 return 0;
362} 363}
@@ -380,7 +381,7 @@ static void filter_context(struct ip_callchain *old, struct resolved_chain *new,
380 381
381 382
382int append_chain(struct callchain_node *root, struct ip_callchain *chain, 383int append_chain(struct callchain_node *root, struct ip_callchain *chain,
383 struct map_symbol *syms) 384 struct map_symbol *syms, u64 period)
384{ 385{
385 struct resolved_chain *filtered; 386 struct resolved_chain *filtered;
386 387
@@ -397,7 +398,7 @@ int append_chain(struct callchain_node *root, struct ip_callchain *chain,
397 if (!filtered->nr) 398 if (!filtered->nr)
398 goto end; 399 goto end;
399 400
400 __append_chain_children(root, filtered, 0); 401 __append_chain_children(root, filtered, 0, period);
401end: 402end:
402 free(filtered); 403 free(filtered);
403 404
diff --git a/tools/perf/util/callchain.h b/tools/perf/util/callchain.h
index 1ca73e4a2723..f2e9ee164bd8 100644
--- a/tools/perf/util/callchain.h
+++ b/tools/perf/util/callchain.h
@@ -49,6 +49,9 @@ static inline void callchain_init(struct callchain_node *node)
49 INIT_LIST_HEAD(&node->brothers); 49 INIT_LIST_HEAD(&node->brothers);
50 INIT_LIST_HEAD(&node->children); 50 INIT_LIST_HEAD(&node->children);
51 INIT_LIST_HEAD(&node->val); 51 INIT_LIST_HEAD(&node->val);
52
53 node->parent = NULL;
54 node->hit = 0;
52} 55}
53 56
54static inline u64 cumul_hits(struct callchain_node *node) 57static inline u64 cumul_hits(struct callchain_node *node)
@@ -58,7 +61,7 @@ static inline u64 cumul_hits(struct callchain_node *node)
58 61
59int register_callchain_param(struct callchain_param *param); 62int register_callchain_param(struct callchain_param *param);
60int append_chain(struct callchain_node *root, struct ip_callchain *chain, 63int append_chain(struct callchain_node *root, struct ip_callchain *chain,
61 struct map_symbol *syms); 64 struct map_symbol *syms, u64 period);
62 65
63bool ip_callchain__valid(struct ip_callchain *chain, event_t *event); 66bool ip_callchain__valid(struct ip_callchain *chain, event_t *event);
64#endif /* __PERF_CALLCHAIN_H */ 67#endif /* __PERF_CALLCHAIN_H */
diff --git a/tools/perf/util/debug.c b/tools/perf/util/debug.c
index dd824cf3b628..6cddff2bc970 100644
--- a/tools/perf/util/debug.c
+++ b/tools/perf/util/debug.c
@@ -22,7 +22,7 @@ int eprintf(int level, const char *fmt, ...)
22 22
23 if (verbose >= level) { 23 if (verbose >= level) {
24 va_start(args, fmt); 24 va_start(args, fmt);
25 if (use_browser) 25 if (use_browser > 0)
26 ret = browser__show_help(fmt, args); 26 ret = browser__show_help(fmt, args);
27 else 27 else
28 ret = vfprintf(stderr, fmt, args); 28 ret = vfprintf(stderr, fmt, args);
diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c
index 50771b5813ee..2fbf6a463c81 100644
--- a/tools/perf/util/event.c
+++ b/tools/perf/util/event.c
@@ -370,9 +370,9 @@ static int thread__set_comm_adjust(struct thread *self, const char *comm)
370 370
371int event__process_comm(event_t *self, struct perf_session *session) 371int event__process_comm(event_t *self, struct perf_session *session)
372{ 372{
373 struct thread *thread = perf_session__findnew(session, self->comm.pid); 373 struct thread *thread = perf_session__findnew(session, self->comm.tid);
374 374
375 dump_printf(": %s:%d\n", self->comm.comm, self->comm.pid); 375 dump_printf(": %s:%d\n", self->comm.comm, self->comm.tid);
376 376
377 if (thread == NULL || thread__set_comm_adjust(thread, self->comm.comm)) { 377 if (thread == NULL || thread__set_comm_adjust(thread, self->comm.comm)) {
378 dump_printf("problem processing PERF_RECORD_COMM, skipping event.\n"); 378 dump_printf("problem processing PERF_RECORD_COMM, skipping event.\n");
@@ -532,19 +532,16 @@ out_problem:
532 532
533int event__process_task(event_t *self, struct perf_session *session) 533int event__process_task(event_t *self, struct perf_session *session)
534{ 534{
535 struct thread *thread = perf_session__findnew(session, self->fork.pid); 535 struct thread *thread = perf_session__findnew(session, self->fork.tid);
536 struct thread *parent = perf_session__findnew(session, self->fork.ppid); 536 struct thread *parent = perf_session__findnew(session, self->fork.ptid);
537 537
538 dump_printf("(%d:%d):(%d:%d)\n", self->fork.pid, self->fork.tid, 538 dump_printf("(%d:%d):(%d:%d)\n", self->fork.pid, self->fork.tid,
539 self->fork.ppid, self->fork.ptid); 539 self->fork.ppid, self->fork.ptid);
540 /*
541 * A thread clone will have the same PID for both parent and child.
542 */
543 if (thread == parent)
544 return 0;
545 540
546 if (self->header.type == PERF_RECORD_EXIT) 541 if (self->header.type == PERF_RECORD_EXIT) {
542 perf_session__remove_thread(session, thread);
547 return 0; 543 return 0;
544 }
548 545
549 if (thread == NULL || parent == NULL || 546 if (thread == NULL || parent == NULL ||
550 thread__fork(thread, parent) < 0) { 547 thread__fork(thread, parent) < 0) {
diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c
index cbf7eae2ce09..07f89b66b318 100644
--- a/tools/perf/util/hist.c
+++ b/tools/perf/util/hist.c
@@ -965,7 +965,7 @@ static int hist_entry__parse_objdump_line(struct hist_entry *self, FILE *file,
965 * Parse hexa addresses followed by ':' 965 * Parse hexa addresses followed by ':'
966 */ 966 */
967 line_ip = strtoull(tmp, &tmp2, 16); 967 line_ip = strtoull(tmp, &tmp2, 16);
968 if (*tmp2 != ':') 968 if (*tmp2 != ':' || tmp == tmp2)
969 line_ip = -1; 969 line_ip = -1;
970 } 970 }
971 971
diff --git a/tools/perf/util/newt.c b/tools/perf/util/newt.c
index d54c540f49db..7537ca15900b 100644
--- a/tools/perf/util/newt.c
+++ b/tools/perf/util/newt.c
@@ -43,6 +43,9 @@ struct ui_progress *ui_progress__new(const char *title, u64 total)
43 43
44 if (self != NULL) { 44 if (self != NULL) {
45 int cols; 45 int cols;
46
47 if (use_browser <= 0)
48 return self;
46 newtGetScreenSize(&cols, NULL); 49 newtGetScreenSize(&cols, NULL);
47 cols -= 4; 50 cols -= 4;
48 newtCenteredWindow(cols, 1, title); 51 newtCenteredWindow(cols, 1, title);
@@ -67,14 +70,22 @@ out_free_self:
67 70
68void ui_progress__update(struct ui_progress *self, u64 curr) 71void ui_progress__update(struct ui_progress *self, u64 curr)
69{ 72{
73 /*
74 * FIXME: We should have a per UI backend way of showing progress,
75 * stdio will just show a percentage as NN%, etc.
76 */
77 if (use_browser <= 0)
78 return;
70 newtScaleSet(self->scale, curr); 79 newtScaleSet(self->scale, curr);
71 newtRefresh(); 80 newtRefresh();
72} 81}
73 82
74void ui_progress__delete(struct ui_progress *self) 83void ui_progress__delete(struct ui_progress *self)
75{ 84{
76 newtFormDestroy(self->form); 85 if (use_browser > 0) {
77 newtPopWindow(); 86 newtFormDestroy(self->form);
87 newtPopWindow();
88 }
78 free(self); 89 free(self);
79} 90}
80 91
@@ -1139,6 +1150,7 @@ void setup_browser(void)
1139 struct newtPercentTreeColors *c = &defaultPercentTreeColors; 1150 struct newtPercentTreeColors *c = &defaultPercentTreeColors;
1140 1151
1141 if (!isatty(1) || !use_browser || dump_trace) { 1152 if (!isatty(1) || !use_browser || dump_trace) {
1153 use_browser = 0;
1142 setup_pager(); 1154 setup_pager();
1143 return; 1155 return;
1144 } 1156 }
diff --git a/tools/perf/util/scripting-engines/trace-event-python.c b/tools/perf/util/scripting-engines/trace-event-python.c
index 81f39cab3aaa..33a632523743 100644
--- a/tools/perf/util/scripting-engines/trace-event-python.c
+++ b/tools/perf/util/scripting-engines/trace-event-python.c
@@ -208,7 +208,7 @@ static void python_process_event(int cpu, void *data,
208 int size __unused, 208 int size __unused,
209 unsigned long long nsecs, char *comm) 209 unsigned long long nsecs, char *comm)
210{ 210{
211 PyObject *handler, *retval, *context, *t, *obj; 211 PyObject *handler, *retval, *context, *t, *obj, *dict = NULL;
212 static char handler_name[256]; 212 static char handler_name[256];
213 struct format_field *field; 213 struct format_field *field;
214 unsigned long long val; 214 unsigned long long val;
@@ -232,6 +232,14 @@ static void python_process_event(int cpu, void *data,
232 232
233 sprintf(handler_name, "%s__%s", event->system, event->name); 233 sprintf(handler_name, "%s__%s", event->system, event->name);
234 234
235 handler = PyDict_GetItemString(main_dict, handler_name);
236 if (handler && !PyCallable_Check(handler))
237 handler = NULL;
238 if (!handler) {
239 dict = PyDict_New();
240 if (!dict)
241 Py_FatalError("couldn't create Python dict");
242 }
235 s = nsecs / NSECS_PER_SEC; 243 s = nsecs / NSECS_PER_SEC;
236 ns = nsecs - s * NSECS_PER_SEC; 244 ns = nsecs - s * NSECS_PER_SEC;
237 245
@@ -242,12 +250,20 @@ static void python_process_event(int cpu, void *data,
242 PyTuple_SetItem(t, n++, PyString_FromString(handler_name)); 250 PyTuple_SetItem(t, n++, PyString_FromString(handler_name));
243 PyTuple_SetItem(t, n++, 251 PyTuple_SetItem(t, n++,
244 PyCObject_FromVoidPtr(scripting_context, NULL)); 252 PyCObject_FromVoidPtr(scripting_context, NULL));
245 PyTuple_SetItem(t, n++, PyInt_FromLong(cpu));
246 PyTuple_SetItem(t, n++, PyInt_FromLong(s));
247 PyTuple_SetItem(t, n++, PyInt_FromLong(ns));
248 PyTuple_SetItem(t, n++, PyInt_FromLong(pid));
249 PyTuple_SetItem(t, n++, PyString_FromString(comm));
250 253
254 if (handler) {
255 PyTuple_SetItem(t, n++, PyInt_FromLong(cpu));
256 PyTuple_SetItem(t, n++, PyInt_FromLong(s));
257 PyTuple_SetItem(t, n++, PyInt_FromLong(ns));
258 PyTuple_SetItem(t, n++, PyInt_FromLong(pid));
259 PyTuple_SetItem(t, n++, PyString_FromString(comm));
260 } else {
261 PyDict_SetItemString(dict, "common_cpu", PyInt_FromLong(cpu));
262 PyDict_SetItemString(dict, "common_s", PyInt_FromLong(s));
263 PyDict_SetItemString(dict, "common_ns", PyInt_FromLong(ns));
264 PyDict_SetItemString(dict, "common_pid", PyInt_FromLong(pid));
265 PyDict_SetItemString(dict, "common_comm", PyString_FromString(comm));
266 }
251 for (field = event->format.fields; field; field = field->next) { 267 for (field = event->format.fields; field; field = field->next) {
252 if (field->flags & FIELD_IS_STRING) { 268 if (field->flags & FIELD_IS_STRING) {
253 int offset; 269 int offset;
@@ -272,27 +288,31 @@ static void python_process_event(int cpu, void *data,
272 obj = PyLong_FromUnsignedLongLong(val); 288 obj = PyLong_FromUnsignedLongLong(val);
273 } 289 }
274 } 290 }
275 PyTuple_SetItem(t, n++, obj); 291 if (handler)
292 PyTuple_SetItem(t, n++, obj);
293 else
294 PyDict_SetItemString(dict, field->name, obj);
295
276 } 296 }
297 if (!handler)
298 PyTuple_SetItem(t, n++, dict);
277 299
278 if (_PyTuple_Resize(&t, n) == -1) 300 if (_PyTuple_Resize(&t, n) == -1)
279 Py_FatalError("error resizing Python tuple"); 301 Py_FatalError("error resizing Python tuple");
280 302
281 handler = PyDict_GetItemString(main_dict, handler_name); 303 if (handler) {
282 if (handler && PyCallable_Check(handler)) {
283 retval = PyObject_CallObject(handler, t); 304 retval = PyObject_CallObject(handler, t);
284 if (retval == NULL) 305 if (retval == NULL)
285 handler_call_die(handler_name); 306 handler_call_die(handler_name);
286 } else { 307 } else {
287 handler = PyDict_GetItemString(main_dict, "trace_unhandled"); 308 handler = PyDict_GetItemString(main_dict, "trace_unhandled");
288 if (handler && PyCallable_Check(handler)) { 309 if (handler && PyCallable_Check(handler)) {
289 if (_PyTuple_Resize(&t, N_COMMON_FIELDS) == -1)
290 Py_FatalError("error resizing Python tuple");
291 310
292 retval = PyObject_CallObject(handler, t); 311 retval = PyObject_CallObject(handler, t);
293 if (retval == NULL) 312 if (retval == NULL)
294 handler_call_die("trace_unhandled"); 313 handler_call_die("trace_unhandled");
295 } 314 }
315 Py_DECREF(dict);
296 } 316 }
297 317
298 Py_DECREF(t); 318 Py_DECREF(t);
@@ -548,12 +568,10 @@ static int python_generate_script(const char *outfile)
548 } 568 }
549 569
550 fprintf(ofp, "def trace_unhandled(event_name, context, " 570 fprintf(ofp, "def trace_unhandled(event_name, context, "
551 "common_cpu, common_secs, common_nsecs,\n\t\t" 571 "event_fields_dict):\n");
552 "common_pid, common_comm):\n");
553 572
554 fprintf(ofp, "\t\tprint_header(event_name, common_cpu, " 573 fprintf(ofp, "\t\tprint ' '.join(['%%s=%%s'%%(k,str(v))"
555 "common_secs, common_nsecs,\n\t\tcommon_pid, " 574 "for k,v in sorted(event_fields_dict.items())])\n\n");
556 "common_comm)\n\n");
557 575
558 fprintf(ofp, "def print_header(" 576 fprintf(ofp, "def print_header("
559 "event_name, cpu, secs, nsecs, pid, comm):\n" 577 "event_name, cpu, secs, nsecs, pid, comm):\n"
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
index 8f83a1835766..c422cd676313 100644
--- a/tools/perf/util/session.c
+++ b/tools/perf/util/session.c
@@ -90,6 +90,7 @@ struct perf_session *perf_session__new(const char *filename, int mode, bool forc
90 90
91 memcpy(self->filename, filename, len); 91 memcpy(self->filename, filename, len);
92 self->threads = RB_ROOT; 92 self->threads = RB_ROOT;
93 INIT_LIST_HEAD(&self->dead_threads);
93 self->hists_tree = RB_ROOT; 94 self->hists_tree = RB_ROOT;
94 self->last_match = NULL; 95 self->last_match = NULL;
95 self->mmap_window = 32; 96 self->mmap_window = 32;
@@ -131,6 +132,16 @@ void perf_session__delete(struct perf_session *self)
131 free(self); 132 free(self);
132} 133}
133 134
135void perf_session__remove_thread(struct perf_session *self, struct thread *th)
136{
137 rb_erase(&th->rb_node, &self->threads);
138 /*
139 * We may have references to this thread, for instance in some hist_entry
140 * instances, so just move them to a separate list.
141 */
142 list_add_tail(&th->node, &self->dead_threads);
143}
144
134static bool symbol__match_parent_regex(struct symbol *sym) 145static bool symbol__match_parent_regex(struct symbol *sym)
135{ 146{
136 if (sym->name && !regexec(&parent_regex, sym->name, 0, NULL, 0)) 147 if (sym->name && !regexec(&parent_regex, sym->name, 0, NULL, 0))
diff --git a/tools/perf/util/session.h b/tools/perf/util/session.h
index 55c6881b218d..9fa0fc2a863f 100644
--- a/tools/perf/util/session.h
+++ b/tools/perf/util/session.h
@@ -26,6 +26,7 @@ struct perf_session {
26 unsigned long size; 26 unsigned long size;
27 unsigned long mmap_window; 27 unsigned long mmap_window;
28 struct rb_root threads; 28 struct rb_root threads;
29 struct list_head dead_threads;
29 struct thread *last_match; 30 struct thread *last_match;
30 struct machine host_machine; 31 struct machine host_machine;
31 struct rb_root machines; 32 struct rb_root machines;
@@ -99,6 +100,7 @@ int perf_session__create_kernel_maps(struct perf_session *self);
99 100
100int do_read(int fd, void *buf, size_t size); 101int do_read(int fd, void *buf, size_t size);
101void perf_session__update_sample_type(struct perf_session *self); 102void perf_session__update_sample_type(struct perf_session *self);
103void perf_session__remove_thread(struct perf_session *self, struct thread *th);
102 104
103static inline 105static inline
104struct machine *perf_session__find_host_machine(struct perf_session *self) 106struct machine *perf_session__find_host_machine(struct perf_session *self)
diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c
index aaa51ba147df..b63e5713849f 100644
--- a/tools/perf/util/symbol.c
+++ b/tools/perf/util/symbol.c
@@ -1695,9 +1695,20 @@ int dso__load_vmlinux_path(struct dso *self, struct map *map,
1695 symbol_filter_t filter) 1695 symbol_filter_t filter)
1696{ 1696{
1697 int i, err = 0; 1697 int i, err = 0;
1698 char *filename;
1698 1699
1699 pr_debug("Looking at the vmlinux_path (%d entries long)\n", 1700 pr_debug("Looking at the vmlinux_path (%d entries long)\n",
1700 vmlinux_path__nr_entries); 1701 vmlinux_path__nr_entries + 1);
1702
1703 filename = dso__build_id_filename(self, NULL, 0);
1704 if (filename != NULL) {
1705 err = dso__load_vmlinux(self, map, filename, filter);
1706 if (err > 0) {
1707 dso__set_long_name(self, filename);
1708 goto out;
1709 }
1710 free(filename);
1711 }
1701 1712
1702 for (i = 0; i < vmlinux_path__nr_entries; ++i) { 1713 for (i = 0; i < vmlinux_path__nr_entries; ++i) {
1703 err = dso__load_vmlinux(self, map, vmlinux_path[i], filter); 1714 err = dso__load_vmlinux(self, map, vmlinux_path[i], filter);
@@ -1706,7 +1717,7 @@ int dso__load_vmlinux_path(struct dso *self, struct map *map,
1706 break; 1717 break;
1707 } 1718 }
1708 } 1719 }
1709 1720out:
1710 return err; 1721 return err;
1711} 1722}
1712 1723
@@ -1734,7 +1745,12 @@ static int dso__load_kernel_sym(struct dso *self, struct map *map,
1734 if (symbol_conf.vmlinux_name != NULL) { 1745 if (symbol_conf.vmlinux_name != NULL) {
1735 err = dso__load_vmlinux(self, map, 1746 err = dso__load_vmlinux(self, map,
1736 symbol_conf.vmlinux_name, filter); 1747 symbol_conf.vmlinux_name, filter);
1737 goto out_try_fixup; 1748 if (err > 0) {
1749 dso__set_long_name(self,
1750 strdup(symbol_conf.vmlinux_name));
1751 goto out_fixup;
1752 }
1753 return err;
1738 } 1754 }
1739 1755
1740 if (vmlinux_path != NULL) { 1756 if (vmlinux_path != NULL) {
@@ -1795,7 +1811,6 @@ do_kallsyms:
1795 pr_debug("Using %s for symbols\n", kallsyms_filename); 1811 pr_debug("Using %s for symbols\n", kallsyms_filename);
1796 free(kallsyms_allocated_filename); 1812 free(kallsyms_allocated_filename);
1797 1813
1798out_try_fixup:
1799 if (err > 0) { 1814 if (err > 0) {
1800out_fixup: 1815out_fixup:
1801 if (kallsyms_filename != NULL) 1816 if (kallsyms_filename != NULL)
@@ -2102,13 +2117,21 @@ out_fail:
2102 return -1; 2117 return -1;
2103} 2118}
2104 2119
2105size_t vmlinux_path__fprintf(FILE *fp) 2120size_t machine__fprintf_vmlinux_path(struct machine *self, FILE *fp)
2106{ 2121{
2107 int i; 2122 int i;
2108 size_t printed = 0; 2123 size_t printed = 0;
2124 struct dso *kdso = self->vmlinux_maps[MAP__FUNCTION]->dso;
2125
2126 if (kdso->has_build_id) {
2127 char filename[PATH_MAX];
2128 if (dso__build_id_filename(kdso, filename, sizeof(filename)))
2129 printed += fprintf(fp, "[0] %s\n", filename);
2130 }
2109 2131
2110 for (i = 0; i < vmlinux_path__nr_entries; ++i) 2132 for (i = 0; i < vmlinux_path__nr_entries; ++i)
2111 printed += fprintf(fp, "[%d] %s\n", i, vmlinux_path[i]); 2133 printed += fprintf(fp, "[%d] %s\n",
2134 i + kdso->has_build_id, vmlinux_path[i]);
2112 2135
2113 return printed; 2136 return printed;
2114} 2137}
diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h
index 5d25b5eb1456..5e02d2c17154 100644
--- a/tools/perf/util/symbol.h
+++ b/tools/perf/util/symbol.h
@@ -216,6 +216,6 @@ int machines__create_guest_kernel_maps(struct rb_root *self);
216int symbol__init(void); 216int symbol__init(void);
217bool symbol_type__is_a(char symbol_type, enum map_type map_type); 217bool symbol_type__is_a(char symbol_type, enum map_type map_type);
218 218
219size_t vmlinux_path__fprintf(FILE *fp); 219size_t machine__fprintf_vmlinux_path(struct machine *self, FILE *fp);
220 220
221#endif /* __PERF_SYMBOL */ 221#endif /* __PERF_SYMBOL */
diff --git a/tools/perf/util/thread.c b/tools/perf/util/thread.c
index 1f7ecd47f499..9a448b47400c 100644
--- a/tools/perf/util/thread.c
+++ b/tools/perf/util/thread.c
@@ -7,6 +7,15 @@
7#include "util.h" 7#include "util.h"
8#include "debug.h" 8#include "debug.h"
9 9
10/* Skip "." and ".." directories */
11static int filter(const struct dirent *dir)
12{
13 if (dir->d_name[0] == '.')
14 return 0;
15 else
16 return 1;
17}
18
10int find_all_tid(int pid, pid_t ** all_tid) 19int find_all_tid(int pid, pid_t ** all_tid)
11{ 20{
12 char name[256]; 21 char name[256];
@@ -16,7 +25,7 @@ int find_all_tid(int pid, pid_t ** all_tid)
16 int i; 25 int i;
17 26
18 sprintf(name, "/proc/%d/task", pid); 27 sprintf(name, "/proc/%d/task", pid);
19 items = scandir(name, &namelist, NULL, NULL); 28 items = scandir(name, &namelist, filter, NULL);
20 if (items <= 0) 29 if (items <= 0)
21 return -ENOENT; 30 return -ENOENT;
22 *all_tid = malloc(sizeof(pid_t) * items); 31 *all_tid = malloc(sizeof(pid_t) * items);
diff --git a/tools/perf/util/thread.h b/tools/perf/util/thread.h
index 1dfd9ff8bdcd..ee6bbcf277ca 100644
--- a/tools/perf/util/thread.h
+++ b/tools/perf/util/thread.h
@@ -6,7 +6,10 @@
6#include "symbol.h" 6#include "symbol.h"
7 7
8struct thread { 8struct thread {
9 struct rb_node rb_node; 9 union {
10 struct rb_node rb_node;
11 struct list_head node;
12 };
10 struct map_groups mg; 13 struct map_groups mg;
11 pid_t pid; 14 pid_t pid;
12 char shortname[3]; 15 char shortname[3];