Remove mojo::system::Mutex's use of base::internal::LockImpl. R=jamesr@chromium.org Review URL: https://codereview.chromium.org/1418043003 .
diff --git a/mojo/edk/embedder/system_impl_private_entrypoints.cc b/mojo/edk/embedder/system_impl_private_entrypoints.cc index e2a369b..59a32f2 100644 --- a/mojo/edk/embedder/system_impl_private_entrypoints.cc +++ b/mojo/edk/embedder/system_impl_private_entrypoints.cc
@@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include "base/logging.h" #include "mojo/edk/embedder/embedder_internal.h" #include "mojo/edk/system/core.h" #include "mojo/edk/system/dispatcher.h"
diff --git a/mojo/edk/system/mutex.cc b/mojo/edk/system/mutex.cc index 216b35a..0f07adf 100644 --- a/mojo/edk/system/mutex.cc +++ b/mojo/edk/system/mutex.cc
@@ -5,34 +5,54 @@ #include "mojo/edk/system/mutex.h" #if !defined(NDEBUG) || defined(DCHECK_ALWAYS_ON) +#include <errno.h> +#include <string.h> #include "base/logging.h" namespace mojo { namespace system { -Mutex::Mutex() : lock_() { +Mutex::Mutex() { + pthread_mutexattr_t attr; + int error = pthread_mutexattr_init(&attr); + DCHECK(!error) << "pthread_mutexattr_init: " << strerror(error); + error = pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ERRORCHECK); + DCHECK(!error) << "pthread_mutexattr_settype: " << strerror(error); + error = pthread_mutex_init(&impl_, &attr); + DCHECK(!error) << "pthread_mutex_init: " << strerror(error); + error = pthread_mutexattr_destroy(&attr); + DCHECK(!error) << "pthread_mutexattr_destroy: " << strerror(error); } Mutex::~Mutex() { - DCHECK(owning_thread_ref_.is_null()); + int error = pthread_mutex_destroy(&impl_); + DCHECK(!error) << "pthread_mutex_destroy: " << strerror(error); } -void Mutex::AssertHeld() const { - DCHECK(owning_thread_ref_ == base::PlatformThread::CurrentRef()); +void Mutex::Lock() MOJO_EXCLUSIVE_LOCK_FUNCTION() { + int error = pthread_mutex_lock(&impl_); + DCHECK(!error) << "pthread_mutex_lock: " << strerror(error); } -void Mutex::CheckHeldAndUnmark() { - DCHECK(owning_thread_ref_ == base::PlatformThread::CurrentRef()); - owning_thread_ref_ = base::PlatformThreadRef(); +void Mutex::Unlock() MOJO_UNLOCK_FUNCTION() { + int error = pthread_mutex_unlock(&impl_); + DCHECK(!error) << "pthread_mutex_unlock: " << strerror(error); } -void Mutex::CheckUnheldAndMark() { - DCHECK(owning_thread_ref_.is_null()); - owning_thread_ref_ = base::PlatformThread::CurrentRef(); +bool Mutex::TryLock() MOJO_EXCLUSIVE_TRYLOCK_FUNCTION(true) { + int error = pthread_mutex_trylock(&impl_); + DCHECK(!error || error == EBUSY) << "pthread_mutex_trylock: " + << strerror(error); + return !error; +} + +void Mutex::AssertHeld() MOJO_ASSERT_EXCLUSIVE_LOCK() { + int error = pthread_mutex_lock(&impl_); + DCHECK_EQ(error, EDEADLK) << ". pthread_mutex_lock: " << strerror(error); } } // namespace system } // namespace mojo -#endif // !NDEBUG || DCHECK_ALWAYS_ON +#endif // !defined(NDEBUG) || defined(DCHECK_ALWAYS_ON)
diff --git a/mojo/edk/system/mutex.h b/mojo/edk/system/mutex.h index 859f6a3..bee54be 100644 --- a/mojo/edk/system/mutex.h +++ b/mojo/edk/system/mutex.h
@@ -4,16 +4,13 @@ // A mutex class, with support for thread annotations. // -// TODO(vtl): Currently, this is a fork of Chromium's -// base/synchronization/lock.h (with names changed and minor modifications; it -// still cheats and uses Chromium's lock_impl.*), but eventually we'll want our -// own and, e.g., add support for non-exclusive (reader) locks. +// TODO(vtl): Add support for non-exclusive (reader) locks. #ifndef MOJO_EDK_SYSTEM_MUTEX_H_ #define MOJO_EDK_SYSTEM_MUTEX_H_ -#include "base/synchronization/lock_impl.h" -#include "base/threading/platform_thread.h" +#include <pthread.h> + #include "mojo/edk/system/thread_annotations.h" #include "mojo/public/cpp/system/macros.h" @@ -25,47 +22,37 @@ class MOJO_LOCKABLE Mutex { public: #if defined(NDEBUG) && !defined(DCHECK_ALWAYS_ON) - Mutex() : lock_() {} - ~Mutex() {} + Mutex() { pthread_mutex_init(&impl_, nullptr); } + ~Mutex() { pthread_mutex_destroy(&impl_); } - void Lock() MOJO_EXCLUSIVE_LOCK_FUNCTION() { lock_.Lock(); } - void Unlock() MOJO_UNLOCK_FUNCTION() { lock_.Unlock(); } + // Takes an exclusive lock. + void Lock() MOJO_EXCLUSIVE_LOCK_FUNCTION() { pthread_mutex_lock(&impl_); } - bool TryLock() MOJO_EXCLUSIVE_TRYLOCK_FUNCTION(true) { return lock_.Try(); } + // Releases a lock. + void Unlock() MOJO_UNLOCK_FUNCTION() { pthread_mutex_unlock(&impl_); } - void AssertHeld() const MOJO_ASSERT_EXCLUSIVE_LOCK() {} + // Tries to take an exclusive lock, returning true if successful. + bool TryLock() MOJO_EXCLUSIVE_TRYLOCK_FUNCTION(true) { + return !pthread_mutex_trylock(&impl_); + } + + // Asserts that an exclusive lock is held by the calling thread. (Does nothing + // for non-Debug builds.) + void AssertHeld() MOJO_ASSERT_EXCLUSIVE_LOCK() {} #else Mutex(); ~Mutex(); - void Lock() MOJO_EXCLUSIVE_LOCK_FUNCTION() { - lock_.Lock(); - CheckUnheldAndMark(); - } - void Unlock() MOJO_UNLOCK_FUNCTION() { - CheckHeldAndUnmark(); - lock_.Unlock(); - } + void Lock() MOJO_EXCLUSIVE_LOCK_FUNCTION(); + void Unlock() MOJO_UNLOCK_FUNCTION(); - bool TryLock() MOJO_EXCLUSIVE_TRYLOCK_FUNCTION(true) { - bool rv = lock_.Try(); - if (rv) - CheckUnheldAndMark(); - return rv; - } + bool TryLock() MOJO_EXCLUSIVE_TRYLOCK_FUNCTION(true); - void AssertHeld() const MOJO_ASSERT_EXCLUSIVE_LOCK(); -#endif // NDEBUG && !DCHECK_ALWAYS_ON + void AssertHeld() MOJO_ASSERT_EXCLUSIVE_LOCK(); +#endif // defined(NDEBUG) && !defined(DCHECK_ALWAYS_ON) private: -#if !defined(NDEBUG) || defined(DCHECK_ALWAYS_ON) - void CheckHeldAndUnmark(); - void CheckUnheldAndMark(); - - base::PlatformThreadRef owning_thread_ref_; -#endif // !NDEBUG || DCHECK_ALWAYS_ON - - base::internal::LockImpl lock_; + pthread_mutex_t impl_; MOJO_DISALLOW_COPY_AND_ASSIGN(Mutex); };
diff --git a/mojo/edk/system/mutex_unittest.cc b/mojo/edk/system/mutex_unittest.cc index 9b51653..c4fce3a 100644 --- a/mojo/edk/system/mutex_unittest.cc +++ b/mojo/edk/system/mutex_unittest.cc
@@ -102,6 +102,20 @@ EXPECT_GE(thread.acquired(), 20); } +TEST(MutexTest, AssertHeld) { + Mutex mutex; + +#if defined(NDEBUG) && !defined(DCHECK_ALWAYS_ON) + // For non-Debug builds, |AssertHeld()| should do nothing. + mutex.AssertHeld(); +#else + EXPECT_DEATH_IF_SUPPORTED({ mutex.AssertHeld(); }, "Check failed"); +#endif // defined(NDEBUG) && !defined(DCHECK_ALWAYS_ON) + + // TODO(vtl): Should also test the case when the mutex is held by another + // thread, though this is more annoying since it requires synchronization. +} + // Test that TryLock() works as expected --------------------------------------- class TryLockTestThread : public base::PlatformThread::Delegate {