#include <folly/detail/Futex.h>
#include <folly/Portability.h>
+#if defined(__clang__)
+#define NO_SANITIZE_ADDRESS __attribute__((no_sanitize_address))
+#else
+#define NO_SANITIZE_ADDRESS
+#endif
+
namespace folly {
/**
* limit yourself to MicroLock slot zero, which will use the two
* least-significant bits in the bottom byte.
*
+ * (Note that such a union is safe only because MicroLock is based on
+ * a character type, and even under a strict interpretation of C++'s
+ * aliasing rules, character types may alias anything.)
+ *
* MicroLock uses a dirty trick: it actually operates on the full
* word-size, word-aligned bit of memory into which it is embedded.
* It never modifies bits outside the ones it's defined to modify, but
class MicroLockCore {
protected:
+#if defined(__SANITIZE_ADDRESS__) && !defined(__clang__) && \
+ (defined(__GNUC__) || defined(__GNUG__))
+ uint32_t lock_;
+#else
uint8_t lock_;
+#endif
inline detail::Futex<>* word() const;
inline uint32_t baseShift(unsigned slot) const;
inline uint32_t heldBit(unsigned slot) const;
unsigned maxYields);
public:
- inline void unlock(unsigned slot);
+ inline void unlock(unsigned slot) NO_SANITIZE_ADDRESS;
inline void unlock() { unlock(0); }
- inline void init(unsigned slot) { lock_ &= ~(3U << (2 * slot)); }
- inline void init() { init(0); }
+ // Initializes all the slots.
+ inline void init() { lock_ = 0; }
};
inline detail::Futex<>* MicroLockCore::word() const {
template <unsigned MaxSpins = 1000, unsigned MaxYields = 0>
class MicroLockBase : public MicroLockCore {
public:
- inline void lock(unsigned slot);
+ inline void lock(unsigned slot) NO_SANITIZE_ADDRESS;
inline void lock() { lock(0); }
- inline bool try_lock(unsigned slot);
+ inline bool try_lock(unsigned slot) NO_SANITIZE_ADDRESS;
inline bool try_lock() { return try_lock(0); }
};
oldWord | heldBit(slot),
std::memory_order_acquire,
std::memory_order_relaxed)) {
- // Fast uncontended case: seq_cst above is our memory barrier
+ // Fast uncontended case: memory_order_acquire above is our barrier
} else {
// lockSlowPath doesn't have any slot-dependent computation; it
// just shifts the input bit. Make sure its shifting produces the