Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S932222AbdIGR4j (ORCPT ); Thu, 7 Sep 2017 13:56:39 -0400 Received: from mga09.intel.com ([134.134.136.24]:19649 "EHLO mga09.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1755601AbdIGR4c (ORCPT ); Thu, 7 Sep 2017 13:56:32 -0400 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.42,359,1500966000"; d="scan'208";a="149347730" From: kan.liang@intel.com To: acme@kernel.org, peterz@infradead.org, mingo@redhat.com, linux-kernel@vger.kernel.org Cc: jolsa@kernel.org, namhyung@kernel.org, adrian.hunter@intel.com, lukasz.odzioba@intel.com, ak@linux.intel.com, Kan Liang Subject: [PATCH RFC 05/10] perf tools: lock to protect thread list Date: Thu, 7 Sep 2017 10:55:49 -0700 Message-Id: <1504806954-150842-6-git-send-email-kan.liang@intel.com> X-Mailer: git-send-email 2.5.5 In-Reply-To: <1504806954-150842-1-git-send-email-kan.liang@intel.com> References: <1504806954-150842-1-git-send-email-kan.liang@intel.com> Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 6650 Lines: 206 From: Kan Liang Add two locks to protect namespaces_list and comm_list. The comm which is used in db-export are not protected. Because the multithread code will not touch it. It can be added later if required. Signed-off-by: Kan Liang --- tools/perf/ui/browsers/hists.c | 2 +- tools/perf/util/thread.c | 60 +++++++++++++++++++++++++++++++++--------- tools/perf/util/thread.h | 6 +++-- 3 files changed, 52 insertions(+), 16 deletions(-) diff --git a/tools/perf/ui/browsers/hists.c b/tools/perf/ui/browsers/hists.c index 13dfb0a..429e1dd 100644 --- a/tools/perf/ui/browsers/hists.c +++ b/tools/perf/ui/browsers/hists.c @@ -2370,7 +2370,7 @@ static int perf_evsel_browser_title(struct hist_browser *browser, char unit; int printed; const struct dso *dso = hists->dso_filter; - const struct thread *thread = hists->thread_filter; + struct thread *thread = hists->thread_filter; int socket_id = hists->socket_filter; unsigned long nr_samples = hists->stats.nr_events[PERF_RECORD_SAMPLE]; u64 nr_events = hists->stats.total_period; diff --git a/tools/perf/util/thread.c b/tools/perf/util/thread.c index b7957da..25830b2 100644 --- a/tools/perf/util/thread.c +++ b/tools/perf/util/thread.c @@ -45,6 +45,8 @@ struct thread *thread__new(pid_t pid, pid_t tid) thread->cpu = -1; INIT_LIST_HEAD(&thread->namespaces_list); INIT_LIST_HEAD(&thread->comm_list); + pthread_mutex_init(&thread->namespaces_lock, NULL); + pthread_mutex_init(&thread->comm_lock, NULL); comm_str = malloc(32); if (!comm_str) @@ -83,15 +85,21 @@ void thread__delete(struct thread *thread) map_groups__put(thread->mg); thread->mg = NULL; } + pthread_mutex_lock(&thread->namespaces_lock); list_for_each_entry_safe(namespaces, tmp_namespaces, &thread->namespaces_list, list) { list_del(&namespaces->list); namespaces__free(namespaces); } + pthread_mutex_unlock(&thread->namespaces_lock); + + pthread_mutex_lock(&thread->comm_lock); list_for_each_entry_safe(comm, tmp_comm, &thread->comm_list, list) { list_del(&comm->list); comm__free(comm); } + pthread_mutex_unlock(&thread->comm_lock); + unwind__finish_access(thread); nsinfo__zput(thread->nsinfo); @@ -128,11 +136,17 @@ struct namespaces *thread__namespaces(const struct thread *thread) int thread__set_namespaces(struct thread *thread, u64 timestamp, struct namespaces_event *event) { - struct namespaces *new, *curr = thread__namespaces(thread); + struct namespaces *new, *curr; + + pthread_mutex_lock(&thread->namespaces_lock); + + curr = thread__namespaces(thread); new = namespaces__new(event); - if (!new) + if (!new) { + pthread_mutex_unlock(&thread->namespaces_lock); return -ENOMEM; + } list_add(&new->list, &thread->namespaces_list); @@ -146,17 +160,21 @@ int thread__set_namespaces(struct thread *thread, u64 timestamp, curr->end_time = timestamp; } + pthread_mutex_unlock(&thread->namespaces_lock); + return 0; } -void thread__namespaces_id(const struct thread *thread, +void thread__namespaces_id(struct thread *thread, u64 *dev, u64 *ino) { struct namespaces *ns; + pthread_mutex_lock(&thread->namespaces_lock); ns = thread__namespaces(thread); *dev = ns ? ns->link_info[CGROUP_NS_INDEX].dev : 0; *ino = ns ? ns->link_info[CGROUP_NS_INDEX].ino : 0; + pthread_mutex_unlock(&thread->namespaces_lock); } struct comm *thread__comm(const struct thread *thread) @@ -183,17 +201,23 @@ struct comm *thread__exec_comm(const struct thread *thread) int __thread__set_comm(struct thread *thread, const char *str, u64 timestamp, bool exec) { - struct comm *new, *curr = thread__comm(thread); + struct comm *new, *curr; + int err = 0; + + pthread_mutex_lock(&thread->comm_lock); + curr = thread__comm(thread); /* Override the default :tid entry */ if (!thread->comm_set) { - int err = comm__override(curr, str, timestamp, exec); + err = comm__override(curr, str, timestamp, exec); if (err) - return err; + goto unlock; } else { new = comm__new(str, timestamp, exec); - if (!new) - return -ENOMEM; + if (!new) { + err = -ENOMEM; + goto unlock; + } list_add(&new->list, &thread->comm_list); if (exec) @@ -202,7 +226,9 @@ int __thread__set_comm(struct thread *thread, const char *str, u64 timestamp, thread->comm_set = true; - return 0; +unlock: + pthread_mutex_unlock(&thread->comm_lock); + return err; } int thread__set_comm_from_proc(struct thread *thread) @@ -222,14 +248,22 @@ int thread__set_comm_from_proc(struct thread *thread) return err; } -const char *thread__comm_str(const struct thread *thread) +const char *thread__comm_str(struct thread *thread) { - const struct comm *comm = thread__comm(thread); + const struct comm *comm; + const char *str; + + pthread_mutex_lock(&thread->comm_lock); + comm = thread__comm(thread); - if (!comm) + if (!comm) { + pthread_mutex_unlock(&thread->comm_lock); return NULL; + } + str = comm__str(comm); - return comm__str(comm); + pthread_mutex_unlock(&thread->comm_lock); + return str; } /* CHECKME: it should probably better return the max comm len from its comm list */ diff --git a/tools/perf/util/thread.h b/tools/perf/util/thread.h index fd7bd41..1d3062a 100644 --- a/tools/perf/util/thread.h +++ b/tools/perf/util/thread.h @@ -29,7 +29,9 @@ struct thread { int comm_len; bool dead; /* if set thread has exited */ struct list_head namespaces_list; + pthread_mutex_t namespaces_lock; struct list_head comm_list; + pthread_mutex_t comm_lock; u64 db_id; void *priv; @@ -68,7 +70,7 @@ static inline void thread__exited(struct thread *thread) struct namespaces *thread__namespaces(const struct thread *thread); int thread__set_namespaces(struct thread *thread, u64 timestamp, struct namespaces_event *event); -void thread__namespaces_id(const struct thread *thread, +void thread__namespaces_id(struct thread *thread, u64 *dev, u64 *ino); int __thread__set_comm(struct thread *thread, const char *comm, u64 timestamp, @@ -84,7 +86,7 @@ int thread__set_comm_from_proc(struct thread *thread); int thread__comm_len(struct thread *thread); struct comm *thread__comm(const struct thread *thread); struct comm *thread__exec_comm(const struct thread *thread); -const char *thread__comm_str(const struct thread *thread); +const char *thread__comm_str(struct thread *thread); int thread__insert_map(struct thread *thread, struct map *map); int thread__fork(struct thread *thread, struct thread *parent, u64 timestamp); size_t thread__fprintf(struct thread *thread, FILE *fp); -- 2.5.5