X-Git-Url: http://plrg.eecs.uci.edu/git/?a=blobdiff_plain;f=folly%2FPicoSpinLock.h;h=5c63583d451ea15a6110308b73900bf2635afe8e;hb=9fb1f368fdab110348559067ce52336242bf26ef;hp=32c5abfb43ae742895a27cde78f9fa802c1eb572;hpb=b1eb6819f3ffe6b645f39d505ca8ace3116b7873;p=folly.git diff --git a/folly/PicoSpinLock.h b/folly/PicoSpinLock.h index 32c5abfb..5c63583d 100644 --- a/folly/PicoSpinLock.h +++ b/folly/PicoSpinLock.h @@ -1,5 +1,5 @@ /* - * 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. @@ -42,16 +42,16 @@ #include #include #include -#include #include -#include #include #include + +#include #include -#if !FOLLY_X64 && !FOLLY_A64 && !FOLLY_PPC64 -# error "PicoSpinLock.h is currently x64, aarch64 and ppc64 only." +#if !FOLLY_X64 && !FOLLY_AARCH64 && !FOLLY_PPC64 +#error "PicoSpinLock.h is currently x64, aarch64 and ppc64 only." #endif namespace folly { @@ -69,7 +69,7 @@ namespace folly { * have a real constructor because we want this to be a POD type so we * can put it into packed structs. */ -template +template struct PicoSpinLock { // Internally we deal with the unsigned version of the type. typedef typename std::make_unsigned::type UIntType; @@ -82,7 +82,7 @@ struct PicoSpinLock { public: static const UIntType kLockBitMask_ = UIntType(1) << Bit; - UIntType lock_; + mutable UIntType lock_; /* * You must call this function before using this class, if you @@ -94,7 +94,8 @@ struct PicoSpinLock { */ void init(IntType initialValue = 0) { CHECK(!(initialValue & kLockBitMask_)); - lock_ = initialValue; + reinterpret_cast*>(&lock_)->store( + UIntType(initialValue), std::memory_order_release); } /* @@ -107,7 +108,10 @@ struct PicoSpinLock { * as you normally get.) */ IntType getData() const { - return static_cast(lock_ & ~kLockBitMask_); + auto res = reinterpret_cast*>(&lock_)->load( + std::memory_order_relaxed) & + ~kLockBitMask_; + return res; } /* @@ -118,7 +122,10 @@ struct PicoSpinLock { */ void setData(IntType w) { CHECK(!(w & kLockBitMask_)); - lock_ = (lock_ & kLockBitMask_) | w; + auto l = reinterpret_cast*>(&lock_); + l->store( + (l->load(std::memory_order_relaxed) & kLockBitMask_) | w, + std::memory_order_relaxed); } /* @@ -128,7 +135,28 @@ struct PicoSpinLock { bool try_lock() const { bool ret = false; -#if FOLLY_X64 +#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*>(&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_, (short)kLockBitMask_) & kLockBitMask_; + break; + case 4: + ret = _interlockedbittestandset((volatile long*)&lock_, Bit); + break; + case 8: + ret = _interlockedbittestandset64((volatile long long*)&lock_, Bit); + break; + } +#elif FOLLY_X64 #define FB_DOBTS(size) \ asm volatile("lock; bts" #size " %1, (%2); setnc %0" \ : "=r" (ret) \ @@ -143,8 +171,10 @@ struct PicoSpinLock { } #undef FB_DOBTS -#elif FOLLY_A64 - ret = __atomic_fetch_or(&lock_, 1 << Bit, __ATOMIC_SEQ_CST); +#elif FOLLY_AARCH64 + ret = + !(__atomic_fetch_or(&lock_, kLockBitMask_, __ATOMIC_SEQ_CST) & + kLockBitMask_); #elif FOLLY_PPC64 #define FB_DOBTS(size) \ asm volatile("\teieio\n" \ @@ -193,7 +223,20 @@ struct PicoSpinLock { * integer. */ void unlock() const { -#if FOLLY_X64 +#ifdef _MSC_VER + switch (sizeof(IntType)) { + case 2: + // There is no _interlockedbittestandreset16 for some reason :( + _InterlockedAnd16((volatile short*)&lock_, (short)~kLockBitMask_); + break; + case 4: + _interlockedbittestandreset((volatile long*)&lock_, Bit); + break; + case 8: + _interlockedbittestandreset64((volatile long long*)&lock_, Bit); + break; + } +#elif FOLLY_X64 #define FB_DOBTR(size) \ asm volatile("lock; btr" #size " %0, (%1)" \ : \ @@ -211,8 +254,8 @@ struct PicoSpinLock { } #undef FB_DOBTR -#elif FOLLY_A64 - __atomic_fetch_and(&lock_, ~(1 << Bit), __ATOMIC_SEQ_CST); +#elif FOLLY_AARCH64 + __atomic_fetch_and(&lock_, ~kLockBitMask_, __ATOMIC_SEQ_CST); #elif FOLLY_PPC64 #define FB_DOBTR(size) \ asm volatile("\teieio\n" \ @@ -241,4 +284,4 @@ struct PicoSpinLock { } }; -} +} // namespace folly