Enable thread safety annotations in open source version.

The thread safety annotations used by leveldb got opensourced in Abseil
[1]. This CL replaces leveldb's stubs with the relevant definitions from
[1], and adds annotations to the Mutex classes in the POSIX port.

[1] https://github.com/abseil/abseil-cpp/blob/master/absl/base/thread_annotations.h
This commit is contained in:
costan 2018-02-13 22:31:50 -08:00 committed by Victor Costan
parent 47cb9e2a21
commit 41172a2401
4 changed files with 94 additions and 25 deletions

View File

@ -202,7 +202,6 @@ EOF
PLATFORM_LIBS="$PLATFORM_LIBS -lcrc32c" PLATFORM_LIBS="$PLATFORM_LIBS -lcrc32c"
fi fi
# Test whether Snappy library is installed # Test whether Snappy library is installed
# https://github.com/google/snappy # https://github.com/google/snappy
$CXX $CXXFLAGS -x c++ - -o $CXXOUTPUT 2>/dev/null <<EOF $CXX $CXXFLAGS -x c++ - -o $CXXOUTPUT 2>/dev/null <<EOF
@ -222,7 +221,23 @@ EOF
PLATFORM_LIBS="$PLATFORM_LIBS -ltcmalloc" PLATFORM_LIBS="$PLATFORM_LIBS -ltcmalloc"
fi fi
rm -f $CXXOUTPUT 2>/dev/null # Test whether -Wthread-safety is available. See
# https://clang.llvm.org/docs/ThreadSafetyAnalysis.html
# -Werror is necessary because unknown attributes only generate warnings.
$CXX $CXXFLAGS -Wthread-safety -Werror -x c++ - -o $CXXOUTPUT 2>/dev/null <<EOF
struct __attribute__((lockable)) Lock {
void Acquire() __attribute__((exclusive_lock_function()));
void Release() __attribute__((unlock_function()));
};
struct ThreadSafeType {
Lock lock_;
int data_ __attribute__((guarded_by(lock_)));
};
int main() { return 0; }
EOF
if [ "$?" = 0 ]; then
COMMON_FLAGS="$COMMON_FLAGS -Wthread-safety"
fi
rm -f $CXXOUTPUT 2>/dev/null rm -f $CXXOUTPUT 2>/dev/null
fi fi

View File

