perf tools: Reference count struct thread
tip-bot for Arnaldo Carvalho de Melo
merge botCommit-ID: f3b623b8490af7a9b819cbcf2d99ab4597ece94b Gitweb: http://git.kernel.org/tip/f3b623b8490af7a9b819cbcf2d99ab4597ece94b Author: Arnaldo Carvalho de Melo <[email protected]> AuthorDate: Mon, 2 Mar 2015 22:21:35 -0300 Committer: Arnaldo Carvalho de Melo <[email protected]> CommitDate: Tue, 3 Mar 2015 00:17:08 -0300
perf tools: Reference count struct thread
We need to do that to stop accumulating entries in the dead_threads linked list, i.e. we were keeping references to threads in struct hists that continue to exist even after a thread exited and was removed from the machine threads rbtree.
We still keep the dead_threads list, but just for debugging, allowing us to iterate at any given point over the threads that still are referenced by things like struct hist_entry.
Cc Adrian Hunter <[email protected]>
Cc Borislav Petkov <[email protected]>
Cc David Ahern <[email protected]>
Cc Don Zickus <[email protected]>
Cc Frederic Weisbecker <[email protected]>
Cc Jiri Olsa <[email protected]>
Cc Namhyung Kim <[email protected]>
Cc Stephane Eranian <[email protected]>
Signed-off-by Arnaldo Carvalho de Melo <[email protected]>
--- tools/perf/builtin-sched.c | 2 +- tools/perf/builtin-trace.c | 7 ++++++- tools/perf/ui/browsers/hists.c | 6 +++--- tools/perf/util/build-id.c | 5 +++-- tools/perf/util/hist.c | 2 ++ tools/perf/util/hist.h | 2 +- tools/perf/util/machine.c | 44 ++++++++++++++++++++++-------------------- tools/perf/util/machine.h | 1 - tools/perf/util/session.c | 6 ------ tools/perf/util/thread.c | 14 ++++++++++++++ tools/perf/util/thread.h | 13 +++++++++++++ 11 files changed, 66 insertions(+), 36 deletions(-)
tools/perf/builtin-sched.c +1 -1
@@ -831,7 +831,7 @@ static int thread_atoms_insert(struct perf_sched *sched, struct thread *thread)return -1 ; } - atoms->thread = thread; + atoms->thread =thread__get (thread);INIT_LIST_HEAD (&atoms->work_list);__thread_latency_insert (&sched->atom_root, atoms, &sched->cmp_pid);return 0 ;
tools/perf/builtin-trace.c +6 -1
@@ -1741,7 +1741,10 @@ static int trace__sys_enter(struct trace *trace, struct perf_evsel *evsel, }else ttrace->entry_pending = true; - trace->current = thread; +if (trace->current != thread) { +thread__put (trace->current); + trace->current =thread__get (thread); + }return 0 ; }
@@ -2274,6 +2277,8 @@ next_event: } out_disable: +thread__zput (trace->current); +perf_evlist__disable (evlist);if (!err) {
tools/perf/ui/browsers/hists.c +3 -3
@@ -1467,7 +1467,7 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events,perf_hpp__set_user_width (symbol_conf.col_width_list_str);while (1 ) { -const struct thread *thread =NULL ; +struct thread *thread =NULL ;const struct dso *dso =NULL ;int choice =0 , annotate = -2, zoom_dso = -2, zoom_thread = -2,
@@ -1754,13 +1754,13 @@ zoom_thread:pstack__remove (fstack, &browser->hists->thread_filter); zoom_out_thread:ui_helpline__pop (); - browser->hists->thread_filter =NULL ; +thread__zput (browser->hists->thread_filter);perf_hpp__set_elide (HISTC_THREAD , false); }else {ui_helpline__fpush ("To zoom out press <- or -> + \"Zoom out of %s(%d) thread\"" , thread->comm_set ?thread__comm_str (thread) :"" , thread->tid); - browser->hists->thread_filter = thread; + browser->hists->thread_filter =thread__get (thread);perf_hpp__set_elide (HISTC_THREAD , false);pstack__push (fstack, &browser->hists->thread_filter); }
tools/perf/util/build-id.c +3 -2
@@ -61,8 +61,9 @@ static int perf_event__exit_del_thread(struct perf_tool *tool __maybe_unused,if (thread) {rb_erase (&thread->rb_node, &machine->threads); - machine->last_match =NULL ; -thread__delete (thread); +if (machine->last_match == thread) +thread__zput (machine->last_match); +thread__put (thread); }return 0 ;
tools/perf/util/hist.c +2 -0
@@ -355,6 +355,7 @@ static struct hist_entry *hist_entry__new(struct hist_entry *template,callchain_init (he->callchain);INIT_LIST_HEAD (&he->pairs.node); +thread__get (he->thread); }return he;
@@ -941,6 +942,7 @@ hist_entry__collapse(struct hist_entry *left, struct hist_entry *right)void hist_entry__delete (struct hist_entry *he) { +thread__zput (he->thread);zfree (&he->branch_info);zfree (&he->mem_info);zfree (&he->stat_acc);
tools/perf/util/hist.h +1 -1
@@ -60,7 +60,7 @@ struct hists {struct rb_root entries_collapsed;u64 nr_entries;u64 nr_non_filtered_entries; -const struct thread *thread_filter; +struct thread *thread_filter;const struct dso *dso_filter;const char *uid_filter_str;const char *symbol_filter_str;
tools/perf/util/machine.c +23 -21
91 lines not on this page · raw message
tools/perf/util/machine.h +0 -1
@@ -118,7 +118,6 @@ void machines__set_comm_exec(struct machines *machines, bool comm_exec);struct machine *machine__new_host (void );int machine__init (struct machine *machine,const char *root_dir,pid_t pid);void machine__exit (struct machine *machine); -void machine__delete_dead_threads (struct machine *machine);void machine__delete_threads (struct machine *machine);void machine__delete (struct machine *machine);
tools/perf/util/session.c +0 -6
@@ -138,11 +138,6 @@ struct perf_session *perf_session__new(struct perf_data_file *file,return NULL ; } -static void perf_session__delete_dead_threads (struct perf_session *session) -{ -machine__delete_dead_threads (&session->machines.host); -} -static void perf_session__delete_threads (struct perf_session *session) {machine__delete_threads (&session->machines.host);
@@ -167,7 +162,6 @@ static void perf_session_env__delete(struct perf_session_env *env)void perf_session__delete (struct perf_session *session) {perf_session__destroy_kernel_maps (session); -perf_session__delete_dead_threads (session);perf_session__delete_threads (session);perf_session_env__delete (&session->header.env);machines__exit (&session->machines);
tools/perf/util/thread.c +14 -0
@@ -82,6 +82,20 @@ void thread__delete(struct thread *thread)free (thread); } +struct thread *thread__get (struct thread *thread) +{ + ++thread->refcnt; +return thread; +} + +void thread__put (struct thread *thread) +{ +if (thread && --thread->refcnt ==0 ) { +list_del_init (&thread->node); +thread__delete (thread); + } +} +struct comm *thread__comm (const struct thread *thread) {if (list_empty (&thread->comm_list))
tools/perf/util/thread.h +13 -0
@@ -20,6 +20,7 @@ struct thread {pid_t tid;pid_t ppid;int cpu; +int refcnt;char shortname[3 ];bool comm_set;bool dead;/* if set thread has exited */
@@ -37,6 +38,18 @@ struct comm;struct thread *thread__new (pid_t pid,pid_t tid);int thread__init_map_groups (struct thread *thread,struct machine *machine);void thread__delete (struct thread *thread); + +struct thread *thread__get (struct thread *thread); +void thread__put (struct thread *thread); + +static inline void __thread__zput (struct thread **thread) +{ +thread__put (*thread); + *thread =NULL ; +} + +#define thread__zput (thread) __thread__zput(&thread) +static inline void thread__exited (struct thread *thread) { thread->dead = true;