perf machine: Protect the machine-> threads with a rwlock
tip-bot for Arnaldo Carvalho de Melo
merge botCommit-ID: b91fc39f4ad7503419dd617df78401fa36266cb3 Gitweb: http://git.kernel.org/tip/b91fc39f4ad7503419dd617df78401fa36266cb3 Author: Arnaldo Carvalho de Melo <[email protected]> AuthorDate: Mon, 6 Apr 2015 20:43:22 -0300 Committer: Arnaldo Carvalho de Melo <[email protected]> CommitDate: Fri, 8 May 2015 16:19:27 -0300
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.
--- tools/perf/builtin-annotate.c | 10 ++-- tools/perf/builtin-diff.c | 9 ++-- tools/perf/builtin-inject.c | 1 + tools/perf/builtin-kmem.c | 7 ++- tools/perf/builtin-kvm.c | 6 ++- tools/perf/builtin-lock.c | 8 +++- tools/perf/builtin-mem.c | 5 +- tools/perf/builtin-report.c | 9 ++-- tools/perf/builtin-sched.c | 82 ++++++++++++++++++++++---------- tools/perf/builtin-script.c | 20 ++++---- tools/perf/builtin-timechart.c | 5 +- tools/perf/builtin-top.c | 2 +- tools/perf/builtin-trace.c | 36 +++++++++----- tools/perf/tests/code-reading.c | 22 +++++---- tools/perf/tests/dwarf-unwind.c | 1 + tools/perf/tests/hists_common.c | 1 + tools/perf/tests/hists_cumulate.c | 4 +- tools/perf/tests/hists_filter.c | 4 +- tools/perf/tests/hists_link.c | 8 +++- tools/perf/tests/hists_output.c | 4 +- tools/perf/tests/mmap-thread-lookup.c | 2 + tools/perf/tests/thread-mg-share.c | 12 ++--- tools/perf/util/build-id.c | 5 +- tools/perf/util/db-export.c | 14 ++++-- tools/perf/util/event.c | 15 ++++++ tools/perf/util/event.h | 2 + tools/perf/util/machine.c | 89 ++++++++++++++++++++++++++++------- tools/perf/util/machine.h | 5 +- tools/perf/util/thread.c | 10 +++- 29 files changed, 284 insertions(+), 114 deletions(-)
tools/perf/builtin-annotate.c +6 -4
@@ -84,6 +84,7 @@ static int process_sample_event(struct perf_tool *tool, { struct perf_annotate *ann = container_of(tool, struct perf_annotate, tool);struct addr_location al; +int ret =0 ;if (perf_event__preprocess_sample (event, machine, &al, sample) <0 ) { pr_warning("problem processing %d event, skipping it.\n",
@@ -92,15 +93,16 @@ static int process_sample_event(struct perf_tool *tool, }if (ann->cpu_list && !test_bit (sample->cpu, ann->cpu_bitmap)) -return 0 ; + goto out_put;if (!al.filtered &&perf_evsel__add_sample (evsel, sample, &al, ann)) {pr_warning ("problem incrementing symbol count, " "skipping event\n" ); -return -1 ; + ret =-1 ; } - -return 0 ; +out_put: +addr_location__put (&al); +return ret; } static int hist_entry__tty_annotate(struct hist_entry *he,
tools/perf/builtin-diff.c +6 -3
@@ -328,6 +328,7 @@ static int diff__process_sample_event(struct perf_tool *tool __maybe_unused, {struct addr_location al;struct hists *hists =evsel__hists (evsel); +int ret =-1 ;if (perf_event__preprocess_sample (event, machine, &al, sample) <0 ) { pr_warning("problem processing %d event, skipping it.\n",
@@ -338,7 +339,7 @@ static int diff__process_sample_event(struct perf_tool *tool __maybe_unused,if (hists__add_entry (hists, &al, sample->period, sample->weight, sample->transaction)) {pr_warning ("problem incrementing symbol period, skipping event\n" ); -return -1 ; + goto out_put; }/*
@@ -350,8 +351,10 @@ static int diff__process_sample_event(struct perf_tool *tool __maybe_unused, hists->stats.total_period += sample->period;if (!al.filtered) hists->stats.total_non_filtered_period += sample->period; - -return 0 ; + ret =0 ; +out_put: +addr_location__put (&al); +return ret; }static struct perf_tool tool = {
tools/perf/builtin-inject.c +1 -0
@@ -365,6 +365,7 @@ static int perf_event__inject_buildid(struct perf_tool *tool, } } +thread__put (thread); repipe:perf_event__repipe (tool, event, sample, machine);return 0 ;
tools/perf/builtin-kmem.c +5 -2
@@ -906,6 +906,7 @@ static int process_sample_event(struct perf_tool *tool __maybe_unused,struct perf_evsel *evsel, struct machine *machine) { + int err = 0;struct thread *thread =machine__findnew_thread (machine, sample->pid, sample->tid);
@@ -919,10 +920,12 @@ static int process_sample_event(struct perf_tool *tool __maybe_unused,if (evsel->handler !=NULL ) {tracepoint_handler f = evsel->handler; -return f (evsel, sample); + err =f (evsel, sample); } -return 0 ; +thread__put (thread); + +return err; }static struct perf_tool perf_kmem = {
tools/perf/builtin-kvm.c +4 -2
@@ -651,6 +651,7 @@ static int process_sample_event(struct perf_tool *tool,struct perf_evsel *evsel, struct machine *machine) { + int err = 0;struct thread *thread; struct perf_kvm_stat *kvm = container_of(tool, struct perf_kvm_stat, tool);
@@ -666,9 +667,10 @@ static int process_sample_event(struct perf_tool *tool, }if (!handle_kvm_event (kvm, thread, evsel, sample)) -return -1 ; + err =-1 ; -return 0 ; +thread__put (thread); +return err; }static int cpu_isa_config (struct perf_kvm_stat *kvm)
tools/perf/builtin-lock.c +6 -2
@@ -769,6 +769,7 @@ static void dump_threads(void) t =perf_session__findnew (session, st->tid);pr_info ("%10d: %s\n" , st->tid,thread__comm_str (t)); node =rb_next (node); +thread__put (t); }; }
@@ -810,6 +811,7 @@ static int process_sample_event(struct perf_tool *tool __maybe_unused,struct perf_evsel *evsel, struct machine *machine) { + int err = 0;struct thread *thread =machine__findnew_thread (machine, sample->pid, sample->tid);
@@ -821,10 +823,12 @@ static int process_sample_event(struct perf_tool *tool __maybe_unused,if (evsel->handler !=NULL ) {tracepoint_handler f = evsel->handler; -return f (evsel, sample); + err =f (evsel, sample); } -return 0 ; +thread__put (thread); + +return err; }static void sort_result (void )
tools/perf/builtin-mem.c +3 -2
@@ -74,7 +74,7 @@ dump_raw_samples(struct perf_tool *tool, }if (al.filtered || (mem->hide_unresolved && al.sym ==NULL )) -return 0 ; + goto out_put;if (al.map !=NULL ) al.map->dso->hit =1 ;
@@ -103,7 +103,8 @@ dump_raw_samples(struct perf_tool *tool, symbol_conf.field_sep, al.map ? (al.map->dso ? al.map->dso->long_name :"???" ) :"???" , al.sym ? al.sym->name : "???"); - +out_put: +addr_location__put (&al);return 0 ; }
tools/perf/builtin-report.c +5 -4
@@ -142,7 +142,7 @@ static int process_sample_event(struct perf_tool *tool, .hide_unresolved = rep->hide_unresolved, .add_entry_cb = hist_iter__report_callback, }; -int ret; +int ret =0 ;if (perf_event__preprocess_sample (event, machine, &al, sample) <0 ) { pr_debug("problem processing %d event, skipping it.\n",
@@ -151,10 +151,10 @@ static int process_sample_event(struct perf_tool *tool, }if (rep->hide_unresolved && al.sym ==NULL ) -return 0 ; + goto out_put;if (rep->cpu_list && !test_bit (sample->cpu, rep->cpu_bitmap)) -return 0 ; + goto out_put;if (sort__mode ==SORT_MODE__BRANCH ) iter.ops = &hist_iter_branch;
@@ -172,7 +172,8 @@ static int process_sample_event(struct perf_tool *tool, rep);if (ret <0 )pr_debug ("problem adding hist entry, skipping event\n" ); - +out_put: +addr_location__put (&al);return ret; }
tools/perf/builtin-sched.c +56 -26
218 lines not on this page · raw message
tools/perf/builtin-script.c +12 -8
@@ -607,13 +607,14 @@ static int process_sample_event(struct perf_tool *tool __maybe_unused, }if (al.filtered) -return 0 ; + goto out_put;if (cpu_list && !test_bit (sample->cpu, cpu_bitmap)) -return 0 ; + goto out_put; scripting_ops->process_event (event, sample, evsel, &al); - +out_put: +addr_location__put (&al);return 0 ; }
@@ -681,8 +682,8 @@ static int process_comm_event(struct perf_tool *tool,print_sample_start (sample, thread, evsel);perf_event__fprintf (event, stdout); ret =0 ; - out: +thread__put (thread);return ret; }
@@ -713,6 +714,7 @@ static int process_fork_event(struct perf_tool *tool, }print_sample_start (sample, thread, evsel);perf_event__fprintf (event, stdout); +thread__put (thread);return 0 ; }
@@ -721,6 +723,7 @@ static int process_exit_event(struct perf_tool *tool,struct perf_sample *sample, struct machine *machine) { + int err = 0;struct thread *thread; struct perf_script *script = container_of(tool, struct perf_script, tool);struct perf_session *session = script->session;
@@ -742,9 +745,10 @@ static int process_exit_event(struct perf_tool *tool,perf_event__fprintf (event, stdout);if (perf_event__process_exit (tool, event, sample, machine) <0 ) -return -1 ; + err =-1 ; -return 0 ; +thread__put (thread); +return err; } static int process_mmap_event(struct perf_tool *tool,
@@ -774,7 +778,7 @@ static int process_mmap_event(struct perf_tool *tool, }print_sample_start (sample, thread, evsel);perf_event__fprintf (event, stdout); - +thread__put (thread);return 0 ; }
@@ -805,7 +809,7 @@ static int process_mmap2_event(struct perf_tool *tool, }print_sample_start (sample, thread, evsel);perf_event__fprintf (event, stdout); - +thread__put (thread);return 0 ; }
tools/perf/builtin-timechart.c +3 -2
@@ -523,7 +523,7 @@ static const char *cat_backtrace(union perf_event *event,* Discard all. */ zfree (&p); - goto exit; + goto exit_put; }continue ; }
@@ -538,7 +538,8 @@ static const char *cat_backtrace(union perf_event *event,else fprintf (f,"..... %016" PRIx64"\n" , ip); } - +exit_put: +addr_location__put (&al); exit:fclose (f);
tools/perf/builtin-top.c +1 -1
@@ -793,7 +793,7 @@ static void perf_event__process_sample(struct perf_tool *tool,pthread_mutex_unlock (&hists->lock); } -return ; +addr_location__put (&al); }static void perf_top__mmap_read_idx (struct perf_top *top,int idx)
tools/perf/builtin-trace.c +23 -13
@@ -1712,7 +1712,7 @@ static int trace__sys_enter(struct trace *trace, struct perf_evsel *evsel,void *args;size_t printed =0 ;struct thread *thread; -int id =perf_evsel__sc_tp_uint (evsel, id, sample); +int id =perf_evsel__sc_tp_uint (evsel, id, sample), err =-1 ;struct syscall *sc =trace__syscall_info (trace, evsel, id);struct thread_trace *ttrace;
@@ -1725,14 +1725,14 @@ static int trace__sys_enter(struct trace *trace, struct perf_evsel *evsel, thread =machine__findnew_thread (trace->host, sample->pid, sample->tid); ttrace =thread__trace (thread, trace->output);if (ttrace ==NULL ) -return -1 ; + goto out_put; args =perf_evsel__sc_tp_ptr (evsel, args, sample);if (ttrace->entry_str ==NULL ) { ttrace->entry_str =malloc (1024 );if (!ttrace->entry_str) -return -1 ; + goto out_put; }if (!trace->summary_only)
@@ -1757,8 +1757,10 @@ static int trace__sys_enter(struct trace *trace, struct perf_evsel *evsel,thread__put (trace->current); trace->current =thread__get (thread); } - -return 0 ; + err =0 ; +out_put: +thread__put (thread); +return err; } static int trace__sys_exit(struct trace *trace, struct perf_evsel *evsel,
@@ -1768,7 +1770,7 @@ static int trace__sys_exit(struct trace *trace, struct perf_evsel *evsel,long ret;u64 duration =0 ;struct thread *thread; -int id =perf_evsel__sc_tp_uint (evsel, id, sample); +int id =perf_evsel__sc_tp_uint (evsel, id, sample), err =-1 ;struct syscall *sc =trace__syscall_info (trace, evsel, id);struct thread_trace *ttrace;
@@ -1781,7 +1783,7 @@ static int trace__sys_exit(struct trace *trace, struct perf_evsel *evsel, thread =machine__findnew_thread (trace->host, sample->pid, sample->tid); ttrace =thread__trace (thread, trace->output);if (ttrace ==NULL ) -return -1 ; + goto out_put;if (trace->summary)thread__update_stats (ttrace, id, sample);
@@ -1835,8 +1837,10 @@ signed_print:fputc ('\n' , trace->output); out: ttrace->entry_pending = false; - -return 0 ; + err =0 ; +out_put: +thread__put (thread); +return err; } static int trace__vfs_getname(struct trace *trace, struct perf_evsel *evsel,
@@ -1863,6 +1867,7 @@ static int trace__sched_stat_runtime(struct trace *trace, struct perf_evsel *evs ttrace->runtime_ms += runtime_ms; trace->runtime_ms += runtime_ms; +thread__put (thread);return 0 ; out_dump:
@@ -1872,6 +1877,7 @@ out_dump: (pid_t )perf_evsel__intval (evsel, sample,"pid" ), runtime, perf_evsel__intval(evsel, sample, "vruntime")); +thread__put (thread);return 0 ; }
@@ -1924,11 +1930,12 @@ static int trace__pgfault(struct trace *trace,struct addr_location al;char map_type ='d' ;struct thread_trace *ttrace; +int err =-1 ; thread =machine__findnew_thread (trace->host, sample->pid, sample->tid); ttrace =thread__trace (thread, trace->output);if (ttrace ==NULL ) -return -1 ; + goto out_put;if (evsel->attr.config ==PERF_COUNT_SW_PAGE_FAULTS_MAJ ) ttrace->pfmaj++;
@@ -1936,7 +1943,7 @@ static int trace__pgfault(struct trace *trace, ttrace->pfmin++;if (trace->summary_only) -return 0 ; + goto out;thread__find_addr_location (thread, cpumode,MAP__FUNCTION , sample->ip, &al);
@@ -1967,8 +1974,11 @@ static int trace__pgfault(struct trace *trace,print_location (trace->output, sample, &al, true, false);fprintf (trace->output," (%c%c)\n" , map_type, al.level); - -return 0 ; +out: + err =0 ; +out_put: +thread__put (thread); +return err; }static bool skip_sample (struct trace *trace,struct perf_sample *sample)
tools/perf/tests/code-reading.c +14 -8
@@ -248,6 +248,7 @@ static int process_sample_event(struct machine *machine,struct perf_sample sample;struct thread *thread;u8 cpumode; +int ret;if (perf_evlist__parse_sample (evlist, event, &sample)) {pr_debug ("perf_evlist__parse_sample failed\n" );
@@ -262,7 +263,9 @@ static int process_sample_event(struct machine *machine, cpumode = event->header.misc &PERF_RECORD_MISC_CPUMODE_MASK ; -return read_object_code (sample.ip,READLEN , cpumode, thread, state); + ret =read_object_code (sample.ip,READLEN , cpumode, thread, state); +thread__put (thread); +return ret; } static int process_event(struct machine *machine, struct perf_evlist *evlist,
@@ -457,13 +460,13 @@ static int do_test_code_reading(bool try_kcore) thread =machine__findnew_thread (machine, pid, pid);if (!thread) {pr_debug ("machine__findnew_thread failed\n" ); - goto out_err; + goto out_put; } cpus =cpu_map__new (NULL );if (!cpus) {pr_debug ("cpu_map__new failed\n" ); - goto out_err; + goto out_put; }while (1 ) {
@@ -472,7 +475,7 @@ static int do_test_code_reading(bool try_kcore) evlist =perf_evlist__new ();if (!evlist) {pr_debug ("perf_evlist__new failed\n" ); - goto out_err; + goto out_put; }perf_evlist__set_maps (evlist, cpus, threads);
@@ -485,7 +488,7 @@ static int do_test_code_reading(bool try_kcore) ret =parse_events (evlist, str,NULL );if (ret <0 ) {pr_debug ("parse_events failed\n" ); - goto out_err; + goto out_put; }perf_evlist__config (evlist, &opts);
@@ -506,7 +509,7 @@ static int do_test_code_reading(bool try_kcore)continue ; }pr_debug ("perf_evlist__open failed\n" ); - goto out_err; + goto out_put; }break ; }
@@ -514,7 +517,7 @@ static int do_test_code_reading(bool try_kcore) ret =perf_evlist__mmap (evlist,UINT_MAX , false);if (ret <0 ) {pr_debug ("perf_evlist__mmap failed\n" ); - goto out_err; + goto out_put; }perf_evlist__enable (evlist);
@@ -525,7 +528,7 @@ static int do_test_code_reading(bool try_kcore) ret =process_events (machine, evlist, &state);if (ret <0 ) - goto out_err; + goto out_put;if (!have_vmlinux && !have_kcore && !try_kcore) err =TEST_CODE_READING_NO_KERNEL_OBJ ;
@@ -535,7 +538,10 @@ static int do_test_code_reading(bool try_kcore) err =TEST_CODE_READING_NO_ACCESS ; else err =TEST_CODE_READING_OK ; +out_put: +thread__put (thread); out_err: +if (evlist) {perf_evlist__delete (evlist); }else {
tools/perf/tests/dwarf-unwind.c +1 -0
@@ -170,6 +170,7 @@ int test__dwarf_unwind(void) } err =krava_1 (thread); +thread__put (thread); out:machine__delete_threads (machine);
tools/perf/tests/hists_common.c +1 -0
@@ -96,6 +96,7 @@ struct machine *setup_fake_machine(struct machines *machines) goto out;thread__set_comm (thread, fake_threads[i].comm,0 ); +thread__put (thread); }for (i =0 ; i <ARRAY_SIZE (fake_mmap_info); i++) {
tools/perf/tests/hists_cumulate.c +3 -1
@@ -105,8 +105,10 @@ static int add_hist_entries(struct hists *hists, struct machine *machine) goto out;if (hist_entry_iter__add (&iter, &al, evsel, &sample, -PERF_MAX_STACK_DEPTH ,NULL ) <0 ) +PERF_MAX_STACK_DEPTH ,NULL ) <0 ) { +addr_location__put (&al); goto out; + } fake_samples[i].thread = al.thread; fake_samples[i].map = al.map;
tools/perf/tests/hists_filter.c +3 -1
@@ -82,8 +82,10 @@ static int add_hist_entries(struct perf_evlist *evlist, goto out;if (hist_entry_iter__add (&iter, &al, evsel, &sample, -PERF_MAX_STACK_DEPTH ,NULL ) <0 ) +PERF_MAX_STACK_DEPTH ,NULL ) <0 ) { +addr_location__put (&al); goto out; + } fake_samples[i].thread = al.thread; fake_samples[i].map = al.map;
tools/perf/tests/hists_link.c +6 -2
@@ -91,8 +91,10 @@ static int add_hist_entries(struct perf_evlist *evlist, struct machine *machine) he =__hists__add_entry (hists, &al,NULL ,NULL ,NULL ,1 ,1 ,0 , true); -if (he ==NULL ) +if (he ==NULL ) { +addr_location__put (&al); goto out; + } fake_common_samples[k].thread = al.thread; fake_common_samples[k].map = al.map;
@@ -115,8 +117,10 @@ static int add_hist_entries(struct perf_evlist *evlist, struct machine *machine) he =__hists__add_entry (hists, &al,NULL ,NULL ,NULL ,1 ,1 ,0 , true); -if (he ==NULL ) +if (he ==NULL ) { +addr_location__put (&al); goto out; + } fake_samples[i][k].thread = al.thread; fake_samples[i][k].map = al.map;
tools/perf/tests/hists_output.c +3 -1
@@ -71,8 +71,10 @@ static int add_hist_entries(struct hists *hists, struct machine *machine) goto out;if (hist_entry_iter__add (&iter, &al, evsel, &sample, -PERF_MAX_STACK_DEPTH ,NULL ) <0 ) +PERF_MAX_STACK_DEPTH ,NULL ) <0 ) { +addr_location__put (&al); goto out; + } fake_samples[i].thread = al.thread; fake_samples[i].map = al.map;
tools/perf/tests/mmap-thread-lookup.c +2 -0
@@ -191,6 +191,8 @@ static int mmap_events(synth_cb synth)PERF_RECORD_MISC_USER ,MAP__FUNCTION , (unsigned long) (td->map + 1), &al); +thread__put (thread); +if (!al.map) {pr_debug ("failed, couldn't find map\n" ); err =-1 ;
tools/perf/tests/thread-mg-share.c +6 -6
@@ -64,22 +64,22 @@ int test__thread_mg_share(void)TEST_ASSERT_VAL ("map groups don't match" , other_mg == other_leader->mg);/* release thread group */ -thread__delete (leader); +thread__put (leader);TEST_ASSERT_VAL ("wrong refcnt" , mg->refcnt ==3 ); -thread__delete (t1); +thread__put (t1);TEST_ASSERT_VAL ("wrong refcnt" , mg->refcnt ==2 ); -thread__delete (t2); +thread__put (t2);TEST_ASSERT_VAL ("wrong refcnt" , mg->refcnt ==1 ); -thread__delete (t3); +thread__put (t3);/* release other group */ -thread__delete (other_leader); +thread__put (other_leader);TEST_ASSERT_VAL ("wrong refcnt" , other_mg->refcnt ==1 ); -thread__delete (other); +thread__put (other);/* * Cannot call machine__delete_threads(machine) now,
tools/perf/util/build-id.c +4 -1
@@ -43,6 +43,7 @@ int build_id__mark_dso_hit(struct perf_tool *tool __maybe_unused,if (al.map !=NULL ) al.map->dso->hit =1 ; +thread__put (thread);return 0 ; }
@@ -59,8 +60,10 @@ static int perf_event__exit_del_thread(struct perf_tool *tool __maybe_unused,dump_printf ("(%d:%d):(%d:%d)\n" , event->fork.pid, event->fork.tid, event->fork.ppid, event->fork.ptid); -if (thread) +if (thread) {machine__remove_thread (machine, thread); +thread__put (thread); + }return 0 ; }
tools/perf/util/db-export.c +10 -4
@@ -122,6 +122,7 @@ int db_export__machine(struct db_export *dbe, struct machine *machine)int db_export__thread (struct db_export *dbe,struct thread *thread,struct machine *machine,struct comm *comm) { +struct thread *main_thread;u64 main_thread_db_id =0 ;int err;
@@ -131,8 +132,6 @@ int db_export__thread(struct db_export *dbe, struct thread *thread, thread->db_id = ++dbe->thread_last_db_id;if (thread->pid_ !=-1 ) { -struct thread *main_thread; -if (thread->pid_ == thread->tid) { main_thread = thread; }else {
@@ -144,14 +143,16 @@ int db_export__thread(struct db_export *dbe, struct thread *thread, err =db_export__thread (dbe, main_thread, machine, comm);if (err) -return err; + goto out_put;if (comm) { err =db_export__comm_thread (dbe, comm, thread);if (err) -return err; + goto out_put; } } main_thread_db_id = main_thread->db_id; +if (main_thread != thread) +thread__put (main_thread); }if (dbe->export_thread)
@@ -159,6 +160,10 @@ int db_export__thread(struct db_export *dbe, struct thread *thread, machine);return 0 ; + +out_put: +thread__put (main_thread); +return err; } int db_export__comm(struct db_export *dbe, struct comm *comm,
@@ -303,6 +308,7 @@ int db_export__sample(struct db_export *dbe, union perf_event *event,if (err)return err; +/* FIXME: check refcounting for get_main_thread, that calls machine__find_thread... */ main_thread =get_main_thread (al->machine, thread);if (main_thread) comm =machine__thread_exec_comm (al->machine, main_thread);
tools/perf/util/event.c +15 -0
@@ -919,6 +919,10 @@ void thread__find_addr_location(struct thread *thread, al->sym =NULL ; } +/* +* Callers need to drop the reference to al->thread, obtained in +* machine__findnew_thread() +*/ int perf_event__preprocess_sample(const union perf_event *event, struct machine *machine, struct addr_location *al,
@@ -979,6 +983,17 @@ int perf_event__preprocess_sample(const union perf_event *event,return 0 ; } +/* +* The preprocess_sample method will return with reference counts for the +* in it, when done using (and perhaps getting ref counts if needing to +* keep a pointer to one of those entries) it must be paired with +* addr_location__put(), so that the refcounts can be decremented. +*/ +void addr_location__put (struct addr_location *al) +{ +thread__zput (al->thread); +} +bool is_bts_event (struct perf_event_attr *attr) { return attr->type == PERF_TYPE_HARDWARE &&
tools/perf/util/event.h +2 -0
@@ -426,6 +426,8 @@ int perf_event__preprocess_sample(const union perf_event *event,struct addr_location *al, struct perf_sample *sample); +void addr_location__put (struct addr_location *al); +struct thread ;bool is_bts_event (struct perf_event_attr *attr);
tools/perf/util/machine.c +72 -17
252 lines not on this page · raw message
tools/perf/util/machine.h +3 -2
@@ -30,6 +30,7 @@ struct machine {bool comm_exec;char *root_dir;struct rb_root threads; +pthread_rwlock_t threads_lock;struct list_head dead_threads;struct thread *last_match;struct vdso_info *vdso_info;
@@ -151,8 +152,8 @@ static inline bool machine__is_host(struct machine *machine)return machine ? machine->pid ==HOST_KERNEL_ID : false; } -struct thread *machine__findnew_thread (struct machine *machine,pid_t pid, -pid_t tid); +struct thread *__machine__findnew_thread (struct machine *machine,pid_t pid,pid_t tid); +struct thread *machine__findnew_thread (struct machine *machine,pid_t pid,pid_t tid);size_t machine__fprintf (struct machine *machine,FILE *fp);
tools/perf/util/thread.c +8 -2
@@ -18,7 +18,7 @@ int thread__init_map_groups(struct thread *thread, struct machine *machine)if (pid == thread->tid || pid ==-1 ) { thread->mg =map_groups__new (machine); }else { - leader =machine__findnew_thread (machine, pid, pid); + leader =__machine__findnew_thread (machine, pid, pid);if (leader) thread->mg =map_groups__get (leader->mg); }
@@ -54,6 +54,8 @@ struct thread *thread__new(pid_t pid, pid_t tid)list_add (&comm->list, &thread->comm_list);atomic_set (&thread->refcnt,0 ); +INIT_LIST_HEAD (&thread->node); +RB_CLEAR_NODE (&thread->rb_node); }return thread;
@@ -67,6 +69,9 @@ void thread__delete(struct thread *thread) {struct comm *comm, *tmp; +BUG_ON (!RB_EMPTY_NODE (&thread->rb_node)); +BUG_ON (!list_empty (&thread->node)); +thread_stack__free (thread);if (thread->mg) {
@@ -84,7 +89,8 @@ void thread__delete(struct thread *thread)struct thread *thread__get (struct thread *thread) { -atomic_inc (&thread->refcnt); +if (thread) +atomic_inc (&thread->refcnt);return thread; }