From f6005cafebab72f8c02100dc896d6cfd5b8918cb Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Thu, 8 Jun 2023 16:28:04 -0700 Subject: [PATCH] perf thread: Add reference count checking Modify struct declaration and accessor functions for the reference count checkers additional layer of indirection. Make sure pid_cmp in builtin-sched.c uses the underlying/original struct in pointer arithmetic, and not the temporary get/put indirection. Signed-off-by: Ian Rogers Cc: Adrian Hunter Cc: Alexander Shishkin Cc: Ali Saidi Cc: Andi Kleen Cc: Athira Rajeev Cc: Brian Robbins Cc: Changbin Du Cc: Dmitrii Dolgov <9erthalion6@gmail.com> Cc: Fangrui Song Cc: German Gomez Cc: Ingo Molnar Cc: Ivan Babrou Cc: James Clark Cc: Jing Zhang Cc: Jiri Olsa Cc: John Garry Cc: K Prateek Nayak Cc: Kan Liang Cc: Leo Yan Cc: Liam Howlett Cc: Mark Rutland Cc: Miguel Ojeda Cc: Mike Leach Cc: Namhyung Kim Cc: Naveen N. Rao Cc: Peter Zijlstra Cc: Ravi Bangoria Cc: Sean Christopherson Cc: Steinar H. Gunderson Cc: Suzuki Poulouse Cc: Wenyu Liu Cc: Will Deacon Cc: Yang Jihong Cc: Ye Xingchen Cc: Yuan Can Cc: coresight@lists.linaro.org Cc: linux-arm-kernel@lists.infradead.org Link: https://lore.kernel.org/r/20230608232823.4027869-8-irogers@google.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-sched.c | 4 +- tools/perf/tests/hists_link.c | 2 +- tools/perf/ui/hist.c | 5 ++- tools/perf/util/hist.c | 2 +- tools/perf/util/machine.c | 2 +- tools/perf/util/sort.c | 2 +- tools/perf/util/thread.c | 20 +++++---- tools/perf/util/thread.h | 79 ++++++++++++++++++----------------- 8 files changed, 63 insertions(+), 53 deletions(-) diff --git a/tools/perf/builtin-sched.c b/tools/perf/builtin-sched.c index c75ad82a6729..cd79068200e5 100644 --- a/tools/perf/builtin-sched.c +++ b/tools/perf/builtin-sched.c @@ -1385,7 +1385,7 @@ static int pid_cmp(struct work_atoms *l, struct work_atoms *r) { pid_t l_tid, r_tid; - if (l->thread == r->thread) + if (RC_CHK_ACCESS(l->thread) == RC_CHK_ACCESS(r->thread)) return 0; l_tid = thread__tid(l->thread); r_tid = thread__tid(r->thread); @@ -1393,7 +1393,7 @@ static int pid_cmp(struct work_atoms *l, struct work_atoms *r) return -1; if (l_tid > r_tid) return 1; - return (int)(l->thread - r->thread); + return (int)(RC_CHK_ACCESS(l->thread) - RC_CHK_ACCESS(r->thread)); } static int avg_cmp(struct work_atoms *l, struct work_atoms *r) diff --git a/tools/perf/tests/hists_link.c b/tools/perf/tests/hists_link.c index 12bad8840699..2d19657ab5e0 100644 --- a/tools/perf/tests/hists_link.c +++ b/tools/perf/tests/hists_link.c @@ -148,7 +148,7 @@ static int find_sample(struct sample *samples, size_t nr_samples, struct thread *t, struct map *m, struct symbol *s) { while (nr_samples--) { - if (samples->thread == t && + if (RC_CHK_ACCESS(samples->thread) == RC_CHK_ACCESS(t) && RC_CHK_ACCESS(samples->map) == RC_CHK_ACCESS(m) && samples->sym == s) return 1; diff --git a/tools/perf/ui/hist.c b/tools/perf/ui/hist.c index f164bd26fc41..2bf959d08354 100644 --- a/tools/perf/ui/hist.c +++ b/tools/perf/ui/hist.c @@ -11,6 +11,7 @@ #include "../util/sort.h" #include "../util/evsel.h" #include "../util/evlist.h" +#include "../util/thread.h" #include "../util/util.h" /* hist period print (hpp) functions */ @@ -274,7 +275,9 @@ static int __hpp__sort_acc(struct hist_entry *a, struct hist_entry *b, if (ret) return ret; - if (a->thread != b->thread || !hist_entry__has_callchains(a) || !symbol_conf.use_callchain) + if ((a->thread == NULL ? NULL : RC_CHK_ACCESS(a->thread)) != + (b->thread == NULL ? NULL : RC_CHK_ACCESS(b->thread)) || + !hist_entry__has_callchains(a) || !symbol_conf.use_callchain) return 0; ret = b->callchain->max_depth - a->callchain->max_depth; diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c index a4c1b617f6e4..dfda52d348a3 100644 --- a/tools/perf/util/hist.c +++ b/tools/perf/util/hist.c @@ -2124,7 +2124,7 @@ static bool hists__filter_entry_by_thread(struct hists *hists, struct hist_entry *he) { if (hists->thread_filter != NULL && - he->thread != hists->thread_filter) { + RC_CHK_ACCESS(he->thread) != RC_CHK_ACCESS(hists->thread_filter)) { he->filtered |= (1 << HIST_FILTER__THREAD); return true; } diff --git a/tools/perf/util/machine.c b/tools/perf/util/machine.c index 9fcf357a4d53..261188766307 100644 --- a/tools/perf/util/machine.c +++ b/tools/perf/util/machine.c @@ -2055,7 +2055,7 @@ static void __machine__remove_thread(struct machine *machine, struct thread_rb_n if (!nd) nd = thread_rb_node__find(th, &threads->entries.rb_root); - if (threads->last_match == th) + if (threads->last_match && RC_CHK_ACCESS(threads->last_match) == RC_CHK_ACCESS(th)) threads__set_last_match(threads, NULL); if (lock) diff --git a/tools/perf/util/sort.c b/tools/perf/util/sort.c index 5e45c770f91d..047c3606802f 100644 --- a/tools/perf/util/sort.c +++ b/tools/perf/util/sort.c @@ -128,7 +128,7 @@ static int hist_entry__thread_filter(struct hist_entry *he, int type, const void if (type != HIST_FILTER__THREAD) return -1; - return th && he->thread != th; + return th && RC_CHK_ACCESS(he->thread) != RC_CHK_ACCESS(th); } struct sort_entry sort_thread = { diff --git a/tools/perf/util/thread.c b/tools/perf/util/thread.c index bee4ac1051ee..0b166404c5c3 100644 --- a/tools/perf/util/thread.c +++ b/tools/perf/util/thread.c @@ -41,9 +41,10 @@ struct thread *thread__new(pid_t pid, pid_t tid) { char *comm_str; struct comm *comm; - struct thread *thread = zalloc(sizeof(*thread)); + RC_STRUCT(thread) *_thread = zalloc(sizeof(*_thread)); + struct thread *thread; - if (thread != NULL) { + if (ADD_RC_CHK(thread, _thread) != NULL) { thread__set_pid(thread, pid); thread__set_tid(thread, tid); thread__set_ppid(thread, -1); @@ -68,7 +69,7 @@ struct thread *thread__new(pid_t pid, pid_t tid) list_add(&comm->list, thread__comm_list(thread)); refcount_set(thread__refcnt(thread), 1); /* Thread holds first ref to nsdata. */ - thread->nsinfo = nsinfo__new(pid); + RC_CHK_ACCESS(thread)->nsinfo = nsinfo__new(pid); srccode_state_init(thread__srccode_state(thread)); } @@ -105,26 +106,31 @@ void thread__delete(struct thread *thread) } up_write(thread__comm_lock(thread)); - nsinfo__zput(thread->nsinfo); + nsinfo__zput(RC_CHK_ACCESS(thread)->nsinfo); srccode_state_free(thread__srccode_state(thread)); exit_rwsem(thread__namespaces_lock(thread)); exit_rwsem(thread__comm_lock(thread)); thread__free_stitch_list(thread); - free(thread); + RC_CHK_FREE(thread); } struct thread *thread__get(struct thread *thread) { - if (thread) + struct thread *result; + + if (RC_CHK_GET(result, thread)) refcount_inc(thread__refcnt(thread)); - return thread; + + return result; } void thread__put(struct thread *thread) { if (thread && refcount_dec_and_test(thread__refcnt(thread))) thread__delete(thread); + else + RC_CHK_PUT(thread); } static struct namespaces *__thread__namespaces(struct thread *thread) diff --git a/tools/perf/util/thread.h b/tools/perf/util/thread.h index b103992c3831..9068a21ce0fa 100644 --- a/tools/perf/util/thread.h +++ b/tools/perf/util/thread.h @@ -15,6 +15,7 @@ #include "rwsem.h" #include "event.h" #include "callchain.h" +#include struct addr_location; struct map; @@ -34,7 +35,7 @@ struct thread_rb_node { struct thread *thread; }; -struct thread { +DECLARE_RC_STRUCT(thread) { struct maps *maps; pid_t pid_; /* Not all tools update this */ pid_t tid; @@ -123,192 +124,192 @@ int thread__memcpy(struct thread *thread, struct machine *machine, static inline struct maps *thread__maps(struct thread *thread) { - return thread->maps; + return RC_CHK_ACCESS(thread)->maps; } static inline void thread__set_maps(struct thread *thread, struct maps *maps) { - thread->maps = maps; + RC_CHK_ACCESS(thread)->maps = maps; } static inline pid_t thread__pid(const struct thread *thread) { - return thread->pid_; + return RC_CHK_ACCESS(thread)->pid_; } static inline void thread__set_pid(struct thread *thread, pid_t pid_) { - thread->pid_ = pid_; + RC_CHK_ACCESS(thread)->pid_ = pid_; } static inline pid_t thread__tid(const struct thread *thread) { - return thread->tid; + return RC_CHK_ACCESS(thread)->tid; } static inline void thread__set_tid(struct thread *thread, pid_t tid) { - thread->tid = tid; + RC_CHK_ACCESS(thread)->tid = tid; } static inline pid_t thread__ppid(const struct thread *thread) { - return thread->ppid; + return RC_CHK_ACCESS(thread)->ppid; } static inline void thread__set_ppid(struct thread *thread, pid_t ppid) { - thread->ppid = ppid; + RC_CHK_ACCESS(thread)->ppid = ppid; } static inline int thread__cpu(const struct thread *thread) { - return thread->cpu; + return RC_CHK_ACCESS(thread)->cpu; } static inline void thread__set_cpu(struct thread *thread, int cpu) { - thread->cpu = cpu; + RC_CHK_ACCESS(thread)->cpu = cpu; } static inline int thread__guest_cpu(const struct thread *thread) { - return thread->guest_cpu; + return RC_CHK_ACCESS(thread)->guest_cpu; } static inline void thread__set_guest_cpu(struct thread *thread, int guest_cpu) { - thread->guest_cpu = guest_cpu; + RC_CHK_ACCESS(thread)->guest_cpu = guest_cpu; } static inline refcount_t *thread__refcnt(struct thread *thread) { - return &thread->refcnt; + return &RC_CHK_ACCESS(thread)->refcnt; } static inline bool thread__comm_set(const struct thread *thread) { - return thread->comm_set; + return RC_CHK_ACCESS(thread)->comm_set; } static inline void thread__set_comm_set(struct thread *thread, bool set) { - thread->comm_set = set; + RC_CHK_ACCESS(thread)->comm_set = set; } static inline int thread__var_comm_len(const struct thread *thread) { - return thread->comm_len; + return RC_CHK_ACCESS(thread)->comm_len; } static inline void thread__set_comm_len(struct thread *thread, int len) { - thread->comm_len = len; + RC_CHK_ACCESS(thread)->comm_len = len; } static inline struct list_head *thread__namespaces_list(struct thread *thread) { - return &thread->namespaces_list; + return &RC_CHK_ACCESS(thread)->namespaces_list; } static inline int thread__namespaces_list_empty(const struct thread *thread) { - return list_empty(&thread->namespaces_list); + return list_empty(&RC_CHK_ACCESS(thread)->namespaces_list); } static inline struct rw_semaphore *thread__namespaces_lock(struct thread *thread) { - return &thread->namespaces_lock; + return &RC_CHK_ACCESS(thread)->namespaces_lock; } static inline struct list_head *thread__comm_list(struct thread *thread) { - return &thread->comm_list; + return &RC_CHK_ACCESS(thread)->comm_list; } static inline struct rw_semaphore *thread__comm_lock(struct thread *thread) { - return &thread->comm_lock; + return &RC_CHK_ACCESS(thread)->comm_lock; } static inline u64 thread__db_id(const struct thread *thread) { - return thread->db_id; + return RC_CHK_ACCESS(thread)->db_id; } static inline void thread__set_db_id(struct thread *thread, u64 db_id) { - thread->db_id = db_id; + RC_CHK_ACCESS(thread)->db_id = db_id; } static inline void *thread__priv(struct thread *thread) { - return thread->priv; + return RC_CHK_ACCESS(thread)->priv; } static inline void thread__set_priv(struct thread *thread, void *p) { - thread->priv = p; + RC_CHK_ACCESS(thread)->priv = p; } static inline struct thread_stack *thread__ts(struct thread *thread) { - return thread->ts; + return RC_CHK_ACCESS(thread)->ts; } static inline void thread__set_ts(struct thread *thread, struct thread_stack *ts) { - thread->ts = ts; + RC_CHK_ACCESS(thread)->ts = ts; } static inline struct nsinfo *thread__nsinfo(struct thread *thread) { - return thread->nsinfo; + return RC_CHK_ACCESS(thread)->nsinfo; } static inline struct srccode_state *thread__srccode_state(struct thread *thread) { - return &thread->srccode_state; + return &RC_CHK_ACCESS(thread)->srccode_state; } static inline bool thread__filter(const struct thread *thread) { - return thread->filter; + return RC_CHK_ACCESS(thread)->filter; } static inline void thread__set_filter(struct thread *thread, bool filter) { - thread->filter = filter; + RC_CHK_ACCESS(thread)->filter = filter; } static inline int thread__filter_entry_depth(const struct thread *thread) { - return thread->filter_entry_depth; + return RC_CHK_ACCESS(thread)->filter_entry_depth; } static inline void thread__set_filter_entry_depth(struct thread *thread, int depth) { - thread->filter_entry_depth = depth; + RC_CHK_ACCESS(thread)->filter_entry_depth = depth; } static inline bool thread__lbr_stitch_enable(const struct thread *thread) { - return thread->lbr_stitch_enable; + return RC_CHK_ACCESS(thread)->lbr_stitch_enable; } static inline void thread__set_lbr_stitch_enable(struct thread *thread, bool en) { - thread->lbr_stitch_enable = en; + RC_CHK_ACCESS(thread)->lbr_stitch_enable = en; } static inline struct lbr_stitch *thread__lbr_stitch(struct thread *thread) { - return thread->lbr_stitch; + return RC_CHK_ACCESS(thread)->lbr_stitch; } static inline void thread__set_lbr_stitch(struct thread *thread, struct lbr_stitch *lbrs) { - thread->lbr_stitch = lbrs; + RC_CHK_ACCESS(thread)->lbr_stitch = lbrs; } static inline bool thread__is_filtered(struct thread *thread)