From: bsimmers Date: Wed, 4 Dec 2013 21:58:07 +0000 (-0800) Subject: Fix asm constraints in folly::MicroSpinLock::cas X-Git-Tag: v0.22.0~771 X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=db56587b0b4cbc33001732589bc79ab9271658bf;p=folly.git Fix asm constraints in folly::MicroSpinLock::cas Summary: If the compare part of cmpxchg fails, it writes the unexpected value to %rax. At certain optimization levels this was causing me to hit an incorrectly failed assertion in some thrift code. I also cleaned up the asm statement to use named operands. Test Plan: Added new test that fails before this diff. Reviewed By: delong.j@fb.com FB internal diff: D1083222 @override-unit-failures --- diff --git a/folly/SmallLocks.h b/folly/SmallLocks.h index 01387aee..b092a917 100644 --- a/folly/SmallLocks.h +++ b/folly/SmallLocks.h @@ -111,12 +111,13 @@ struct MicroSpinLock { */ bool cas(uint8_t compare, uint8_t newVal) { bool out; - asm volatile("lock; cmpxchgb %2, (%3);" - "setz %0;" - : "=r" (out) + bool memVal; // only set if the cmpxchg fails + asm volatile("lock; cmpxchgb %[newVal], (%[lockPtr]);" + "setz %[output];" + : [output] "=r" (out), "=a" (memVal) : "a" (compare), // cmpxchgb constrains this to be in %al - "q" (newVal), // Needs to be byte-accessible - "r" (&lock_) + [newVal] "q" (newVal), // Needs to be byte-accessible + [lockPtr] "r" (&lock_) : "memory", "flags"); return out; } diff --git a/folly/test/SmallLocksTest.cpp b/folly/test/SmallLocksTest.cpp index e7cc04fc..dedc476f 100644 --- a/folly/test/SmallLocksTest.cpp +++ b/folly/test/SmallLocksTest.cpp @@ -17,6 +17,7 @@ #include "folly/SmallLocks.h" #include #include +#include #include #include #include @@ -102,6 +103,22 @@ void doPslTest() { } } +struct TestClobber { + TestClobber() { + lock_.init(); + } + + void go() { + std::lock_guard g(lock_); + // This bug depends on gcc register allocation and is very sensitive. We + // have to use DCHECK instead of EXPECT_*. + DCHECK(!lock_.try_lock()); + } + + private: + MicroSpinLock lock_; +}; + } TEST(SmallLocks, SpinLockCorrectness) { @@ -140,3 +157,7 @@ TEST(SmallLocks, PicoSpinSigned) { } EXPECT_EQ(val.getData(), -8); } + +TEST(SmallLocks, RegClobber) { + TestClobber().go(); +}