From 848cbd2562bb85953884be72b3bdbee0b2f32474 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Fri, 15 May 2015 15:20:44 -0300 Subject: [PATCH 01/18] perf tools: Use atomic.h for the map_groups refcount Now that we have atomic.h, we should convert all of the existing refcounts to use it. Cc: Adrian Hunter Cc: Borislav Petkov Cc: David Ahern Cc: Don Zickus Cc: Frederic Weisbecker Cc: Jiri Olsa Cc: Namhyung Kim Cc: Stephane Eranian Link: http://lkml.kernel.org/n/tip-onm5u3pioba1hqqhjs8on03e@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/tests/thread-mg-share.c | 12 ++++++------ tools/perf/util/map.c | 4 ++-- tools/perf/util/map.h | 6 ++++-- 3 files changed, 12 insertions(+), 10 deletions(-) diff --git a/tools/perf/tests/thread-mg-share.c b/tools/perf/tests/thread-mg-share.c index c0ed56f7efc6..01fabb19d746 100644 --- a/tools/perf/tests/thread-mg-share.c +++ b/tools/perf/tests/thread-mg-share.c @@ -43,7 +43,7 @@ int test__thread_mg_share(void) leader && t1 && t2 && t3 && other); mg = leader->mg; - TEST_ASSERT_EQUAL("wrong refcnt", mg->refcnt, 4); + TEST_ASSERT_EQUAL("wrong refcnt", atomic_read(&mg->refcnt), 4); /* test the map groups pointer is shared */ TEST_ASSERT_VAL("map groups don't match", mg == t1->mg); @@ -71,25 +71,25 @@ int test__thread_mg_share(void) machine__remove_thread(machine, other_leader); other_mg = other->mg; - TEST_ASSERT_EQUAL("wrong refcnt", other_mg->refcnt, 2); + TEST_ASSERT_EQUAL("wrong refcnt", atomic_read(&other_mg->refcnt), 2); TEST_ASSERT_VAL("map groups don't match", other_mg == other_leader->mg); /* release thread group */ thread__put(leader); - TEST_ASSERT_EQUAL("wrong refcnt", mg->refcnt, 3); + TEST_ASSERT_EQUAL("wrong refcnt", atomic_read(&mg->refcnt), 3); thread__put(t1); - TEST_ASSERT_EQUAL("wrong refcnt", mg->refcnt, 2); + TEST_ASSERT_EQUAL("wrong refcnt", atomic_read(&mg->refcnt), 2); thread__put(t2); - TEST_ASSERT_EQUAL("wrong refcnt", mg->refcnt, 1); + TEST_ASSERT_EQUAL("wrong refcnt", atomic_read(&mg->refcnt), 1); thread__put(t3); /* release other group */ thread__put(other_leader); - TEST_ASSERT_EQUAL("wrong refcnt", other_mg->refcnt, 1); + TEST_ASSERT_EQUAL("wrong refcnt", atomic_read(&other_mg->refcnt), 1); thread__put(other); diff --git a/tools/perf/util/map.c b/tools/perf/util/map.c index cd0e335008b4..2d20c5ff8653 100644 --- a/tools/perf/util/map.c +++ b/tools/perf/util/map.c @@ -426,7 +426,7 @@ void map_groups__init(struct map_groups *mg, struct machine *machine) INIT_LIST_HEAD(&mg->removed_maps[i]); } mg->machine = machine; - mg->refcnt = 1; + atomic_set(&mg->refcnt, 1); } static void maps__delete(struct rb_root *maps) @@ -494,7 +494,7 @@ void map_groups__delete(struct map_groups *mg) void map_groups__put(struct map_groups *mg) { - if (--mg->refcnt == 0) + if (mg && atomic_dec_and_test(&mg->refcnt)) map_groups__delete(mg); } diff --git a/tools/perf/util/map.h b/tools/perf/util/map.h index 4e0c729841ab..7f39217d29bf 100644 --- a/tools/perf/util/map.h +++ b/tools/perf/util/map.h @@ -1,6 +1,7 @@ #ifndef __PERF_MAP_H #define __PERF_MAP_H +#include #include #include #include @@ -61,7 +62,7 @@ struct map_groups { struct rb_root maps[MAP__NR_TYPES]; struct list_head removed_maps[MAP__NR_TYPES]; struct machine *machine; - int refcnt; + atomic_t refcnt; }; struct map_groups *map_groups__new(struct machine *machine); @@ -70,7 +71,8 @@ bool map_groups__empty(struct map_groups *mg); static inline struct map_groups *map_groups__get(struct map_groups *mg) { - ++mg->refcnt; + if (mg) + atomic_inc(&mg->refcnt); return mg; } From 59a51c1dc9fbb3fb4af928b852d7b35df83edd74 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Fri, 15 May 2015 15:32:55 -0300 Subject: [PATCH 02/18] perf machine: Stop accessing atomic_t::counter directly Use atomic_read(&counter) instead. Cc: Adrian Hunter Cc: Borislav Petkov Cc: David Ahern Cc: Don Zickus Cc: Frederic Weisbecker Cc: Jiri Olsa Cc: Namhyung Kim Cc: Stephane Eranian Link: http://lkml.kernel.org/n/tip-k3hvfvpaut8wp02lzq27muhb@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/machine.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/perf/util/machine.c b/tools/perf/util/machine.c index 34bf89f7f4f3..daa55910ff28 100644 --- a/tools/perf/util/machine.c +++ b/tools/perf/util/machine.c @@ -1311,7 +1311,7 @@ static void __machine__remove_thread(struct machine *machine, struct thread *th, if (machine->last_match == th) machine->last_match = NULL; - BUG_ON(th->refcnt.counter == 0); + BUG_ON(atomic_read(&th->refcnt) == 0); if (lock) pthread_rwlock_wrlock(&machine->threads_lock); rb_erase(&th->rb_node, &machine->threads); From 7143849a5d6a5c623d81790d92f0033507c5b14f Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Fri, 15 May 2015 15:45:16 -0300 Subject: [PATCH 03/18] perf evlist: Use atomic.h for the perf_mmap refcount Now that we have atomic.h, we should convert all of the existing refcounts to use it. Cc: Adrian Hunter Cc: Borislav Petkov Cc: David Ahern Cc: Don Zickus Cc: Frederic Weisbecker Cc: Jiri Olsa Cc: Namhyung Kim Cc: Stephane Eranian Link: http://lkml.kernel.org/n/tip-qhpv2etncj3hfofgj1aitkyv@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/evlist.c | 12 ++++++------ tools/perf/util/evlist.h | 3 ++- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c index 7ec1bf93ab28..dc1dc2c181ef 100644 --- a/tools/perf/util/evlist.c +++ b/tools/perf/util/evlist.c @@ -700,14 +700,14 @@ static bool perf_mmap__empty(struct perf_mmap *md) static void perf_evlist__mmap_get(struct perf_evlist *evlist, int idx) { - ++evlist->mmap[idx].refcnt; + atomic_inc(&evlist->mmap[idx].refcnt); } static void perf_evlist__mmap_put(struct perf_evlist *evlist, int idx) { - BUG_ON(evlist->mmap[idx].refcnt == 0); + BUG_ON(atomic_read(&evlist->mmap[idx].refcnt) == 0); - if (--evlist->mmap[idx].refcnt == 0) + if (atomic_dec_and_test(&evlist->mmap[idx].refcnt)) __perf_evlist__munmap(evlist, idx); } @@ -721,7 +721,7 @@ void perf_evlist__mmap_consume(struct perf_evlist *evlist, int idx) perf_mmap__write_tail(md, old); } - if (md->refcnt == 1 && perf_mmap__empty(md)) + if (atomic_read(&md->refcnt) == 1 && perf_mmap__empty(md)) perf_evlist__mmap_put(evlist, idx); } @@ -758,7 +758,7 @@ static void __perf_evlist__munmap(struct perf_evlist *evlist, int idx) if (evlist->mmap[idx].base != NULL) { munmap(evlist->mmap[idx].base, evlist->mmap_len); evlist->mmap[idx].base = NULL; - evlist->mmap[idx].refcnt = 0; + atomic_set(&evlist->mmap[idx].refcnt, 0); } auxtrace_mmap__munmap(&evlist->mmap[idx].auxtrace_mmap); } @@ -807,7 +807,7 @@ static int __perf_evlist__mmap(struct perf_evlist *evlist, int idx, * evlist layer can't just drop it when filtering events in * perf_evlist__filter_pollfd(). */ - evlist->mmap[idx].refcnt = 2; + atomic_set(&evlist->mmap[idx].refcnt, 2); evlist->mmap[idx].prev = 0; evlist->mmap[idx].mask = mp->mask; evlist->mmap[idx].base = mmap(NULL, evlist->mmap_len, mp->prot, diff --git a/tools/perf/util/evlist.h b/tools/perf/util/evlist.h index c07b1a94a724..670e7f2114b1 100644 --- a/tools/perf/util/evlist.h +++ b/tools/perf/util/evlist.h @@ -1,6 +1,7 @@ #ifndef __PERF_EVLIST_H #define __PERF_EVLIST_H 1 +#include #include #include #include @@ -27,7 +28,7 @@ struct record_opts; struct perf_mmap { void *base; int mask; - int refcnt; + atomic_t refcnt; u64 prev; struct auxtrace_mmap auxtrace_mmap; char event_copy[PERF_SAMPLE_MAX_SIZE] __attribute__((aligned(8))); From f812d3045c2385ac16237e68b156859c4005526e Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Fri, 15 May 2015 16:12:20 -0300 Subject: [PATCH 04/18] perf cgroup: Use atomic.h for refcounting Now that we have atomic.h, we should convert all of the existing refcounts to use it. Cc: Adrian Hunter Cc: Borislav Petkov Cc: David Ahern Cc: Don Zickus Cc: Frederic Weisbecker Cc: Jiri Olsa Cc: Namhyung Kim Cc: Stephane Eranian Link: http://lkml.kernel.org/n/tip-t3v2uma5digcj2tpkrs3m84u@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/cgroup.c | 10 +++------- tools/perf/util/cgroup.h | 4 +++- 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/tools/perf/util/cgroup.c b/tools/perf/util/cgroup.c index 88f7be399432..32e12ecfe9c5 100644 --- a/tools/perf/util/cgroup.c +++ b/tools/perf/util/cgroup.c @@ -115,23 +115,19 @@ static int add_cgroup(struct perf_evlist *evlist, char *str) goto found; n++; } - if (cgrp->refcnt == 0) + if (atomic_read(&cgrp->refcnt) == 0) free(cgrp); return -1; found: - cgrp->refcnt++; + atomic_inc(&cgrp->refcnt); counter->cgrp = cgrp; return 0; } void close_cgroup(struct cgroup_sel *cgrp) { - if (!cgrp) - return; - - /* XXX: not reentrant */ - if (--cgrp->refcnt == 0) { + if (cgrp && atomic_dec_and_test(&cgrp->refcnt)) { close(cgrp->fd); zfree(&cgrp->name); free(cgrp); diff --git a/tools/perf/util/cgroup.h b/tools/perf/util/cgroup.h index 89acd6debdc5..b4b8cb42fe5e 100644 --- a/tools/perf/util/cgroup.h +++ b/tools/perf/util/cgroup.h @@ -1,12 +1,14 @@ #ifndef __CGROUP_H__ #define __CGROUP_H__ +#include + struct option; struct cgroup_sel { char *name; int fd; - int refcnt; + atomic_t refcnt; }; From c1b9034db7c85428f96db4ecf77abbf02d96de71 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Fri, 15 May 2015 18:23:11 +0200 Subject: [PATCH 05/18] perf tools: Fix dwarf-aux.c compilation on i386 Replacing %lu format strings for Dwarf_Addr type with PRIu64 as it fits for Dwarf_Addr (defined as uint64_t) type and works also on both 32/64 bits. Signed-off-by: Jiri Olsa Cc: David Ahern Cc: He Kuang Cc: Namhyung Kim Cc: Paul Mackerras Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/1431706991-15646-1-git-send-email-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/dwarf-aux.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tools/perf/util/dwarf-aux.c b/tools/perf/util/dwarf-aux.c index eb47abdcf0ac..57f3ef41c2bc 100644 --- a/tools/perf/util/dwarf-aux.c +++ b/tools/perf/util/dwarf-aux.c @@ -994,11 +994,11 @@ static int die_get_var_innermost_scope(Dwarf_Die *sp_die, Dwarf_Die *vr_die, end -= entry; if (first) { - strbuf_addf(buf, "@<%s+[%lu-%lu", + strbuf_addf(buf, "@<%s+[%" PRIu64 "-%" PRIu64, name, start, end); first = false; } else { - strbuf_addf(buf, ",%lu-%lu", + strbuf_addf(buf, ",%" PRIu64 "-%" PRIu64, start, end); } } @@ -1057,11 +1057,11 @@ int die_get_var_range(Dwarf_Die *sp_die, Dwarf_Die *vr_die, struct strbuf *buf) start -= entry; end -= entry; if (first) { - strbuf_addf(buf, "@<%s+[%lu-%lu", + strbuf_addf(buf, "@<%s+[%" PRIu64 "-%" PRIu64, name, start, end); first = false; } else { - strbuf_addf(buf, ",%lu-%lu", + strbuf_addf(buf, ",%" PRIu64 "-%" PRIu64, start, end); } } From 2f15bd8c6c6e80f15c899ea84b53fa607a2f08b2 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Fri, 15 May 2015 17:54:28 +0200 Subject: [PATCH 06/18] perf tools: Fix "Command" sort_entry's cmp and collapse function Currently the se_cmp and se_collapse use pointer comparison, which is ok for for testing equality of strings. It's not ok as comparing function for rbtree insertion, because it gives different results based on current pointer values. We saw test 32 (hists cumulation test) failing based on different environment setup. Having all sort functions straightened fix the test for us. Reported-by: Jan Stancek Signed-off-by: Jiri Olsa Cc: David Ahern Cc: Jan Stancek Cc: Namhyung Kim Cc: Paul Mackerras Cc: Peter Zijlstra Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/sort.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/perf/util/sort.c b/tools/perf/util/sort.c index 4593f36ecc4c..09d4696fd9a1 100644 --- a/tools/perf/util/sort.c +++ b/tools/perf/util/sort.c @@ -89,14 +89,14 @@ static int64_t sort__comm_cmp(struct hist_entry *left, struct hist_entry *right) { /* Compare the addr that should be unique among comm */ - return comm__str(right->comm) - comm__str(left->comm); + return strcmp(comm__str(right->comm), comm__str(left->comm)); } static int64_t sort__comm_collapse(struct hist_entry *left, struct hist_entry *right) { /* Compare the addr that should be unique among comm */ - return comm__str(right->comm) - comm__str(left->comm); + return strcmp(comm__str(right->comm), comm__str(left->comm)); } static int64_t From 75e4a2a6af15e956993913314ced2582b350a647 Mon Sep 17 00:00:00 2001 From: Wang Nan Date: Fri, 15 May 2015 12:14:44 +0000 Subject: [PATCH 07/18] perf probe: Load map before glob matching Commit 4c859351226c920b227fec040a3b447f0d482af3 ("perf probe: Support glob wildcards for function name") introduces a problem: # /root/perf probe kmem_cache_free Failed to find symbol kmem_cache_free in kernel Error: Failed to add events. The reason is the replacement of map__for_each_symbol_by_name() (by map__for_each_symbol()). Although their names are similar, map__for_each_symbol doesn't call map__load() and dso__sort_by_name() before searching. The missing of map__load() causes this problem because it search symbol before load dso map. This patch ensures map__load() is called before using map__for_each_symbol(). After this patch: # /root/perf probe kmem_cache_free Added new event: probe:kmem_cache_free (on kmem_cache_free%return) You can now use it in all perf tools, such as: perf record -e probe:kmem_cache_free -aR sleep 1 Signed-off-by: Wang Nan Acked-by: Masami Hiramatsu Cc: Namhyung Kim Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Zefan Li Cc: pi3orama@163.com Link: http://lkml.kernel.org/r/1431692084-46287-1-git-send-email-wangnan0@huawei.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/probe-event.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c index 2399dc4f6089..1faa1e67398b 100644 --- a/tools/perf/util/probe-event.c +++ b/tools/perf/util/probe-event.c @@ -2499,6 +2499,9 @@ static int find_probe_functions(struct map *map, char *name) struct symbol *sym; struct rb_node *tmp; + if (map__load(map, NULL) < 0) + return 0; + map__for_each_symbol(map, sym, tmp) { if (strglobmatch(sym->name, name)) found++; From 70ba6b8f975bcff56e180e2c7550d2302fcbf923 Mon Sep 17 00:00:00 2001 From: Wang Nan Date: Fri, 15 May 2015 07:50:57 +0000 Subject: [PATCH 08/18] tools include: add __aligned_u64 to types.h. Following patches will introduce linux/bpf.h to a new libbpf library, which requires definition of __aligned_u64. This patch add it to the common types.h for tools. Signed-off-by: Wang Nan Cc: Adrian Hunter Cc: Alexei Starovoitov Cc: Brendan Gregg Cc: Daniel Borkmann Cc: David Ahern Cc: Jiri Olsa Cc: Masami Hiramatsu Cc: Namhyung Kim Cc: Paul Mackerras Cc: Peter Zijlstra Cc: pi3orama@163.com Cc: Zefan Li Link: http://lkml.kernel.org/r/1431676290-1230-5-git-send-email-wangnan0@huawei.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/include/linux/types.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tools/include/linux/types.h b/tools/include/linux/types.h index 0bdeda66aae5..8ebf6278b2ef 100644 --- a/tools/include/linux/types.h +++ b/tools/include/linux/types.h @@ -64,6 +64,10 @@ typedef struct { int counter; } atomic_t; +#ifndef __aligned_u64 +# define __aligned_u64 __u64 __attribute__((aligned(8))) +#endif + struct list_head { struct list_head *next, *prev; }; From 86066064e3e545338e9b48b49256d5e51213915a Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Fri, 15 May 2015 17:29:56 -0300 Subject: [PATCH 09/18] perf tools: Elliminate alignment holes perf_evsel: Before: /* size: 320, cachelines: 5, members: 35 */ /* sum members: 304, holes: 3, sum holes: 16 */ After: /* size: 304, cachelines: 5, members: 35 */ /* last cacheline: 48 bytes */ perf_evlist: Before: /* size: 2544, cachelines: 40, members: 17 */ /* sum members: 2533, holes: 2, sum holes: 11 */ /* last cacheline: 48 bytes */ After: /* size: 2536, cachelines: 40, members: 17 */ /* sum members: 2533, holes: 1, sum holes: 3 */ /* last cacheline: 40 bytes */ timechart: Before: /* size: 288, cachelines: 5, members: 21 */ /* sum members: 271, holes: 2, sum holes: 10 */ /* padding: 7 */ /* last cacheline: 32 bytes */ After: /* size: 272, cachelines: 5, members: 21 */ /* sum members: 271, holes: 1, sum holes: 1 */ /* last cacheline: 16 bytes */ thread: Before: /* size: 112, cachelines: 2, members: 15 */ /* sum members: 101, holes: 2, sum holes: 11 */ /* last cacheline: 48 bytes */ After: /* size: 104, cachelines: 2, members: 15 */ /* sum members: 101, holes: 1, sum holes: 3 */ /* last cacheline: 40 bytes */ Cc: Adrian Hunter Cc: Borislav Petkov Cc: David Ahern Cc: Don Zickus Cc: Frederic Weisbecker Cc: Jiri Olsa Cc: Namhyung Kim Cc: Stephane Eranian Link: http://lkml.kernel.org/n/tip-a543w7zjl9yyrg9nkf1teukp@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-timechart.c | 4 ++-- tools/perf/util/evlist.h | 2 +- tools/perf/util/evsel.h | 4 ++-- tools/perf/util/thread.h | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/tools/perf/builtin-timechart.c b/tools/perf/builtin-timechart.c index 3b884e37ab8b..30e59620179d 100644 --- a/tools/perf/builtin-timechart.c +++ b/tools/perf/builtin-timechart.c @@ -61,13 +61,13 @@ struct timechart { tasks_only, with_backtrace, topology; + bool force; /* IO related settings */ - u64 io_events; bool io_only, skip_eagain; + u64 io_events; u64 min_time, merge_dist; - bool force; }; struct per_pidcomm; diff --git a/tools/perf/util/evlist.h b/tools/perf/util/evlist.h index 670e7f2114b1..955bf31b7dd3 100644 --- a/tools/perf/util/evlist.h +++ b/tools/perf/util/evlist.h @@ -40,6 +40,7 @@ struct perf_evlist { int nr_entries; int nr_groups; int nr_mmaps; + bool overwrite; size_t mmap_len; int id_pos; int is_pos; @@ -48,7 +49,6 @@ struct perf_evlist { int cork_fd; pid_t pid; } workload; - bool overwrite; struct fdarray pollfd; struct perf_mmap *mmap; struct thread_map *threads; diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h index e486151b0308..21ec08247d47 100644 --- a/tools/perf/util/evsel.h +++ b/tools/perf/util/evsel.h @@ -73,7 +73,6 @@ struct perf_evsel { char *name; double scale; const char *unit; - bool snapshot; struct event_format *tp_format; union { void *priv; @@ -86,6 +85,7 @@ struct perf_evsel { unsigned int sample_size; int id_pos; int is_pos; + bool snapshot; bool supported; bool needs_swap; bool no_aux_samples; @@ -93,11 +93,11 @@ struct perf_evsel { bool system_wide; bool tracking; bool per_pkg; - unsigned long *per_pkg_mask; /* parse modifier helper */ int exclude_GH; int nr_members; int sample_read; + unsigned long *per_pkg_mask; struct perf_evsel *leader; char *group_name; }; diff --git a/tools/perf/util/thread.h b/tools/perf/util/thread.h index f33c48cfdaa0..a0ac0317affb 100644 --- a/tools/perf/util/thread.h +++ b/tools/perf/util/thread.h @@ -25,9 +25,9 @@ struct thread { atomic_t refcnt; char shortname[3]; bool comm_set; + int comm_len; bool dead; /* if set thread has exited */ struct list_head comm_list; - int comm_len; u64 db_id; void *priv; From 0b1de0be1eac7b23e89cb43c17b02d38ead6b6c8 Mon Sep 17 00:00:00 2001 From: Namhyung Kim Date: Mon, 18 May 2015 09:30:17 +0900 Subject: [PATCH 10/18] perf tools: Add rm_rf() utility function The rm_rf() function does same as the shell command 'rm -rf' which removes all directory entries recursively. Signed-off-by: Namhyung Kim Acked-by: Jiri Olsa Cc: Adrian Hunter Cc: Andi Kleen Cc: David Ahern Cc: Frederic Weisbecker Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lkml.kernel.org/r/1431909055-21442-3-git-send-email-namhyung@kernel.org Link: http://lkml.kernel.org/r/20150130150256.GF6188@krava.brq.redhat.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/util.c | 43 ++++++++++++++++++++++++++++++++++++++++++ tools/perf/util/util.h | 1 + 2 files changed, 44 insertions(+) diff --git a/tools/perf/util/util.c b/tools/perf/util/util.c index 4ee6d0d4c993..6104afb7e1ef 100644 --- a/tools/perf/util/util.c +++ b/tools/perf/util/util.c @@ -72,6 +72,49 @@ int mkdir_p(char *path, mode_t mode) return (stat(path, &st) && mkdir(path, mode)) ? -1 : 0; } +int rm_rf(char *path) +{ + DIR *dir; + int ret = 0; + struct dirent *d; + char namebuf[PATH_MAX]; + + dir = opendir(path); + if (dir == NULL) + return 0; + + while ((d = readdir(dir)) != NULL && !ret) { + struct stat statbuf; + + if (!strcmp(d->d_name, ".") || !strcmp(d->d_name, "..")) + continue; + + scnprintf(namebuf, sizeof(namebuf), "%s/%s", + path, d->d_name); + + ret = stat(namebuf, &statbuf); + if (ret < 0) { + pr_debug("stat failed: %s\n", namebuf); + break; + } + + if (S_ISREG(statbuf.st_mode)) + ret = unlink(namebuf); + else if (S_ISDIR(statbuf.st_mode)) + ret = rm_rf(namebuf); + else { + pr_debug("unknown file: %s\n", namebuf); + ret = -1; + } + } + closedir(dir); + + if (ret < 0) + return ret; + + return rmdir(path); +} + static int slow_copyfile(const char *from, const char *to, mode_t mode) { int err = -1; diff --git a/tools/perf/util/util.h b/tools/perf/util/util.h index 3601ffd3d8b4..c4fe38ac8c00 100644 --- a/tools/perf/util/util.h +++ b/tools/perf/util/util.h @@ -249,6 +249,7 @@ static inline int sane_case(int x, int high) } int mkdir_p(char *path, mode_t mode); +int rm_rf(char *path); int copyfile(const char *from, const char *to); int copyfile_mode(const char *from, const char *to, mode_t mode); From 9c9f5a2f1944e8b6bf2b618d04b31e1c1760637e Mon Sep 17 00:00:00 2001 From: Namhyung Kim Date: Mon, 18 May 2015 09:30:18 +0900 Subject: [PATCH 11/18] perf tools: Introduce copyfile_offset() function The copyfile_offset() function is to copy source data from given offset to a destination file with an offset. It'll be used to build an indexed data file. Signed-off-by: Namhyung Kim Acked-by: Jiri Olsa Cc: Adrian Hunter Cc: Andi Kleen Cc: David Ahern Cc: Frederic Weisbecker Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lkml.kernel.org/r/20150304145824.GD7519@krava.brq.redhat.com Link: http://lkml.kernel.org/r/1431909055-21442-4-git-send-email-namhyung@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/util.c | 38 +++++++++++++++++++++++++++++--------- tools/perf/util/util.h | 1 + 2 files changed, 30 insertions(+), 9 deletions(-) diff --git a/tools/perf/util/util.c b/tools/perf/util/util.c index 6104afb7e1ef..0c264bc685ac 100644 --- a/tools/perf/util/util.c +++ b/tools/perf/util/util.c @@ -145,11 +145,38 @@ out: return err; } +int copyfile_offset(int ifd, loff_t off_in, int ofd, loff_t off_out, u64 size) +{ + void *ptr; + loff_t pgoff; + + pgoff = off_in & ~(page_size - 1); + off_in -= pgoff; + + ptr = mmap(NULL, off_in + size, PROT_READ, MAP_PRIVATE, ifd, pgoff); + if (ptr == MAP_FAILED) + return -1; + + while (size) { + ssize_t ret = pwrite(ofd, ptr + off_in, size, off_out); + if (ret < 0 && errno == EINTR) + continue; + if (ret <= 0) + break; + + size -= ret; + off_in += ret; + off_out -= ret; + } + munmap(ptr, off_in + size); + + return size ? -1 : 0; +} + int copyfile_mode(const char *from, const char *to, mode_t mode) { int fromfd, tofd; struct stat st; - void *addr; int err = -1; if (stat(from, &st)) @@ -166,15 +193,8 @@ int copyfile_mode(const char *from, const char *to, mode_t mode) if (tofd < 0) goto out_close_from; - addr = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fromfd, 0); - if (addr == MAP_FAILED) - goto out_close_to; + err = copyfile_offset(fromfd, 0, tofd, 0, st.st_size); - if (write(tofd, addr, st.st_size) == st.st_size) - err = 0; - - munmap(addr, st.st_size); -out_close_to: close(tofd); if (err) unlink(to); diff --git a/tools/perf/util/util.h b/tools/perf/util/util.h index c4fe38ac8c00..8bce58b47a82 100644 --- a/tools/perf/util/util.h +++ b/tools/perf/util/util.h @@ -252,6 +252,7 @@ int mkdir_p(char *path, mode_t mode); int rm_rf(char *path); int copyfile(const char *from, const char *to); int copyfile_mode(const char *from, const char *to, mode_t mode); +int copyfile_offset(int fromfd, loff_t from_ofs, int tofd, loff_t to_ofs, u64 size); s64 perf_atoll(const char *str); char **argv_split(const char *str, int *argcp); From 4a936edc317005e8cd2b501e7865721bec104544 Mon Sep 17 00:00:00 2001 From: Namhyung Kim Date: Mon, 18 May 2015 09:30:40 +0900 Subject: [PATCH 12/18] perf symbols: Protect dso symbol loading using a mutex Add mutex to protect it from concurrent dso__load(). Signed-off-by: Namhyung Kim Cc: Adrian Hunter Cc: Andi Kleen Cc: David Ahern Cc: Frederic Weisbecker Cc: Jiri Olsa Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lkml.kernel.org/r/1431909055-21442-26-git-send-email-namhyung@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/dso.c | 2 ++ tools/perf/util/dso.h | 1 + tools/perf/util/symbol.c | 34 ++++++++++++++++++++++++---------- 3 files changed, 27 insertions(+), 10 deletions(-) diff --git a/tools/perf/util/dso.c b/tools/perf/util/dso.c index 13d9ae0bd15c..482d6024ef13 100644 --- a/tools/perf/util/dso.c +++ b/tools/perf/util/dso.c @@ -936,6 +936,7 @@ struct dso *dso__new(const char *name) RB_CLEAR_NODE(&dso->rb_node); INIT_LIST_HEAD(&dso->node); INIT_LIST_HEAD(&dso->data.open_entry); + pthread_mutex_init(&dso->lock, NULL); } return dso; @@ -966,6 +967,7 @@ void dso__delete(struct dso *dso) dso_cache__free(&dso->data.cache); dso__free_a2l(dso); zfree(&dso->symsrc_filename); + pthread_mutex_destroy(&dso->lock); free(dso); } diff --git a/tools/perf/util/dso.h b/tools/perf/util/dso.h index 3d79c749934c..b26ec3ab1336 100644 --- a/tools/perf/util/dso.h +++ b/tools/perf/util/dso.h @@ -129,6 +129,7 @@ struct dsos { struct auxtrace_cache; struct dso { + pthread_mutex_t lock; struct list_head node; struct rb_node rb_node; /* rbtree node sorted by long name */ struct rb_root symbols[MAP__NR_TYPES]; diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c index 45ba48a7acb3..9ef8b8946b11 100644 --- a/tools/perf/util/symbol.c +++ b/tools/perf/util/symbol.c @@ -1383,12 +1383,22 @@ int dso__load(struct dso *dso, struct map *map, symbol_filter_t filter) struct symsrc *syms_ss = NULL, *runtime_ss = NULL; bool kmod; - dso__set_loaded(dso, map->type); + pthread_mutex_lock(&dso->lock); - if (dso->kernel == DSO_TYPE_KERNEL) - return dso__load_kernel_sym(dso, map, filter); - else if (dso->kernel == DSO_TYPE_GUEST_KERNEL) - return dso__load_guest_kernel_sym(dso, map, filter); + /* check again under the dso->lock */ + if (dso__loaded(dso, map->type)) { + ret = 1; + goto out; + } + + if (dso->kernel) { + if (dso->kernel == DSO_TYPE_KERNEL) + ret = dso__load_kernel_sym(dso, map, filter); + else if (dso->kernel == DSO_TYPE_GUEST_KERNEL) + ret = dso__load_guest_kernel_sym(dso, map, filter); + + goto out; + } if (map->groups && map->groups->machine) machine = map->groups->machine; @@ -1401,18 +1411,18 @@ int dso__load(struct dso *dso, struct map *map, symbol_filter_t filter) struct stat st; if (lstat(dso->name, &st) < 0) - return -1; + goto out; if (st.st_uid && (st.st_uid != geteuid())) { pr_warning("File %s not owned by current user or root, " "ignoring it.\n", dso->name); - return -1; + goto out; } ret = dso__load_perf_map(dso, map, filter); dso->symtab_type = ret > 0 ? DSO_BINARY_TYPE__JAVA_JIT : DSO_BINARY_TYPE__NOT_FOUND; - return ret; + goto out; } if (machine) @@ -1420,7 +1430,7 @@ int dso__load(struct dso *dso, struct map *map, symbol_filter_t filter) name = malloc(PATH_MAX); if (!name) - return -1; + goto out; kmod = dso->symtab_type == DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE || dso->symtab_type == DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE_COMP || @@ -1501,7 +1511,11 @@ int dso__load(struct dso *dso, struct map *map, symbol_filter_t filter) out_free: free(name); if (ret < 0 && strstr(dso->name, " (deleted)") != NULL) - return 0; + ret = 0; +out: + dso__set_loaded(dso, map->type); + pthread_mutex_unlock(&dso->lock); + return ret; } From 8e67b7258e582998ab635bdc3c884d7a8077af5b Mon Sep 17 00:00:00 2001 From: Namhyung Kim Date: Mon, 18 May 2015 09:30:41 +0900 Subject: [PATCH 13/18] perf symbols: Protect dso cache tree using dso->lock The dso cache is accessed during dwarf callchain unwind and it might be processed concurrently. Protect it under dso->lock. Note that it doesn't protect dso_cache__find(). I think it's safe to access to the cache tree without the lock since we don't delete nodes. It it missed an existing node due to rotation, it'll find it during dso_cache__insert() anyway. Signed-off-by: Namhyung Kim Cc: Adrian Hunter Cc: Andi Kleen Cc: David Ahern Cc: Frederic Weisbecker Cc: Jiri Olsa Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lkml.kernel.org/r/1431909055-21442-27-git-send-email-namhyung@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/dso.c | 34 +++++++++++++++++++++++++++------- 1 file changed, 27 insertions(+), 7 deletions(-) diff --git a/tools/perf/util/dso.c b/tools/perf/util/dso.c index 482d6024ef13..666e1db44541 100644 --- a/tools/perf/util/dso.c +++ b/tools/perf/util/dso.c @@ -495,10 +495,12 @@ bool dso__data_status_seen(struct dso *dso, enum dso_data_status_seen by) } static void -dso_cache__free(struct rb_root *root) +dso_cache__free(struct dso *dso) { + struct rb_root *root = &dso->data.cache; struct rb_node *next = rb_first(root); + pthread_mutex_lock(&dso->lock); while (next) { struct dso_cache *cache; @@ -507,10 +509,12 @@ dso_cache__free(struct rb_root *root) rb_erase(&cache->rb_node, root); free(cache); } + pthread_mutex_unlock(&dso->lock); } -static struct dso_cache *dso_cache__find(const struct rb_root *root, u64 offset) +static struct dso_cache *dso_cache__find(struct dso *dso, u64 offset) { + const struct rb_root *root = &dso->data.cache; struct rb_node * const *p = &root->rb_node; const struct rb_node *parent = NULL; struct dso_cache *cache; @@ -529,17 +533,20 @@ static struct dso_cache *dso_cache__find(const struct rb_root *root, u64 offset) else return cache; } + return NULL; } -static void -dso_cache__insert(struct rb_root *root, struct dso_cache *new) +static struct dso_cache * +dso_cache__insert(struct dso *dso, struct dso_cache *new) { + struct rb_root *root = &dso->data.cache; struct rb_node **p = &root->rb_node; struct rb_node *parent = NULL; struct dso_cache *cache; u64 offset = new->offset; + pthread_mutex_lock(&dso->lock); while (*p != NULL) { u64 end; @@ -551,10 +558,17 @@ dso_cache__insert(struct rb_root *root, struct dso_cache *new) p = &(*p)->rb_left; else if (offset >= end) p = &(*p)->rb_right; + else + goto out; } rb_link_node(&new->rb_node, parent, p); rb_insert_color(&new->rb_node, root); + + cache = NULL; +out: + pthread_mutex_unlock(&dso->lock); + return cache; } static ssize_t @@ -572,6 +586,7 @@ static ssize_t dso_cache__read(struct dso *dso, u64 offset, u8 *data, ssize_t size) { struct dso_cache *cache; + struct dso_cache *old; ssize_t ret; do { @@ -591,7 +606,12 @@ dso_cache__read(struct dso *dso, u64 offset, u8 *data, ssize_t size) cache->offset = cache_offset; cache->size = ret; - dso_cache__insert(&dso->data.cache, cache); + old = dso_cache__insert(dso, cache); + if (old) { + /* we lose the race */ + free(cache); + cache = old; + } ret = dso_cache__memcpy(cache, offset, data, size); @@ -608,7 +628,7 @@ static ssize_t dso_cache_read(struct dso *dso, u64 offset, { struct dso_cache *cache; - cache = dso_cache__find(&dso->data.cache, offset); + cache = dso_cache__find(dso, offset); if (cache) return dso_cache__memcpy(cache, offset, data, size); else @@ -964,7 +984,7 @@ void dso__delete(struct dso *dso) dso__data_close(dso); auxtrace_cache__free(dso->auxtrace_cache); - dso_cache__free(&dso->data.cache); + dso_cache__free(dso); dso__free_a2l(dso); zfree(&dso->symsrc_filename); pthread_mutex_destroy(&dso->lock); From 33bdedcea2d77231fe46b1204cf6fc3a7d7c96c9 Mon Sep 17 00:00:00 2001 From: Namhyung Kim Date: Mon, 18 May 2015 09:30:42 +0900 Subject: [PATCH 14/18] perf tools: Protect dso cache fd with a mutex When dso cache is accessed in multi-thread environment, it's possible to close other dso->data.fd during operation due to open file limit. Protect the file descriptors using a separate mutex. Signed-off-by: Namhyung Kim Cc: Adrian Hunter Cc: Andi Kleen Cc: David Ahern Cc: Frederic Weisbecker Cc: Jiri Olsa Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lkml.kernel.org/r/1431909055-21442-28-git-send-email-namhyung@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/dso.c | 98 +++++++++++++++++++++++++++++++------------ 1 file changed, 72 insertions(+), 26 deletions(-) diff --git a/tools/perf/util/dso.c b/tools/perf/util/dso.c index 666e1db44541..1b96c8d18435 100644 --- a/tools/perf/util/dso.c +++ b/tools/perf/util/dso.c @@ -265,6 +265,7 @@ int __kmod_path__parse(struct kmod_path *m, const char *path, */ static LIST_HEAD(dso__data_open); static long dso__data_open_cnt; +static pthread_mutex_t dso__data_open_lock = PTHREAD_MUTEX_INITIALIZER; static void dso__list_add(struct dso *dso) { @@ -434,7 +435,9 @@ static void check_data_close(void) */ void dso__data_close(struct dso *dso) { + pthread_mutex_lock(&dso__data_open_lock); close_dso(dso); + pthread_mutex_unlock(&dso__data_open_lock); } /** @@ -457,6 +460,8 @@ int dso__data_fd(struct dso *dso, struct machine *machine) if (dso->data.status == DSO_DATA_STATUS_ERROR) return -1; + pthread_mutex_lock(&dso__data_open_lock); + if (dso->data.fd >= 0) goto out; @@ -479,6 +484,7 @@ out: else dso->data.status = DSO_DATA_STATUS_ERROR; + pthread_mutex_unlock(&dso__data_open_lock); return dso->data.fd; } @@ -583,7 +589,8 @@ dso_cache__memcpy(struct dso_cache *cache, u64 offset, } static ssize_t -dso_cache__read(struct dso *dso, u64 offset, u8 *data, ssize_t size) +dso_cache__read(struct dso *dso, struct machine *machine, + u64 offset, u8 *data, ssize_t size) { struct dso_cache *cache; struct dso_cache *old; @@ -592,11 +599,24 @@ dso_cache__read(struct dso *dso, u64 offset, u8 *data, ssize_t size) do { u64 cache_offset; - ret = -ENOMEM; - cache = zalloc(sizeof(*cache) + DSO__DATA_CACHE_SIZE); if (!cache) - break; + return -ENOMEM; + + pthread_mutex_lock(&dso__data_open_lock); + + /* + * dso->data.fd might be closed if other thread opened another + * file (dso) due to open file limit (RLIMIT_NOFILE). + */ + if (dso->data.fd < 0) { + dso->data.fd = open_dso(dso, machine); + if (dso->data.fd < 0) { + ret = -errno; + dso->data.status = DSO_DATA_STATUS_ERROR; + break; + } + } cache_offset = offset & DSO__DATA_CACHE_MASK; @@ -606,6 +626,11 @@ dso_cache__read(struct dso *dso, u64 offset, u8 *data, ssize_t size) cache->offset = cache_offset; cache->size = ret; + } while (0); + + pthread_mutex_unlock(&dso__data_open_lock); + + if (ret > 0) { old = dso_cache__insert(dso, cache); if (old) { /* we lose the race */ @@ -614,8 +639,7 @@ dso_cache__read(struct dso *dso, u64 offset, u8 *data, ssize_t size) } ret = dso_cache__memcpy(cache, offset, data, size); - - } while (0); + } if (ret <= 0) free(cache); @@ -623,8 +647,8 @@ dso_cache__read(struct dso *dso, u64 offset, u8 *data, ssize_t size) return ret; } -static ssize_t dso_cache_read(struct dso *dso, u64 offset, - u8 *data, ssize_t size) +static ssize_t dso_cache_read(struct dso *dso, struct machine *machine, + u64 offset, u8 *data, ssize_t size) { struct dso_cache *cache; @@ -632,7 +656,7 @@ static ssize_t dso_cache_read(struct dso *dso, u64 offset, if (cache) return dso_cache__memcpy(cache, offset, data, size); else - return dso_cache__read(dso, offset, data, size); + return dso_cache__read(dso, machine, offset, data, size); } /* @@ -640,7 +664,8 @@ static ssize_t dso_cache_read(struct dso *dso, u64 offset, * in the rb_tree. Any read to already cached data is served * by cached data. */ -static ssize_t cached_read(struct dso *dso, u64 offset, u8 *data, ssize_t size) +static ssize_t cached_read(struct dso *dso, struct machine *machine, + u64 offset, u8 *data, ssize_t size) { ssize_t r = 0; u8 *p = data; @@ -648,7 +673,7 @@ static ssize_t cached_read(struct dso *dso, u64 offset, u8 *data, ssize_t size) do { ssize_t ret; - ret = dso_cache_read(dso, offset, p, size); + ret = dso_cache_read(dso, machine, offset, p, size); if (ret < 0) return ret; @@ -668,21 +693,42 @@ static ssize_t cached_read(struct dso *dso, u64 offset, u8 *data, ssize_t size) return r; } -static int data_file_size(struct dso *dso) +static int data_file_size(struct dso *dso, struct machine *machine) { + int ret = 0; struct stat st; char sbuf[STRERR_BUFSIZE]; - if (!dso->data.file_size) { - if (fstat(dso->data.fd, &st)) { - pr_err("dso mmap failed, fstat: %s\n", - strerror_r(errno, sbuf, sizeof(sbuf))); - return -1; + if (dso->data.file_size) + return 0; + + pthread_mutex_lock(&dso__data_open_lock); + + /* + * dso->data.fd might be closed if other thread opened another + * file (dso) due to open file limit (RLIMIT_NOFILE). + */ + if (dso->data.fd < 0) { + dso->data.fd = open_dso(dso, machine); + if (dso->data.fd < 0) { + ret = -errno; + dso->data.status = DSO_DATA_STATUS_ERROR; + goto out; } - dso->data.file_size = st.st_size; } - return 0; + if (fstat(dso->data.fd, &st) < 0) { + ret = -errno; + pr_err("dso cache fstat failed: %s\n", + strerror_r(errno, sbuf, sizeof(sbuf))); + dso->data.status = DSO_DATA_STATUS_ERROR; + goto out; + } + dso->data.file_size = st.st_size; + +out: + pthread_mutex_unlock(&dso__data_open_lock); + return ret; } /** @@ -700,17 +746,17 @@ off_t dso__data_size(struct dso *dso, struct machine *machine) if (fd < 0) return fd; - if (data_file_size(dso)) + if (data_file_size(dso, machine)) return -1; /* For now just estimate dso data size is close to file size */ return dso->data.file_size; } -static ssize_t data_read_offset(struct dso *dso, u64 offset, - u8 *data, ssize_t size) +static ssize_t data_read_offset(struct dso *dso, struct machine *machine, + u64 offset, u8 *data, ssize_t size) { - if (data_file_size(dso)) + if (data_file_size(dso, machine)) return -1; /* Check the offset sanity. */ @@ -720,7 +766,7 @@ static ssize_t data_read_offset(struct dso *dso, u64 offset, if (offset + size < offset) return -1; - return cached_read(dso, offset, data, size); + return cached_read(dso, machine, offset, data, size); } /** @@ -737,10 +783,10 @@ static ssize_t data_read_offset(struct dso *dso, u64 offset, ssize_t dso__data_read_offset(struct dso *dso, struct machine *machine, u64 offset, u8 *data, ssize_t size) { - if (dso__data_fd(dso, machine) < 0) + if (dso->data.status == DSO_DATA_STATUS_ERROR) return -1; - return data_read_offset(dso, offset, data, size); + return data_read_offset(dso, machine, offset, data, size); } /** From c4f035473d93c1594d8225f6dd97332317820801 Mon Sep 17 00:00:00 2001 From: Wang Nan Date: Sun, 17 May 2015 10:56:27 +0000 Subject: [PATCH 15/18] perf tools: Set vmlinux_path__nr_entries to 0 in vmlinux_path__exit Original vmlinux_path__exit() doesn't revert vmlinux_path__nr_entries to its original state. After the while loop vmlinux_path__nr_entries becomes -1 instead of 0. This makes a problem that, if runs twice, during the second run vmlinux_path__init() will set vmlinux_path[-1] to strdup("vmlinux"), corrupts random memory. This patch reset vmlinux_path__nr_entries to 0 after the while loop. Signed-off-by: Wang Nan Acked-by: Namhyung Kim Cc: Alexei Starovoitov Cc: Daniel Borkmann Cc: David Ahern Cc: Jiri Olsa Cc: Masami Hiramatsu Cc: Paul Mackerras Cc: Peter Zijlstra Cc: pi3orama@163.com Cc: Zefan Li Link: http://lkml.kernel.org/r/1431860222-61636-3-git-send-email-wangnan0@huawei.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/symbol.c | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c index 9ef8b8946b11..82a31fd0fcf5 100644 --- a/tools/perf/util/symbol.c +++ b/tools/perf/util/symbol.c @@ -1819,6 +1819,7 @@ static void vmlinux_path__exit(void) { while (--vmlinux_path__nr_entries >= 0) zfree(&vmlinux_path[vmlinux_path__nr_entries]); + vmlinux_path__nr_entries = 0; zfree(&vmlinux_path); } From bb53e176fed9b6c9321904558b4e605b4770e454 Mon Sep 17 00:00:00 2001 From: Wang Nan Date: Sun, 17 May 2015 10:56:28 +0000 Subject: [PATCH 16/18] tools lib traceevent: Install libtraceevent.a into libdir Before this patch, 'make install' installs libraries into bindir: $ make install DESTDIR=./tree INSTALL trace_plugins INSTALL libtraceevent.a INSTALL libtraceevent.so $ find ./tree ./tree/ ./tree/usr ./tree/usr/local ./tree/usr/local/bin ./tree/usr/local/bin/libtraceevent.a ./tree/usr/local/bin/libtraceevent.so ... /usr/local/lib( or lib64) should be a better place. This patch replaces 'bin' with libdir. For __LP64__ building, libraries are installed to /usr/local/lib64. For other building, to /usr/local/lib instead. After applying this patch: $ make install DESTDIR=./tree INSTALL trace_plugins INSTALL libtraceevent.a INSTALL libtraceevent.so $ find ./tree ./tree ./tree/usr ./tree/usr/local ./tree/usr/local/lib64 ./tree/usr/local/lib64/libtraceevent.a ./tree/usr/local/lib64/traceevent ./tree/usr/local/lib64/traceevent/plugins ./tree/usr/local/lib64/traceevent/plugins/plugin_mac80211.so ./tree/usr/local/lib64/traceevent/plugins/plugin_hrtimer.so ... ./tree/usr/local/lib64/libtraceevent.so Signed-off-by: Wang Nan Acked-by: Jiri Olsa Acked-by: Steven Rostedt Cc: Alexei Starovoitov Cc: Brendan Gregg Cc: Daniel Borkmann Cc: David Ahern Cc: Masami Hiramatsu Cc: Namhyung Kim Cc: Paul Mackerras Cc: Peter Zijlstra Cc: pi3orama@163.com Cc: Zefan Li Link: http://lkml.kernel.org/r/1431860222-61636-4-git-send-email-wangnan0@huawei.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/lib/traceevent/Makefile | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/tools/lib/traceevent/Makefile b/tools/lib/traceevent/Makefile index d410da335e3d..84640394ebf9 100644 --- a/tools/lib/traceevent/Makefile +++ b/tools/lib/traceevent/Makefile @@ -34,9 +34,15 @@ INSTALL = install DESTDIR ?= DESTDIR_SQ = '$(subst ','\'',$(DESTDIR))' +LP64 := $(shell echo __LP64__ | ${CC} ${CFLAGS} -E -x c - | tail -n 1) +ifeq ($(LP64), 1) + libdir_relative = lib64 +else + libdir_relative = lib +endif + prefix ?= /usr/local -bindir_relative = bin -bindir = $(prefix)/$(bindir_relative) +libdir = $(prefix)/$(libdir_relative) man_dir = $(prefix)/share/man man_dir_SQ = '$(subst ','\'',$(man_dir))' @@ -58,7 +64,7 @@ ifeq ($(prefix),$(HOME)) override plugin_dir = $(HOME)/.traceevent/plugins set_plugin_dir := 0 else -override plugin_dir = $(prefix)/lib/traceevent/plugins +override plugin_dir = $(libdir)/traceevent/plugins endif endif @@ -85,11 +91,11 @@ srctree := $(patsubst %/,%,$(dir $(srctree))) #$(info Determined 'srctree' to be $(srctree)) endif -export prefix bindir src obj +export prefix libdir src obj # Shell quotes -bindir_SQ = $(subst ','\'',$(bindir)) -bindir_relative_SQ = $(subst ','\'',$(bindir_relative)) +libdir_SQ = $(subst ','\'',$(libdir)) +libdir_relative_SQ = $(subst ','\'',$(libdir_relative)) plugin_dir_SQ = $(subst ','\'',$(plugin_dir)) LIB_FILE = libtraceevent.a libtraceevent.so @@ -240,7 +246,7 @@ endef install_lib: all_cmd install_plugins $(call QUIET_INSTALL, $(LIB_FILE)) \ - $(call do_install,$(LIB_FILE),$(bindir_SQ)) + $(call do_install,$(LIB_FILE),$(libdir_SQ)) install_plugins: $(PLUGINS) $(call QUIET_INSTALL, trace_plugins) \ From 8135c8c750cf018cd43bf955117529467ba178db Mon Sep 17 00:00:00 2001 From: Wang Nan Date: Sun, 17 May 2015 10:56:29 +0000 Subject: [PATCH 17/18] tools build: Change FEATURE_TESTS and FEATURE_DISPLAY to weak binding Replace strong binding of FEATURE_TESTS and FEATURE_DISPLAY by weak binding. This patch enables other makefiles which include tools/build/Makefile.feature enable only limited feathres to check. Signed-off-by: Wang Nan Acked-by: Jiri Olsa Cc: Alexei Starovoitov Cc: Brendan Gregg Cc: Daniel Borkmann Cc: David Ahern Cc: Ingo Molnar Cc: Masami Hiramatsu Cc: Namhyung Kim Cc: Paul Mackerras Cc: Peter Zijlstra Cc: pi3orama@163.com Cc: Zefan Li Link: http://lkml.kernel.org/r/1431860222-61636-5-git-send-email-wangnan0@huawei.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/build/Makefile.feature | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/build/Makefile.feature b/tools/build/Makefile.feature index 3a0b0ca2a28c..2975632d51e2 100644 --- a/tools/build/Makefile.feature +++ b/tools/build/Makefile.feature @@ -27,7 +27,7 @@ endef # the rule that uses them - an example for that is the 'bionic' # feature check. ] # -FEATURE_TESTS = \ +FEATURE_TESTS ?= \ backtrace \ dwarf \ fortify-source \ @@ -53,7 +53,7 @@ FEATURE_TESTS = \ zlib \ lzma -FEATURE_DISPLAY = \ +FEATURE_DISPLAY ?= \ dwarf \ glibc \ gtk2 \ From 2d8e405acd787f4b975f73e0f8d9804b272c00f0 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Mon, 18 May 2015 12:24:41 -0300 Subject: [PATCH 18/18] perf bench numa: Share sched_getcpu() __weak def with cloexec.c We really should move the sched_getcpu() to some more suitable place, but this one-liner fixes this build problem on ancient distros like RHEL5. Cc: Adrian Hunter Cc: Borislav Petkov Cc: David Ahern Cc: Don Zickus Cc: Frederic Weisbecker Cc: Jiri Olsa Cc: Namhyung Kim Cc: Stephane Eranian Cc: Vinson Lee Link: http://lkml.kernel.org/n/tip-5yqg4p11f9uii6yremz3r35v@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/bench/numa.c | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/perf/bench/numa.c b/tools/perf/bench/numa.c index e2415f40343a..870b7e665a20 100644 --- a/tools/perf/bench/numa.c +++ b/tools/perf/bench/numa.c @@ -8,6 +8,7 @@ #include "../builtin.h" #include "../util/util.h" #include "../util/parse-options.h" +#include "../util/cloexec.h" #include "bench.h"