summaryrefslogtreecommitdiffstats
path: root/base/lazy_instance.cc
diff options
context:
space:
mode:
authordvyukov@google.com <dvyukov@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2011-05-16 15:01:54 +0000
committerdvyukov@google.com <dvyukov@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2011-05-16 15:01:54 +0000
commit1b651d537c95fcd5863662092aa6778176571605 (patch)
treef23a1bbaa502bd7ffc2cd65d3b794ac0c32cf1ca /base/lazy_instance.cc
parentfad5a1acfee3ee76009853a48c2c3dc9965e41f8 (diff)
downloadchromium_src-1b651d537c95fcd5863662092aa6778176571605.zip
chromium_src-1b651d537c95fcd5863662092aa6778176571605.tar.gz
chromium_src-1b651d537c95fcd5863662092aa6778176571605.tar.bz2
Fix data races in LazyInstance<>.
BUG=82122 Review URL: http://codereview.chromium.org/6997014 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@85487 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'base/lazy_instance.cc')
-rw-r--r--base/lazy_instance.cc27
1 files changed, 19 insertions, 8 deletions
diff --git a/base/lazy_instance.cc b/base/lazy_instance.cc
index 32bb788..1be3488 100644
--- a/base/lazy_instance.cc
+++ b/base/lazy_instance.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
@@ -15,15 +15,21 @@ namespace base {
bool LazyInstanceHelper::NeedsInstance() {
// Try to create the instance, if we're the first, will go from EMPTY
// to CREATING, otherwise we've already been beaten here.
- if (base::subtle::Acquire_CompareAndSwap(
- &state_, STATE_EMPTY, STATE_CREATING) == STATE_EMPTY) {
+ // The memory access has no memory ordering as STATE_EMPTY and STATE_CREATING
+ // has no associated data (memory barriers are all about ordering
+ // of memory accesses to *associated* data).
+ if (base::subtle::NoBarrier_CompareAndSwap(
+ &state_, STATE_EMPTY, STATE_CREATING) == STATE_EMPTY)
// Caller must create instance
return true;
- } else {
- // It's either in the process of being created, or already created. Spin.
- while (base::subtle::NoBarrier_Load(&state_) != STATE_CREATED)
- PlatformThread::YieldCurrentThread();
- }
+
+ // It's either in the process of being created, or already created. Spin.
+ // The load has acquire memory ordering as a thread which sees
+ // state_ == STATE_CREATED needs to acquire visibility over
+ // the associated data (buf_). Pairing Release_Store is in
+ // CompleteInstance().
+ while (base::subtle::Acquire_Load(&state_) != STATE_CREATED)
+ PlatformThread::YieldCurrentThread();
// Someone else created the instance.
return false;
@@ -34,6 +40,8 @@ void LazyInstanceHelper::CompleteInstance(void* instance, void (*dtor)(void*)) {
ANNOTATE_HAPPENS_BEFORE(&state_);
// Instance is created, go from CREATING to CREATED.
+ // Releases visibility over buf_ to readers. Pairing Acquire_Load's are in
+ // NeedsInstance() and Pointer().
base::subtle::Release_Store(&state_, STATE_CREATED);
// Make sure that the lazily instantiated object will get destroyed at exit.
@@ -42,3 +50,6 @@ void LazyInstanceHelper::CompleteInstance(void* instance, void (*dtor)(void*)) {
}
} // namespace base
+
+
+