Commit 47260645 authored by Namhyung Kim's avatar Namhyung Kim Committed by Arnaldo Carvalho de Melo

perf callchain: Make callchain cursors TLS

perf top -G has a race on callchain cursor between main thread and
display thread. Since the callchain cursors are used locally make them
thread-local data would solve the problem.
Signed-off-by: default avatarNamhyung Kim <namhyung.kim@lge.com>
Reported-by: default avatarSunjin Yang <fan4326@gmail.com>
Suggested-by: default avatarArnaldo Carvalho de Melo <acme@ghostprotocols.net>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: Namhyung Kim <namhyung@gmail.com>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Sunjin Yang <fan4326@gmail.com>
Link: http://lkml.kernel.org/r/1338443007-24857-1-git-send-email-namhyung.kim@lge.comSigned-off-by: default avatarArnaldo Carvalho de Melo <acme@redhat.com>
parent ea1b3eba
...@@ -152,7 +152,7 @@ static int perf_evsel__add_hist_entry(struct perf_evsel *evsel, ...@@ -152,7 +152,7 @@ static int perf_evsel__add_hist_entry(struct perf_evsel *evsel,
if (symbol_conf.use_callchain) { if (symbol_conf.use_callchain) {
err = callchain_append(he->callchain, err = callchain_append(he->callchain,
&evsel->hists.callchain_cursor, &callchain_cursor,
sample->period); sample->period);
if (err) if (err)
return err; return err;
......
...@@ -787,7 +787,7 @@ static void perf_event__process_sample(struct perf_tool *tool, ...@@ -787,7 +787,7 @@ static void perf_event__process_sample(struct perf_tool *tool,
} }
if (symbol_conf.use_callchain) { if (symbol_conf.use_callchain) {
err = callchain_append(he->callchain, &evsel->hists.callchain_cursor, err = callchain_append(he->callchain, &callchain_cursor,
sample->period); sample->period);
if (err) if (err)
return; return;
......
...@@ -18,6 +18,8 @@ ...@@ -18,6 +18,8 @@
#include "util.h" #include "util.h"
#include "callchain.h" #include "callchain.h"
__thread struct callchain_cursor callchain_cursor;
bool ip_callchain__valid(struct ip_callchain *chain, bool ip_callchain__valid(struct ip_callchain *chain,
const union perf_event *event) const union perf_event *event)
{ {
......
...@@ -76,6 +76,8 @@ struct callchain_cursor { ...@@ -76,6 +76,8 @@ struct callchain_cursor {
struct callchain_cursor_node *curr; struct callchain_cursor_node *curr;
}; };
extern __thread struct callchain_cursor callchain_cursor;
static inline void callchain_init(struct callchain_root *root) static inline void callchain_init(struct callchain_root *root)
{ {
INIT_LIST_HEAD(&root->node.siblings); INIT_LIST_HEAD(&root->node.siblings);
......
...@@ -378,7 +378,7 @@ void hist_entry__free(struct hist_entry *he) ...@@ -378,7 +378,7 @@ void hist_entry__free(struct hist_entry *he)
* collapse the histogram * collapse the histogram
*/ */
static bool hists__collapse_insert_entry(struct hists *hists, static bool hists__collapse_insert_entry(struct hists *hists __used,
struct rb_root *root, struct rb_root *root,
struct hist_entry *he) struct hist_entry *he)
{ {
...@@ -397,8 +397,9 @@ static bool hists__collapse_insert_entry(struct hists *hists, ...@@ -397,8 +397,9 @@ static bool hists__collapse_insert_entry(struct hists *hists,
iter->period += he->period; iter->period += he->period;
iter->nr_events += he->nr_events; iter->nr_events += he->nr_events;
if (symbol_conf.use_callchain) { if (symbol_conf.use_callchain) {
callchain_cursor_reset(&hists->callchain_cursor); callchain_cursor_reset(&callchain_cursor);
callchain_merge(&hists->callchain_cursor, iter->callchain, callchain_merge(&callchain_cursor,
iter->callchain,
he->callchain); he->callchain);
} }
hist_entry__free(he); hist_entry__free(he);
......
...@@ -67,8 +67,6 @@ struct hists { ...@@ -67,8 +67,6 @@ struct hists {
struct events_stats stats; struct events_stats stats;
u64 event_stream; u64 event_stream;
u16 col_len[HISTC_NR_COLS]; u16 col_len[HISTC_NR_COLS];
/* Best would be to reuse the session callchain cursor */
struct callchain_cursor callchain_cursor;
}; };
struct hist_entry *__hists__add_entry(struct hists *self, struct hist_entry *__hists__add_entry(struct hists *self,
......
...@@ -288,7 +288,8 @@ struct branch_info *machine__resolve_bstack(struct machine *self, ...@@ -288,7 +288,8 @@ struct branch_info *machine__resolve_bstack(struct machine *self,
return bi; return bi;
} }
int machine__resolve_callchain(struct machine *self, struct perf_evsel *evsel, int machine__resolve_callchain(struct machine *self,
struct perf_evsel *evsel __used,
struct thread *thread, struct thread *thread,
struct ip_callchain *chain, struct ip_callchain *chain,
struct symbol **parent) struct symbol **parent)
...@@ -297,7 +298,7 @@ int machine__resolve_callchain(struct machine *self, struct perf_evsel *evsel, ...@@ -297,7 +298,7 @@ int machine__resolve_callchain(struct machine *self, struct perf_evsel *evsel,
unsigned int i; unsigned int i;
int err; int err;
callchain_cursor_reset(&evsel->hists.callchain_cursor); callchain_cursor_reset(&callchain_cursor);
for (i = 0; i < chain->nr; i++) { for (i = 0; i < chain->nr; i++) {
u64 ip; u64 ip;
...@@ -333,7 +334,7 @@ int machine__resolve_callchain(struct machine *self, struct perf_evsel *evsel, ...@@ -333,7 +334,7 @@ int machine__resolve_callchain(struct machine *self, struct perf_evsel *evsel,
break; break;
} }
err = callchain_cursor_append(&evsel->hists.callchain_cursor, err = callchain_cursor_append(&callchain_cursor,
ip, al.map, al.sym); ip, al.map, al.sym);
if (err) if (err)
return err; return err;
...@@ -1428,7 +1429,6 @@ void perf_event__print_ip(union perf_event *event, struct perf_sample *sample, ...@@ -1428,7 +1429,6 @@ void perf_event__print_ip(union perf_event *event, struct perf_sample *sample,
int print_sym, int print_dso, int print_symoffset) int print_sym, int print_dso, int print_symoffset)
{ {
struct addr_location al; struct addr_location al;
struct callchain_cursor *cursor = &evsel->hists.callchain_cursor;
struct callchain_cursor_node *node; struct callchain_cursor_node *node;
if (perf_event__preprocess_sample(event, machine, &al, sample, if (perf_event__preprocess_sample(event, machine, &al, sample,
...@@ -1446,10 +1446,10 @@ void perf_event__print_ip(union perf_event *event, struct perf_sample *sample, ...@@ -1446,10 +1446,10 @@ void perf_event__print_ip(union perf_event *event, struct perf_sample *sample,
error("Failed to resolve callchain. Skipping\n"); error("Failed to resolve callchain. Skipping\n");
return; return;
} }
callchain_cursor_commit(cursor); callchain_cursor_commit(&callchain_cursor);
while (1) { while (1) {
node = callchain_cursor_current(cursor); node = callchain_cursor_current(&callchain_cursor);
if (!node) if (!node)
break; break;
...@@ -1465,7 +1465,7 @@ void perf_event__print_ip(union perf_event *event, struct perf_sample *sample, ...@@ -1465,7 +1465,7 @@ void perf_event__print_ip(union perf_event *event, struct perf_sample *sample,
} }
printf("\n"); printf("\n");
callchain_cursor_advance(cursor); callchain_cursor_advance(&callchain_cursor);
} }
} else { } else {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment