suppress warnings in tests for deprecated functions
[folly.git] / folly / MicroLock.h
index 8f0b09f7d2902a1591bae1d48ab77c716e665476..bb130b0032a568b02077a8e13d633e37c1e49802 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright 2016 Facebook, Inc.
+ * Copyright 2016-present Facebook, Inc.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
 
 #pragma once
 
-#include <assert.h>
+#include <cassert>
 #include <climits>
-#include <stdint.h>
-#include <folly/detail/Futex.h>
+#include <cstdint>
+
 #include <folly/Portability.h>
+#include <folly/detail/Futex.h>
+
+#if defined(__clang__)
+#define NO_SANITIZE_ADDRESS __attribute__((no_sanitize_address))
+#else
+#define NO_SANITIZE_ADDRESS
+#endif
 
 namespace folly {
 
@@ -48,10 +55,10 @@ namespace folly {
  * 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.
+ * 32-bit, four-byte-aligned bit of memory into which it is embedded.
  * It never modifies bits outside the ones it's defined to modify, but
- * it _accesses_ all the bits in the word for purposes of
- * futex management.
+ * it _accesses_ all the bits in the 32-bit memory location for
+ * purposes of futex management.
  *
  * The MaxSpins template parameter controls the number of times we
  * spin trying to acquire the lock.  MaxYields controls the number of
@@ -80,16 +87,24 @@ namespace folly {
  *
  * (The virtual dispatch benchmark is provided for scale.)
  *
- * The contended case for MicroLock is likely to be worse compared to
- * std::mutex than the contended case is.  Make sure to benchmark your
- * particular workload.
+ * While the uncontended case for MicroLock is competitive with the
+ * glibc 2.2.0 implementation of std::mutex, std::mutex is likely to be
+ * faster in the contended case, because we need to wake up all waiters
+ * when we release.
+ *
+ * Make sure to benchmark your particular workload.
  *
  */
 
 class MicroLockCore {
  protected:
+#if defined(__SANITIZE_ADDRESS__) && !defined(__clang__) && \
+    (defined(__GNUC__) || defined(__GNUG__))
+  uint32_t lock_;
+#else
   uint8_t lock_;
-  inline detail::Futex<>* word() const;
+#endif
+  inline detail::Futex<>* word() const; // Well, halfword on 64-bit systems
   inline uint32_t baseShift(unsigned slot) const;
   inline uint32_t heldBit(unsigned slot) const;
   inline uint32_t waitBit(unsigned slot) const;
@@ -100,7 +115,7 @@ class MicroLockCore {
                            unsigned maxYields);
 
  public:
-  inline void unlock(unsigned slot);
+  inline void unlock(unsigned slot) NO_SANITIZE_ADDRESS;
   inline void unlock() { unlock(0); }
   // Initializes all the slots.
   inline void init() { lock_ = 0; }
@@ -117,9 +132,8 @@ inline unsigned MicroLockCore::baseShift(unsigned slot) const {
 
   unsigned offset_bytes = (unsigned)((uintptr_t)&lock_ - (uintptr_t)word());
 
-  return kIsLittleEndian
-             ? offset_bytes * CHAR_BIT + slot * 2
-             : CHAR_BIT * (sizeof(uint32_t) - offset_bytes - 1) + slot * 2;
+  return (
+      unsigned)(kIsLittleEndian ? offset_bytes * CHAR_BIT + slot * 2 : CHAR_BIT * (sizeof(uint32_t) - offset_bytes - 1) + slot * 2);
 }
 
 inline uint32_t MicroLockCore::heldBit(unsigned slot) const {
@@ -151,9 +165,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); }
 };
 
@@ -209,4 +223,4 @@ void MicroLockBase<MaxSpins, MaxYields>::lock(unsigned slot) {
 }
 
 typedef MicroLockBase<> MicroLock;
-}
+} // namespace folly