Commit 799a718f authored by Yedidya Feldblum's avatar Yedidya Feldblum Committed by Facebook Github Bot

Pure C++ for TSAN annotation wrappers

Summary:
[Folly] Pure C++ for TSAN annotation wrappers, v.s. using the preprocessor.

The implementation uses the preprocessor in order to support platforms without weak symbols, but the interface is now pure C++.

Reviewed By: nbronson

Differential Revision: D10291176

fbshipit-source-id: 3636652793b8d0da59c7c9b1095d4c1b0c506372
parent 07515573
...@@ -174,9 +174,8 @@ ...@@ -174,9 +174,8 @@
#endif #endif
#endif #endif
/* These functions are defined by the TSAN runtime library and allow us to // These functions are defined by the TSAN runtime library and enable
* annotate mutexes appopriately for TSAN. */ // annotating mutexes for TSAN.
#ifdef FOLLY_SANITIZE_THREAD
extern "C" FOLLY_ATTR_WEAK void extern "C" FOLLY_ATTR_WEAK void
AnnotateRWLockCreate(const char* f, int l, const volatile void* addr); AnnotateRWLockCreate(const char* f, int l, const volatile void* addr);
extern "C" FOLLY_ATTR_WEAK void extern "C" FOLLY_ATTR_WEAK void
...@@ -193,61 +192,3 @@ extern "C" FOLLY_ATTR_WEAK void AnnotateBenignRaceSized( ...@@ -193,61 +192,3 @@ extern "C" FOLLY_ATTR_WEAK void AnnotateBenignRaceSized(
const volatile void* addr, const volatile void* addr,
long size, long size,
const char* desc); const char* desc);
#define FOLLY_ANNOTATE_RWLOCK_CREATE(addr) \
AnnotateRWLockCreate(__FILE__, __LINE__, (addr))
#define FOLLY_ANNOTATE_RWLOCK_CREATE_STATIC(addr) \
AnnotateRWLockCreateStatic(__FILE__, __LINE__, (addr))
#define FOLLY_ANNOTATE_RWLOCK_DESTROY(addr) \
AnnotateRWLockDestroy(__FILE__, __LINE__, (addr))
#define FOLLY_ANNOTATE_RWLOCK_ACQUIRED(addr, w) \
AnnotateRWLockAcquired(__FILE__, __LINE__, (addr), (w))
#define FOLLY_ANNOTATE_RWLOCK_TRY_ACQUIRED(result, addr, w) \
if ((result)) { \
FOLLY_ANNOTATE_RWLOCK_ACQUIRED((addr), (w)); \
}
#define FOLLY_ANNOTATE_RWLOCK_RELEASED(addr, w) \
AnnotateRWLockReleased(__FILE__, __LINE__, (addr), (w))
#define FOLLY_ANNOTATE_BENIGN_RACE_SIZED(addr, size, desc) \
AnnotateBenignRaceSized(__FILE__, __LINE__, (addr), (size), (desc))
#else
#define FOLLY_ANNOTATE_RWLOCK_CREATE(addr) \
(void)addr; \
do { \
} while (0)
#define FOLLY_ANNOTATE_RWLOCK_CREATE_STATIC(addr) \
(void)addr; \
do { \
} while (0)
#define FOLLY_ANNOTATE_RWLOCK_DESTROY(addr) \
(void)addr; \
do { \
} while (0)
#define FOLLY_ANNOTATE_RWLOCK_ACQUIRED(addr, w) \
(void)addr; \
(void)w; \
do { \
} while (0)
#define FOLLY_ANNOTATE_RWLOCK_TRY_ACQUIRED(result, addr, w) \
(void)result; \
(void)addr; \
(void)w; \
do { \
} while (0)
#define FOLLY_ANNOTATE_RWLOCK_RELEASED(addr, w) \
(void)addr; \
(void)w; \
do { \
} while (0)
#define FOLLY_ANNOTATE_BENIGN_RACE_SIZED(addr, size, desc) \
(void)addr; \
(void)size; \
(void)desc; \
do { \
} while (0)
#endif
#define FOLLY_ANNOTATE_RWLOCK_RDLOCK 0L
#define FOLLY_ANNOTATE_RWLOCK_WRLOCK 1L
...@@ -30,6 +30,7 @@ ...@@ -30,6 +30,7 @@
#include <folly/detail/Futex.h> #include <folly/detail/Futex.h>
#include <folly/portability/Asm.h> #include <folly/portability/Asm.h>
#include <folly/portability/SysResource.h> #include <folly/portability/SysResource.h>
#include <folly/synchronization/SanitizeThread.h>
// SharedMutex is a reader-writer lock. It is small, very fast, scalable // SharedMutex is a reader-writer lock. It is small, very fast, scalable
// on multi-core, and suitable for use when readers or writers may block. // on multi-core, and suitable for use when readers or writers may block.
...@@ -259,8 +260,7 @@ struct SharedMutexToken { ...@@ -259,8 +260,7 @@ struct SharedMutexToken {
namespace detail { namespace detail {
// Returns a guard that gives permission for the current thread to // Returns a guard that gives permission for the current thread to
// call FOLLY_ANNOTATE_RWLOCK_CREATE and adjust the annotation bits // annotate, and adjust the annotation bits in, the SharedMutex at ptr.
// in the SharedMutex at ptr.
std::unique_lock<std::mutex> sharedMutexAnnotationGuard(void* ptr); std::unique_lock<std::mutex> sharedMutexAnnotationGuard(void* ptr);
} // namespace detail } // namespace detail
...@@ -325,13 +325,13 @@ class SharedMutexImpl { ...@@ -325,13 +325,13 @@ class SharedMutexImpl {
void lock() { void lock() {
WaitForever ctx; WaitForever ctx;
(void)lockExclusiveImpl(kHasSolo, ctx); (void)lockExclusiveImpl(kHasSolo, ctx);
annotateAcquired(FOLLY_ANNOTATE_RWLOCK_WRLOCK); annotateAcquired(annotate_rwlock_level::wrlock);
} }
bool try_lock() { bool try_lock() {
WaitNever ctx; WaitNever ctx;
auto result = lockExclusiveImpl(kHasSolo, ctx); auto result = lockExclusiveImpl(kHasSolo, ctx);
annotateTryAcquired(result, FOLLY_ANNOTATE_RWLOCK_WRLOCK); annotateTryAcquired(result, annotate_rwlock_level::wrlock);
return result; return result;
} }
...@@ -339,7 +339,7 @@ class SharedMutexImpl { ...@@ -339,7 +339,7 @@ class SharedMutexImpl {
bool try_lock_for(const std::chrono::duration<Rep, Period>& duration) { bool try_lock_for(const std::chrono::duration<Rep, Period>& duration) {
WaitForDuration<Rep, Period> ctx(duration); WaitForDuration<Rep, Period> ctx(duration);
auto result = lockExclusiveImpl(kHasSolo, ctx); auto result = lockExclusiveImpl(kHasSolo, ctx);
annotateTryAcquired(result, FOLLY_ANNOTATE_RWLOCK_WRLOCK); annotateTryAcquired(result, annotate_rwlock_level::wrlock);
return result; return result;
} }
...@@ -348,12 +348,12 @@ class SharedMutexImpl { ...@@ -348,12 +348,12 @@ class SharedMutexImpl {
const std::chrono::time_point<Clock, Duration>& absDeadline) { const std::chrono::time_point<Clock, Duration>& absDeadline) {
WaitUntilDeadline<Clock, Duration> ctx{absDeadline}; WaitUntilDeadline<Clock, Duration> ctx{absDeadline};
auto result = lockExclusiveImpl(kHasSolo, ctx); auto result = lockExclusiveImpl(kHasSolo, ctx);
annotateTryAcquired(result, FOLLY_ANNOTATE_RWLOCK_WRLOCK); annotateTryAcquired(result, annotate_rwlock_level::wrlock);
return result; return result;
} }
void unlock() { void unlock() {
annotateReleased(FOLLY_ANNOTATE_RWLOCK_WRLOCK); annotateReleased(annotate_rwlock_level::wrlock);
// It is possible that we have a left-over kWaitingNotS if the last // It is possible that we have a left-over kWaitingNotS if the last
// unlock_shared() that let our matching lock() complete finished // unlock_shared() that let our matching lock() complete finished
// releasing before lock()'s futexWait went to sleep. Clean it up now // releasing before lock()'s futexWait went to sleep. Clean it up now
...@@ -367,26 +367,26 @@ class SharedMutexImpl { ...@@ -367,26 +367,26 @@ class SharedMutexImpl {
void lock_shared() { void lock_shared() {
WaitForever ctx; WaitForever ctx;
(void)lockSharedImpl(nullptr, ctx); (void)lockSharedImpl(nullptr, ctx);
annotateAcquired(FOLLY_ANNOTATE_RWLOCK_RDLOCK); annotateAcquired(annotate_rwlock_level::rdlock);
} }
void lock_shared(Token& token) { void lock_shared(Token& token) {
WaitForever ctx; WaitForever ctx;
(void)lockSharedImpl(&token, ctx); (void)lockSharedImpl(&token, ctx);
annotateAcquired(FOLLY_ANNOTATE_RWLOCK_RDLOCK); annotateAcquired(annotate_rwlock_level::rdlock);
} }
bool try_lock_shared() { bool try_lock_shared() {
WaitNever ctx; WaitNever ctx;
auto result = lockSharedImpl(nullptr, ctx); auto result = lockSharedImpl(nullptr, ctx);
annotateTryAcquired(result, FOLLY_ANNOTATE_RWLOCK_RDLOCK); annotateTryAcquired(result, annotate_rwlock_level::rdlock);
return result; return result;
} }
bool try_lock_shared(Token& token) { bool try_lock_shared(Token& token) {
WaitNever ctx; WaitNever ctx;
auto result = lockSharedImpl(&token, ctx); auto result = lockSharedImpl(&token, ctx);
annotateTryAcquired(result, FOLLY_ANNOTATE_RWLOCK_RDLOCK); annotateTryAcquired(result, annotate_rwlock_level::rdlock);
return result; return result;
} }
...@@ -394,7 +394,7 @@ class SharedMutexImpl { ...@@ -394,7 +394,7 @@ class SharedMutexImpl {
bool try_lock_shared_for(const std::chrono::duration<Rep, Period>& duration) { bool try_lock_shared_for(const std::chrono::duration<Rep, Period>& duration) {
WaitForDuration<Rep, Period> ctx(duration); WaitForDuration<Rep, Period> ctx(duration);
auto result = lockSharedImpl(nullptr, ctx); auto result = lockSharedImpl(nullptr, ctx);
annotateTryAcquired(result, FOLLY_ANNOTATE_RWLOCK_RDLOCK); annotateTryAcquired(result, annotate_rwlock_level::rdlock);
return result; return result;
} }
...@@ -404,7 +404,7 @@ class SharedMutexImpl { ...@@ -404,7 +404,7 @@ class SharedMutexImpl {
Token& token) { Token& token) {
WaitForDuration<Rep, Period> ctx(duration); WaitForDuration<Rep, Period> ctx(duration);
auto result = lockSharedImpl(&token, ctx); auto result = lockSharedImpl(&token, ctx);
annotateTryAcquired(result, FOLLY_ANNOTATE_RWLOCK_RDLOCK); annotateTryAcquired(result, annotate_rwlock_level::rdlock);
return result; return result;
} }
...@@ -413,7 +413,7 @@ class SharedMutexImpl { ...@@ -413,7 +413,7 @@ class SharedMutexImpl {
const std::chrono::time_point<Clock, Duration>& absDeadline) { const std::chrono::time_point<Clock, Duration>& absDeadline) {
WaitUntilDeadline<Clock, Duration> ctx{absDeadline}; WaitUntilDeadline<Clock, Duration> ctx{absDeadline};
auto result = lockSharedImpl(nullptr, ctx); auto result = lockSharedImpl(nullptr, ctx);
annotateTryAcquired(result, FOLLY_ANNOTATE_RWLOCK_RDLOCK); annotateTryAcquired(result, annotate_rwlock_level::rdlock);
return result; return result;
} }
...@@ -423,12 +423,12 @@ class SharedMutexImpl { ...@@ -423,12 +423,12 @@ class SharedMutexImpl {
Token& token) { Token& token) {
WaitUntilDeadline<Clock, Duration> ctx{absDeadline}; WaitUntilDeadline<Clock, Duration> ctx{absDeadline};
auto result = lockSharedImpl(&token, ctx); auto result = lockSharedImpl(&token, ctx);
annotateTryAcquired(result, FOLLY_ANNOTATE_RWLOCK_RDLOCK); annotateTryAcquired(result, annotate_rwlock_level::rdlock);
return result; return result;
} }
void unlock_shared() { void unlock_shared() {
annotateReleased(FOLLY_ANNOTATE_RWLOCK_RDLOCK); annotateReleased(annotate_rwlock_level::rdlock);
auto state = state_.load(std::memory_order_acquire); auto state = state_.load(std::memory_order_acquire);
...@@ -447,7 +447,7 @@ class SharedMutexImpl { ...@@ -447,7 +447,7 @@ class SharedMutexImpl {
} }
void unlock_shared(Token& token) { void unlock_shared(Token& token) {
annotateReleased(FOLLY_ANNOTATE_RWLOCK_RDLOCK); annotateReleased(annotate_rwlock_level::rdlock);
assert( assert(
token.type_ == Token::Type::INLINE_SHARED || token.type_ == Token::Type::INLINE_SHARED ||
...@@ -463,8 +463,8 @@ class SharedMutexImpl { ...@@ -463,8 +463,8 @@ class SharedMutexImpl {
} }
void unlock_and_lock_shared() { void unlock_and_lock_shared() {
annotateReleased(FOLLY_ANNOTATE_RWLOCK_WRLOCK); annotateReleased(annotate_rwlock_level::wrlock);
annotateAcquired(FOLLY_ANNOTATE_RWLOCK_RDLOCK); annotateAcquired(annotate_rwlock_level::rdlock);
// We can't use state_ -=, because we need to clear 2 bits (1 of which // We can't use state_ -=, because we need to clear 2 bits (1 of which
// has an uncertain initial state) and set 1 other. We might as well // has an uncertain initial state) and set 1 other. We might as well
// clear the relevant wake bits at the same time. Note that since S // clear the relevant wake bits at the same time. Note that since S
...@@ -491,13 +491,13 @@ class SharedMutexImpl { ...@@ -491,13 +491,13 @@ class SharedMutexImpl {
WaitForever ctx; WaitForever ctx;
(void)lockUpgradeImpl(ctx); (void)lockUpgradeImpl(ctx);
// For TSAN: treat upgrade locks as equivalent to read locks // For TSAN: treat upgrade locks as equivalent to read locks
annotateAcquired(FOLLY_ANNOTATE_RWLOCK_RDLOCK); annotateAcquired(annotate_rwlock_level::rdlock);
} }
bool try_lock_upgrade() { bool try_lock_upgrade() {
WaitNever ctx; WaitNever ctx;
auto result = lockUpgradeImpl(ctx); auto result = lockUpgradeImpl(ctx);
annotateTryAcquired(result, FOLLY_ANNOTATE_RWLOCK_RDLOCK); annotateTryAcquired(result, annotate_rwlock_level::rdlock);
return result; return result;
} }
...@@ -506,7 +506,7 @@ class SharedMutexImpl { ...@@ -506,7 +506,7 @@ class SharedMutexImpl {
const std::chrono::duration<Rep, Period>& duration) { const std::chrono::duration<Rep, Period>& duration) {
WaitForDuration<Rep, Period> ctx(duration); WaitForDuration<Rep, Period> ctx(duration);
auto result = lockUpgradeImpl(ctx); auto result = lockUpgradeImpl(ctx);
annotateTryAcquired(result, FOLLY_ANNOTATE_RWLOCK_RDLOCK); annotateTryAcquired(result, annotate_rwlock_level::rdlock);
return result; return result;
} }
...@@ -515,12 +515,12 @@ class SharedMutexImpl { ...@@ -515,12 +515,12 @@ class SharedMutexImpl {
const std::chrono::time_point<Clock, Duration>& absDeadline) { const std::chrono::time_point<Clock, Duration>& absDeadline) {
WaitUntilDeadline<Clock, Duration> ctx{absDeadline}; WaitUntilDeadline<Clock, Duration> ctx{absDeadline};
auto result = lockUpgradeImpl(ctx); auto result = lockUpgradeImpl(ctx);
annotateTryAcquired(result, FOLLY_ANNOTATE_RWLOCK_RDLOCK); annotateTryAcquired(result, annotate_rwlock_level::rdlock);
return result; return result;
} }
void unlock_upgrade() { void unlock_upgrade() {
annotateReleased(FOLLY_ANNOTATE_RWLOCK_RDLOCK); annotateReleased(annotate_rwlock_level::rdlock);
auto state = (state_ -= kHasU); auto state = (state_ -= kHasU);
assert((state & (kWaitingNotS | kHasSolo)) == 0); assert((state & (kWaitingNotS | kHasSolo)) == 0);
wakeRegisteredWaiters(state, kWaitingE | kWaitingU); wakeRegisteredWaiters(state, kWaitingE | kWaitingU);
...@@ -530,8 +530,8 @@ class SharedMutexImpl { ...@@ -530,8 +530,8 @@ class SharedMutexImpl {
// no waiting necessary, so waitMask is empty // no waiting necessary, so waitMask is empty
WaitForever ctx; WaitForever ctx;
(void)lockExclusiveImpl(0, ctx); (void)lockExclusiveImpl(0, ctx);
annotateReleased(FOLLY_ANNOTATE_RWLOCK_RDLOCK); annotateReleased(annotate_rwlock_level::rdlock);
annotateAcquired(FOLLY_ANNOTATE_RWLOCK_WRLOCK); annotateAcquired(annotate_rwlock_level::wrlock);
} }
void unlock_upgrade_and_lock_shared() { void unlock_upgrade_and_lock_shared() {
...@@ -548,8 +548,8 @@ class SharedMutexImpl { ...@@ -548,8 +548,8 @@ class SharedMutexImpl {
} }
void unlock_and_lock_upgrade() { void unlock_and_lock_upgrade() {
annotateReleased(FOLLY_ANNOTATE_RWLOCK_WRLOCK); annotateReleased(annotate_rwlock_level::wrlock);
annotateAcquired(FOLLY_ANNOTATE_RWLOCK_RDLOCK); annotateAcquired(annotate_rwlock_level::rdlock);
// We can't use state_ -=, because we need to clear 2 bits (1 of // We can't use state_ -=, because we need to clear 2 bits (1 of
// which has an uncertain initial state) and set 1 other. We might // which has an uncertain initial state) and set 1 other. We might
// as well clear the relevant wake bits at the same time. // as well clear the relevant wake bits at the same time.
...@@ -676,8 +676,9 @@ class SharedMutexImpl { ...@@ -676,8 +676,9 @@ class SharedMutexImpl {
// check again // check again
if ((state_.load() & kAnnotationCreated) == 0) { if ((state_.load() & kAnnotationCreated) == 0) {
state_.fetch_or(kAnnotationCreated); state_.fetch_or(kAnnotationCreated);
FOLLY_ANNOTATE_BENIGN_RACE_SIZED(&state_, sizeof(state_), "init TSAN"); annotate_benign_race_sized(
FOLLY_ANNOTATE_RWLOCK_CREATE(this); &state_, sizeof(state_), "init TSAN", __FILE__, __LINE__);
annotate_rwlock_create(this, __FILE__, __LINE__);
} }
} }
} }
...@@ -685,30 +686,28 @@ class SharedMutexImpl { ...@@ -685,30 +686,28 @@ class SharedMutexImpl {
void annotateDestroy() { void annotateDestroy() {
if (AnnotateForThreadSanitizer) { if (AnnotateForThreadSanitizer) {
annotateLazyCreate(); annotateLazyCreate();
FOLLY_ANNOTATE_RWLOCK_DESTROY(this); annotate_rwlock_destroy(this, __FILE__, __LINE__);
} }
} }
void annotateAcquired(long w) { void annotateAcquired(annotate_rwlock_level w) {
if (AnnotateForThreadSanitizer) { if (AnnotateForThreadSanitizer) {
annotateLazyCreate(); annotateLazyCreate();
FOLLY_ANNOTATE_RWLOCK_ACQUIRED(this, w); annotate_rwlock_acquired(this, w, __FILE__, __LINE__);
} }
} }
void annotateTryAcquired(bool result, long w) { void annotateTryAcquired(bool result, annotate_rwlock_level w) {
if (AnnotateForThreadSanitizer) { if (AnnotateForThreadSanitizer) {
annotateLazyCreate(); annotateLazyCreate();
if (result) { annotate_rwlock_try_acquired(this, w, result, __FILE__, __LINE__);
FOLLY_ANNOTATE_RWLOCK_ACQUIRED(this, w);
}
} }
} }
void annotateReleased(long w) { void annotateReleased(annotate_rwlock_level w) {
if (AnnotateForThreadSanitizer) { if (AnnotateForThreadSanitizer) {
assert((state_.load() & kAnnotationCreated) != 0); assert((state_.load() & kAnnotationCreated) != 0);
FOLLY_ANNOTATE_RWLOCK_RELEASED(this, w); annotate_rwlock_released(this, w, __FILE__, __LINE__);
} }
} }
...@@ -726,9 +725,8 @@ class SharedMutexImpl { ...@@ -726,9 +725,8 @@ class SharedMutexImpl {
static constexpr uint32_t kIncrHasS = 1 << 11; static constexpr uint32_t kIncrHasS = 1 << 11;
static constexpr uint32_t kHasS = ~(kIncrHasS - 1); static constexpr uint32_t kHasS = ~(kIncrHasS - 1);
// Set if it a call to FOLLY_ANNOTATE_RWLOCK_CREATE has been // Set if annotation has been completed for this instance. That annotation
// completed for this instance. That annotation call (and setting // (and setting this bit afterward) must be guarded by one of the mutexes in
// this bit afterward) must be guarded by one of the mutexes in
// annotationCreationGuards. // annotationCreationGuards.
static constexpr uint32_t kAnnotationCreated = 1 << 10; static constexpr uint32_t kAnnotationCreated = 1 << 10;
......
...@@ -20,6 +20,7 @@ ...@@ -20,6 +20,7 @@
#include <folly/experimental/observer/detail/Core.h> #include <folly/experimental/observer/detail/Core.h>
#include <folly/experimental/observer/detail/GraphCycleDetector.h> #include <folly/experimental/observer/detail/GraphCycleDetector.h>
#include <folly/futures/Future.h> #include <folly/futures/Future.h>
#include <folly/synchronization/SanitizeThread.h>
namespace folly { namespace folly {
namespace observer_detail { namespace observer_detail {
...@@ -84,16 +85,22 @@ class ObserverManager { ...@@ -84,16 +85,22 @@ class ObserverManager {
// work will be the one that unlocks it. To avoid noise with TSAN, // work will be the one that unlocks it. To avoid noise with TSAN,
// annotate that the thread has released the mutex, and then annotate // annotate that the thread has released the mutex, and then annotate
// the async thread as acquiring the mutex. // the async thread as acquiring the mutex.
FOLLY_ANNOTATE_RWLOCK_RELEASED( annotate_rwlock_released(
&instance->versionMutex_, FOLLY_ANNOTATE_RWLOCK_RDLOCK); &instance->versionMutex_,
annotate_rwlock_level::rdlock,
__FILE__,
__LINE__);
instance->scheduleCurrent([core = std::move(core), instance->scheduleCurrent([core = std::move(core),
instancePtr = instance.get(), instancePtr = instance.get(),
rh = std::move(rh), rh = std::move(rh),
force]() { force]() {
// Make TSAN know that the current thread owns the read lock now. // Make TSAN know that the current thread owns the read lock now.
FOLLY_ANNOTATE_RWLOCK_ACQUIRED( annotate_rwlock_acquired(
&instancePtr->versionMutex_, FOLLY_ANNOTATE_RWLOCK_RDLOCK); &instancePtr->versionMutex_,
annotate_rwlock_level::rdlock,
__FILE__,
__LINE__);
core->refresh(instancePtr->version_, force); core->refresh(instancePtr->version_, force);
}); });
......
/*
* Copyright 2013-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.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#pragma once
#include <folly/CPortability.h>
#include <folly/Portability.h>
namespace folly {
enum class annotate_rwlock_level : long {
rdlock = 0,
wrlock = 1,
};
namespace detail {
FOLLY_ALWAYS_INLINE static void annotate_ignore(...) {}
} // namespace detail
#if _MSC_VER
#define FOLLY_DETAIL_ANNOTATE(name, ...) detail::annotate_ignore(__VA_ARGS__)
#else
#define FOLLY_DETAIL_ANNOTATE(name, ...) Annotate##name(__VA_ARGS__)
#endif
FOLLY_ALWAYS_INLINE static void annotate_rwlock_create(
void const volatile* const addr,
char const* const f,
int const l) {
if (kIsSanitizeThread) {
FOLLY_DETAIL_ANNOTATE(RWLockCreate, f, l, addr);
}
}
FOLLY_ALWAYS_INLINE static void annotate_rwlock_create_static(
void const volatile* const addr,
char const* const f,
int const l) {
if (kIsSanitizeThread) {
FOLLY_DETAIL_ANNOTATE(RWLockCreateStatic, f, l, addr);
}
}
FOLLY_ALWAYS_INLINE static void annotate_rwlock_destroy(
void const volatile* const addr,
char const* const f,
int const l) {
if (kIsSanitizeThread) {
FOLLY_DETAIL_ANNOTATE(RWLockDestroy, f, l, addr);
}
}
FOLLY_ALWAYS_INLINE static void annotate_rwlock_acquired(
void const volatile* const addr,
annotate_rwlock_level const w,
char const* const f,
int const l) {
if (kIsSanitizeThread) {
FOLLY_DETAIL_ANNOTATE(RWLockAcquired, f, l, addr, static_cast<long>(w));
}
}
FOLLY_ALWAYS_INLINE static void annotate_rwlock_try_acquired(
void const volatile* const addr,
annotate_rwlock_level const w,
bool const result,
char const* const f,
int const l) {
if (result) {
annotate_rwlock_acquired(addr, w, f, l);
}
}
FOLLY_ALWAYS_INLINE static void annotate_rwlock_released(
void const volatile* const addr,
annotate_rwlock_level const w,
char const* const f,
int const l) {
if (kIsSanitizeThread) {
FOLLY_DETAIL_ANNOTATE(RWLockReleased, f, l, addr, static_cast<long>(w));
}
}
FOLLY_ALWAYS_INLINE static void annotate_benign_race_sized(
void const volatile* const addr,
long const size,
char const* const desc,
char const* const f,
int const l) {
if (kIsSanitizeThread) {
FOLLY_DETAIL_ANNOTATE(BenignRaceSized, f, l, addr, size, desc);
}
}
#undef FOLLY_DETAIL_ANNOTATE
} // namespace folly
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