Commit 85465c8e authored by Dan Melnic's avatar Dan Melnic Committed by Facebook Github Bot

Add PicoSpinLock TSAN annotations

Summary: Add PicoSpinLock TSAN annotations

Reviewed By: yfeldblum

Differential Revision: D16653917

fbshipit-source-id: d388a31824f1278fe79ab4a42e21a66781b879df
parent 113e159c
...@@ -49,6 +49,7 @@ ...@@ -49,6 +49,7 @@
#include <folly/Portability.h> #include <folly/Portability.h>
#include <folly/synchronization/AtomicUtil.h> #include <folly/synchronization/AtomicUtil.h>
#include <folly/synchronization/SanitizeThread.h>
#include <folly/synchronization/detail/Sleeper.h> #include <folly/synchronization/detail/Sleeper.h>
namespace folly { namespace folly {
...@@ -131,11 +132,10 @@ struct PicoSpinLock { ...@@ -131,11 +132,10 @@ struct PicoSpinLock {
* got it. * got it.
*/ */
bool try_lock() const { bool try_lock() const {
auto previous = atomic_fetch_set( auto ret = try_lock_internal();
*reinterpret_cast<std::atomic<UIntType>*>(&lock_), annotate_rwlock_try_acquired(
Bit, this, annotate_rwlock_level::wrlock, ret, __FILE__, __LINE__);
std::memory_order_acquire); return ret;
return !previous;
} }
/* /*
...@@ -143,9 +143,11 @@ struct PicoSpinLock { ...@@ -143,9 +143,11 @@ struct PicoSpinLock {
*/ */
void lock() const { void lock() const {
detail::Sleeper sleeper; detail::Sleeper sleeper;
while (!try_lock()) { while (!try_lock_internal()) {
sleeper.wait(); sleeper.wait();
} }
annotate_rwlock_acquired(
this, annotate_rwlock_level::wrlock, __FILE__, __LINE__);
} }
/* /*
...@@ -153,12 +155,24 @@ struct PicoSpinLock { ...@@ -153,12 +155,24 @@ struct PicoSpinLock {
* integer. * integer.
*/ */
void unlock() const { void unlock() const {
annotate_rwlock_released(
this, annotate_rwlock_level::wrlock, __FILE__, __LINE__);
auto previous = atomic_fetch_reset( auto previous = atomic_fetch_reset(
*reinterpret_cast<std::atomic<UIntType>*>(&lock_), *reinterpret_cast<std::atomic<UIntType>*>(&lock_),
Bit, Bit,
std::memory_order_release); std::memory_order_release);
DCHECK(previous); DCHECK(previous);
} }
private:
// called by lock/try_lock - this is not TSAN aware
bool try_lock_internal() const {
auto previous = atomic_fetch_set(
*reinterpret_cast<std::atomic<UIntType>*>(&lock_),
Bit,
std::memory_order_acquire);
return !previous;
}
}; };
} // namespace folly } // namespace folly
...@@ -189,6 +189,29 @@ TEST(SmallLocks, PicoSpinSigned) { ...@@ -189,6 +189,29 @@ TEST(SmallLocks, PicoSpinSigned) {
} }
EXPECT_EQ(val.getData(), -8); EXPECT_EQ(val.getData(), -8);
} }
TEST(SmallLocks, PicoSpinLockThreadSanitizer) {
SKIP_IF(!folly::kIsSanitizeThread) << "Enabled in TSAN mode only";
typedef PicoSpinLock<int16_t, 0> Lock;
{
Lock a;
Lock b;
a.init(-8);
b.init(-8);
{
std::lock_guard<Lock> ga(a);
std::lock_guard<Lock> gb(b);
}
{
std::lock_guard<Lock> gb(b);
EXPECT_DEATH(
[&]() { std::lock_guard<Lock> ga(a); }(),
"Cycle in lock order graph");
}
}
}
#endif #endif
TEST(SmallLocks, RegClobber) { TEST(SmallLocks, RegClobber) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment