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 {