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 {