Index: third_party/tcmalloc/chromium/src/base/spinlock.h |
=================================================================== |
--- third_party/tcmalloc/chromium/src/base/spinlock.h (revision 87277) |
+++ third_party/tcmalloc/chromium/src/base/spinlock.h (working copy) |
@@ -44,14 +44,14 @@ |
#define BASE_SPINLOCK_H_ |
#include <config.h> |
-#include "base/basictypes.h" |
#include "base/atomicops.h" |
+#include "base/basictypes.h" |
#include "base/dynamic_annotations.h" |
#include "base/thread_annotations.h" |
class LOCKABLE SpinLock { |
public: |
- SpinLock() : lockword_(0) { } |
+ SpinLock() : lockword_(kSpinLockFree) { } |
// Special constructor for use with static SpinLock objects. E.g., |
// |
@@ -70,18 +70,21 @@ |
// TODO(csilvers): uncomment the annotation when we figure out how to |
// support this macro with 0 args (see thread_annotations.h) |
inline void Lock() /*EXCLUSIVE_LOCK_FUNCTION()*/ { |
- if (Acquire_CompareAndSwap(&lockword_, 0, 1) != 0) { |
+ if (base::subtle::Acquire_CompareAndSwap(&lockword_, kSpinLockFree, |
+ kSpinLockHeld) != kSpinLockFree) { |
SlowLock(); |
} |
ANNOTATE_RWLOCK_ACQUIRED(this, 1); |
} |
- // Acquire this SpinLock and return true if the acquisition can be |
- // done without blocking, else return false. If this SpinLock is |
- // free at the time of the call, TryLock will return true with high |
- // probability. |
+ // Try to acquire this SpinLock without blocking and return true if the |
+ // acquisition was successful. If the lock was not acquired, false is |
+ // returned. If this SpinLock is free at the time of the call, TryLock |
+ // will return true with high probability. |
inline bool TryLock() EXCLUSIVE_TRYLOCK_FUNCTION(true) { |
- bool res = (Acquire_CompareAndSwap(&lockword_, 0, 1) == 0); |
+ bool res = |
+ (base::subtle::Acquire_CompareAndSwap(&lockword_, kSpinLockFree, |
+ kSpinLockHeld) == kSpinLockFree); |
if (res) { |
ANNOTATE_RWLOCK_ACQUIRED(this, 1); |
} |
@@ -92,47 +95,37 @@ |
// TODO(csilvers): uncomment the annotation when we figure out how to |
// support this macro with 0 args (see thread_annotations.h) |
inline void Unlock() /*UNLOCK_FUNCTION()*/ { |
- // This is defined in mutex.cc. |
- extern void SubmitSpinLockProfileData(const void *, int64); |
- |
- int64 wait_timestamp = static_cast<uint32>(lockword_); |
+ uint64 wait_cycles = |
+ static_cast<uint64>(base::subtle::NoBarrier_Load(&lockword_)); |
ANNOTATE_RWLOCK_RELEASED(this, 1); |
- Release_Store(&lockword_, 0); |
- if (wait_timestamp != 1) { |
+ base::subtle::Release_Store(&lockword_, kSpinLockFree); |
+ if (wait_cycles != kSpinLockHeld) { |
// Collect contentionz profile info, and speed the wakeup of any waiter. |
- // The lockword_ value indicates when the waiter started waiting. |
- SlowUnlock(wait_timestamp); |
+ // The wait_cycles value indicates how long this thread spent waiting |
+ // for the lock. |
+ SlowUnlock(wait_cycles); |
} |
} |
- // Report if we think the lock can be held by this thread. |
- // When the lock is truly held by the invoking thread |
- // we will always return true. |
- // Indended to be used as CHECK(lock.IsHeld()); |
+ // Determine if the lock is held. When the lock is held by the invoking |
+ // thread, true will always be returned. Intended to be used as |
+ // CHECK(lock.IsHeld()). |
inline bool IsHeld() const { |
- return lockword_ != 0; |
+ return base::subtle::NoBarrier_Load(&lockword_) != kSpinLockFree; |
} |
- // The timestamp for contention lock profiling must fit into 31 bits. |
- // as lockword_ is 32 bits and we loose an additional low-order bit due |
- // to the statement "now |= 1" in SlowLock(). |
- // To select 31 bits from the 64-bit cycle counter, we shift right by |
- // PROFILE_TIMESTAMP_SHIFT = 7. |
- // Using these 31 bits, we reduce granularity of time measurement to |
- // 256 cycles, and will loose track of wait time for waits greater than |
- // 109 seconds on a 5 GHz machine, longer for faster clock cycles. |
- // Waits this long should be very rare. |
- enum { PROFILE_TIMESTAMP_SHIFT = 7 }; |
- |
static const base::LinkerInitialized LINKER_INITIALIZED; // backwards compat |
private: |
- // Lock-state: 0 means unlocked; 1 means locked with no waiters; values |
- // greater than 1 indicate locked with waiters, where the value is the time |
- // the first waiter started waiting and is used for contention profiling. |
+ enum { kSpinLockFree = 0 }; |
+ enum { kSpinLockHeld = 1 }; |
+ enum { kSpinLockSleeper = 2 }; |
+ |
volatile Atomic32 lockword_; |
void SlowLock(); |
- void SlowUnlock(int64 wait_timestamp); |
+ void SlowUnlock(uint64 wait_cycles); |
+ Atomic32 SpinLoop(int64 initial_wait_timestamp, Atomic32* wait_cycles); |
+ inline int32 CalculateWaitCycles(int64 wait_start_time); |
DISALLOW_COPY_AND_ASSIGN(SpinLock); |
}; |