Loading adb/transport.cpp +5 −14 Original line number Diff line number Diff line Loading @@ -52,6 +52,8 @@ #include "fdevent.h" #include "sysdeps/chrono.h" using android::base::ScopedLockAssertion; static void remove_transport(atransport* transport); static void transport_unref(atransport* transport); Loading @@ -72,17 +74,6 @@ const char* const kFeatureAbb = "abb"; namespace { // A class that helps the Clang Thread Safety Analysis deal with // std::unique_lock. Given that std::unique_lock is movable, and the analysis // can not currently perform alias analysis, it is not annotated. In order to // assert that the mutex is held, a ScopedAssumeLocked can be created just after // the std::unique_lock. class SCOPED_CAPABILITY ScopedAssumeLocked { public: ScopedAssumeLocked(std::mutex& mutex) ACQUIRE(mutex) {} ~ScopedAssumeLocked() RELEASE() {} }; #if ADB_HOST // Tracks and handles atransport*s that are attempting reconnection. class ReconnectHandler { Loading Loading @@ -180,7 +171,7 @@ void ReconnectHandler::Run() { ReconnectAttempt attempt; { std::unique_lock<std::mutex> lock(reconnect_mutex_); ScopedAssumeLocked assume_lock(reconnect_mutex_); ScopedLockAssertion assume_lock(reconnect_mutex_); if (!reconnect_queue_.empty()) { // FIXME: libstdc++ (used on Windows) implements condition_variable with Loading Loading @@ -296,7 +287,7 @@ void BlockingConnectionAdapter::Start() { LOG(INFO) << this->transport_name_ << ": write thread spawning"; while (true) { std::unique_lock<std::mutex> lock(mutex_); ScopedAssumeLocked assume_locked(mutex_); ScopedLockAssertion assume_locked(mutex_); cv_.wait(lock, [this]() REQUIRES(mutex_) { return this->stopped_ || !this->write_queue_.empty(); }); Loading Loading @@ -923,7 +914,7 @@ atransport* acquire_one_transport(TransportType type, const char* serial, Transp bool ConnectionWaitable::WaitForConnection(std::chrono::milliseconds timeout) { std::unique_lock<std::mutex> lock(mutex_); ScopedAssumeLocked assume_locked(mutex_); ScopedLockAssertion assume_locked(mutex_); return cv_.wait_for(lock, timeout, [&]() REQUIRES(mutex_) { return connection_established_ready_; }) && connection_established_; Loading base/include/android-base/thread_annotations.h +38 −0 Original line number Diff line number Diff line Loading @@ -16,6 +16,8 @@ #pragma once #include <mutex> #define THREAD_ANNOTATION_ATTRIBUTE__(x) __attribute__((x)) #define CAPABILITY(x) \ Loading Loading @@ -104,3 +106,39 @@ #define NO_THREAD_SAFETY_ANALYSIS \ THREAD_ANNOTATION_ATTRIBUTE__(no_thread_safety_analysis) namespace android { namespace base { // A class to help thread safety analysis deal with std::unique_lock and condition_variable. // // Clang's thread safety analysis currently doesn't perform alias analysis, so movable types // like std::unique_lock can't be marked with thread safety annotations. This helper allows // for manual assertion of lock state in a scope. // // For example: // // std::mutex mutex; // std::condition_variable cv; // std::vector<int> vec GUARDED_BY(mutex); // // int pop() { // std::unique_lock lock(mutex); // ScopedLockAssertion lock_assertion(mutex); // cv.wait(lock, []() { // ScopedLockAssertion lock_assertion(mutex); // return !vec.empty(); // }); // // int result = vec.back(); // vec.pop_back(); // return result; // } class SCOPED_CAPABILITY ScopedLockAssertion { public: ScopedLockAssertion(std::mutex& mutex) ACQUIRE(mutex) {} ~ScopedLockAssertion() RELEASE() {} }; } // namespace base } // namespace android Loading
adb/transport.cpp +5 −14 Original line number Diff line number Diff line Loading @@ -52,6 +52,8 @@ #include "fdevent.h" #include "sysdeps/chrono.h" using android::base::ScopedLockAssertion; static void remove_transport(atransport* transport); static void transport_unref(atransport* transport); Loading @@ -72,17 +74,6 @@ const char* const kFeatureAbb = "abb"; namespace { // A class that helps the Clang Thread Safety Analysis deal with // std::unique_lock. Given that std::unique_lock is movable, and the analysis // can not currently perform alias analysis, it is not annotated. In order to // assert that the mutex is held, a ScopedAssumeLocked can be created just after // the std::unique_lock. class SCOPED_CAPABILITY ScopedAssumeLocked { public: ScopedAssumeLocked(std::mutex& mutex) ACQUIRE(mutex) {} ~ScopedAssumeLocked() RELEASE() {} }; #if ADB_HOST // Tracks and handles atransport*s that are attempting reconnection. class ReconnectHandler { Loading Loading @@ -180,7 +171,7 @@ void ReconnectHandler::Run() { ReconnectAttempt attempt; { std::unique_lock<std::mutex> lock(reconnect_mutex_); ScopedAssumeLocked assume_lock(reconnect_mutex_); ScopedLockAssertion assume_lock(reconnect_mutex_); if (!reconnect_queue_.empty()) { // FIXME: libstdc++ (used on Windows) implements condition_variable with Loading Loading @@ -296,7 +287,7 @@ void BlockingConnectionAdapter::Start() { LOG(INFO) << this->transport_name_ << ": write thread spawning"; while (true) { std::unique_lock<std::mutex> lock(mutex_); ScopedAssumeLocked assume_locked(mutex_); ScopedLockAssertion assume_locked(mutex_); cv_.wait(lock, [this]() REQUIRES(mutex_) { return this->stopped_ || !this->write_queue_.empty(); }); Loading Loading @@ -923,7 +914,7 @@ atransport* acquire_one_transport(TransportType type, const char* serial, Transp bool ConnectionWaitable::WaitForConnection(std::chrono::milliseconds timeout) { std::unique_lock<std::mutex> lock(mutex_); ScopedAssumeLocked assume_locked(mutex_); ScopedLockAssertion assume_locked(mutex_); return cv_.wait_for(lock, timeout, [&]() REQUIRES(mutex_) { return connection_established_ready_; }) && connection_established_; Loading
base/include/android-base/thread_annotations.h +38 −0 Original line number Diff line number Diff line Loading @@ -16,6 +16,8 @@ #pragma once #include <mutex> #define THREAD_ANNOTATION_ATTRIBUTE__(x) __attribute__((x)) #define CAPABILITY(x) \ Loading Loading @@ -104,3 +106,39 @@ #define NO_THREAD_SAFETY_ANALYSIS \ THREAD_ANNOTATION_ATTRIBUTE__(no_thread_safety_analysis) namespace android { namespace base { // A class to help thread safety analysis deal with std::unique_lock and condition_variable. // // Clang's thread safety analysis currently doesn't perform alias analysis, so movable types // like std::unique_lock can't be marked with thread safety annotations. This helper allows // for manual assertion of lock state in a scope. // // For example: // // std::mutex mutex; // std::condition_variable cv; // std::vector<int> vec GUARDED_BY(mutex); // // int pop() { // std::unique_lock lock(mutex); // ScopedLockAssertion lock_assertion(mutex); // cv.wait(lock, []() { // ScopedLockAssertion lock_assertion(mutex); // return !vec.empty(); // }); // // int result = vec.back(); // vec.pop_back(); // return result; // } class SCOPED_CAPABILITY ScopedLockAssertion { public: ScopedLockAssertion(std::mutex& mutex) ACQUIRE(mutex) {} ~ScopedLockAssertion() RELEASE() {} }; } // namespace base } // namespace android