Folly parseJson doesn't handle minInt properly
[folly.git] / folly / MicroLock.h
index 3ff158b8728570c968f3df9f022ec7842996feca..15c8d414d69da25937977c8f00b428c0a613c4bb 100644 (file)
 #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 {
 
 /**
@@ -43,6 +49,10 @@ 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
@@ -84,7 +94,12 @@ namespace folly {
 
 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;
@@ -96,10 +111,10 @@ class MicroLockCore {
                            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 {
@@ -147,9 +162,9 @@ void MicroLockCore::unlock(unsigned slot) {
 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); }
 };
 
@@ -193,7 +208,7 @@ void MicroLockBase<MaxSpins, MaxYields>::lock(unsigned slot) {
                                      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