diff options
| author | Namhyung Kim <namhyung.kim@lge.com> | 2012-05-31 01:43:26 -0400 |
|---|---|---|
| committer | Arnaldo Carvalho de Melo <acme@redhat.com> | 2012-05-31 09:47:12 -0400 |
| commit | 472606458f3e1ced5fe3cc5f04e90a6b5a4732cf (patch) | |
| tree | a4110008697cc1e80d0c2a47cf9871e3cf32b299 /tools | |
| parent | ea1b3ebac9a1c72c4362c784b4ed069a938a4ddb (diff) | |
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: Namhyung Kim <namhyung.kim@lge.com>
Reported-by: Sunjin Yang <fan4326@gmail.com>
Suggested-by: Arnaldo 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.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Diffstat (limited to 'tools')
| -rw-r--r-- | tools/perf/builtin-report.c | 2 | ||||
| -rw-r--r-- | tools/perf/builtin-top.c | 2 | ||||
| -rw-r--r-- | tools/perf/util/callchain.c | 2 | ||||
| -rw-r--r-- | tools/perf/util/callchain.h | 2 | ||||
| -rw-r--r-- | tools/perf/util/hist.c | 7 | ||||
| -rw-r--r-- | tools/perf/util/hist.h | 2 | ||||
| -rw-r--r-- | tools/perf/util/session.c | 14 |
7 files changed, 17 insertions, 14 deletions
diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c index 2400e009f149..25249f76329d 100644 --- a/tools/perf/builtin-report.c +++ b/tools/perf/builtin-report.c | |||
| @@ -152,7 +152,7 @@ static int perf_evsel__add_hist_entry(struct perf_evsel *evsel, | |||
| 152 | 152 | ||
| 153 | if (symbol_conf.use_callchain) { | 153 | if (symbol_conf.use_callchain) { |
| 154 | err = callchain_append(he->callchain, | 154 | err = callchain_append(he->callchain, |
| 155 | &evsel->hists.callchain_cursor, | 155 | &callchain_cursor, |
| 156 | sample->period); | 156 | sample->period); |
| 157 | if (err) | 157 | if (err) |
| 158 | return err; | 158 | return err; |
diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c index 871b540293e1..6bb0277b7dfe 100644 --- a/tools/perf/builtin-top.c +++ b/tools/perf/builtin-top.c | |||
| @@ -787,7 +787,7 @@ static void perf_event__process_sample(struct perf_tool *tool, | |||
| 787 | } | 787 | } |
| 788 | 788 | ||
| 789 | if (symbol_conf.use_callchain) { | 789 | if (symbol_conf.use_callchain) { |
| 790 | err = callchain_append(he->callchain, &evsel->hists.callchain_cursor, | 790 | err = callchain_append(he->callchain, &callchain_cursor, |
| 791 | sample->period); | 791 | sample->period); |
| 792 | if (err) | 792 | if (err) |
| 793 | return; | 793 | return; |
diff --git a/tools/perf/util/callchain.c b/tools/perf/util/callchain.c index 9f7106a8d9a4..3a6bff47614f 100644 --- a/tools/perf/util/callchain.c +++ b/tools/perf/util/callchain.c | |||
| @@ -18,6 +18,8 @@ | |||
| 18 | #include "util.h" | 18 | #include "util.h" |
| 19 | #include "callchain.h" | 19 | #include "callchain.h" |
| 20 | 20 | ||
| 21 | __thread struct callchain_cursor callchain_cursor; | ||
| 22 | |||
| 21 | bool ip_callchain__valid(struct ip_callchain *chain, | 23 | bool ip_callchain__valid(struct ip_callchain *chain, |
| 22 | const union perf_event *event) | 24 | const union perf_event *event) |
| 23 | { | 25 | { |
diff --git a/tools/perf/util/callchain.h b/tools/perf/util/callchain.h index 7f9c0f1ae3a9..3bdb407f9cd9 100644 --- a/tools/perf/util/callchain.h +++ b/tools/perf/util/callchain.h | |||
| @@ -76,6 +76,8 @@ struct callchain_cursor { | |||
| 76 | struct callchain_cursor_node *curr; | 76 | struct callchain_cursor_node *curr; |
| 77 | }; | 77 | }; |
| 78 | 78 | ||
| 79 | extern __thread struct callchain_cursor callchain_cursor; | ||
| 80 | |||
| 79 | static inline void callchain_init(struct callchain_root *root) | 81 | static inline void callchain_init(struct callchain_root *root) |
| 80 | { | 82 | { |
| 81 | INIT_LIST_HEAD(&root->node.siblings); | 83 | INIT_LIST_HEAD(&root->node.siblings); |
diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c index 1293b5ebea4d..514e2a4b367d 100644 --- a/tools/perf/util/hist.c +++ b/tools/perf/util/hist.c | |||
| @@ -378,7 +378,7 @@ void hist_entry__free(struct hist_entry *he) | |||
| 378 | * collapse the histogram | 378 | * collapse the histogram |
| 379 | */ | 379 | */ |
| 380 | 380 | ||
| 381 | static bool hists__collapse_insert_entry(struct hists *hists, | 381 | static bool hists__collapse_insert_entry(struct hists *hists __used, |
| 382 | struct rb_root *root, | 382 | struct rb_root *root, |
| 383 | struct hist_entry *he) | 383 | struct hist_entry *he) |
| 384 | { | 384 | { |
| @@ -397,8 +397,9 @@ static bool hists__collapse_insert_entry(struct hists *hists, | |||
| 397 | iter->period += he->period; | 397 | iter->period += he->period; |
| 398 | iter->nr_events += he->nr_events; | 398 | iter->nr_events += he->nr_events; |
| 399 | if (symbol_conf.use_callchain) { | 399 | if (symbol_conf.use_callchain) { |
| 400 | callchain_cursor_reset(&hists->callchain_cursor); | 400 | callchain_cursor_reset(&callchain_cursor); |
| 401 | callchain_merge(&hists->callchain_cursor, iter->callchain, | 401 | callchain_merge(&callchain_cursor, |
| 402 | iter->callchain, | ||
| 402 | he->callchain); | 403 | he->callchain); |
| 403 | } | 404 | } |
| 404 | hist_entry__free(he); | 405 | hist_entry__free(he); |
diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h index cfc64e293f90..34bb556d6219 100644 --- a/tools/perf/util/hist.h +++ b/tools/perf/util/hist.h | |||
| @@ -67,8 +67,6 @@ struct hists { | |||
| 67 | struct events_stats stats; | 67 | struct events_stats stats; |
| 68 | u64 event_stream; | 68 | u64 event_stream; |
| 69 | u16 col_len[HISTC_NR_COLS]; | 69 | u16 col_len[HISTC_NR_COLS]; |
| 70 | /* Best would be to reuse the session callchain cursor */ | ||
| 71 | struct callchain_cursor callchain_cursor; | ||
| 72 | }; | 70 | }; |
| 73 | 71 | ||
| 74 | struct hist_entry *__hists__add_entry(struct hists *self, | 72 | struct hist_entry *__hists__add_entry(struct hists *self, |
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c index 48206144758e..3b6f8e460a31 100644 --- a/tools/perf/util/session.c +++ b/tools/perf/util/session.c | |||
| @@ -288,7 +288,8 @@ struct branch_info *machine__resolve_bstack(struct machine *self, | |||
| 288 | return bi; | 288 | return bi; |
| 289 | } | 289 | } |
| 290 | 290 | ||
| 291 | int machine__resolve_callchain(struct machine *self, struct perf_evsel *evsel, | 291 | int machine__resolve_callchain(struct machine *self, |
| 292 | struct perf_evsel *evsel __used, | ||
| 292 | struct thread *thread, | 293 | struct thread *thread, |
| 293 | struct ip_callchain *chain, | 294 | struct ip_callchain *chain, |
| 294 | struct symbol **parent) | 295 | struct symbol **parent) |
| @@ -297,7 +298,7 @@ int machine__resolve_callchain(struct machine *self, struct perf_evsel *evsel, | |||
| 297 | unsigned int i; | 298 | unsigned int i; |
| 298 | int err; | 299 | int err; |
| 299 | 300 | ||
| 300 | callchain_cursor_reset(&evsel->hists.callchain_cursor); | 301 | callchain_cursor_reset(&callchain_cursor); |
| 301 | 302 | ||
| 302 | for (i = 0; i < chain->nr; i++) { | 303 | for (i = 0; i < chain->nr; i++) { |
| 303 | u64 ip; | 304 | u64 ip; |
| @@ -333,7 +334,7 @@ int machine__resolve_callchain(struct machine *self, struct perf_evsel *evsel, | |||
| 333 | break; | 334 | break; |
| 334 | } | 335 | } |
| 335 | 336 | ||
| 336 | err = callchain_cursor_append(&evsel->hists.callchain_cursor, | 337 | err = callchain_cursor_append(&callchain_cursor, |
| 337 | ip, al.map, al.sym); | 338 | ip, al.map, al.sym); |
| 338 | if (err) | 339 | if (err) |
| 339 | return err; | 340 | return err; |
| @@ -1428,7 +1429,6 @@ void perf_event__print_ip(union perf_event *event, struct perf_sample *sample, | |||
| 1428 | int print_sym, int print_dso, int print_symoffset) | 1429 | int print_sym, int print_dso, int print_symoffset) |
| 1429 | { | 1430 | { |
| 1430 | struct addr_location al; | 1431 | struct addr_location al; |
| 1431 | struct callchain_cursor *cursor = &evsel->hists.callchain_cursor; | ||
| 1432 | struct callchain_cursor_node *node; | 1432 | struct callchain_cursor_node *node; |
| 1433 | 1433 | ||
| 1434 | if (perf_event__preprocess_sample(event, machine, &al, sample, | 1434 | 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 | error("Failed to resolve callchain. Skipping\n"); | 1446 | error("Failed to resolve callchain. Skipping\n"); |
| 1447 | return; | 1447 | return; |
| 1448 | } | 1448 | } |
| 1449 | callchain_cursor_commit(cursor); | 1449 | callchain_cursor_commit(&callchain_cursor); |
| 1450 | 1450 | ||
| 1451 | while (1) { | 1451 | while (1) { |
| 1452 | node = callchain_cursor_current(cursor); | 1452 | node = callchain_cursor_current(&callchain_cursor); |
| 1453 | if (!node) | 1453 | if (!node) |
| 1454 | break; | 1454 | break; |
| 1455 | 1455 | ||
| @@ -1465,7 +1465,7 @@ void perf_event__print_ip(union perf_event *event, struct perf_sample *sample, | |||
| 1465 | } | 1465 | } |
| 1466 | printf("\n"); | 1466 | printf("\n"); |
| 1467 | 1467 | ||
| 1468 | callchain_cursor_advance(cursor); | 1468 | callchain_cursor_advance(&callchain_cursor); |
| 1469 | } | 1469 | } |
| 1470 | 1470 | ||
| 1471 | } else { | 1471 | } else { |
