Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

perf thread: Ensure comm_lock held for comm_list

Add thread safety annotations for comm_list and add locking for two
instances where the list is accessed without the lock held (in
contradiction to ____thread__set_comm()).

Signed-off-by: Ian Rogers <irogers@google.com>
Cc: Adrian Hunter <adrian.hunter@intel.com>
Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Cc: Athira Rajeev <atrajeev@linux.vnet.ibm.com>
Cc: Bill Wendling <morbo@google.com>
Cc: Chaitanya S Prakash <chaitanyas.prakash@arm.com>
Cc: Fei Lang <langfei@huawei.com>
Cc: Howard Chu <howardchu95@gmail.com>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: James Clark <james.clark@linaro.org>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Justin Stitt <justinstitt@google.com>
Cc: Kan Liang <kan.liang@linux.intel.com>
Cc: Mark Rutland <mark.rutland@arm.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Nathan Chancellor <nathan@kernel.org>
Cc: Nick Desaulniers <nick.desaulniers+lkml@gmail.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Stephen Brennan <stephen.s.brennan@oracle.com>
Link: https://lore.kernel.org/r/20250519224645.1810891-3-irogers@google.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>

authored by

Ian Rogers and committed by
Arnaldo Carvalho de Melo
8f454c95 6fe06449

+21 -9
+2
tools/perf/util/comm.c
··· 24 24 static void comm_strs__remove_if_last(struct comm_str *cs); 25 25 26 26 static void comm_strs__init(void) 27 + NO_THREAD_SAFETY_ANALYSIS /* Inherently single threaded due to pthread_once. */ 27 28 { 28 29 init_rwsem(&_comm_strs.lock); 29 30 _comm_strs.capacity = 16; ··· 120 119 } 121 120 122 121 static struct comm_str *__comm_strs__find(struct comm_strs *comm_strs, const char *str) 122 + SHARED_LOCKS_REQUIRED(comm_strs->lock) 123 123 { 124 124 struct comm_str **result; 125 125
+13 -4
tools/perf/util/thread.c
··· 41 41 } 42 42 43 43 struct thread *thread__new(pid_t pid, pid_t tid) 44 + NO_THREAD_SAFETY_ANALYSIS /* Allocation/creation is inherently single threaded. */ 44 45 { 45 46 RC_STRUCT(thread) *_thread = zalloc(sizeof(*_thread)); 46 47 struct thread *thread; ··· 203 202 204 203 struct comm *thread__comm(struct thread *thread) 205 204 { 206 - if (list_empty(thread__comm_list(thread))) 207 - return NULL; 205 + struct comm *res = NULL; 208 206 209 - return list_first_entry(thread__comm_list(thread), struct comm, list); 207 + down_read(thread__comm_lock(thread)); 208 + if (!list_empty(thread__comm_list(thread))) 209 + res = list_first_entry(thread__comm_list(thread), struct comm, list); 210 + up_read(thread__comm_lock(thread)); 211 + return res; 210 212 } 211 213 212 214 struct comm *thread__exec_comm(struct thread *thread) 213 215 { 214 216 struct comm *comm, *last = NULL, *second_last = NULL; 215 217 218 + down_read(thread__comm_lock(thread)); 216 219 list_for_each_entry(comm, thread__comm_list(thread), list) { 217 - if (comm->exec) 220 + if (comm->exec) { 221 + up_read(thread__comm_lock(thread)); 218 222 return comm; 223 + } 219 224 second_last = last; 220 225 last = comm; 221 226 } 227 + up_read(thread__comm_lock(thread)); 222 228 223 229 /* 224 230 * 'last' with no start time might be the parent's comm of a synthesized ··· 241 233 242 234 static int ____thread__set_comm(struct thread *thread, const char *str, 243 235 u64 timestamp, bool exec) 236 + EXCLUSIVE_LOCKS_REQUIRED(thread__comm_lock(thread)) 244 237 { 245 238 struct comm *new, *curr = thread__comm(thread); 246 239
+6 -5
tools/perf/util/thread.h
··· 236 236 return &RC_CHK_ACCESS(thread)->namespaces_lock; 237 237 } 238 238 239 - static inline struct list_head *thread__comm_list(struct thread *thread) 240 - { 241 - return &RC_CHK_ACCESS(thread)->comm_list; 242 - } 243 - 244 239 static inline struct rw_semaphore *thread__comm_lock(struct thread *thread) 245 240 { 246 241 return &RC_CHK_ACCESS(thread)->comm_lock; 242 + } 243 + 244 + static inline struct list_head *thread__comm_list(struct thread *thread) 245 + SHARED_LOCKS_REQUIRED(thread__comm_lock(thread)) 246 + { 247 + return &RC_CHK_ACCESS(thread)->comm_list; 247 248 } 248 249 249 250 static inline u64 thread__db_id(const struct thread *thread)