diff options
Diffstat (limited to 'tools/perf')
| -rw-r--r-- | tools/perf/builtin-annotate.c | 2 | ||||
| -rw-r--r-- | tools/perf/builtin-buildid-list.c | 4 | ||||
| -rw-r--r-- | tools/perf/builtin-record.c | 5 | ||||
| -rw-r--r-- | tools/perf/builtin-report.c | 2 | ||||
| -rw-r--r-- | tools/perf/builtin-sched.c | 1 | ||||
| -rw-r--r-- | tools/perf/builtin-top.c | 2 | ||||
| -rw-r--r-- | tools/perf/scripts/python/check-perf-trace.py | 3 | ||||
| -rwxr-xr-x | tools/perf/util/PERF-VERSION-GEN | 17 | ||||
| -rw-r--r-- | tools/perf/util/callchain.c | 35 | ||||
| -rw-r--r-- | tools/perf/util/callchain.h | 5 | ||||
| -rw-r--r-- | tools/perf/util/debug.c | 2 | ||||
| -rw-r--r-- | tools/perf/util/event.c | 17 | ||||
| -rw-r--r-- | tools/perf/util/hist.c | 2 | ||||
| -rw-r--r-- | tools/perf/util/newt.c | 16 | ||||
| -rw-r--r-- | tools/perf/util/scripting-engines/trace-event-python.c | 50 | ||||
| -rw-r--r-- | tools/perf/util/session.c | 11 | ||||
| -rw-r--r-- | tools/perf/util/session.h | 2 | ||||
| -rw-r--r-- | tools/perf/util/symbol.c | 35 | ||||
| -rw-r--r-- | tools/perf/util/symbol.h | 2 | ||||
| -rw-r--r-- | tools/perf/util/thread.c | 11 | ||||
| -rw-r--r-- | tools/perf/util/thread.h | 5 |
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 | ||
| 194 | static void sig_atexit(void) | 194 | static 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 | ||
| 54 | def trace_unhandled(event_name, context, common_cpu, common_secs, common_nsecs, | 54 | def 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 | |||
| 5 | fi | 5 | fi |
| 6 | 6 | ||
| 7 | GVF=${OUTPUT}PERF-VERSION-FILE | 7 | GVF=${OUTPUT}PERF-VERSION-FILE |
| 8 | DEF_VER=v0.0.2.PERF | ||
| 9 | 8 | ||
| 10 | LF=' | 9 | LF=' |
| 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 |
| 15 | if test -f version | 14 | if test -d ../../.git -o -f ../../.git && |
| 16 | then | ||
| 17 | VN=$(cat version) || VN="$DEF_VER" | ||
| 18 | elif 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 && | |||
| 27 | then | 23 | then |
| 28 | VN=$(echo "$VN" | sed -e 's/-/./g'); | 24 | VN=$(echo "$VN" | sed -e 's/-/./g'); |
| 29 | else | 25 | else |
| 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}" | ||
| 31 | fi | 32 | fi |
| 32 | 33 | ||
| 33 | VN=$(expr "$VN" : v*'\(.*\)') | 34 | VN=$(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 | ||
| 231 | static void | 231 | static void |
| 232 | add_child(struct callchain_node *parent, struct resolved_chain *chain, | 232 | add_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 | */ |
| 249 | static void | 249 | static void |
| 250 | split_add_child(struct callchain_node *parent, struct resolved_chain *chain, | 250 | split_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 | ||
| 285 | static int | 286 | static 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 | ||
| 289 | static void | 290 | static 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 | ||
| 306 | inc_children_hit: | 307 | inc_children_hit: |
| 307 | root->children_hit++; | 308 | root->children_hit += period; |
| 308 | } | 309 | } |
| 309 | 310 | ||
| 310 | static int | 311 | static 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 | ||
| 382 | int append_chain(struct callchain_node *root, struct ip_callchain *chain, | 383 | int 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); |
| 401 | end: | 402 | end: |
| 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 | ||
| 54 | static inline u64 cumul_hits(struct callchain_node *node) | 57 | static inline u64 cumul_hits(struct callchain_node *node) |
| @@ -58,7 +61,7 @@ static inline u64 cumul_hits(struct callchain_node *node) | |||
| 58 | 61 | ||
| 59 | int register_callchain_param(struct callchain_param *param); | 62 | int register_callchain_param(struct callchain_param *param); |
| 60 | int append_chain(struct callchain_node *root, struct ip_callchain *chain, | 63 | int append_chain(struct callchain_node *root, struct ip_callchain *chain, |
| 61 | struct map_symbol *syms); | 64 | struct map_symbol *syms, u64 period); |
| 62 | 65 | ||
| 63 | bool ip_callchain__valid(struct ip_callchain *chain, event_t *event); | 66 | bool 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 | ||
| 371 | int event__process_comm(event_t *self, struct perf_session *session) | 371 | int 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 | ||
| 533 | int event__process_task(event_t *self, struct perf_session *session) | 533 | int 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 | ||
| 68 | void ui_progress__update(struct ui_progress *self, u64 curr) | 71 | void 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 | ||
| 74 | void ui_progress__delete(struct ui_progress *self) | 83 | void 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 | ||
| 135 | void 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 | |||
| 134 | static bool symbol__match_parent_regex(struct symbol *sym) | 145 | static 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 | ||
| 100 | int do_read(int fd, void *buf, size_t size); | 101 | int do_read(int fd, void *buf, size_t size); |
| 101 | void perf_session__update_sample_type(struct perf_session *self); | 102 | void perf_session__update_sample_type(struct perf_session *self); |
| 103 | void perf_session__remove_thread(struct perf_session *self, struct thread *th); | ||
| 102 | 104 | ||
| 103 | static inline | 105 | static inline |
| 104 | struct machine *perf_session__find_host_machine(struct perf_session *self) | 106 | struct 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 | 1720 | out: | |
| 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 | ||
| 1798 | out_try_fixup: | ||
| 1799 | if (err > 0) { | 1814 | if (err > 0) { |
| 1800 | out_fixup: | 1815 | out_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 | ||
| 2105 | size_t vmlinux_path__fprintf(FILE *fp) | 2120 | size_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); | |||
| 216 | int symbol__init(void); | 216 | int symbol__init(void); |
| 217 | bool symbol_type__is_a(char symbol_type, enum map_type map_type); | 217 | bool symbol_type__is_a(char symbol_type, enum map_type map_type); |
| 218 | 218 | ||
| 219 | size_t vmlinux_path__fprintf(FILE *fp); | 219 | size_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 */ | ||
| 11 | static int filter(const struct dirent *dir) | ||
| 12 | { | ||
| 13 | if (dir->d_name[0] == '.') | ||
| 14 | return 0; | ||
| 15 | else | ||
| 16 | return 1; | ||
| 17 | } | ||
| 18 | |||
| 10 | int find_all_tid(int pid, pid_t ** all_tid) | 19 | int 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 | ||
| 8 | struct thread { | 8 | struct 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]; |