@ -10,6 +10,8 @@
#ifndef STORAGE_LEVELDB_PORT_PORT_EXAMPLE_H_ #ifndef STORAGE_LEVELDB_PORT_PORT_EXAMPLE_H_
#define STORAGE_LEVELDB_PORT_PORT_EXAMPLE_H_ #define STORAGE_LEVELDB_PORT_PORT_EXAMPLE_H_
#include "port/thread_annotations.h"
namespace leveldb { namespace leveldb {
namespace port { namespace port {
@ -23,23 +25,23 @@ static const bool kLittleEndian = true /* or some other expression */;
// ------------------ Threading ------------------- // ------------------ Threading -------------------
// A Mutex represents an exclusive lock. // A Mutex represents an exclusive lock.
class Mutex { class LOCKABLE Mutex {
public: public:
Mutex(); Mutex();
~Mutex(); ~Mutex();
// Lock the mutex. Waits until other lockers have exited. // Lock the mutex. Waits until other lockers have exited.
// Will deadlock if the mutex is already locked by this thread. // Will deadlock if the mutex is already locked by this thread.
void Lock(); void Lock() EXCLUSIVE_LOCK_FUNCTION();
// Unlock the mutex. // Unlock the mutex.
// REQUIRES: This mutex was locked by this thread. // REQUIRES: This mutex was locked by this thread.
void Unlock(); void Unlock() UNLOCK_FUNCTION();
// Optionally crash if this thread does not hold this mutex. // Optionally crash if this thread does not hold this mutex.
// The implementation must be fast, especially if NDEBUG is // The implementation must be fast, especially if NDEBUG is
// defined. The implementation is allowed to skip all checks. // defined. The implementation is allowed to skip all checks.
void AssertHeld(); void AssertHeld() ASSERT_EXCLUSIVE_LOCK();
}; };
class CondVar { class CondVar {

View File

@ -48,6 +48,7 @@
#include <stdint.h> #include <stdint.h>
#include <string> #include <string>
#include "port/atomic_pointer.h" #include "port/atomic_pointer.h"
#include "port/thread_annotations.h"
#ifndef PLATFORM_IS_LITTLE_ENDIAN #ifndef PLATFORM_IS_LITTLE_ENDIAN
#define PLATFORM_IS_LITTLE_ENDIAN (__BYTE_ORDER == __LITTLE_ENDIAN) #define PLATFORM_IS_LITTLE_ENDIAN (__BYTE_ORDER == __LITTLE_ENDIAN)
@ -73,14 +74,14 @@ static const bool kLittleEndian = PLATFORM_IS_LITTLE_ENDIAN;
class CondVar; class CondVar;
class Mutex { class LOCKABLE Mutex {
public: public:
Mutex(); Mutex();
~Mutex(); ~Mutex();
void Lock(); void Lock() EXCLUSIVE_LOCK_FUNCTION();
void Unlock(); void Unlock() UNLOCK_FUNCTION();
void AssertHeld() { } void AssertHeld() ASSERT_EXCLUSIVE_LOCK() { }
private: private:
friend class CondVar; friend class CondVar;

View File

@ -5,56 +5,107 @@
#ifndef STORAGE_LEVELDB_PORT_THREAD_ANNOTATIONS_H_ #ifndef STORAGE_LEVELDB_PORT_THREAD_ANNOTATIONS_H_
#define STORAGE_LEVELDB_PORT_THREAD_ANNOTATIONS_H_ #define STORAGE_LEVELDB_PORT_THREAD_ANNOTATIONS_H_
// Some environments provide custom macros to aid in static thread-safety // Use Clang's thread safety analysis annotations when available. In other
// analysis. Provide empty definitions of such macros unless they are already // environments, the macros receive empty definitions.
// defined. // Usage documentation: https://clang.llvm.org/docs/ThreadSafetyAnalysis.html
#if !defined(THREAD_ANNOTATION_ATTRIBUTE__)
#if defined(__clang__)
#define THREAD_ANNOTATION_ATTRIBUTE__(x) __attribute__((x))
#else
#define THREAD_ANNOTATION_ATTRIBUTE__(x) // no-op
#endif
#endif // !defined(THREAD_ANNOTATION_ATTRIBUTE__)
#ifndef GUARDED_BY
#define GUARDED_BY(x) THREAD_ANNOTATION_ATTRIBUTE__(guarded_by(x))
#endif
#ifndef PT_GUARDED_BY
#define PT_GUARDED_BY(x) THREAD_ANNOTATION_ATTRIBUTE__(pt_guarded_by(x))
#endif
#ifndef ACQUIRED_AFTER
#define ACQUIRED_AFTER(...) \
THREAD_ANNOTATION_ATTRIBUTE__(acquired_after(__VA_ARGS__))
#endif
#ifndef ACQUIRED_BEFORE
#define ACQUIRED_BEFORE(...) \
THREAD_ANNOTATION_ATTRIBUTE__(acquired_before(__VA_ARGS__))
#endif
#ifndef EXCLUSIVE_LOCKS_REQUIRED #ifndef EXCLUSIVE_LOCKS_REQUIRED
#define EXCLUSIVE_LOCKS_REQUIRED(...) #define EXCLUSIVE_LOCKS_REQUIRED(...) \
THREAD_ANNOTATION_ATTRIBUTE__(exclusive_locks_required(__VA_ARGS__))
#endif #endif
#ifndef SHARED_LOCKS_REQUIRED #ifndef SHARED_LOCKS_REQUIRED
#define SHARED_LOCKS_REQUIRED(...) #define SHARED_LOCKS_REQUIRED(...) \
THREAD_ANNOTATION_ATTRIBUTE__(shared_locks_required(__VA_ARGS__))
#endif #endif
#ifndef LOCKS_EXCLUDED #ifndef LOCKS_EXCLUDED
#define LOCKS_EXCLUDED(...) #define LOCKS_EXCLUDED(...) \
THREAD_ANNOTATION_ATTRIBUTE__(locks_excluded(__VA_ARGS__))
#endif #endif
#ifndef LOCK_RETURNED #ifndef LOCK_RETURNED
#define LOCK_RETURNED(x) #define LOCK_RETURNED(x) \
THREAD_ANNOTATION_ATTRIBUTE__(lock_returned(x))
#endif #endif
#ifndef LOCKABLE #ifndef LOCKABLE
#define LOCKABLE #define LOCKABLE \
THREAD_ANNOTATION_ATTRIBUTE__(lockable)
#endif #endif
#ifndef SCOPED_LOCKABLE #ifndef SCOPED_LOCKABLE
#define SCOPED_LOCKABLE #define SCOPED_LOCKABLE \
THREAD_ANNOTATION_ATTRIBUTE__(scoped_lockable)
#endif #endif
#ifndef EXCLUSIVE_LOCK_FUNCTION #ifndef EXCLUSIVE_LOCK_FUNCTION
#define EXCLUSIVE_LOCK_FUNCTION(...) #define EXCLUSIVE_LOCK_FUNCTION(...) \
THREAD_ANNOTATION_ATTRIBUTE__(exclusive_lock_function(__VA_ARGS__))
#endif #endif
#ifndef SHARED_LOCK_FUNCTION #ifndef SHARED_LOCK_FUNCTION
#define SHARED_LOCK_FUNCTION(...) #define SHARED_LOCK_FUNCTION(...) \
THREAD_ANNOTATION_ATTRIBUTE__(shared_lock_function(__VA_ARGS__))
#endif #endif
#ifndef EXCLUSIVE_TRYLOCK_FUNCTION #ifndef EXCLUSIVE_TRYLOCK_FUNCTION
#define EXCLUSIVE_TRYLOCK_FUNCTION(...) #define EXCLUSIVE_TRYLOCK_FUNCTION(...) \
THREAD_ANNOTATION_ATTRIBUTE__(exclusive_trylock_function(__VA_ARGS__))
#endif #endif
#ifndef SHARED_TRYLOCK_FUNCTION #ifndef SHARED_TRYLOCK_FUNCTION
#define SHARED_TRYLOCK_FUNCTION(...) #define SHARED_TRYLOCK_FUNCTION(...) \
THREAD_ANNOTATION_ATTRIBUTE__(shared_trylock_function(__VA_ARGS__))
#endif #endif
#ifndef UNLOCK_FUNCTION #ifndef UNLOCK_FUNCTION
#define UNLOCK_FUNCTION(...) #define UNLOCK_FUNCTION(...) \
THREAD_ANNOTATION_ATTRIBUTE__(unlock_function(__VA_ARGS__))
#endif #endif
#ifndef NO_THREAD_SAFETY_ANALYSIS #ifndef NO_THREAD_SAFETY_ANALYSIS
#define NO_THREAD_SAFETY_ANALYSIS #define NO_THREAD_SAFETY_ANALYSIS \
THREAD_ANNOTATION_ATTRIBUTE__(no_thread_safety_analysis)
#endif
#ifndef ASSERT_EXCLUSIVE_LOCK
#define ASSERT_EXCLUSIVE_LOCK(...) \
THREAD_ANNOTATION_ATTRIBUTE__(assert_exclusive_lock(__VA_ARGS__))
#endif
#ifndef ASSERT_SHARED_LOCK
#define ASSERT_SHARED_LOCK(...) \
THREAD_ANNOTATION_ATTRIBUTE__(assert_shared_lock(__VA_ARGS__))
#endif #endif
#endif // STORAGE_LEVELDB_PORT_THREAD_ANNOTATIONS_H_ #endif // STORAGE_LEVELDB_PORT_THREAD_ANNOTATIONS_H_