aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf/tests/code-reading.c
diff options
context:
space:
mode:
authorArnaldo Carvalho de Melo <acme@redhat.com>2015-04-06 19:43:22 -0400
committerArnaldo Carvalho de Melo <acme@redhat.com>2015-05-08 15:19:27 -0400
commitb91fc39f4ad7503419dd617df78401fa36266cb3 (patch)
tree370d4454766d031be63ac06a9407055b528954da /tools/perf/tests/code-reading.c
parente1ed3a5b87ed6759e16ec93f16aae83d2cc77ca2 (diff)
perf machine: Protect the machine->threads with a rwlock
In addition to using refcounts for the struct thread lifetime management, we need to protect access to machine->threads from concurrent access. That happens in 'perf top', where a thread processes events, inserting and deleting entries from that rb_tree while another thread decays hist_entries, that end up dropping references and ultimately deleting threads from the rb_tree and releasing its resources when no further hist_entry (or other data structures, like in 'perf sched') references it. So the rule is the same for refcounts + protected trees in the kernel, get the tree lock, find object, bump the refcount, drop the tree lock, return, use object, drop the refcount if no more use of it is needed, keep it if storing it in some other data structure, drop when releasing that data structure. I.e. pair "t = machine__find(new)_thread()" with a "thread__put(t)", and "perf_event__preprocess_sample(&al)" with "addr_location__put(&al)". The addr_location__put() one is because as we return references to several data structures, we may end up adding more reference counting for the other data structures and then we'll drop it at addr_location__put() time. Acked-by: David Ahern <dsahern@gmail.com> Cc: Adrian Hunter <adrian.hunter@intel.com> Cc: Borislav Petkov <bp@suse.de> Cc: Don Zickus <dzickus@redhat.com> Cc: Frederic Weisbecker <fweisbec@gmail.com> Cc: Jiri Olsa <jolsa@redhat.com> Cc: Namhyung Kim <namhyung@kernel.org> Cc: Stephane Eranian <eranian@google.com> Link: http://lkml.kernel.org/n/tip-bs9rt4n0jw3hi9f3zxyy3xln@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Diffstat (limited to 'tools/perf/tests/code-reading.c')
-rw-r--r--tools/perf/tests/code-reading.c22
1 files changed, 14 insertions, 8 deletions
diff --git a/tools/perf/tests/code-reading.c b/tools/perf/tests/code-reading.c
index ca0e480e741b..e2a432b67d52 100644
--- a/tools/perf/tests/code-reading.c
+++ b/tools/perf/tests/code-reading.c
@@ -248,6 +248,7 @@ static int process_sample_event(struct machine *machine,
248 struct perf_sample sample; 248 struct perf_sample sample;
249 struct thread *thread; 249 struct thread *thread;
250 u8 cpumode; 250 u8 cpumode;
251 int ret;
251 252
252 if (perf_evlist__parse_sample(evlist, event, &sample)) { 253 if (perf_evlist__parse_sample(evlist, event, &sample)) {
253 pr_debug("perf_evlist__parse_sample failed\n"); 254 pr_debug("perf_evlist__parse_sample failed\n");
@@ -262,7 +263,9 @@ static int process_sample_event(struct machine *machine,
262 263
263 cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK; 264 cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK;
264 265
265 return read_object_code(sample.ip, READLEN, cpumode, thread, state); 266 ret = read_object_code(sample.ip, READLEN, cpumode, thread, state);
267 thread__put(thread);
268 return ret;
266} 269}
267 270
268static int process_event(struct machine *machine, struct perf_evlist *evlist, 271static int process_event(struct machine *machine, struct perf_evlist *evlist,
@@ -457,13 +460,13 @@ static int do_test_code_reading(bool try_kcore)
457 thread = machine__findnew_thread(machine, pid, pid); 460 thread = machine__findnew_thread(machine, pid, pid);
458 if (!thread) { 461 if (!thread) {
459 pr_debug("machine__findnew_thread failed\n"); 462 pr_debug("machine__findnew_thread failed\n");
460 goto out_err; 463 goto out_put;
461 } 464 }
462 465
463 cpus = cpu_map__new(NULL); 466 cpus = cpu_map__new(NULL);
464 if (!cpus) { 467 if (!cpus) {
465 pr_debug("cpu_map__new failed\n"); 468 pr_debug("cpu_map__new failed\n");
466 goto out_err; 469 goto out_put;
467 } 470 }
468 471
469 while (1) { 472 while (1) {
@@ -472,7 +475,7 @@ static int do_test_code_reading(bool try_kcore)
472 evlist = perf_evlist__new(); 475 evlist = perf_evlist__new();
473 if (!evlist) { 476 if (!evlist) {
474 pr_debug("perf_evlist__new failed\n"); 477 pr_debug("perf_evlist__new failed\n");
475 goto out_err; 478 goto out_put;
476 } 479 }
477 480
478 perf_evlist__set_maps(evlist, cpus, threads); 481 perf_evlist__set_maps(evlist, cpus, threads);
@@ -485,7 +488,7 @@ static int do_test_code_reading(bool try_kcore)
485 ret = parse_events(evlist, str, NULL); 488 ret = parse_events(evlist, str, NULL);
486 if (ret < 0) { 489 if (ret < 0) {
487 pr_debug("parse_events failed\n"); 490 pr_debug("parse_events failed\n");
488 goto out_err; 491 goto out_put;
489 } 492 }
490 493
491 perf_evlist__config(evlist, &opts); 494 perf_evlist__config(evlist, &opts);
@@ -506,7 +509,7 @@ static int do_test_code_reading(bool try_kcore)
506 continue; 509 continue;
507 } 510 }
508 pr_debug("perf_evlist__open failed\n"); 511 pr_debug("perf_evlist__open failed\n");
509 goto out_err; 512 goto out_put;
510 } 513 }
511 break; 514 break;
512 } 515 }
@@ -514,7 +517,7 @@ static int do_test_code_reading(bool try_kcore)
514 ret = perf_evlist__mmap(evlist, UINT_MAX, false); 517 ret = perf_evlist__mmap(evlist, UINT_MAX, false);
515 if (ret < 0) { 518 if (ret < 0) {
516 pr_debug("perf_evlist__mmap failed\n"); 519 pr_debug("perf_evlist__mmap failed\n");
517 goto out_err; 520 goto out_put;
518 } 521 }
519 522
520 perf_evlist__enable(evlist); 523 perf_evlist__enable(evlist);
@@ -525,7 +528,7 @@ static int do_test_code_reading(bool try_kcore)
525 528
526 ret = process_events(machine, evlist, &state); 529 ret = process_events(machine, evlist, &state);
527 if (ret < 0) 530 if (ret < 0)
528 goto out_err; 531 goto out_put;
529 532
530 if (!have_vmlinux && !have_kcore && !try_kcore) 533 if (!have_vmlinux && !have_kcore && !try_kcore)
531 err = TEST_CODE_READING_NO_KERNEL_OBJ; 534 err = TEST_CODE_READING_NO_KERNEL_OBJ;
@@ -535,7 +538,10 @@ static int do_test_code_reading(bool try_kcore)
535 err = TEST_CODE_READING_NO_ACCESS; 538 err = TEST_CODE_READING_NO_ACCESS;
536 else 539 else
537 err = TEST_CODE_READING_OK; 540 err = TEST_CODE_READING_OK;
541out_put:
542 thread__put(thread);
538out_err: 543out_err:
544
539 if (evlist) { 545 if (evlist) {
540 perf_evlist__delete(evlist); 546 perf_evlist__delete(evlist);
541 } else { 547 } else {