Merge "PIMutexUnlock: load owner_tid in non-common case"
diff --git a/libc/bionic/pthread_mutex.cpp b/libc/bionic/pthread_mutex.cpp
index f03e55b..37031ad 100644
--- a/libc/bionic/pthread_mutex.cpp
+++ b/libc/bionic/pthread_mutex.cpp
@@ -199,6 +199,8 @@
                                                                    memory_order_relaxed))) {
             return 0;
         }
+    } else {
+        old_owner = atomic_load_explicit(&mutex.owner_tid, memory_order_relaxed);
     }
 
     if (tid != (old_owner & FUTEX_TID_MASK)) {
diff --git a/tests/pthread_test.cpp b/tests/pthread_test.cpp
index 7b64401..0bf8e29 100644
--- a/tests/pthread_test.cpp
+++ b/tests/pthread_test.cpp
@@ -1843,10 +1843,25 @@
   DISALLOW_COPY_AND_ASSIGN(PthreadMutex);
 };
 
+static int UnlockFromAnotherThread(pthread_mutex_t* mutex) {
+  pthread_t thread;
+  pthread_create(&thread, nullptr, [](void* mutex_voidp) -> void* {
+    pthread_mutex_t* mutex = static_cast<pthread_mutex_t*>(mutex_voidp);
+    intptr_t result = pthread_mutex_unlock(mutex);
+    return reinterpret_cast<void*>(result);
+  }, mutex);
+  void* result;
+  EXPECT_EQ(0, pthread_join(thread, &result));
+  return reinterpret_cast<intptr_t>(result);
+};
+
 static void TestPthreadMutexLockNormal(int protocol) {
   PthreadMutex m(PTHREAD_MUTEX_NORMAL, protocol);
 
   ASSERT_EQ(0, pthread_mutex_lock(&m.lock));
+  if (protocol == PTHREAD_PRIO_INHERIT) {
+    ASSERT_EQ(EPERM, UnlockFromAnotherThread(&m.lock));
+  }
   ASSERT_EQ(0, pthread_mutex_unlock(&m.lock));
   ASSERT_EQ(0, pthread_mutex_trylock(&m.lock));
   ASSERT_EQ(EBUSY, pthread_mutex_trylock(&m.lock));
@@ -1857,6 +1872,7 @@
   PthreadMutex m(PTHREAD_MUTEX_ERRORCHECK, protocol);
 
   ASSERT_EQ(0, pthread_mutex_lock(&m.lock));
+  ASSERT_EQ(EPERM, UnlockFromAnotherThread(&m.lock));
   ASSERT_EQ(EDEADLK, pthread_mutex_lock(&m.lock));
   ASSERT_EQ(0, pthread_mutex_unlock(&m.lock));
   ASSERT_EQ(0, pthread_mutex_trylock(&m.lock));
@@ -1873,7 +1889,9 @@
   PthreadMutex m(PTHREAD_MUTEX_RECURSIVE, protocol);
 
   ASSERT_EQ(0, pthread_mutex_lock(&m.lock));
+  ASSERT_EQ(EPERM, UnlockFromAnotherThread(&m.lock));
   ASSERT_EQ(0, pthread_mutex_lock(&m.lock));
+  ASSERT_EQ(EPERM, UnlockFromAnotherThread(&m.lock));
   ASSERT_EQ(0, pthread_mutex_unlock(&m.lock));
   ASSERT_EQ(0, pthread_mutex_unlock(&m.lock));
   ASSERT_EQ(0, pthread_mutex_trylock(&m.lock));