From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753717AbbETMZr (ORCPT ); Wed, 20 May 2015 08:25:47 -0400 Received: from terminus.zytor.com ([198.137.202.10]:56838 "EHLO terminus.zytor.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S932091AbbETMZk (ORCPT ); Wed, 20 May 2015 08:25:40 -0400 Date: Wed, 20 May 2015 05:25:20 -0700 From: tip-bot for Namhyung Kim Message-ID: Cc: tglx@linutronix.de, jolsa@redhat.com, acme@redhat.com, andi@firstfloor.org, hpa@zytor.com, namhyung@kernel.org, dsahern@gmail.com, mingo@kernel.org, adrian.hunter@intel.com, a.p.zijlstra@chello.nl, linux-kernel@vger.kernel.org, eranian@google.com, fweisbec@gmail.com Reply-To: dsahern@gmail.com, namhyung@kernel.org, mingo@kernel.org, jolsa@redhat.com, tglx@linutronix.de, hpa@zytor.com, andi@firstfloor.org, acme@redhat.com, linux-kernel@vger.kernel.org, fweisbec@gmail.com, eranian@google.com, adrian.hunter@intel.com, a.p.zijlstra@chello.nl In-Reply-To: <1431909055-21442-27-git-send-email-namhyung@kernel.org> References: <1431909055-21442-27-git-send-email-namhyung@kernel.org> To: linux-tip-commits@vger.kernel.org Subject: [tip:perf/core] perf symbols: Protect dso cache tree using dso-> lock Git-Commit-ID: 8e67b7258e582998ab635bdc3c884d7a8077af5b X-Mailer: tip-git-log-daemon Robot-ID: Robot-Unsubscribe: Contact to get blacklisted from these emails MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Content-Type: text/plain; charset=UTF-8 Content-Disposition: inline Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Commit-ID: 8e67b7258e582998ab635bdc3c884d7a8077af5b Gitweb: http://git.kernel.org/tip/8e67b7258e582998ab635bdc3c884d7a8077af5b Author: Namhyung Kim AuthorDate: Mon, 18 May 2015 09:30:41 +0900 Committer: Arnaldo Carvalho de Melo CommitDate: Mon, 18 May 2015 10:17:37 -0300 perf symbols: Protect dso cache tree using dso->lock The dso cache is accessed during dwarf callchain unwind and it might be processed concurrently. Protect it under dso->lock. Note that it doesn't protect dso_cache__find(). I think it's safe to access to the cache tree without the lock since we don't delete nodes. It it missed an existing node due to rotation, it'll find it during dso_cache__insert() anyway. Signed-off-by: Namhyung Kim Cc: Adrian Hunter Cc: Andi Kleen Cc: David Ahern Cc: Frederic Weisbecker Cc: Jiri Olsa Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lkml.kernel.org/r/1431909055-21442-27-git-send-email-namhyung@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/dso.c | 34 +++++++++++++++++++++++++++------- 1 file changed, 27 insertions(+), 7 deletions(-) diff --git a/tools/perf/util/dso.c b/tools/perf/util/dso.c index 482d602..666e1db 100644 --- a/tools/perf/util/dso.c +++ b/tools/perf/util/dso.c @@ -495,10 +495,12 @@ bool dso__data_status_seen(struct dso *dso, enum dso_data_status_seen by) } static void -dso_cache__free(struct rb_root *root) +dso_cache__free(struct dso *dso) { + struct rb_root *root = &dso->data.cache; struct rb_node *next = rb_first(root); + pthread_mutex_lock(&dso->lock); while (next) { struct dso_cache *cache; @@ -507,10 +509,12 @@ dso_cache__free(struct rb_root *root) rb_erase(&cache->rb_node, root); free(cache); } + pthread_mutex_unlock(&dso->lock); } -static struct dso_cache *dso_cache__find(const struct rb_root *root, u64 offset) +static struct dso_cache *dso_cache__find(struct dso *dso, u64 offset) { + const struct rb_root *root = &dso->data.cache; struct rb_node * const *p = &root->rb_node; const struct rb_node *parent = NULL; struct dso_cache *cache; @@ -529,17 +533,20 @@ static struct dso_cache *dso_cache__find(const struct rb_root *root, u64 offset) else return cache; } + return NULL; } -static void -dso_cache__insert(struct rb_root *root, struct dso_cache *new) +static struct dso_cache * +dso_cache__insert(struct dso *dso, struct dso_cache *new) { + struct rb_root *root = &dso->data.cache; struct rb_node **p = &root->rb_node; struct rb_node *parent = NULL; struct dso_cache *cache; u64 offset = new->offset; + pthread_mutex_lock(&dso->lock); while (*p != NULL) { u64 end; @@ -551,10 +558,17 @@ dso_cache__insert(struct rb_root *root, struct dso_cache *new) p = &(*p)->rb_left; else if (offset >= end) p = &(*p)->rb_right; + else + goto out; } rb_link_node(&new->rb_node, parent, p); rb_insert_color(&new->rb_node, root); + + cache = NULL; +out: + pthread_mutex_unlock(&dso->lock); + return cache; } static ssize_t @@ -572,6 +586,7 @@ static ssize_t dso_cache__read(struct dso *dso, u64 offset, u8 *data, ssize_t size) { struct dso_cache *cache; + struct dso_cache *old; ssize_t ret; do { @@ -591,7 +606,12 @@ dso_cache__read(struct dso *dso, u64 offset, u8 *data, ssize_t size) cache->offset = cache_offset; cache->size = ret; - dso_cache__insert(&dso->data.cache, cache); + old = dso_cache__insert(dso, cache); + if (old) { + /* we lose the race */ + free(cache); + cache = old; + } ret = dso_cache__memcpy(cache, offset, data, size); @@ -608,7 +628,7 @@ static ssize_t dso_cache_read(struct dso *dso, u64 offset, { struct dso_cache *cache; - cache = dso_cache__find(&dso->data.cache, offset); + cache = dso_cache__find(dso, offset); if (cache) return dso_cache__memcpy(cache, offset, data, size); else @@ -964,7 +984,7 @@ void dso__delete(struct dso *dso) dso__data_close(dso); auxtrace_cache__free(dso->auxtrace_cache); - dso_cache__free(&dso->data.cache); + dso_cache__free(dso); dso__free_a2l(dso); zfree(&dso->symsrc_filename); pthread_mutex_destroy(&dso->lock);