diff options
author | dvyukov@google.com <dvyukov@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-05-16 15:01:54 +0000 |
---|---|---|
committer | dvyukov@google.com <dvyukov@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-05-16 15:01:54 +0000 |
commit | 1b651d537c95fcd5863662092aa6778176571605 (patch) | |
tree | f23a1bbaa502bd7ffc2cd65d3b794ac0c32cf1ca /base/lazy_instance.cc | |
parent | fad5a1acfee3ee76009853a48c2c3dc9965e41f8 (diff) | |
download | chromium_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.cc | 27 |
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 + + + |