/*
- * Copyright 2016 Facebook, Inc.
+ * Copyright 2017 Facebook, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
#include <cstdlib>
#include <folly/Portability.h>
#include <mutex>
-#include <pthread.h>
#include <type_traits>
-#include <glog/logging.h>
#include <folly/detail/Sleeper.h>
+#include <glog/logging.h>
#if !FOLLY_X64 && !FOLLY_A64 && !FOLLY_PPC64
# error "PicoSpinLock.h is currently x64, aarch64 and ppc64 only."
public:
static const UIntType kLockBitMask_ = UIntType(1) << Bit;
- UIntType lock_;
+ mutable UIntType lock_;
/*
* You must call this function before using this class, if you
*/
void init(IntType initialValue = 0) {
CHECK(!(initialValue & kLockBitMask_));
- lock_ = initialValue;
+ reinterpret_cast<std::atomic<UIntType>*>(&lock_)->store(
+ UIntType(initialValue), std::memory_order_release);
}
/*
* as you normally get.)
*/
IntType getData() const {
- return static_cast<IntType>(lock_ & ~kLockBitMask_);
+ auto res = reinterpret_cast<std::atomic<UIntType>*>(&lock_)->load(
+ std::memory_order_relaxed) &
+ ~kLockBitMask_;
+ return res;
}
/*
*/
void setData(IntType w) {
CHECK(!(w & kLockBitMask_));
- lock_ = (lock_ & kLockBitMask_) | w;
+ auto l = reinterpret_cast<std::atomic<UIntType>*>(&lock_);
+ l->store(
+ (l->load(std::memory_order_relaxed) & kLockBitMask_) | w,
+ std::memory_order_relaxed);
}
/*
bool try_lock() const {
bool ret = false;
-#ifdef _MSC_VER
+#if defined(FOLLY_SANITIZE_THREAD)
+ // TODO: Might be able to fully move to std::atomic when gcc emits lock btr:
+ // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=49244
+ ret =
+ !(reinterpret_cast<std::atomic<UIntType>*>(&lock_)->fetch_or(
+ kLockBitMask_, std::memory_order_acquire) &
+ kLockBitMask_);
+#elif _MSC_VER
switch (sizeof(IntType)) {
case 2:
// There is no _interlockedbittestandset16 for some reason :(
- ret = _InterlockedOr16((volatile short*)&lock, 1 << Bit) & (1 << Bit);
+ ret = _InterlockedOr16(
+ (volatile short*)&lock_, (short)kLockBitMask_) & kLockBitMask_;
break;
case 4:
ret = _interlockedbittestandset((volatile long*)&lock_, Bit);
#undef FB_DOBTS
#elif FOLLY_A64
- ret = __atomic_fetch_or(&lock_, 1 << Bit, __ATOMIC_SEQ_CST);
+ ret =
+ !(__atomic_fetch_or(&lock_, kLockBitMask_, __ATOMIC_SEQ_CST) &
+ kLockBitMask_);
#elif FOLLY_PPC64
#define FB_DOBTS(size) \
asm volatile("\teieio\n" \
switch (sizeof(IntType)) {
case 2:
// There is no _interlockedbittestandreset16 for some reason :(
- _InterlockedAnd16((volatile short*)&lock, ~(1 << Bit));
+ _InterlockedAnd16((volatile short*)&lock_, (short)~kLockBitMask_);
break;
case 4:
_interlockedbittestandreset((volatile long*)&lock_, Bit);
#undef FB_DOBTR
#elif FOLLY_A64
- __atomic_fetch_and(&lock_, ~(1 << Bit), __ATOMIC_SEQ_CST);
+ __atomic_fetch_and(&lock_, ~kLockBitMask_, __ATOMIC_SEQ_CST);
#elif FOLLY_PPC64
#define FB_DOBTR(size) \
asm volatile("\teieio\n" \