18daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes/*
28daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes * Copyright (C) 2011 The Android Open Source Project
38daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes *
48daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes * Licensed under the Apache License, Version 2.0 (the "License");
58daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes * you may not use this file except in compliance with the License.
68daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes * You may obtain a copy of the License at
78daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes *
88daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes *      http://www.apache.org/licenses/LICENSE-2.0
98daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes *
108daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes * Unless required by applicable law or agreed to in writing, software
118daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes * distributed under the License is distributed on an "AS IS" BASIS,
128daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
138daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes * See the License for the specific language governing permissions and
148daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes * limitations under the License.
158daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes */
168daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes
178daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes#include "mutex.h"
188daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes
198daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes#include <errno.h>
20c604d731730b43231f63040c8db1d58304da0cf3Ian Rogers#include <sys/time.h>
218daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes
22cf7f19135f0e273f7b0136315633c2abfc715343Ian Rogers#define ATRACE_TAG ATRACE_TAG_DALVIK
23cf7f19135f0e273f7b0136315633c2abfc715343Ian Rogers#include "cutils/trace.h"
24cf7f19135f0e273f7b0136315633c2abfc715343Ian Rogers
251afde13b36cc1d67528104c2b1395495f669cd3fHiroshi Yamauchi#include "atomic.h"
2607ed66b5ae659c452cbe1ab20c3dbf1d6f546461Elliott Hughes#include "base/logging.h"
2741b175aba41c9365a1c53b8a1afbd17129c87c14Vladimir Marko#include "base/time_utils.h"
28cf7f19135f0e273f7b0136315633c2abfc715343Ian Rogers#include "base/value_object.h"
29693ff61274cd2c9b8eb7e68c370f84a911b8ca52Ian Rogers#include "mutex-inl.h"
306b3557571e798b60df995f978fa01c0ca1980dfdElliott Hughes#include "runtime.h"
31c604d731730b43231f63040c8db1d58304da0cf3Ian Rogers#include "scoped_thread_state_change.h"
3204d7aa92bc5548bc4d272b9480614f06248194ccIan Rogers#include "thread-inl.h"
338daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes
348daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughesnamespace art {
358daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes
36719d1a33f6569864f529e5a3fff59e7bca97aad0Ian RogersMutex* Locks::abort_lock_ = nullptr;
37306db81aba41eb244a4e8299cf58ac18ae9999c7Brian CarlstromMutex* Locks::alloc_tracker_lock_ = nullptr;
3874240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas GampeMutex* Locks::allocated_monitor_ids_lock_ = nullptr;
399e36931cc79ca665908db9575126881d1cfdea5aChao-ying FuMutex* Locks::allocated_thread_ids_lock_ = nullptr;
40ed2be1725fb79075892b1a9103487c9d9a95b350Sebastien HertzReaderWriterMutex* Locks::breakpoint_lock_ = nullptr;
41719d1a33f6569864f529e5a3fff59e7bca97aad0Ian RogersReaderWriterMutex* Locks::classlinker_classes_lock_ = nullptr;
42306db81aba41eb244a4e8299cf58ac18ae9999c7Brian CarlstromMutex* Locks::deoptimization_lock_ = nullptr;
43719d1a33f6569864f529e5a3fff59e7bca97aad0Ian RogersReaderWriterMutex* Locks::heap_bitmap_lock_ = nullptr;
449ef78b59da51080882e47505896b420977fd79aeMathieu ChartierMutex* Locks::instrument_entrypoints_lock_ = nullptr;
45a5a53efea976af505f4f849b5925d5e14c4f8e5cMathieu ChartierMutex* Locks::intern_table_lock_ = nullptr;
4668d8b42ddec39ec0174162d90d4abaa004d1983eIan RogersMutex* Locks::jni_libraries_lock_ = nullptr;
47719d1a33f6569864f529e5a3fff59e7bca97aad0Ian RogersMutex* Locks::logging_lock_ = nullptr;
483eed93dd5be03e5539827bebf0f414251a12e15eHiroshi YamauchiMutex* Locks::mem_maps_lock_ = nullptr;
499e36931cc79ca665908db9575126881d1cfdea5aChao-ying FuMutex* Locks::modify_ldt_lock_ = nullptr;
50719d1a33f6569864f529e5a3fff59e7bca97aad0Ian RogersReaderWriterMutex* Locks::mutator_lock_ = nullptr;
51306db81aba41eb244a4e8299cf58ac18ae9999c7Brian CarlstromMutex* Locks::profiler_lock_ = nullptr;
52a5a53efea976af505f4f849b5925d5e14c4f8e5cMathieu ChartierMutex* Locks::reference_processor_lock_ = nullptr;
53a5a53efea976af505f4f849b5925d5e14c4f8e5cMathieu ChartierMutex* Locks::reference_queue_cleared_references_lock_ = nullptr;
54a5a53efea976af505f4f849b5925d5e14c4f8e5cMathieu ChartierMutex* Locks::reference_queue_finalizer_references_lock_ = nullptr;
55a5a53efea976af505f4f849b5925d5e14c4f8e5cMathieu ChartierMutex* Locks::reference_queue_phantom_references_lock_ = nullptr;
56a5a53efea976af505f4f849b5925d5e14c4f8e5cMathieu ChartierMutex* Locks::reference_queue_soft_references_lock_ = nullptr;
57a5a53efea976af505f4f849b5925d5e14c4f8e5cMathieu ChartierMutex* Locks::reference_queue_weak_references_lock_ = nullptr;
58719d1a33f6569864f529e5a3fff59e7bca97aad0Ian RogersMutex* Locks::runtime_shutdown_lock_ = nullptr;
59719d1a33f6569864f529e5a3fff59e7bca97aad0Ian RogersMutex* Locks::thread_list_lock_ = nullptr;
6091e56692c6bd9fa1d41951ee7dc311f19461f4beMathieu ChartierConditionVariable* Locks::thread_exit_cond_ = nullptr;
61719d1a33f6569864f529e5a3fff59e7bca97aad0Ian RogersMutex* Locks::thread_suspend_count_lock_ = nullptr;
62719d1a33f6569864f529e5a3fff59e7bca97aad0Ian RogersMutex* Locks::trace_lock_ = nullptr;
63719d1a33f6569864f529e5a3fff59e7bca97aad0Ian RogersMutex* Locks::unexpected_signal_lock_ = nullptr;
64719d1a33f6569864f529e5a3fff59e7bca97aad0Ian Rogers
65719d1a33f6569864f529e5a3fff59e7bca97aad0Ian Rogersstruct AllMutexData {
66719d1a33f6569864f529e5a3fff59e7bca97aad0Ian Rogers  // A guard for all_mutexes_ that's not a mutex (Mutexes must CAS to acquire and busy wait).
67719d1a33f6569864f529e5a3fff59e7bca97aad0Ian Rogers  Atomic<const BaseMutex*> all_mutexes_guard;
68719d1a33f6569864f529e5a3fff59e7bca97aad0Ian Rogers  // All created mutexes guarded by all_mutexes_guard_.
69719d1a33f6569864f529e5a3fff59e7bca97aad0Ian Rogers  std::set<BaseMutex*>* all_mutexes;
702cebb24bfc3247d3e9be138a3350106737455918Mathieu Chartier  AllMutexData() : all_mutexes(nullptr) {}
71719d1a33f6569864f529e5a3fff59e7bca97aad0Ian Rogers};
72719d1a33f6569864f529e5a3fff59e7bca97aad0Ian Rogersstatic struct AllMutexData gAllMutexData[kAllMutexDataSize];
73719d1a33f6569864f529e5a3fff59e7bca97aad0Ian Rogers
74c604d731730b43231f63040c8db1d58304da0cf3Ian Rogers#if ART_USE_FUTEXES
75c604d731730b43231f63040c8db1d58304da0cf3Ian Rogersstatic bool ComputeRelativeTimeSpec(timespec* result_ts, const timespec& lhs, const timespec& rhs) {
76fb6996fe2b1bb28526751650441d7ac29dcdb4e6Brian Carlstrom  const int32_t one_sec = 1000 * 1000 * 1000;  // one second in nanoseconds.
77c604d731730b43231f63040c8db1d58304da0cf3Ian Rogers  result_ts->tv_sec = lhs.tv_sec - rhs.tv_sec;
78c604d731730b43231f63040c8db1d58304da0cf3Ian Rogers  result_ts->tv_nsec = lhs.tv_nsec - rhs.tv_nsec;
79c604d731730b43231f63040c8db1d58304da0cf3Ian Rogers  if (result_ts->tv_nsec < 0) {
80c604d731730b43231f63040c8db1d58304da0cf3Ian Rogers    result_ts->tv_sec--;
81c604d731730b43231f63040c8db1d58304da0cf3Ian Rogers    result_ts->tv_nsec += one_sec;
82c604d731730b43231f63040c8db1d58304da0cf3Ian Rogers  } else if (result_ts->tv_nsec > one_sec) {
83c604d731730b43231f63040c8db1d58304da0cf3Ian Rogers    result_ts->tv_sec++;
84c604d731730b43231f63040c8db1d58304da0cf3Ian Rogers    result_ts->tv_nsec -= one_sec;
85c604d731730b43231f63040c8db1d58304da0cf3Ian Rogers  }
86c604d731730b43231f63040c8db1d58304da0cf3Ian Rogers  return result_ts->tv_sec < 0;
87c604d731730b43231f63040c8db1d58304da0cf3Ian Rogers}
88c604d731730b43231f63040c8db1d58304da0cf3Ian Rogers#endif
89c604d731730b43231f63040c8db1d58304da0cf3Ian Rogers
906f3dbbadf4ce66982eb3d400e0a74cb73eb034f3Ian Rogersclass ScopedAllMutexesLock FINAL {
9156edc432fa914f7ccfa87ce443e64f5ef475666dIan Rogers public:
9293ba893c20532990a430741e0a97212900094e8cBrian Carlstrom  explicit ScopedAllMutexesLock(const BaseMutex* mutex) : mutex_(mutex) {
933e5cf305db800b2989ad57b7cde8fb3cc9fa1b9eIan Rogers    while (!gAllMutexData->all_mutexes_guard.CompareExchangeWeakAcquire(0, mutex)) {
9456edc432fa914f7ccfa87ce443e64f5ef475666dIan Rogers      NanoSleep(100);
9556edc432fa914f7ccfa87ce443e64f5ef475666dIan Rogers    }
9656edc432fa914f7ccfa87ce443e64f5ef475666dIan Rogers  }
976f3dbbadf4ce66982eb3d400e0a74cb73eb034f3Ian Rogers
9856edc432fa914f7ccfa87ce443e64f5ef475666dIan Rogers  ~ScopedAllMutexesLock() {
996f3dbbadf4ce66982eb3d400e0a74cb73eb034f3Ian Rogers#if !defined(__clang__)
1006f3dbbadf4ce66982eb3d400e0a74cb73eb034f3Ian Rogers    // TODO: remove this workaround target GCC/libc++/bionic bug "invalid failure memory model".
1016f3dbbadf4ce66982eb3d400e0a74cb73eb034f3Ian Rogers    while (!gAllMutexData->all_mutexes_guard.CompareExchangeWeakSequentiallyConsistent(mutex_, 0)) {
1026f3dbbadf4ce66982eb3d400e0a74cb73eb034f3Ian Rogers#else
1033e5cf305db800b2989ad57b7cde8fb3cc9fa1b9eIan Rogers    while (!gAllMutexData->all_mutexes_guard.CompareExchangeWeakRelease(mutex_, 0)) {
1046f3dbbadf4ce66982eb3d400e0a74cb73eb034f3Ian Rogers#endif
10556edc432fa914f7ccfa87ce443e64f5ef475666dIan Rogers      NanoSleep(100);
10656edc432fa914f7ccfa87ce443e64f5ef475666dIan Rogers    }
10756edc432fa914f7ccfa87ce443e64f5ef475666dIan Rogers  }
1086f3dbbadf4ce66982eb3d400e0a74cb73eb034f3Ian Rogers
10956edc432fa914f7ccfa87ce443e64f5ef475666dIan Rogers private:
11056edc432fa914f7ccfa87ce443e64f5ef475666dIan Rogers  const BaseMutex* const mutex_;
11156edc432fa914f7ccfa87ce443e64f5ef475666dIan Rogers};
11256edc432fa914f7ccfa87ce443e64f5ef475666dIan Rogers
113cf7f19135f0e273f7b0136315633c2abfc715343Ian Rogers// Scoped class that generates events at the beginning and end of lock contention.
114cf7f19135f0e273f7b0136315633c2abfc715343Ian Rogersclass ScopedContentionRecorder FINAL : public ValueObject {
115cf7f19135f0e273f7b0136315633c2abfc715343Ian Rogers public:
116cf7f19135f0e273f7b0136315633c2abfc715343Ian Rogers  ScopedContentionRecorder(BaseMutex* mutex, uint64_t blocked_tid, uint64_t owner_tid)
1172cebb24bfc3247d3e9be138a3350106737455918Mathieu Chartier      : mutex_(kLogLockContentions ? mutex : nullptr),
118cf7f19135f0e273f7b0136315633c2abfc715343Ian Rogers        blocked_tid_(kLogLockContentions ? blocked_tid : 0),
119cf7f19135f0e273f7b0136315633c2abfc715343Ian Rogers        owner_tid_(kLogLockContentions ? owner_tid : 0),
120cf7f19135f0e273f7b0136315633c2abfc715343Ian Rogers        start_nano_time_(kLogLockContentions ? NanoTime() : 0) {
121cf7f19135f0e273f7b0136315633c2abfc715343Ian Rogers    if (ATRACE_ENABLED()) {
122cf7f19135f0e273f7b0136315633c2abfc715343Ian Rogers      std::string msg = StringPrintf("Lock contention on %s (owner tid: %" PRIu64 ")",
123cf7f19135f0e273f7b0136315633c2abfc715343Ian Rogers                                     mutex->GetName(), owner_tid);
124cf7f19135f0e273f7b0136315633c2abfc715343Ian Rogers      ATRACE_BEGIN(msg.c_str());
125cf7f19135f0e273f7b0136315633c2abfc715343Ian Rogers    }
126cf7f19135f0e273f7b0136315633c2abfc715343Ian Rogers  }
127cf7f19135f0e273f7b0136315633c2abfc715343Ian Rogers
128cf7f19135f0e273f7b0136315633c2abfc715343Ian Rogers  ~ScopedContentionRecorder() {
129cf7f19135f0e273f7b0136315633c2abfc715343Ian Rogers    ATRACE_END();
130cf7f19135f0e273f7b0136315633c2abfc715343Ian Rogers    if (kLogLockContentions) {
131cf7f19135f0e273f7b0136315633c2abfc715343Ian Rogers      uint64_t end_nano_time = NanoTime();
132cf7f19135f0e273f7b0136315633c2abfc715343Ian Rogers      mutex_->RecordContention(blocked_tid_, owner_tid_, end_nano_time - start_nano_time_);
133cf7f19135f0e273f7b0136315633c2abfc715343Ian Rogers    }
134cf7f19135f0e273f7b0136315633c2abfc715343Ian Rogers  }
135cf7f19135f0e273f7b0136315633c2abfc715343Ian Rogers
136cf7f19135f0e273f7b0136315633c2abfc715343Ian Rogers private:
137cf7f19135f0e273f7b0136315633c2abfc715343Ian Rogers  BaseMutex* const mutex_;
138cf7f19135f0e273f7b0136315633c2abfc715343Ian Rogers  const uint64_t blocked_tid_;
139cf7f19135f0e273f7b0136315633c2abfc715343Ian Rogers  const uint64_t owner_tid_;
140cf7f19135f0e273f7b0136315633c2abfc715343Ian Rogers  const uint64_t start_nano_time_;
141cf7f19135f0e273f7b0136315633c2abfc715343Ian Rogers};
142cf7f19135f0e273f7b0136315633c2abfc715343Ian Rogers
14356edc432fa914f7ccfa87ce443e64f5ef475666dIan RogersBaseMutex::BaseMutex(const char* name, LockLevel level) : level_(level), name_(name) {
1441afde13b36cc1d67528104c2b1395495f669cd3fHiroshi Yamauchi  if (kLogLockContentions) {
1451afde13b36cc1d67528104c2b1395495f669cd3fHiroshi Yamauchi    ScopedAllMutexesLock mu(this);
146d9c4fc94fa618617f94e1de9af5f034549100753Ian Rogers    std::set<BaseMutex*>** all_mutexes_ptr = &gAllMutexData->all_mutexes;
1472cebb24bfc3247d3e9be138a3350106737455918Mathieu Chartier    if (*all_mutexes_ptr == nullptr) {
1481afde13b36cc1d67528104c2b1395495f669cd3fHiroshi Yamauchi      // We leak the global set of all mutexes to avoid ordering issues in global variable
1491afde13b36cc1d67528104c2b1395495f669cd3fHiroshi Yamauchi      // construction/destruction.
1501afde13b36cc1d67528104c2b1395495f669cd3fHiroshi Yamauchi      *all_mutexes_ptr = new std::set<BaseMutex*>();
1511afde13b36cc1d67528104c2b1395495f669cd3fHiroshi Yamauchi    }
1521afde13b36cc1d67528104c2b1395495f669cd3fHiroshi Yamauchi    (*all_mutexes_ptr)->insert(this);
15356edc432fa914f7ccfa87ce443e64f5ef475666dIan Rogers  }
15456edc432fa914f7ccfa87ce443e64f5ef475666dIan Rogers}
15556edc432fa914f7ccfa87ce443e64f5ef475666dIan Rogers
15656edc432fa914f7ccfa87ce443e64f5ef475666dIan RogersBaseMutex::~BaseMutex() {
1571afde13b36cc1d67528104c2b1395495f669cd3fHiroshi Yamauchi  if (kLogLockContentions) {
1581afde13b36cc1d67528104c2b1395495f669cd3fHiroshi Yamauchi    ScopedAllMutexesLock mu(this);
159d9c4fc94fa618617f94e1de9af5f034549100753Ian Rogers    gAllMutexData->all_mutexes->erase(this);
1601afde13b36cc1d67528104c2b1395495f669cd3fHiroshi Yamauchi  }
16156edc432fa914f7ccfa87ce443e64f5ef475666dIan Rogers}
16256edc432fa914f7ccfa87ce443e64f5ef475666dIan Rogers
16356edc432fa914f7ccfa87ce443e64f5ef475666dIan Rogersvoid BaseMutex::DumpAll(std::ostream& os) {
1641afde13b36cc1d67528104c2b1395495f669cd3fHiroshi Yamauchi  if (kLogLockContentions) {
1651afde13b36cc1d67528104c2b1395495f669cd3fHiroshi Yamauchi    os << "Mutex logging:\n";
1661afde13b36cc1d67528104c2b1395495f669cd3fHiroshi Yamauchi    ScopedAllMutexesLock mu(reinterpret_cast<const BaseMutex*>(-1));
167d9c4fc94fa618617f94e1de9af5f034549100753Ian Rogers    std::set<BaseMutex*>* all_mutexes = gAllMutexData->all_mutexes;
1682cebb24bfc3247d3e9be138a3350106737455918Mathieu Chartier    if (all_mutexes == nullptr) {
1691afde13b36cc1d67528104c2b1395495f669cd3fHiroshi Yamauchi      // No mutexes have been created yet during at startup.
1701afde13b36cc1d67528104c2b1395495f669cd3fHiroshi Yamauchi      return;
1711afde13b36cc1d67528104c2b1395495f669cd3fHiroshi Yamauchi    }
1721afde13b36cc1d67528104c2b1395495f669cd3fHiroshi Yamauchi    typedef std::set<BaseMutex*>::const_iterator It;
173d9c4fc94fa618617f94e1de9af5f034549100753Ian Rogers    os << "(Contended)\n";
1741afde13b36cc1d67528104c2b1395495f669cd3fHiroshi Yamauchi    for (It it = all_mutexes->begin(); it != all_mutexes->end(); ++it) {
1751afde13b36cc1d67528104c2b1395495f669cd3fHiroshi Yamauchi      BaseMutex* mutex = *it;
1761afde13b36cc1d67528104c2b1395495f669cd3fHiroshi Yamauchi      if (mutex->HasEverContended()) {
1771afde13b36cc1d67528104c2b1395495f669cd3fHiroshi Yamauchi        mutex->Dump(os);
1781afde13b36cc1d67528104c2b1395495f669cd3fHiroshi Yamauchi        os << "\n";
1791afde13b36cc1d67528104c2b1395495f669cd3fHiroshi Yamauchi      }
1801afde13b36cc1d67528104c2b1395495f669cd3fHiroshi Yamauchi    }
1811afde13b36cc1d67528104c2b1395495f669cd3fHiroshi Yamauchi    os << "(Never contented)\n";
1821afde13b36cc1d67528104c2b1395495f669cd3fHiroshi Yamauchi    for (It it = all_mutexes->begin(); it != all_mutexes->end(); ++it) {
1831afde13b36cc1d67528104c2b1395495f669cd3fHiroshi Yamauchi      BaseMutex* mutex = *it;
1841afde13b36cc1d67528104c2b1395495f669cd3fHiroshi Yamauchi      if (!mutex->HasEverContended()) {
1851afde13b36cc1d67528104c2b1395495f669cd3fHiroshi Yamauchi        mutex->Dump(os);
1861afde13b36cc1d67528104c2b1395495f669cd3fHiroshi Yamauchi        os << "\n";
1871afde13b36cc1d67528104c2b1395495f669cd3fHiroshi Yamauchi      }
1881afde13b36cc1d67528104c2b1395495f669cd3fHiroshi Yamauchi    }
18956edc432fa914f7ccfa87ce443e64f5ef475666dIan Rogers  }
19056edc432fa914f7ccfa87ce443e64f5ef475666dIan Rogers}
19100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers
19281d425b0b232962441616f8b14f73620bffef5e5Ian Rogersvoid BaseMutex::CheckSafeToWait(Thread* self) {
1932cebb24bfc3247d3e9be138a3350106737455918Mathieu Chartier  if (self == nullptr) {
19400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers    CheckUnattachedThread(level_);
19567d920071fe4a0aa8b8bc339e93b18276238c320Elliott Hughes    return;
19667d920071fe4a0aa8b8bc339e93b18276238c320Elliott Hughes  }
19725fd14b87cced64a179dee885573113be5e11944Ian Rogers  if (kDebugLocking) {
198d9c4fc94fa618617f94e1de9af5f034549100753Ian Rogers    CHECK(self->GetHeldMutex(level_) == this || level_ == kMonitorLock)
199d9c4fc94fa618617f94e1de9af5f034549100753Ian Rogers        << "Waiting on unacquired mutex: " << name_;
20025fd14b87cced64a179dee885573113be5e11944Ian Rogers    bool bad_mutexes_held = false;
2010f827169742aad6209d830db773a101849c32a83Elliott Hughes    for (int i = kLockLevelCount - 1; i >= 0; --i) {
20225fd14b87cced64a179dee885573113be5e11944Ian Rogers      if (i != level_) {
20381d425b0b232962441616f8b14f73620bffef5e5Ian Rogers        BaseMutex* held_mutex = self->GetHeldMutex(static_cast<LockLevel>(i));
204f3d874c60ee3ada19ce26a5c4e532312b6f3a9e9Ian Rogers        // We expect waits to happen while holding the thread list suspend thread lock.
2052cebb24bfc3247d3e9be138a3350106737455918Mathieu Chartier        if (held_mutex != nullptr) {
2060f827169742aad6209d830db773a101849c32a83Elliott Hughes          LOG(ERROR) << "Holding \"" << held_mutex->name_ << "\" "
2070f827169742aad6209d830db773a101849c32a83Elliott Hughes                     << "(level " << LockLevel(i) << ") while performing wait on "
2080f827169742aad6209d830db773a101849c32a83Elliott Hughes                     << "\"" << name_ << "\" (level " << level_ << ")";
20925fd14b87cced64a179dee885573113be5e11944Ian Rogers          bad_mutexes_held = true;
21025fd14b87cced64a179dee885573113be5e11944Ian Rogers        }
21100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers      }
21200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers    }
213db978719dbcb73fc6acfd193561445c4462786b8Nicolas Geoffray    if (gAborting == 0) {  // Avoid recursive aborts.
214db978719dbcb73fc6acfd193561445c4462786b8Nicolas Geoffray      CHECK(!bad_mutexes_held);
215db978719dbcb73fc6acfd193561445c4462786b8Nicolas Geoffray    }
21600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  }
217ffb465f23d9549dd591e6aa62e9250523cb00233Elliott Hughes}
218ffb465f23d9549dd591e6aa62e9250523cb00233Elliott Hughes
21937f3c968ecd04e77802fe17bb82dabc07de21ca1Ian Rogersvoid BaseMutex::ContentionLogData::AddToWaitTime(uint64_t value) {
2201afde13b36cc1d67528104c2b1395495f669cd3fHiroshi Yamauchi  if (kLogLockContentions) {
2211afde13b36cc1d67528104c2b1395495f669cd3fHiroshi Yamauchi    // Atomically add value to wait_time.
22237f3c968ecd04e77802fe17bb82dabc07de21ca1Ian Rogers    wait_time.FetchAndAddSequentiallyConsistent(value);
2231afde13b36cc1d67528104c2b1395495f669cd3fHiroshi Yamauchi  }
2241afde13b36cc1d67528104c2b1395495f669cd3fHiroshi Yamauchi}
2251afde13b36cc1d67528104c2b1395495f669cd3fHiroshi Yamauchi
2260de7985b29257bb60be511db774a4f0119a81f20Brian Carlstromvoid BaseMutex::RecordContention(uint64_t blocked_tid,
2270de7985b29257bb60be511db774a4f0119a81f20Brian Carlstrom                                 uint64_t owner_tid,
2281afde13b36cc1d67528104c2b1395495f669cd3fHiroshi Yamauchi                                 uint64_t nano_time_blocked) {
2291afde13b36cc1d67528104c2b1395495f669cd3fHiroshi Yamauchi  if (kLogLockContentions) {
2303e5cf305db800b2989ad57b7cde8fb3cc9fa1b9eIan Rogers    ContentionLogData* data = contention_log_data_;
2311afde13b36cc1d67528104c2b1395495f669cd3fHiroshi Yamauchi    ++(data->contention_count);
2321afde13b36cc1d67528104c2b1395495f669cd3fHiroshi Yamauchi    data->AddToWaitTime(nano_time_blocked);
2331afde13b36cc1d67528104c2b1395495f669cd3fHiroshi Yamauchi    ContentionLogEntry* log = data->contention_log;
2341afde13b36cc1d67528104c2b1395495f669cd3fHiroshi Yamauchi    // This code is intentionally racy as it is only used for diagnostics.
2353e5cf305db800b2989ad57b7cde8fb3cc9fa1b9eIan Rogers    uint32_t slot = data->cur_content_log_entry.LoadRelaxed();
2361afde13b36cc1d67528104c2b1395495f669cd3fHiroshi Yamauchi    if (log[slot].blocked_tid == blocked_tid &&
2371afde13b36cc1d67528104c2b1395495f669cd3fHiroshi Yamauchi        log[slot].owner_tid == blocked_tid) {
2381afde13b36cc1d67528104c2b1395495f669cd3fHiroshi Yamauchi      ++log[slot].count;
2391afde13b36cc1d67528104c2b1395495f669cd3fHiroshi Yamauchi    } else {
2401afde13b36cc1d67528104c2b1395495f669cd3fHiroshi Yamauchi      uint32_t new_slot;
2411afde13b36cc1d67528104c2b1395495f669cd3fHiroshi Yamauchi      do {
2423e5cf305db800b2989ad57b7cde8fb3cc9fa1b9eIan Rogers        slot = data->cur_content_log_entry.LoadRelaxed();
2431afde13b36cc1d67528104c2b1395495f669cd3fHiroshi Yamauchi        new_slot = (slot + 1) % kContentionLogSize;
2443e5cf305db800b2989ad57b7cde8fb3cc9fa1b9eIan Rogers      } while (!data->cur_content_log_entry.CompareExchangeWeakRelaxed(slot, new_slot));
2451afde13b36cc1d67528104c2b1395495f669cd3fHiroshi Yamauchi      log[new_slot].blocked_tid = blocked_tid;
2461afde13b36cc1d67528104c2b1395495f669cd3fHiroshi Yamauchi      log[new_slot].owner_tid = owner_tid;
2473e5cf305db800b2989ad57b7cde8fb3cc9fa1b9eIan Rogers      log[new_slot].count.StoreRelaxed(1);
2481afde13b36cc1d67528104c2b1395495f669cd3fHiroshi Yamauchi    }
24956edc432fa914f7ccfa87ce443e64f5ef475666dIan Rogers  }
25056edc432fa914f7ccfa87ce443e64f5ef475666dIan Rogers}
25156edc432fa914f7ccfa87ce443e64f5ef475666dIan Rogers
25256edc432fa914f7ccfa87ce443e64f5ef475666dIan Rogersvoid BaseMutex::DumpContention(std::ostream& os) const {
2531afde13b36cc1d67528104c2b1395495f669cd3fHiroshi Yamauchi  if (kLogLockContentions) {
2543e5cf305db800b2989ad57b7cde8fb3cc9fa1b9eIan Rogers    const ContentionLogData* data = contention_log_data_;
2551afde13b36cc1d67528104c2b1395495f669cd3fHiroshi Yamauchi    const ContentionLogEntry* log = data->contention_log;
25637f3c968ecd04e77802fe17bb82dabc07de21ca1Ian Rogers    uint64_t wait_time = data->wait_time.LoadRelaxed();
2573e5cf305db800b2989ad57b7cde8fb3cc9fa1b9eIan Rogers    uint32_t contention_count = data->contention_count.LoadRelaxed();
2581afde13b36cc1d67528104c2b1395495f669cd3fHiroshi Yamauchi    if (contention_count == 0) {
2591afde13b36cc1d67528104c2b1395495f669cd3fHiroshi Yamauchi      os << "never contended";
2601afde13b36cc1d67528104c2b1395495f669cd3fHiroshi Yamauchi    } else {
2611afde13b36cc1d67528104c2b1395495f669cd3fHiroshi Yamauchi      os << "contended " << contention_count
26273d1e17b3afc7d5e56184f90bf819dc64956448aMathieu Chartier         << " total wait of contender " << PrettyDuration(wait_time)
26373d1e17b3afc7d5e56184f90bf819dc64956448aMathieu Chartier         << " average " << PrettyDuration(wait_time / contention_count);
2641afde13b36cc1d67528104c2b1395495f669cd3fHiroshi Yamauchi      SafeMap<uint64_t, size_t> most_common_blocker;
2651afde13b36cc1d67528104c2b1395495f669cd3fHiroshi Yamauchi      SafeMap<uint64_t, size_t> most_common_blocked;
2661afde13b36cc1d67528104c2b1395495f669cd3fHiroshi Yamauchi      for (size_t i = 0; i < kContentionLogSize; ++i) {
2671afde13b36cc1d67528104c2b1395495f669cd3fHiroshi Yamauchi        uint64_t blocked_tid = log[i].blocked_tid;
2681afde13b36cc1d67528104c2b1395495f669cd3fHiroshi Yamauchi        uint64_t owner_tid = log[i].owner_tid;
2693e5cf305db800b2989ad57b7cde8fb3cc9fa1b9eIan Rogers        uint32_t count = log[i].count.LoadRelaxed();
2701afde13b36cc1d67528104c2b1395495f669cd3fHiroshi Yamauchi        if (count > 0) {
27173d1e17b3afc7d5e56184f90bf819dc64956448aMathieu Chartier          auto it = most_common_blocked.find(blocked_tid);
2721afde13b36cc1d67528104c2b1395495f669cd3fHiroshi Yamauchi          if (it != most_common_blocked.end()) {
2731afde13b36cc1d67528104c2b1395495f669cd3fHiroshi Yamauchi            most_common_blocked.Overwrite(blocked_tid, it->second + count);
2741afde13b36cc1d67528104c2b1395495f669cd3fHiroshi Yamauchi          } else {
2751afde13b36cc1d67528104c2b1395495f669cd3fHiroshi Yamauchi            most_common_blocked.Put(blocked_tid, count);
2761afde13b36cc1d67528104c2b1395495f669cd3fHiroshi Yamauchi          }
2771afde13b36cc1d67528104c2b1395495f669cd3fHiroshi Yamauchi          it = most_common_blocker.find(owner_tid);
2781afde13b36cc1d67528104c2b1395495f669cd3fHiroshi Yamauchi          if (it != most_common_blocker.end()) {
2791afde13b36cc1d67528104c2b1395495f669cd3fHiroshi Yamauchi            most_common_blocker.Overwrite(owner_tid, it->second + count);
2801afde13b36cc1d67528104c2b1395495f669cd3fHiroshi Yamauchi          } else {
2811afde13b36cc1d67528104c2b1395495f669cd3fHiroshi Yamauchi            most_common_blocker.Put(owner_tid, count);
2821afde13b36cc1d67528104c2b1395495f669cd3fHiroshi Yamauchi          }
28356edc432fa914f7ccfa87ce443e64f5ef475666dIan Rogers        }
2841afde13b36cc1d67528104c2b1395495f669cd3fHiroshi Yamauchi      }
2851afde13b36cc1d67528104c2b1395495f669cd3fHiroshi Yamauchi      uint64_t max_tid = 0;
2861afde13b36cc1d67528104c2b1395495f669cd3fHiroshi Yamauchi      size_t max_tid_count = 0;
28773d1e17b3afc7d5e56184f90bf819dc64956448aMathieu Chartier      for (const auto& pair : most_common_blocked) {
28873d1e17b3afc7d5e56184f90bf819dc64956448aMathieu Chartier        if (pair.second > max_tid_count) {
28973d1e17b3afc7d5e56184f90bf819dc64956448aMathieu Chartier          max_tid = pair.first;
29073d1e17b3afc7d5e56184f90bf819dc64956448aMathieu Chartier          max_tid_count = pair.second;
29156edc432fa914f7ccfa87ce443e64f5ef475666dIan Rogers        }
29256edc432fa914f7ccfa87ce443e64f5ef475666dIan Rogers      }
2931afde13b36cc1d67528104c2b1395495f669cd3fHiroshi Yamauchi      if (max_tid != 0) {
2941afde13b36cc1d67528104c2b1395495f669cd3fHiroshi Yamauchi        os << " sample shows most blocked tid=" << max_tid;
29556edc432fa914f7ccfa87ce443e64f5ef475666dIan Rogers      }
2961afde13b36cc1d67528104c2b1395495f669cd3fHiroshi Yamauchi      max_tid = 0;
2971afde13b36cc1d67528104c2b1395495f669cd3fHiroshi Yamauchi      max_tid_count = 0;
29873d1e17b3afc7d5e56184f90bf819dc64956448aMathieu Chartier      for (const auto& pair : most_common_blocker) {
29973d1e17b3afc7d5e56184f90bf819dc64956448aMathieu Chartier        if (pair.second > max_tid_count) {
30073d1e17b3afc7d5e56184f90bf819dc64956448aMathieu Chartier          max_tid = pair.first;
30173d1e17b3afc7d5e56184f90bf819dc64956448aMathieu Chartier          max_tid_count = pair.second;
3021afde13b36cc1d67528104c2b1395495f669cd3fHiroshi Yamauchi        }
3031afde13b36cc1d67528104c2b1395495f669cd3fHiroshi Yamauchi      }
3041afde13b36cc1d67528104c2b1395495f669cd3fHiroshi Yamauchi      if (max_tid != 0) {
3051afde13b36cc1d67528104c2b1395495f669cd3fHiroshi Yamauchi        os << " sample shows tid=" << max_tid << " owning during this time";
30656edc432fa914f7ccfa87ce443e64f5ef475666dIan Rogers      }
30756edc432fa914f7ccfa87ce443e64f5ef475666dIan Rogers    }
30856edc432fa914f7ccfa87ce443e64f5ef475666dIan Rogers  }
30956edc432fa914f7ccfa87ce443e64f5ef475666dIan Rogers}
31056edc432fa914f7ccfa87ce443e64f5ef475666dIan Rogers
31156edc432fa914f7ccfa87ce443e64f5ef475666dIan Rogers
31281d425b0b232962441616f8b14f73620bffef5e5Ian RogersMutex::Mutex(const char* name, LockLevel level, bool recursive)
31300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers    : BaseMutex(name, level), recursive_(recursive), recursion_count_(0) {
314c604d731730b43231f63040c8db1d58304da0cf3Ian Rogers#if ART_USE_FUTEXES
315c7190697f8665e706f6ebb4ae36fa63c46a32cd5Ian Rogers  DCHECK_EQ(0, state_.LoadRelaxed());
3163e5cf305db800b2989ad57b7cde8fb3cc9fa1b9eIan Rogers  DCHECK_EQ(0, num_contenders_.LoadRelaxed());
31700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers#else
318c5f17732d8144491c642776b6b48c85dfadf4b52Ian Rogers  CHECK_MUTEX_CALL(pthread_mutex_init, (&mutex_, nullptr));
31900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers#endif
320c5f17732d8144491c642776b6b48c85dfadf4b52Ian Rogers  exclusive_owner_ = 0;
3218daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes}
3228daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes
3238f1fa100ee037131976c616ec72a6608dccb51e2Andreas Gampe// Helper to ignore the lock requirement.
3248f1fa100ee037131976c616ec72a6608dccb51e2Andreas Gampestatic bool IsShuttingDown() NO_THREAD_SAFETY_ANALYSIS {
3258f1fa100ee037131976c616ec72a6608dccb51e2Andreas Gampe  Runtime* runtime = Runtime::Current();
3268f1fa100ee037131976c616ec72a6608dccb51e2Andreas Gampe  return runtime == nullptr || runtime->IsShuttingDownLocked();
3278f1fa100ee037131976c616ec72a6608dccb51e2Andreas Gampe}
3288f1fa100ee037131976c616ec72a6608dccb51e2Andreas Gampe
3298daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott HughesMutex::~Mutex() {
3308f1fa100ee037131976c616ec72a6608dccb51e2Andreas Gampe  bool shutting_down = IsShuttingDown();
331c604d731730b43231f63040c8db1d58304da0cf3Ian Rogers#if ART_USE_FUTEXES
332c7190697f8665e706f6ebb4ae36fa63c46a32cd5Ian Rogers  if (state_.LoadRelaxed() != 0) {
333c604d731730b43231f63040c8db1d58304da0cf3Ian Rogers    LOG(shutting_down ? WARNING : FATAL) << "destroying mutex with owner: " << exclusive_owner_;
334c604d731730b43231f63040c8db1d58304da0cf3Ian Rogers  } else {
3358f1fa100ee037131976c616ec72a6608dccb51e2Andreas Gampe    if (exclusive_owner_ != 0) {
3368f1fa100ee037131976c616ec72a6608dccb51e2Andreas Gampe      LOG(shutting_down ? WARNING : FATAL) << "unexpectedly found an owner on unlocked mutex "
3378f1fa100ee037131976c616ec72a6608dccb51e2Andreas Gampe                                           << name_;
3388f1fa100ee037131976c616ec72a6608dccb51e2Andreas Gampe    }
3398f1fa100ee037131976c616ec72a6608dccb51e2Andreas Gampe    if (num_contenders_.LoadSequentiallyConsistent() != 0) {
3408f1fa100ee037131976c616ec72a6608dccb51e2Andreas Gampe      LOG(shutting_down ? WARNING : FATAL) << "unexpectedly found a contender on mutex " << name_;
341cef50f0487929f72183623bc2a5819cf3a63bff6Mathieu Chartier    }
342c604d731730b43231f63040c8db1d58304da0cf3Ian Rogers  }
343c604d731730b43231f63040c8db1d58304da0cf3Ian Rogers#else
344e62934d85fbc2d935afdad57eeade39ecbd7440aElliott Hughes  // We can't use CHECK_MUTEX_CALL here because on shutdown a suspended daemon thread
345e62934d85fbc2d935afdad57eeade39ecbd7440aElliott Hughes  // may still be using locks.
3466b3557571e798b60df995f978fa01c0ca1980dfdElliott Hughes  int rc = pthread_mutex_destroy(&mutex_);
3476b3557571e798b60df995f978fa01c0ca1980dfdElliott Hughes  if (rc != 0) {
3486b3557571e798b60df995f978fa01c0ca1980dfdElliott Hughes    errno = rc;
349b3bd5f07884f5a1f2b84224363b1372d7c28d447Elliott Hughes    // TODO: should we just not log at all if shutting down? this could be the logging mutex!
35050b35e2fd1a68cd1240e4a9d9f363e11764957d1Ian Rogers    MutexLock mu(Thread::Current(), *Locks::runtime_shutdown_lock_);
3516b3557571e798b60df995f978fa01c0ca1980dfdElliott Hughes    PLOG(shutting_down ? WARNING : FATAL) << "pthread_mutex_destroy failed for " << name_;
3526b3557571e798b60df995f978fa01c0ca1980dfdElliott Hughes  }
353c604d731730b43231f63040c8db1d58304da0cf3Ian Rogers#endif
3548daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes}
3558daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes
35681d425b0b232962441616f8b14f73620bffef5e5Ian Rogersvoid Mutex::ExclusiveLock(Thread* self) {
3572cebb24bfc3247d3e9be138a3350106737455918Mathieu Chartier  DCHECK(self == nullptr || self == Thread::Current());
35825fd14b87cced64a179dee885573113be5e11944Ian Rogers  if (kDebugLocking && !recursive_) {
35981d425b0b232962441616f8b14f73620bffef5e5Ian Rogers    AssertNotHeld(self);
36025fd14b87cced64a179dee885573113be5e11944Ian Rogers  }
36181d425b0b232962441616f8b14f73620bffef5e5Ian Rogers  if (!recursive_ || !IsExclusiveHeld(self)) {
362c604d731730b43231f63040c8db1d58304da0cf3Ian Rogers#if ART_USE_FUTEXES
363c604d731730b43231f63040c8db1d58304da0cf3Ian Rogers    bool done = false;
364c604d731730b43231f63040c8db1d58304da0cf3Ian Rogers    do {
365c7190697f8665e706f6ebb4ae36fa63c46a32cd5Ian Rogers      int32_t cur_state = state_.LoadRelaxed();
366967a0adf8b93a23d2a8fef82e06bd913db94ac19Hiroshi Yamauchi      if (LIKELY(cur_state == 0)) {
367c7190697f8665e706f6ebb4ae36fa63c46a32cd5Ian Rogers        // Change state from 0 to 1 and impose load/store ordering appropriate for lock acquisition.
368c7190697f8665e706f6ebb4ae36fa63c46a32cd5Ian Rogers        done = state_.CompareExchangeWeakAcquire(0 /* cur_state */, 1 /* new state */);
369c604d731730b43231f63040c8db1d58304da0cf3Ian Rogers      } else {
370c604d731730b43231f63040c8db1d58304da0cf3Ian Rogers        // Failed to acquire, hang up.
371b3733086ab415088b97fac20b3eea24433a7d2c5Hiroshi Yamauchi        ScopedContentionRecorder scr(this, SafeGetTid(self), GetExclusiveOwnerTid());
372b122a4bbed34ab22b4c1541ee25e5cf22f12a926Ian Rogers        num_contenders_++;
3732cebb24bfc3247d3e9be138a3350106737455918Mathieu Chartier        if (futex(state_.Address(), FUTEX_WAIT, 1, nullptr, nullptr, 0) != 0) {
3740de7985b29257bb60be511db774a4f0119a81f20Brian Carlstrom          // EAGAIN and EINTR both indicate a spurious failure, try again from the beginning.
3750de7985b29257bb60be511db774a4f0119a81f20Brian Carlstrom          // We don't use TEMP_FAILURE_RETRY so we can intentionally retry to acquire the lock.
3760de7985b29257bb60be511db774a4f0119a81f20Brian Carlstrom          if ((errno != EAGAIN) && (errno != EINTR)) {
377c604d731730b43231f63040c8db1d58304da0cf3Ian Rogers            PLOG(FATAL) << "futex wait failed for " << name_;
378c604d731730b43231f63040c8db1d58304da0cf3Ian Rogers          }
379c604d731730b43231f63040c8db1d58304da0cf3Ian Rogers        }
380b122a4bbed34ab22b4c1541ee25e5cf22f12a926Ian Rogers        num_contenders_--;
381c604d731730b43231f63040c8db1d58304da0cf3Ian Rogers      }
382df62950e7a32031b82360c407d46a37b94188fbbBrian Carlstrom    } while (!done);
383c7190697f8665e706f6ebb4ae36fa63c46a32cd5Ian Rogers    DCHECK_EQ(state_.LoadRelaxed(), 1);
384c604d731730b43231f63040c8db1d58304da0cf3Ian Rogers#else
38500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers    CHECK_MUTEX_CALL(pthread_mutex_lock, (&mutex_));
386c604d731730b43231f63040c8db1d58304da0cf3Ian Rogers#endif
387c5f17732d8144491c642776b6b48c85dfadf4b52Ian Rogers    DCHECK_EQ(exclusive_owner_, 0U);
388c5f17732d8144491c642776b6b48c85dfadf4b52Ian Rogers    exclusive_owner_ = SafeGetTid(self);
38981d425b0b232962441616f8b14f73620bffef5e5Ian Rogers    RegisterAsLocked(self);
39000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  }
39100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  recursion_count_++;
39225fd14b87cced64a179dee885573113be5e11944Ian Rogers  if (kDebugLocking) {
39325fd14b87cced64a179dee885573113be5e11944Ian Rogers    CHECK(recursion_count_ == 1 || recursive_) << "Unexpected recursion count on mutex: "
39425fd14b87cced64a179dee885573113be5e11944Ian Rogers        << name_ << " " << recursion_count_;
39581d425b0b232962441616f8b14f73620bffef5e5Ian Rogers    AssertHeld(self);
39625fd14b87cced64a179dee885573113be5e11944Ian Rogers  }
3978daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes}
3988daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes
39981d425b0b232962441616f8b14f73620bffef5e5Ian Rogersbool Mutex::ExclusiveTryLock(Thread* self) {
4002cebb24bfc3247d3e9be138a3350106737455918Mathieu Chartier  DCHECK(self == nullptr || self == Thread::Current());
40125fd14b87cced64a179dee885573113be5e11944Ian Rogers  if (kDebugLocking && !recursive_) {
40281d425b0b232962441616f8b14f73620bffef5e5Ian Rogers    AssertNotHeld(self);
40325fd14b87cced64a179dee885573113be5e11944Ian Rogers  }
40481d425b0b232962441616f8b14f73620bffef5e5Ian Rogers  if (!recursive_ || !IsExclusiveHeld(self)) {
405c604d731730b43231f63040c8db1d58304da0cf3Ian Rogers#if ART_USE_FUTEXES
406c604d731730b43231f63040c8db1d58304da0cf3Ian Rogers    bool done = false;
407c604d731730b43231f63040c8db1d58304da0cf3Ian Rogers    do {
408c7190697f8665e706f6ebb4ae36fa63c46a32cd5Ian Rogers      int32_t cur_state = state_.LoadRelaxed();
409c604d731730b43231f63040c8db1d58304da0cf3Ian Rogers      if (cur_state == 0) {
410c7190697f8665e706f6ebb4ae36fa63c46a32cd5Ian Rogers        // Change state from 0 to 1 and impose load/store ordering appropriate for lock acquisition.
411c7190697f8665e706f6ebb4ae36fa63c46a32cd5Ian Rogers        done = state_.CompareExchangeWeakAcquire(0 /* cur_state */, 1 /* new state */);
412c604d731730b43231f63040c8db1d58304da0cf3Ian Rogers      } else {
413c604d731730b43231f63040c8db1d58304da0cf3Ian Rogers        return false;
414c604d731730b43231f63040c8db1d58304da0cf3Ian Rogers      }
415df62950e7a32031b82360c407d46a37b94188fbbBrian Carlstrom    } while (!done);
416c7190697f8665e706f6ebb4ae36fa63c46a32cd5Ian Rogers    DCHECK_EQ(state_.LoadRelaxed(), 1);
417c604d731730b43231f63040c8db1d58304da0cf3Ian Rogers#else
41800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers    int result = pthread_mutex_trylock(&mutex_);
41900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers    if (result == EBUSY) {
42000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers      return false;
42100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers    }
42200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers    if (result != 0) {
42300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers      errno = result;
42400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers      PLOG(FATAL) << "pthread_mutex_trylock failed for " << name_;
42500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers    }
426c604d731730b43231f63040c8db1d58304da0cf3Ian Rogers#endif
427c5f17732d8144491c642776b6b48c85dfadf4b52Ian Rogers    DCHECK_EQ(exclusive_owner_, 0U);
428c5f17732d8144491c642776b6b48c85dfadf4b52Ian Rogers    exclusive_owner_ = SafeGetTid(self);
42981d425b0b232962441616f8b14f73620bffef5e5Ian Rogers    RegisterAsLocked(self);
4308daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes  }
43100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  recursion_count_++;
43225fd14b87cced64a179dee885573113be5e11944Ian Rogers  if (kDebugLocking) {
43325fd14b87cced64a179dee885573113be5e11944Ian Rogers    CHECK(recursion_count_ == 1 || recursive_) << "Unexpected recursion count on mutex: "
43425fd14b87cced64a179dee885573113be5e11944Ian Rogers        << name_ << " " << recursion_count_;
43581d425b0b232962441616f8b14f73620bffef5e5Ian Rogers    AssertHeld(self);
43625fd14b87cced64a179dee885573113be5e11944Ian Rogers  }
4378daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes  return true;
4388daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes}
4398daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes
44081d425b0b232962441616f8b14f73620bffef5e5Ian Rogersvoid Mutex::ExclusiveUnlock(Thread* self) {
441eb0a179508f3c0533dd7db86ec7ab9dfa3773256Mathieu Chartier  if (kIsDebugBuild && self != nullptr && self != Thread::Current()) {
442eb0a179508f3c0533dd7db86ec7ab9dfa3773256Mathieu Chartier    std::string name1 = "<null>";
443eb0a179508f3c0533dd7db86ec7ab9dfa3773256Mathieu Chartier    std::string name2 = "<null>";
444eb0a179508f3c0533dd7db86ec7ab9dfa3773256Mathieu Chartier    if (self != nullptr) {
445eb0a179508f3c0533dd7db86ec7ab9dfa3773256Mathieu Chartier      self->GetThreadName(name1);
446eb0a179508f3c0533dd7db86ec7ab9dfa3773256Mathieu Chartier    }
447eb0a179508f3c0533dd7db86ec7ab9dfa3773256Mathieu Chartier    if (Thread::Current() != nullptr) {
448eb0a179508f3c0533dd7db86ec7ab9dfa3773256Mathieu Chartier      Thread::Current()->GetThreadName(name2);
449eb0a179508f3c0533dd7db86ec7ab9dfa3773256Mathieu Chartier    }
4504c10110b144eafa47333dc9d30da9220a03e7c08Mathieu Chartier    LOG(FATAL) << GetName() << " level=" << level_ << " self=" << name1
4514c10110b144eafa47333dc9d30da9220a03e7c08Mathieu Chartier               << " Thread::Current()=" << name2;
452eb0a179508f3c0533dd7db86ec7ab9dfa3773256Mathieu Chartier  }
45381d425b0b232962441616f8b14f73620bffef5e5Ian Rogers  AssertHeld(self);
454c5f17732d8144491c642776b6b48c85dfadf4b52Ian Rogers  DCHECK_NE(exclusive_owner_, 0U);
45500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  recursion_count_--;
45600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  if (!recursive_ || recursion_count_ == 0) {
45725fd14b87cced64a179dee885573113be5e11944Ian Rogers    if (kDebugLocking) {
45825fd14b87cced64a179dee885573113be5e11944Ian Rogers      CHECK(recursion_count_ == 0 || recursive_) << "Unexpected recursion count on mutex: "
45925fd14b87cced64a179dee885573113be5e11944Ian Rogers          << name_ << " " << recursion_count_;
46025fd14b87cced64a179dee885573113be5e11944Ian Rogers    }
46181d425b0b232962441616f8b14f73620bffef5e5Ian Rogers    RegisterAsUnlocked(self);
462c604d731730b43231f63040c8db1d58304da0cf3Ian Rogers#if ART_USE_FUTEXES
463c5f17732d8144491c642776b6b48c85dfadf4b52Ian Rogers    bool done = false;
464c5f17732d8144491c642776b6b48c85dfadf4b52Ian Rogers    do {
465c7190697f8665e706f6ebb4ae36fa63c46a32cd5Ian Rogers      int32_t cur_state = state_.LoadRelaxed();
466c5f17732d8144491c642776b6b48c85dfadf4b52Ian Rogers      if (LIKELY(cur_state == 1)) {
467c5f17732d8144491c642776b6b48c85dfadf4b52Ian Rogers        // We're no longer the owner.
468c5f17732d8144491c642776b6b48c85dfadf4b52Ian Rogers        exclusive_owner_ = 0;
469c7190697f8665e706f6ebb4ae36fa63c46a32cd5Ian Rogers        // Change state to 0 and impose load/store ordering appropriate for lock release.
470c7190697f8665e706f6ebb4ae36fa63c46a32cd5Ian Rogers        // Note, the relaxed loads below musn't reorder before the CompareExchange.
471c7190697f8665e706f6ebb4ae36fa63c46a32cd5Ian Rogers        // TODO: the ordering here is non-trivial as state is split across 3 fields, fix by placing
472c7190697f8665e706f6ebb4ae36fa63c46a32cd5Ian Rogers        // a status bit into the state on contention.
473c7190697f8665e706f6ebb4ae36fa63c46a32cd5Ian Rogers        done =  state_.CompareExchangeWeakSequentiallyConsistent(cur_state, 0 /* new state */);
474c5f17732d8144491c642776b6b48c85dfadf4b52Ian Rogers        if (LIKELY(done)) {  // Spurious fail?
475c7190697f8665e706f6ebb4ae36fa63c46a32cd5Ian Rogers          // Wake a contender.
476c5f17732d8144491c642776b6b48c85dfadf4b52Ian Rogers          if (UNLIKELY(num_contenders_.LoadRelaxed() > 0)) {
4772cebb24bfc3247d3e9be138a3350106737455918Mathieu Chartier            futex(state_.Address(), FUTEX_WAKE, 1, nullptr, nullptr, 0);
478c5f17732d8144491c642776b6b48c85dfadf4b52Ian Rogers          }
479c604d731730b43231f63040c8db1d58304da0cf3Ian Rogers        }
480c4ee12e73fc844f28a9812a9141985cf05143a57Ian Rogers      } else {
481c5f17732d8144491c642776b6b48c85dfadf4b52Ian Rogers        // Logging acquires the logging lock, avoid infinite recursion in that case.
482c5f17732d8144491c642776b6b48c85dfadf4b52Ian Rogers        if (this != Locks::logging_lock_) {
483c5f17732d8144491c642776b6b48c85dfadf4b52Ian Rogers          LOG(FATAL) << "Unexpected state_ in unlock " << cur_state << " for " << name_;
484c5f17732d8144491c642776b6b48c85dfadf4b52Ian Rogers        } else {
485c7dd295a4e0cc1d15c0c96088e55a85389bade74Ian Rogers          LogMessage::LogLine(__FILE__, __LINE__, INTERNAL_FATAL,
486c7dd295a4e0cc1d15c0c96088e55a85389bade74Ian Rogers                              StringPrintf("Unexpected state_ %d in unlock for %s",
487c7dd295a4e0cc1d15c0c96088e55a85389bade74Ian Rogers                                           cur_state, name_).c_str());
488c5f17732d8144491c642776b6b48c85dfadf4b52Ian Rogers          _exit(1);
489c5f17732d8144491c642776b6b48c85dfadf4b52Ian Rogers        }
490c4ee12e73fc844f28a9812a9141985cf05143a57Ian Rogers      }
491c5f17732d8144491c642776b6b48c85dfadf4b52Ian Rogers    } while (!done);
492c604d731730b43231f63040c8db1d58304da0cf3Ian Rogers#else
493c5f17732d8144491c642776b6b48c85dfadf4b52Ian Rogers    exclusive_owner_ = 0;
49400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers    CHECK_MUTEX_CALL(pthread_mutex_unlock, (&mutex_));
495c604d731730b43231f63040c8db1d58304da0cf3Ian Rogers#endif
49600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  }
497f1498437b0d6beb9f4f91980b98cbeb0b5c773ceElliott Hughes}
498f1498437b0d6beb9f4f91980b98cbeb0b5c773ceElliott Hughes
49956edc432fa914f7ccfa87ce443e64f5ef475666dIan Rogersvoid Mutex::Dump(std::ostream& os) const {
50056edc432fa914f7ccfa87ce443e64f5ef475666dIan Rogers  os << (recursive_ ? "recursive " : "non-recursive ")
50156edc432fa914f7ccfa87ce443e64f5ef475666dIan Rogers      << name_
50256edc432fa914f7ccfa87ce443e64f5ef475666dIan Rogers      << " level=" << static_cast<int>(level_)
50356edc432fa914f7ccfa87ce443e64f5ef475666dIan Rogers      << " rec=" << recursion_count_
50456edc432fa914f7ccfa87ce443e64f5ef475666dIan Rogers      << " owner=" << GetExclusiveOwnerTid() << " ";
50556edc432fa914f7ccfa87ce443e64f5ef475666dIan Rogers  DumpContention(os);
50601ae5808367e641a983e3f8bb82b3e0d364cd03eIan Rogers}
50701ae5808367e641a983e3f8bb82b3e0d364cd03eIan Rogers
50801ae5808367e641a983e3f8bb82b3e0d364cd03eIan Rogersstd::ostream& operator<<(std::ostream& os, const Mutex& mu) {
50956edc432fa914f7ccfa87ce443e64f5ef475666dIan Rogers  mu.Dump(os);
51056edc432fa914f7ccfa87ce443e64f5ef475666dIan Rogers  return os;
51101ae5808367e641a983e3f8bb82b3e0d364cd03eIan Rogers}
51201ae5808367e641a983e3f8bb82b3e0d364cd03eIan Rogers
51302c8cc6d1312a2b55533f02f6369dc7c94672f90Brian CarlstromReaderWriterMutex::ReaderWriterMutex(const char* name, LockLevel level)
51402c8cc6d1312a2b55533f02f6369dc7c94672f90Brian Carlstrom    : BaseMutex(name, level)
51581d425b0b232962441616f8b14f73620bffef5e5Ian Rogers#if ART_USE_FUTEXES
516c5f17732d8144491c642776b6b48c85dfadf4b52Ian Rogers    , state_(0), num_pending_readers_(0), num_pending_writers_(0)
51781d425b0b232962441616f8b14f73620bffef5e5Ian Rogers#endif
5187934ac288acfb2552bb0b06ec1f61e5820d924a4Brian Carlstrom{  // NOLINT(whitespace/braces)
51981d425b0b232962441616f8b14f73620bffef5e5Ian Rogers#if !ART_USE_FUTEXES
520c5f17732d8144491c642776b6b48c85dfadf4b52Ian Rogers  CHECK_MUTEX_CALL(pthread_rwlock_init, (&rwlock_, nullptr));
52181d425b0b232962441616f8b14f73620bffef5e5Ian Rogers#endif
522c5f17732d8144491c642776b6b48c85dfadf4b52Ian Rogers  exclusive_owner_ = 0;
52300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers}
52400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers
52500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan RogersReaderWriterMutex::~ReaderWriterMutex() {
52681d425b0b232962441616f8b14f73620bffef5e5Ian Rogers#if ART_USE_FUTEXES
527c7190697f8665e706f6ebb4ae36fa63c46a32cd5Ian Rogers  CHECK_EQ(state_.LoadRelaxed(), 0);
52881d425b0b232962441616f8b14f73620bffef5e5Ian Rogers  CHECK_EQ(exclusive_owner_, 0U);
529c7190697f8665e706f6ebb4ae36fa63c46a32cd5Ian Rogers  CHECK_EQ(num_pending_readers_.LoadRelaxed(), 0);
5303e5cf305db800b2989ad57b7cde8fb3cc9fa1b9eIan Rogers  CHECK_EQ(num_pending_writers_.LoadRelaxed(), 0);
53181d425b0b232962441616f8b14f73620bffef5e5Ian Rogers#else
53200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  // We can't use CHECK_MUTEX_CALL here because on shutdown a suspended daemon thread
53300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  // may still be using locks.
53400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  int rc = pthread_rwlock_destroy(&rwlock_);
53500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  if (rc != 0) {
53600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers    errno = rc;
53700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers    // TODO: should we just not log at all if shutting down? this could be the logging mutex!
53850b35e2fd1a68cd1240e4a9d9f363e11764957d1Ian Rogers    MutexLock mu(Thread::Current(), *Locks::runtime_shutdown_lock_);
539120f1c74a9768e958377b6c97897511b27ae58c8Ian Rogers    Runtime* runtime = Runtime::Current();
5402cebb24bfc3247d3e9be138a3350106737455918Mathieu Chartier    bool shutting_down = runtime == nullptr || runtime->IsShuttingDownLocked();
541120f1c74a9768e958377b6c97897511b27ae58c8Ian Rogers    PLOG(shutting_down ? WARNING : FATAL) << "pthread_rwlock_destroy failed for " << name_;
54200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  }
54381d425b0b232962441616f8b14f73620bffef5e5Ian Rogers#endif
54400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers}
54500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers
54681d425b0b232962441616f8b14f73620bffef5e5Ian Rogersvoid ReaderWriterMutex::ExclusiveLock(Thread* self) {
5472cebb24bfc3247d3e9be138a3350106737455918Mathieu Chartier  DCHECK(self == nullptr || self == Thread::Current());
54881d425b0b232962441616f8b14f73620bffef5e5Ian Rogers  AssertNotExclusiveHeld(self);
54981d425b0b232962441616f8b14f73620bffef5e5Ian Rogers#if ART_USE_FUTEXES
55081d425b0b232962441616f8b14f73620bffef5e5Ian Rogers  bool done = false;
55181d425b0b232962441616f8b14f73620bffef5e5Ian Rogers  do {
552c7190697f8665e706f6ebb4ae36fa63c46a32cd5Ian Rogers    int32_t cur_state = state_.LoadRelaxed();
553967a0adf8b93a23d2a8fef82e06bd913db94ac19Hiroshi Yamauchi    if (LIKELY(cur_state == 0)) {
554c7190697f8665e706f6ebb4ae36fa63c46a32cd5Ian Rogers      // Change state from 0 to -1 and impose load/store ordering appropriate for lock acquisition.
555c7190697f8665e706f6ebb4ae36fa63c46a32cd5Ian Rogers      done =  state_.CompareExchangeWeakAcquire(0 /* cur_state*/, -1 /* new state */);
55681d425b0b232962441616f8b14f73620bffef5e5Ian Rogers    } else {
55781d425b0b232962441616f8b14f73620bffef5e5Ian Rogers      // Failed to acquire, hang up.
558b3733086ab415088b97fac20b3eea24433a7d2c5Hiroshi Yamauchi      ScopedContentionRecorder scr(this, SafeGetTid(self), GetExclusiveOwnerTid());
559c7190697f8665e706f6ebb4ae36fa63c46a32cd5Ian Rogers      ++num_pending_writers_;
5602cebb24bfc3247d3e9be138a3350106737455918Mathieu Chartier      if (futex(state_.Address(), FUTEX_WAIT, cur_state, nullptr, nullptr, 0) != 0) {
5610de7985b29257bb60be511db774a4f0119a81f20Brian Carlstrom        // EAGAIN and EINTR both indicate a spurious failure, try again from the beginning.
5620de7985b29257bb60be511db774a4f0119a81f20Brian Carlstrom        // We don't use TEMP_FAILURE_RETRY so we can intentionally retry to acquire the lock.
5630de7985b29257bb60be511db774a4f0119a81f20Brian Carlstrom        if ((errno != EAGAIN) && (errno != EINTR)) {
56481d425b0b232962441616f8b14f73620bffef5e5Ian Rogers          PLOG(FATAL) << "futex wait failed for " << name_;
56581d425b0b232962441616f8b14f73620bffef5e5Ian Rogers        }
56681d425b0b232962441616f8b14f73620bffef5e5Ian Rogers      }
567c7190697f8665e706f6ebb4ae36fa63c46a32cd5Ian Rogers      --num_pending_writers_;
56881d425b0b232962441616f8b14f73620bffef5e5Ian Rogers    }
569df62950e7a32031b82360c407d46a37b94188fbbBrian Carlstrom  } while (!done);
570c7190697f8665e706f6ebb4ae36fa63c46a32cd5Ian Rogers  DCHECK_EQ(state_.LoadRelaxed(), -1);
57181d425b0b232962441616f8b14f73620bffef5e5Ian Rogers#else
57200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  CHECK_MUTEX_CALL(pthread_rwlock_wrlock, (&rwlock_));
57381d425b0b232962441616f8b14f73620bffef5e5Ian Rogers#endif
574c5f17732d8144491c642776b6b48c85dfadf4b52Ian Rogers  DCHECK_EQ(exclusive_owner_, 0U);
575c5f17732d8144491c642776b6b48c85dfadf4b52Ian Rogers  exclusive_owner_ = SafeGetTid(self);
57681d425b0b232962441616f8b14f73620bffef5e5Ian Rogers  RegisterAsLocked(self);
57781d425b0b232962441616f8b14f73620bffef5e5Ian Rogers  AssertExclusiveHeld(self);
57800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers}
57900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers
58081d425b0b232962441616f8b14f73620bffef5e5Ian Rogersvoid ReaderWriterMutex::ExclusiveUnlock(Thread* self) {
5812cebb24bfc3247d3e9be138a3350106737455918Mathieu Chartier  DCHECK(self == nullptr || self == Thread::Current());
58281d425b0b232962441616f8b14f73620bffef5e5Ian Rogers  AssertExclusiveHeld(self);
58381d425b0b232962441616f8b14f73620bffef5e5Ian Rogers  RegisterAsUnlocked(self);
584c5f17732d8144491c642776b6b48c85dfadf4b52Ian Rogers  DCHECK_NE(exclusive_owner_, 0U);
58581d425b0b232962441616f8b14f73620bffef5e5Ian Rogers#if ART_USE_FUTEXES
58681d425b0b232962441616f8b14f73620bffef5e5Ian Rogers  bool done = false;
58781d425b0b232962441616f8b14f73620bffef5e5Ian Rogers  do {
588c7190697f8665e706f6ebb4ae36fa63c46a32cd5Ian Rogers    int32_t cur_state = state_.LoadRelaxed();
589967a0adf8b93a23d2a8fef82e06bd913db94ac19Hiroshi Yamauchi    if (LIKELY(cur_state == -1)) {
59081d425b0b232962441616f8b14f73620bffef5e5Ian Rogers      // We're no longer the owner.
59181d425b0b232962441616f8b14f73620bffef5e5Ian Rogers      exclusive_owner_ = 0;
592c7190697f8665e706f6ebb4ae36fa63c46a32cd5Ian Rogers      // Change state from -1 to 0 and impose load/store ordering appropriate for lock release.
593c7190697f8665e706f6ebb4ae36fa63c46a32cd5Ian Rogers      // Note, the relaxed loads below musn't reorder before the CompareExchange.
594c7190697f8665e706f6ebb4ae36fa63c46a32cd5Ian Rogers      // TODO: the ordering here is non-trivial as state is split across 3 fields, fix by placing
595c7190697f8665e706f6ebb4ae36fa63c46a32cd5Ian Rogers      // a status bit into the state on contention.
596c7190697f8665e706f6ebb4ae36fa63c46a32cd5Ian Rogers      done =  state_.CompareExchangeWeakSequentiallyConsistent(-1 /* cur_state*/, 0 /* new state */);
597c7190697f8665e706f6ebb4ae36fa63c46a32cd5Ian Rogers      if (LIKELY(done)) {  // Weak CAS may fail spuriously.
59881d425b0b232962441616f8b14f73620bffef5e5Ian Rogers        // Wake any waiters.
599c7190697f8665e706f6ebb4ae36fa63c46a32cd5Ian Rogers        if (UNLIKELY(num_pending_readers_.LoadRelaxed() > 0 ||
600c7190697f8665e706f6ebb4ae36fa63c46a32cd5Ian Rogers                     num_pending_writers_.LoadRelaxed() > 0)) {
6012cebb24bfc3247d3e9be138a3350106737455918Mathieu Chartier          futex(state_.Address(), FUTEX_WAKE, -1, nullptr, nullptr, 0);
60281d425b0b232962441616f8b14f73620bffef5e5Ian Rogers        }
60381d425b0b232962441616f8b14f73620bffef5e5Ian Rogers      }
60481d425b0b232962441616f8b14f73620bffef5e5Ian Rogers    } else {
60581d425b0b232962441616f8b14f73620bffef5e5Ian Rogers      LOG(FATAL) << "Unexpected state_:" << cur_state << " for " << name_;
60681d425b0b232962441616f8b14f73620bffef5e5Ian Rogers    }
607df62950e7a32031b82360c407d46a37b94188fbbBrian Carlstrom  } while (!done);
60881d425b0b232962441616f8b14f73620bffef5e5Ian Rogers#else
609c5f17732d8144491c642776b6b48c85dfadf4b52Ian Rogers  exclusive_owner_ = 0;
61000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  CHECK_MUTEX_CALL(pthread_rwlock_unlock, (&rwlock_));
61181d425b0b232962441616f8b14f73620bffef5e5Ian Rogers#endif
61200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers}
61300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers
61466aee5cd571cf4739d2735769304202ea5051fb8Ian Rogers#if HAVE_TIMED_RWLOCK
615c604d731730b43231f63040c8db1d58304da0cf3Ian Rogersbool ReaderWriterMutex::ExclusiveLockWithTimeout(Thread* self, int64_t ms, int32_t ns) {
6162cebb24bfc3247d3e9be138a3350106737455918Mathieu Chartier  DCHECK(self == nullptr || self == Thread::Current());
61781d425b0b232962441616f8b14f73620bffef5e5Ian Rogers#if ART_USE_FUTEXES
61881d425b0b232962441616f8b14f73620bffef5e5Ian Rogers  bool done = false;
619c604d731730b43231f63040c8db1d58304da0cf3Ian Rogers  timespec end_abs_ts;
620071e48ecfc95b1c67b07c975190d51f646ac4276tony.ys_liu  InitTimeSpec(true, CLOCK_MONOTONIC, ms, ns, &end_abs_ts);
62181d425b0b232962441616f8b14f73620bffef5e5Ian Rogers  do {
622c7190697f8665e706f6ebb4ae36fa63c46a32cd5Ian Rogers    int32_t cur_state = state_.LoadRelaxed();
62381d425b0b232962441616f8b14f73620bffef5e5Ian Rogers    if (cur_state == 0) {
624c7190697f8665e706f6ebb4ae36fa63c46a32cd5Ian Rogers      // Change state from 0 to -1 and impose load/store ordering appropriate for lock acquisition.
625c7190697f8665e706f6ebb4ae36fa63c46a32cd5Ian Rogers      done =  state_.CompareExchangeWeakAcquire(0 /* cur_state */, -1 /* new state */);
62681d425b0b232962441616f8b14f73620bffef5e5Ian Rogers    } else {
62781d425b0b232962441616f8b14f73620bffef5e5Ian Rogers      // Failed to acquire, hang up.
628c604d731730b43231f63040c8db1d58304da0cf3Ian Rogers      timespec now_abs_ts;
629071e48ecfc95b1c67b07c975190d51f646ac4276tony.ys_liu      InitTimeSpec(true, CLOCK_MONOTONIC, 0, 0, &now_abs_ts);
630c604d731730b43231f63040c8db1d58304da0cf3Ian Rogers      timespec rel_ts;
631c604d731730b43231f63040c8db1d58304da0cf3Ian Rogers      if (ComputeRelativeTimeSpec(&rel_ts, end_abs_ts, now_abs_ts)) {
632c604d731730b43231f63040c8db1d58304da0cf3Ian Rogers        return false;  // Timed out.
633c604d731730b43231f63040c8db1d58304da0cf3Ian Rogers      }
634b3733086ab415088b97fac20b3eea24433a7d2c5Hiroshi Yamauchi      ScopedContentionRecorder scr(this, SafeGetTid(self), GetExclusiveOwnerTid());
635c7190697f8665e706f6ebb4ae36fa63c46a32cd5Ian Rogers      ++num_pending_writers_;
6362cebb24bfc3247d3e9be138a3350106737455918Mathieu Chartier      if (futex(state_.Address(), FUTEX_WAIT, cur_state, &rel_ts, nullptr, 0) != 0) {
63781d425b0b232962441616f8b14f73620bffef5e5Ian Rogers        if (errno == ETIMEDOUT) {
638c7190697f8665e706f6ebb4ae36fa63c46a32cd5Ian Rogers          --num_pending_writers_;
639c604d731730b43231f63040c8db1d58304da0cf3Ian Rogers          return false;  // Timed out.
6400de7985b29257bb60be511db774a4f0119a81f20Brian Carlstrom        } else if ((errno != EAGAIN) && (errno != EINTR)) {
6410de7985b29257bb60be511db774a4f0119a81f20Brian Carlstrom          // EAGAIN and EINTR both indicate a spurious failure,
6420de7985b29257bb60be511db774a4f0119a81f20Brian Carlstrom          // recompute the relative time out from now and try again.
6430de7985b29257bb60be511db774a4f0119a81f20Brian Carlstrom          // We don't use TEMP_FAILURE_RETRY so we can recompute rel_ts;
64481d425b0b232962441616f8b14f73620bffef5e5Ian Rogers          PLOG(FATAL) << "timed futex wait failed for " << name_;
64581d425b0b232962441616f8b14f73620bffef5e5Ian Rogers        }
64681d425b0b232962441616f8b14f73620bffef5e5Ian Rogers      }
647c7190697f8665e706f6ebb4ae36fa63c46a32cd5Ian Rogers      --num_pending_writers_;
64881d425b0b232962441616f8b14f73620bffef5e5Ian Rogers    }
649df62950e7a32031b82360c407d46a37b94188fbbBrian Carlstrom  } while (!done);
65081d425b0b232962441616f8b14f73620bffef5e5Ian Rogers#else
651c604d731730b43231f63040c8db1d58304da0cf3Ian Rogers  timespec ts;
652bcc2926b9721f94c17ed98fae5264cc98f0e066fBrian Carlstrom  InitTimeSpec(true, CLOCK_REALTIME, ms, ns, &ts);
653c604d731730b43231f63040c8db1d58304da0cf3Ian Rogers  int result = pthread_rwlock_timedwrlock(&rwlock_, &ts);
65400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  if (result == ETIMEDOUT) {
65500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers    return false;
656cd74c4b3a6893c876c6e03fd99a1264249653d80Brian Carlstrom  }
65700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  if (result != 0) {
65800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers    errno = result;
659a5acfd318d46c4720bb9b25181021ee7471b6be9Ian Rogers    PLOG(FATAL) << "pthread_rwlock_timedwrlock failed for " << name_;
66000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  }
66181d425b0b232962441616f8b14f73620bffef5e5Ian Rogers#endif
662c5f17732d8144491c642776b6b48c85dfadf4b52Ian Rogers  exclusive_owner_ = SafeGetTid(self);
66381d425b0b232962441616f8b14f73620bffef5e5Ian Rogers  RegisterAsLocked(self);
66481d425b0b232962441616f8b14f73620bffef5e5Ian Rogers  AssertSharedHeld(self);
66500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  return true;
66600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers}
66766aee5cd571cf4739d2735769304202ea5051fb8Ian Rogers#endif
66800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers
66951d212ef31945743abe8a469707aaa25bab95357Ian Rogers#if ART_USE_FUTEXES
670cf7f19135f0e273f7b0136315633c2abfc715343Ian Rogersvoid ReaderWriterMutex::HandleSharedLockContention(Thread* self, int32_t cur_state) {
671cf7f19135f0e273f7b0136315633c2abfc715343Ian Rogers  // Owner holds it exclusively, hang up.
672cf7f19135f0e273f7b0136315633c2abfc715343Ian Rogers  ScopedContentionRecorder scr(this, GetExclusiveOwnerTid(), SafeGetTid(self));
673cf7f19135f0e273f7b0136315633c2abfc715343Ian Rogers  ++num_pending_readers_;
6742cebb24bfc3247d3e9be138a3350106737455918Mathieu Chartier  if (futex(state_.Address(), FUTEX_WAIT, cur_state, nullptr, nullptr, 0) != 0) {
675cf7f19135f0e273f7b0136315633c2abfc715343Ian Rogers    if (errno != EAGAIN) {
676cf7f19135f0e273f7b0136315633c2abfc715343Ian Rogers      PLOG(FATAL) << "futex wait failed for " << name_;
677cf7f19135f0e273f7b0136315633c2abfc715343Ian Rogers    }
678cf7f19135f0e273f7b0136315633c2abfc715343Ian Rogers  }
679cf7f19135f0e273f7b0136315633c2abfc715343Ian Rogers  --num_pending_readers_;
680cf7f19135f0e273f7b0136315633c2abfc715343Ian Rogers}
68151d212ef31945743abe8a469707aaa25bab95357Ian Rogers#endif
682cf7f19135f0e273f7b0136315633c2abfc715343Ian Rogers
68381d425b0b232962441616f8b14f73620bffef5e5Ian Rogersbool ReaderWriterMutex::SharedTryLock(Thread* self) {
6842cebb24bfc3247d3e9be138a3350106737455918Mathieu Chartier  DCHECK(self == nullptr || self == Thread::Current());
68581d425b0b232962441616f8b14f73620bffef5e5Ian Rogers#if ART_USE_FUTEXES
68681d425b0b232962441616f8b14f73620bffef5e5Ian Rogers  bool done = false;
68781d425b0b232962441616f8b14f73620bffef5e5Ian Rogers  do {
688c7190697f8665e706f6ebb4ae36fa63c46a32cd5Ian Rogers    int32_t cur_state = state_.LoadRelaxed();
68981d425b0b232962441616f8b14f73620bffef5e5Ian Rogers    if (cur_state >= 0) {
690c7190697f8665e706f6ebb4ae36fa63c46a32cd5Ian Rogers      // Add as an extra reader and impose load/store ordering appropriate for lock acquisition.
691c7190697f8665e706f6ebb4ae36fa63c46a32cd5Ian Rogers      done =  state_.CompareExchangeWeakAcquire(cur_state, cur_state + 1);
69281d425b0b232962441616f8b14f73620bffef5e5Ian Rogers    } else {
69381d425b0b232962441616f8b14f73620bffef5e5Ian Rogers      // Owner holds it exclusively.
69481d425b0b232962441616f8b14f73620bffef5e5Ian Rogers      return false;
69581d425b0b232962441616f8b14f73620bffef5e5Ian Rogers    }
696df62950e7a32031b82360c407d46a37b94188fbbBrian Carlstrom  } while (!done);
69781d425b0b232962441616f8b14f73620bffef5e5Ian Rogers#else
69800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  int result = pthread_rwlock_tryrdlock(&rwlock_);
69900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  if (result == EBUSY) {
70000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers    return false;
70100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  }
70200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  if (result != 0) {
70300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers    errno = result;
70400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers    PLOG(FATAL) << "pthread_mutex_trylock failed for " << name_;
70500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  }
70681d425b0b232962441616f8b14f73620bffef5e5Ian Rogers#endif
70781d425b0b232962441616f8b14f73620bffef5e5Ian Rogers  RegisterAsLocked(self);
70881d425b0b232962441616f8b14f73620bffef5e5Ian Rogers  AssertSharedHeld(self);
70900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  return true;
71000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers}
71100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers
71281d425b0b232962441616f8b14f73620bffef5e5Ian Rogersbool ReaderWriterMutex::IsSharedHeld(const Thread* self) const {
7132cebb24bfc3247d3e9be138a3350106737455918Mathieu Chartier  DCHECK(self == nullptr || self == Thread::Current());
71400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  bool result;
7152cebb24bfc3247d3e9be138a3350106737455918Mathieu Chartier  if (UNLIKELY(self == nullptr)) {  // Handle unattached threads.
71601ae5808367e641a983e3f8bb82b3e0d364cd03eIan Rogers    result = IsExclusiveHeld(self);  // TODO: a better best effort here.
71700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  } else {
71800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers    result = (self->GetHeldMutex(level_) == this);
71900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  }
72000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  return result;
72100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers}
72200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers
72356edc432fa914f7ccfa87ce443e64f5ef475666dIan Rogersvoid ReaderWriterMutex::Dump(std::ostream& os) const {
72456edc432fa914f7ccfa87ce443e64f5ef475666dIan Rogers  os << name_
72556edc432fa914f7ccfa87ce443e64f5ef475666dIan Rogers      << " level=" << static_cast<int>(level_)
7265869a2c27ee0dbd7b420614c76ff14a706f0c5fbMathieu Chartier      << " owner=" << GetExclusiveOwnerTid()
7275869a2c27ee0dbd7b420614c76ff14a706f0c5fbMathieu Chartier#if ART_USE_FUTEXES
7285869a2c27ee0dbd7b420614c76ff14a706f0c5fbMathieu Chartier      << " state=" << state_.LoadSequentiallyConsistent()
7295869a2c27ee0dbd7b420614c76ff14a706f0c5fbMathieu Chartier      << " num_pending_writers=" << num_pending_writers_.LoadSequentiallyConsistent()
7305869a2c27ee0dbd7b420614c76ff14a706f0c5fbMathieu Chartier      << " num_pending_readers=" << num_pending_readers_.LoadSequentiallyConsistent()
7315869a2c27ee0dbd7b420614c76ff14a706f0c5fbMathieu Chartier#endif
7325869a2c27ee0dbd7b420614c76ff14a706f0c5fbMathieu Chartier      << " ";
73356edc432fa914f7ccfa87ce443e64f5ef475666dIan Rogers  DumpContention(os);
73401ae5808367e641a983e3f8bb82b3e0d364cd03eIan Rogers}
73501ae5808367e641a983e3f8bb82b3e0d364cd03eIan Rogers
73601ae5808367e641a983e3f8bb82b3e0d364cd03eIan Rogersstd::ostream& operator<<(std::ostream& os, const ReaderWriterMutex& mu) {
73756edc432fa914f7ccfa87ce443e64f5ef475666dIan Rogers  mu.Dump(os);
73856edc432fa914f7ccfa87ce443e64f5ef475666dIan Rogers  return os;
73901ae5808367e641a983e3f8bb82b3e0d364cd03eIan Rogers}
74001ae5808367e641a983e3f8bb82b3e0d364cd03eIan Rogers
74123055dc5d7a90c4a12e259fd0ed7cd4d04d89182Ian RogersConditionVariable::ConditionVariable(const char* name, Mutex& guard)
742c604d731730b43231f63040c8db1d58304da0cf3Ian Rogers    : name_(name), guard_(guard) {
743c604d731730b43231f63040c8db1d58304da0cf3Ian Rogers#if ART_USE_FUTEXES
7443e5cf305db800b2989ad57b7cde8fb3cc9fa1b9eIan Rogers  DCHECK_EQ(0, sequence_.LoadRelaxed());
745c604d731730b43231f63040c8db1d58304da0cf3Ian Rogers  num_waiters_ = 0;
746c604d731730b43231f63040c8db1d58304da0cf3Ian Rogers#else
74751b71028661092e8860cca4f8ca79848e03cdc2cNarayan Kamath  pthread_condattr_t cond_attrs;
748c5f17732d8144491c642776b6b48c85dfadf4b52Ian Rogers  CHECK_MUTEX_CALL(pthread_condattr_init, (&cond_attrs));
74951b71028661092e8860cca4f8ca79848e03cdc2cNarayan Kamath#if !defined(__APPLE__)
75051b71028661092e8860cca4f8ca79848e03cdc2cNarayan Kamath  // Apple doesn't have CLOCK_MONOTONIC or pthread_condattr_setclock.
75151d212ef31945743abe8a469707aaa25bab95357Ian Rogers  CHECK_MUTEX_CALL(pthread_condattr_setclock, (&cond_attrs, CLOCK_MONOTONIC));
75251b71028661092e8860cca4f8ca79848e03cdc2cNarayan Kamath#endif
75351b71028661092e8860cca4f8ca79848e03cdc2cNarayan Kamath  CHECK_MUTEX_CALL(pthread_cond_init, (&cond_, &cond_attrs));
754c604d731730b43231f63040c8db1d58304da0cf3Ian Rogers#endif
7555f79133a435ebcb20000370d56046fe01201dd80Elliott Hughes}
7565f79133a435ebcb20000370d56046fe01201dd80Elliott Hughes
7575f79133a435ebcb20000370d56046fe01201dd80Elliott HughesConditionVariable::~ConditionVariable() {
7585bd97c483c1de1eb97afe76123b1b9ab53095edfIan Rogers#if ART_USE_FUTEXES
7595bd97c483c1de1eb97afe76123b1b9ab53095edfIan Rogers  if (num_waiters_!= 0) {
7605bd97c483c1de1eb97afe76123b1b9ab53095edfIan Rogers    Runtime* runtime = Runtime::Current();
761590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier    bool shutting_down = runtime == nullptr || runtime->IsShuttingDown(Thread::Current());
762d45f201e9bd43490e30a35710865789b8d70e249Ian Rogers    LOG(shutting_down ? WARNING : FATAL) << "ConditionVariable::~ConditionVariable for " << name_
763d45f201e9bd43490e30a35710865789b8d70e249Ian Rogers        << " called with " << num_waiters_ << " waiters.";
7645bd97c483c1de1eb97afe76123b1b9ab53095edfIan Rogers  }
7655bd97c483c1de1eb97afe76123b1b9ab53095edfIan Rogers#else
766e62934d85fbc2d935afdad57eeade39ecbd7440aElliott Hughes  // We can't use CHECK_MUTEX_CALL here because on shutdown a suspended daemon thread
767e62934d85fbc2d935afdad57eeade39ecbd7440aElliott Hughes  // may still be using condition variables.
768e62934d85fbc2d935afdad57eeade39ecbd7440aElliott Hughes  int rc = pthread_cond_destroy(&cond_);
769e62934d85fbc2d935afdad57eeade39ecbd7440aElliott Hughes  if (rc != 0) {
770e62934d85fbc2d935afdad57eeade39ecbd7440aElliott Hughes    errno = rc;
77150b35e2fd1a68cd1240e4a9d9f363e11764957d1Ian Rogers    MutexLock mu(Thread::Current(), *Locks::runtime_shutdown_lock_);
772120f1c74a9768e958377b6c97897511b27ae58c8Ian Rogers    Runtime* runtime = Runtime::Current();
7732cebb24bfc3247d3e9be138a3350106737455918Mathieu Chartier    bool shutting_down = (runtime == nullptr) || runtime->IsShuttingDownLocked();
774e62934d85fbc2d935afdad57eeade39ecbd7440aElliott Hughes    PLOG(shutting_down ? WARNING : FATAL) << "pthread_cond_destroy failed for " << name_;
775e62934d85fbc2d935afdad57eeade39ecbd7440aElliott Hughes  }
776c604d731730b43231f63040c8db1d58304da0cf3Ian Rogers#endif
7775f79133a435ebcb20000370d56046fe01201dd80Elliott Hughes}
7785f79133a435ebcb20000370d56046fe01201dd80Elliott Hughes
779c604d731730b43231f63040c8db1d58304da0cf3Ian Rogersvoid ConditionVariable::Broadcast(Thread* self) {
7802cebb24bfc3247d3e9be138a3350106737455918Mathieu Chartier  DCHECK(self == nullptr || self == Thread::Current());
781c604d731730b43231f63040c8db1d58304da0cf3Ian Rogers  // TODO: enable below, there's a race in thread creation that causes false failures currently.
782c604d731730b43231f63040c8db1d58304da0cf3Ian Rogers  // guard_.AssertExclusiveHeld(self);
783e46cd75f182a3d738c5e2ef3cc90b2f0b1de56eeMathieu Chartier  DCHECK_EQ(guard_.GetExclusiveOwnerTid(), SafeGetTid(self));
784c604d731730b43231f63040c8db1d58304da0cf3Ian Rogers#if ART_USE_FUTEXES
785d45f201e9bd43490e30a35710865789b8d70e249Ian Rogers  if (num_waiters_ > 0) {
786b122a4bbed34ab22b4c1541ee25e5cf22f12a926Ian Rogers    sequence_++;  // Indicate the broadcast occurred.
787c604d731730b43231f63040c8db1d58304da0cf3Ian Rogers    bool done = false;
788c604d731730b43231f63040c8db1d58304da0cf3Ian Rogers    do {
7893e5cf305db800b2989ad57b7cde8fb3cc9fa1b9eIan Rogers      int32_t cur_sequence = sequence_.LoadRelaxed();
790d45f201e9bd43490e30a35710865789b8d70e249Ian Rogers      // Requeue waiters onto mutex. The waiter holds the contender count on the mutex high ensuring
791d45f201e9bd43490e30a35710865789b8d70e249Ian Rogers      // mutex unlocks will awaken the requeued waiter thread.
792b122a4bbed34ab22b4c1541ee25e5cf22f12a926Ian Rogers      done = futex(sequence_.Address(), FUTEX_CMP_REQUEUE, 0,
7935bd97c483c1de1eb97afe76123b1b9ab53095edfIan Rogers                   reinterpret_cast<const timespec*>(std::numeric_limits<int32_t>::max()),
794c7190697f8665e706f6ebb4ae36fa63c46a32cd5Ian Rogers                   guard_.state_.Address(), cur_sequence) != -1;
7955bd97c483c1de1eb97afe76123b1b9ab53095edfIan Rogers      if (!done) {
7965bd97c483c1de1eb97afe76123b1b9ab53095edfIan Rogers        if (errno != EAGAIN) {
7975bd97c483c1de1eb97afe76123b1b9ab53095edfIan Rogers          PLOG(FATAL) << "futex cmp requeue failed for " << name_;
7985bd97c483c1de1eb97afe76123b1b9ab53095edfIan Rogers        }
7995bd97c483c1de1eb97afe76123b1b9ab53095edfIan Rogers      }
800c604d731730b43231f63040c8db1d58304da0cf3Ian Rogers    } while (!done);
801c604d731730b43231f63040c8db1d58304da0cf3Ian Rogers  }
802c604d731730b43231f63040c8db1d58304da0cf3Ian Rogers#else
8035f79133a435ebcb20000370d56046fe01201dd80Elliott Hughes  CHECK_MUTEX_CALL(pthread_cond_broadcast, (&cond_));
804c604d731730b43231f63040c8db1d58304da0cf3Ian Rogers#endif
8055f79133a435ebcb20000370d56046fe01201dd80Elliott Hughes}
8065f79133a435ebcb20000370d56046fe01201dd80Elliott Hughes
807c604d731730b43231f63040c8db1d58304da0cf3Ian Rogersvoid ConditionVariable::Signal(Thread* self) {
8082cebb24bfc3247d3e9be138a3350106737455918Mathieu Chartier  DCHECK(self == nullptr || self == Thread::Current());
809c604d731730b43231f63040c8db1d58304da0cf3Ian Rogers  guard_.AssertExclusiveHeld(self);
810c604d731730b43231f63040c8db1d58304da0cf3Ian Rogers#if ART_USE_FUTEXES
811d45f201e9bd43490e30a35710865789b8d70e249Ian Rogers  if (num_waiters_ > 0) {
812b122a4bbed34ab22b4c1541ee25e5cf22f12a926Ian Rogers    sequence_++;  // Indicate a signal occurred.
813c604d731730b43231f63040c8db1d58304da0cf3Ian Rogers    // Futex wake 1 waiter who will then come and in contend on mutex. It'd be nice to requeue them
814c604d731730b43231f63040c8db1d58304da0cf3Ian Rogers    // to avoid this, however, requeueing can only move all waiters.
8152cebb24bfc3247d3e9be138a3350106737455918Mathieu Chartier    int num_woken = futex(sequence_.Address(), FUTEX_WAKE, 1, nullptr, nullptr, 0);
816d45f201e9bd43490e30a35710865789b8d70e249Ian Rogers    // Check something was woken or else we changed sequence_ before they had chance to wait.
8175bd97c483c1de1eb97afe76123b1b9ab53095edfIan Rogers    CHECK((num_woken == 0) || (num_woken == 1));
818c604d731730b43231f63040c8db1d58304da0cf3Ian Rogers  }
819c604d731730b43231f63040c8db1d58304da0cf3Ian Rogers#else
8205f79133a435ebcb20000370d56046fe01201dd80Elliott Hughes  CHECK_MUTEX_CALL(pthread_cond_signal, (&cond_));
821c604d731730b43231f63040c8db1d58304da0cf3Ian Rogers#endif
8225f79133a435ebcb20000370d56046fe01201dd80Elliott Hughes}
8235f79133a435ebcb20000370d56046fe01201dd80Elliott Hughes
824c604d731730b43231f63040c8db1d58304da0cf3Ian Rogersvoid ConditionVariable::Wait(Thread* self) {
8251d54e73444e017d3a65234e0f193846f3e27472bIan Rogers  guard_.CheckSafeToWait(self);
8261d54e73444e017d3a65234e0f193846f3e27472bIan Rogers  WaitHoldingLocks(self);
8271d54e73444e017d3a65234e0f193846f3e27472bIan Rogers}
8281d54e73444e017d3a65234e0f193846f3e27472bIan Rogers
8291d54e73444e017d3a65234e0f193846f3e27472bIan Rogersvoid ConditionVariable::WaitHoldingLocks(Thread* self) {
8302cebb24bfc3247d3e9be138a3350106737455918Mathieu Chartier  DCHECK(self == nullptr || self == Thread::Current());
831c604d731730b43231f63040c8db1d58304da0cf3Ian Rogers  guard_.AssertExclusiveHeld(self);
832c604d731730b43231f63040c8db1d58304da0cf3Ian Rogers  unsigned int old_recursion_count = guard_.recursion_count_;
833c604d731730b43231f63040c8db1d58304da0cf3Ian Rogers#if ART_USE_FUTEXES
834c604d731730b43231f63040c8db1d58304da0cf3Ian Rogers  num_waiters_++;
835d45f201e9bd43490e30a35710865789b8d70e249Ian Rogers  // Ensure the Mutex is contended so that requeued threads are awoken.
836b122a4bbed34ab22b4c1541ee25e5cf22f12a926Ian Rogers  guard_.num_contenders_++;
837c604d731730b43231f63040c8db1d58304da0cf3Ian Rogers  guard_.recursion_count_ = 1;
8383e5cf305db800b2989ad57b7cde8fb3cc9fa1b9eIan Rogers  int32_t cur_sequence = sequence_.LoadRelaxed();
839c604d731730b43231f63040c8db1d58304da0cf3Ian Rogers  guard_.ExclusiveUnlock(self);
8402cebb24bfc3247d3e9be138a3350106737455918Mathieu Chartier  if (futex(sequence_.Address(), FUTEX_WAIT, cur_sequence, nullptr, nullptr, 0) != 0) {
841d45f201e9bd43490e30a35710865789b8d70e249Ian Rogers    // Futex failed, check it is an expected error.
842d45f201e9bd43490e30a35710865789b8d70e249Ian Rogers    // EAGAIN == EWOULDBLK, so we let the caller try again.
843d45f201e9bd43490e30a35710865789b8d70e249Ian Rogers    // EINTR implies a signal was sent to this thread.
844d45f201e9bd43490e30a35710865789b8d70e249Ian Rogers    if ((errno != EINTR) && (errno != EAGAIN)) {
845c604d731730b43231f63040c8db1d58304da0cf3Ian Rogers      PLOG(FATAL) << "futex wait failed for " << name_;
846c604d731730b43231f63040c8db1d58304da0cf3Ian Rogers    }
847c604d731730b43231f63040c8db1d58304da0cf3Ian Rogers  }
848c604d731730b43231f63040c8db1d58304da0cf3Ian Rogers  guard_.ExclusiveLock(self);
849d45f201e9bd43490e30a35710865789b8d70e249Ian Rogers  CHECK_GE(num_waiters_, 0);
850c604d731730b43231f63040c8db1d58304da0cf3Ian Rogers  num_waiters_--;
851d45f201e9bd43490e30a35710865789b8d70e249Ian Rogers  // We awoke and so no longer require awakes from the guard_'s unlock.
8523e5cf305db800b2989ad57b7cde8fb3cc9fa1b9eIan Rogers  CHECK_GE(guard_.num_contenders_.LoadRelaxed(), 0);
853b122a4bbed34ab22b4c1541ee25e5cf22f12a926Ian Rogers  guard_.num_contenders_--;
854c604d731730b43231f63040c8db1d58304da0cf3Ian Rogers#else
855c5f17732d8144491c642776b6b48c85dfadf4b52Ian Rogers  uint64_t old_owner = guard_.exclusive_owner_;
856c5f17732d8144491c642776b6b48c85dfadf4b52Ian Rogers  guard_.exclusive_owner_ = 0;
857c604d731730b43231f63040c8db1d58304da0cf3Ian Rogers  guard_.recursion_count_ = 0;
858c604d731730b43231f63040c8db1d58304da0cf3Ian Rogers  CHECK_MUTEX_CALL(pthread_cond_wait, (&cond_, &guard_.mutex_));
859c5f17732d8144491c642776b6b48c85dfadf4b52Ian Rogers  guard_.exclusive_owner_ = old_owner;
860c604d731730b43231f63040c8db1d58304da0cf3Ian Rogers#endif
861c604d731730b43231f63040c8db1d58304da0cf3Ian Rogers  guard_.recursion_count_ = old_recursion_count;
8625f79133a435ebcb20000370d56046fe01201dd80Elliott Hughes}
8635f79133a435ebcb20000370d56046fe01201dd80Elliott Hughes
8647b078e8c04f3e1451dbdd18543c8b9692b5b067eIan Rogersbool ConditionVariable::TimedWait(Thread* self, int64_t ms, int32_t ns) {
8652cebb24bfc3247d3e9be138a3350106737455918Mathieu Chartier  DCHECK(self == nullptr || self == Thread::Current());
8667b078e8c04f3e1451dbdd18543c8b9692b5b067eIan Rogers  bool timed_out = false;
867c604d731730b43231f63040c8db1d58304da0cf3Ian Rogers  guard_.AssertExclusiveHeld(self);
8681d54e73444e017d3a65234e0f193846f3e27472bIan Rogers  guard_.CheckSafeToWait(self);
869c604d731730b43231f63040c8db1d58304da0cf3Ian Rogers  unsigned int old_recursion_count = guard_.recursion_count_;
870c604d731730b43231f63040c8db1d58304da0cf3Ian Rogers#if ART_USE_FUTEXES
871c604d731730b43231f63040c8db1d58304da0cf3Ian Rogers  timespec rel_ts;
8725bd97c483c1de1eb97afe76123b1b9ab53095edfIan Rogers  InitTimeSpec(false, CLOCK_REALTIME, ms, ns, &rel_ts);
873c604d731730b43231f63040c8db1d58304da0cf3Ian Rogers  num_waiters_++;
874d45f201e9bd43490e30a35710865789b8d70e249Ian Rogers  // Ensure the Mutex is contended so that requeued threads are awoken.
875b122a4bbed34ab22b4c1541ee25e5cf22f12a926Ian Rogers  guard_.num_contenders_++;
876c604d731730b43231f63040c8db1d58304da0cf3Ian Rogers  guard_.recursion_count_ = 1;
8773e5cf305db800b2989ad57b7cde8fb3cc9fa1b9eIan Rogers  int32_t cur_sequence = sequence_.LoadRelaxed();
878c604d731730b43231f63040c8db1d58304da0cf3Ian Rogers  guard_.ExclusiveUnlock(self);
8792cebb24bfc3247d3e9be138a3350106737455918Mathieu Chartier  if (futex(sequence_.Address(), FUTEX_WAIT, cur_sequence, &rel_ts, nullptr, 0) != 0) {
880c604d731730b43231f63040c8db1d58304da0cf3Ian Rogers    if (errno == ETIMEDOUT) {
881d45f201e9bd43490e30a35710865789b8d70e249Ian Rogers      // Timed out we're done.
8827b078e8c04f3e1451dbdd18543c8b9692b5b067eIan Rogers      timed_out = true;
8830de7985b29257bb60be511db774a4f0119a81f20Brian Carlstrom    } else if ((errno == EAGAIN) || (errno == EINTR)) {
884d45f201e9bd43490e30a35710865789b8d70e249Ian Rogers      // A signal or ConditionVariable::Signal/Broadcast has come in.
885c604d731730b43231f63040c8db1d58304da0cf3Ian Rogers    } else {
886c604d731730b43231f63040c8db1d58304da0cf3Ian Rogers      PLOG(FATAL) << "timed futex wait failed for " << name_;
887c604d731730b43231f63040c8db1d58304da0cf3Ian Rogers    }
888c604d731730b43231f63040c8db1d58304da0cf3Ian Rogers  }
889c604d731730b43231f63040c8db1d58304da0cf3Ian Rogers  guard_.ExclusiveLock(self);
890d45f201e9bd43490e30a35710865789b8d70e249Ian Rogers  CHECK_GE(num_waiters_, 0);
891c604d731730b43231f63040c8db1d58304da0cf3Ian Rogers  num_waiters_--;
892d45f201e9bd43490e30a35710865789b8d70e249Ian Rogers  // We awoke and so no longer require awakes from the guard_'s unlock.
8933e5cf305db800b2989ad57b7cde8fb3cc9fa1b9eIan Rogers  CHECK_GE(guard_.num_contenders_.LoadRelaxed(), 0);
894b122a4bbed34ab22b4c1541ee25e5cf22f12a926Ian Rogers  guard_.num_contenders_--;
895c604d731730b43231f63040c8db1d58304da0cf3Ian Rogers#else
89651b71028661092e8860cca4f8ca79848e03cdc2cNarayan Kamath#if !defined(__APPLE__)
897c604d731730b43231f63040c8db1d58304da0cf3Ian Rogers  int clock = CLOCK_MONOTONIC;
8985f79133a435ebcb20000370d56046fe01201dd80Elliott Hughes#else
899c604d731730b43231f63040c8db1d58304da0cf3Ian Rogers  int clock = CLOCK_REALTIME;
9005f79133a435ebcb20000370d56046fe01201dd80Elliott Hughes#endif
901c5f17732d8144491c642776b6b48c85dfadf4b52Ian Rogers  uint64_t old_owner = guard_.exclusive_owner_;
902c5f17732d8144491c642776b6b48c85dfadf4b52Ian Rogers  guard_.exclusive_owner_ = 0;
903c604d731730b43231f63040c8db1d58304da0cf3Ian Rogers  guard_.recursion_count_ = 0;
904c604d731730b43231f63040c8db1d58304da0cf3Ian Rogers  timespec ts;
905bcc2926b9721f94c17ed98fae5264cc98f0e066fBrian Carlstrom  InitTimeSpec(true, clock, ms, ns, &ts);
90651b71028661092e8860cca4f8ca79848e03cdc2cNarayan Kamath  int rc = TEMP_FAILURE_RETRY(pthread_cond_timedwait(&cond_, &guard_.mutex_, &ts));
9077b078e8c04f3e1451dbdd18543c8b9692b5b067eIan Rogers  if (rc == ETIMEDOUT) {
9087b078e8c04f3e1451dbdd18543c8b9692b5b067eIan Rogers    timed_out = true;
9097b078e8c04f3e1451dbdd18543c8b9692b5b067eIan Rogers  } else if (rc != 0) {
9105f79133a435ebcb20000370d56046fe01201dd80Elliott Hughes    errno = rc;
9115f79133a435ebcb20000370d56046fe01201dd80Elliott Hughes    PLOG(FATAL) << "TimedWait failed for " << name_;
9125f79133a435ebcb20000370d56046fe01201dd80Elliott Hughes  }
913c5f17732d8144491c642776b6b48c85dfadf4b52Ian Rogers  guard_.exclusive_owner_ = old_owner;
914c604d731730b43231f63040c8db1d58304da0cf3Ian Rogers#endif
915c604d731730b43231f63040c8db1d58304da0cf3Ian Rogers  guard_.recursion_count_ = old_recursion_count;
9167b078e8c04f3e1451dbdd18543c8b9692b5b067eIan Rogers  return timed_out;
9175f79133a435ebcb20000370d56046fe01201dd80Elliott Hughes}
9185f79133a435ebcb20000370d56046fe01201dd80Elliott Hughes
919719d1a33f6569864f529e5a3fff59e7bca97aad0Ian Rogersvoid Locks::Init() {
920719d1a33f6569864f529e5a3fff59e7bca97aad0Ian Rogers  if (logging_lock_ != nullptr) {
921719d1a33f6569864f529e5a3fff59e7bca97aad0Ian Rogers    // Already initialized.
9227f0a6d6a699111e254a91c3980eb0522d4f8f0cdNicolas Geoffray    if (kRuntimeISA == kX86 || kRuntimeISA == kX86_64) {
9239e36931cc79ca665908db9575126881d1cfdea5aChao-ying Fu      DCHECK(modify_ldt_lock_ != nullptr);
9249e36931cc79ca665908db9575126881d1cfdea5aChao-ying Fu    } else {
9259e36931cc79ca665908db9575126881d1cfdea5aChao-ying Fu      DCHECK(modify_ldt_lock_ == nullptr);
9269e36931cc79ca665908db9575126881d1cfdea5aChao-ying Fu    }
927719d1a33f6569864f529e5a3fff59e7bca97aad0Ian Rogers    DCHECK(abort_lock_ != nullptr);
928306db81aba41eb244a4e8299cf58ac18ae9999c7Brian Carlstrom    DCHECK(alloc_tracker_lock_ != nullptr);
92974240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe    DCHECK(allocated_monitor_ids_lock_ != nullptr);
9309e36931cc79ca665908db9575126881d1cfdea5aChao-ying Fu    DCHECK(allocated_thread_ids_lock_ != nullptr);
931719d1a33f6569864f529e5a3fff59e7bca97aad0Ian Rogers    DCHECK(breakpoint_lock_ != nullptr);
932719d1a33f6569864f529e5a3fff59e7bca97aad0Ian Rogers    DCHECK(classlinker_classes_lock_ != nullptr);
933306db81aba41eb244a4e8299cf58ac18ae9999c7Brian Carlstrom    DCHECK(deoptimization_lock_ != nullptr);
934719d1a33f6569864f529e5a3fff59e7bca97aad0Ian Rogers    DCHECK(heap_bitmap_lock_ != nullptr);
935306db81aba41eb244a4e8299cf58ac18ae9999c7Brian Carlstrom    DCHECK(intern_table_lock_ != nullptr);
93668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    DCHECK(jni_libraries_lock_ != nullptr);
937719d1a33f6569864f529e5a3fff59e7bca97aad0Ian Rogers    DCHECK(logging_lock_ != nullptr);
938719d1a33f6569864f529e5a3fff59e7bca97aad0Ian Rogers    DCHECK(mutator_lock_ != nullptr);
939306db81aba41eb244a4e8299cf58ac18ae9999c7Brian Carlstrom    DCHECK(profiler_lock_ != nullptr);
940719d1a33f6569864f529e5a3fff59e7bca97aad0Ian Rogers    DCHECK(thread_list_lock_ != nullptr);
941719d1a33f6569864f529e5a3fff59e7bca97aad0Ian Rogers    DCHECK(thread_suspend_count_lock_ != nullptr);
942719d1a33f6569864f529e5a3fff59e7bca97aad0Ian Rogers    DCHECK(trace_lock_ != nullptr);
943719d1a33f6569864f529e5a3fff59e7bca97aad0Ian Rogers    DCHECK(unexpected_signal_lock_ != nullptr);
944719d1a33f6569864f529e5a3fff59e7bca97aad0Ian Rogers  } else {
9459e36931cc79ca665908db9575126881d1cfdea5aChao-ying Fu    // Create global locks in level order from highest lock level to lowest.
9464ad5cd3e7d519484559ef778d96fb3f0be8919faIan Rogers    LockLevel current_lock_level = kInstrumentEntrypointsLock;
9474ad5cd3e7d519484559ef778d96fb3f0be8919faIan Rogers    DCHECK(instrument_entrypoints_lock_ == nullptr);
9484ad5cd3e7d519484559ef778d96fb3f0be8919faIan Rogers    instrument_entrypoints_lock_ = new Mutex("instrument entrypoint lock", current_lock_level);
949719d1a33f6569864f529e5a3fff59e7bca97aad0Ian Rogers
9509e36931cc79ca665908db9575126881d1cfdea5aChao-ying Fu    #define UPDATE_CURRENT_LOCK_LEVEL(new_level) \
951306db81aba41eb244a4e8299cf58ac18ae9999c7Brian Carlstrom      if (new_level >= current_lock_level) { \
952306db81aba41eb244a4e8299cf58ac18ae9999c7Brian Carlstrom        /* Do not use CHECKs or FATAL here, abort_lock_ is not setup yet. */ \
953306db81aba41eb244a4e8299cf58ac18ae9999c7Brian Carlstrom        fprintf(stderr, "New local level %d is not less than current level %d\n", \
954306db81aba41eb244a4e8299cf58ac18ae9999c7Brian Carlstrom                new_level, current_lock_level); \
955306db81aba41eb244a4e8299cf58ac18ae9999c7Brian Carlstrom        exit(1); \
956306db81aba41eb244a4e8299cf58ac18ae9999c7Brian Carlstrom      } \
957f3d874c60ee3ada19ce26a5c4e532312b6f3a9e9Ian Rogers      current_lock_level = new_level;
958f3d874c60ee3ada19ce26a5c4e532312b6f3a9e9Ian Rogers
959f3d874c60ee3ada19ce26a5c4e532312b6f3a9e9Ian Rogers    UPDATE_CURRENT_LOCK_LEVEL(kMutatorLock);
960f3d874c60ee3ada19ce26a5c4e532312b6f3a9e9Ian Rogers    DCHECK(mutator_lock_ == nullptr);
961f3d874c60ee3ada19ce26a5c4e532312b6f3a9e9Ian Rogers    mutator_lock_ = new ReaderWriterMutex("mutator lock", current_lock_level);
9629e36931cc79ca665908db9575126881d1cfdea5aChao-ying Fu
9639e36931cc79ca665908db9575126881d1cfdea5aChao-ying Fu    UPDATE_CURRENT_LOCK_LEVEL(kHeapBitmapLock);
964719d1a33f6569864f529e5a3fff59e7bca97aad0Ian Rogers    DCHECK(heap_bitmap_lock_ == nullptr);
9659e36931cc79ca665908db9575126881d1cfdea5aChao-ying Fu    heap_bitmap_lock_ = new ReaderWriterMutex("heap bitmap lock", current_lock_level);
9669e36931cc79ca665908db9575126881d1cfdea5aChao-ying Fu
96769dbec6d9d55eeb2867949c2791d01dc9aa916c8Jeff Hao    UPDATE_CURRENT_LOCK_LEVEL(kTraceLock);
96869dbec6d9d55eeb2867949c2791d01dc9aa916c8Jeff Hao    DCHECK(trace_lock_ == nullptr);
96969dbec6d9d55eeb2867949c2791d01dc9aa916c8Jeff Hao    trace_lock_ = new Mutex("trace lock", current_lock_level);
97069dbec6d9d55eeb2867949c2791d01dc9aa916c8Jeff Hao
9719e36931cc79ca665908db9575126881d1cfdea5aChao-ying Fu    UPDATE_CURRENT_LOCK_LEVEL(kRuntimeShutdownLock);
972719d1a33f6569864f529e5a3fff59e7bca97aad0Ian Rogers    DCHECK(runtime_shutdown_lock_ == nullptr);
9739e36931cc79ca665908db9575126881d1cfdea5aChao-ying Fu    runtime_shutdown_lock_ = new Mutex("runtime shutdown lock", current_lock_level);
9749e36931cc79ca665908db9575126881d1cfdea5aChao-ying Fu
9759e36931cc79ca665908db9575126881d1cfdea5aChao-ying Fu    UPDATE_CURRENT_LOCK_LEVEL(kProfilerLock);
9769e36931cc79ca665908db9575126881d1cfdea5aChao-ying Fu    DCHECK(profiler_lock_ == nullptr);
9779e36931cc79ca665908db9575126881d1cfdea5aChao-ying Fu    profiler_lock_ = new Mutex("profiler lock", current_lock_level);
9789e36931cc79ca665908db9575126881d1cfdea5aChao-ying Fu
979306db81aba41eb244a4e8299cf58ac18ae9999c7Brian Carlstrom    UPDATE_CURRENT_LOCK_LEVEL(kDeoptimizationLock);
980306db81aba41eb244a4e8299cf58ac18ae9999c7Brian Carlstrom    DCHECK(deoptimization_lock_ == nullptr);
981306db81aba41eb244a4e8299cf58ac18ae9999c7Brian Carlstrom    deoptimization_lock_ = new Mutex("Deoptimization lock", current_lock_level);
982306db81aba41eb244a4e8299cf58ac18ae9999c7Brian Carlstrom
983306db81aba41eb244a4e8299cf58ac18ae9999c7Brian Carlstrom    UPDATE_CURRENT_LOCK_LEVEL(kAllocTrackerLock);
984306db81aba41eb244a4e8299cf58ac18ae9999c7Brian Carlstrom    DCHECK(alloc_tracker_lock_ == nullptr);
985306db81aba41eb244a4e8299cf58ac18ae9999c7Brian Carlstrom    alloc_tracker_lock_ = new Mutex("AllocTracker lock", current_lock_level);
986306db81aba41eb244a4e8299cf58ac18ae9999c7Brian Carlstrom
9879e36931cc79ca665908db9575126881d1cfdea5aChao-ying Fu    UPDATE_CURRENT_LOCK_LEVEL(kThreadListLock);
988719d1a33f6569864f529e5a3fff59e7bca97aad0Ian Rogers    DCHECK(thread_list_lock_ == nullptr);
9899e36931cc79ca665908db9575126881d1cfdea5aChao-ying Fu    thread_list_lock_ = new Mutex("thread list lock", current_lock_level);
9909e36931cc79ca665908db9575126881d1cfdea5aChao-ying Fu
99168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    UPDATE_CURRENT_LOCK_LEVEL(kJniLoadLibraryLock);
99268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    DCHECK(jni_libraries_lock_ == nullptr);
99368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    jni_libraries_lock_ = new Mutex("JNI shared libraries map lock", current_lock_level);
99468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers
9959e36931cc79ca665908db9575126881d1cfdea5aChao-ying Fu    UPDATE_CURRENT_LOCK_LEVEL(kBreakpointLock);
9969e36931cc79ca665908db9575126881d1cfdea5aChao-ying Fu    DCHECK(breakpoint_lock_ == nullptr);
997ed2be1725fb79075892b1a9103487c9d9a95b350Sebastien Hertz    breakpoint_lock_ = new ReaderWriterMutex("breakpoint lock", current_lock_level);
9989e36931cc79ca665908db9575126881d1cfdea5aChao-ying Fu
9999e36931cc79ca665908db9575126881d1cfdea5aChao-ying Fu    UPDATE_CURRENT_LOCK_LEVEL(kClassLinkerClassesLock);
10009e36931cc79ca665908db9575126881d1cfdea5aChao-ying Fu    DCHECK(classlinker_classes_lock_ == nullptr);
10019e36931cc79ca665908db9575126881d1cfdea5aChao-ying Fu    classlinker_classes_lock_ = new ReaderWriterMutex("ClassLinker classes lock",
10029e36931cc79ca665908db9575126881d1cfdea5aChao-ying Fu                                                      current_lock_level);
10039e36931cc79ca665908db9575126881d1cfdea5aChao-ying Fu
100474240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe    UPDATE_CURRENT_LOCK_LEVEL(kMonitorPoolLock);
100574240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe    DCHECK(allocated_monitor_ids_lock_ == nullptr);
100674240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe    allocated_monitor_ids_lock_ =  new Mutex("allocated monitor ids lock", current_lock_level);
100774240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe
10089e36931cc79ca665908db9575126881d1cfdea5aChao-ying Fu    UPDATE_CURRENT_LOCK_LEVEL(kAllocatedThreadIdsLock);
10099e36931cc79ca665908db9575126881d1cfdea5aChao-ying Fu    DCHECK(allocated_thread_ids_lock_ == nullptr);
10109e36931cc79ca665908db9575126881d1cfdea5aChao-ying Fu    allocated_thread_ids_lock_ =  new Mutex("allocated thread ids lock", current_lock_level);
10119e36931cc79ca665908db9575126881d1cfdea5aChao-ying Fu
10127f0a6d6a699111e254a91c3980eb0522d4f8f0cdNicolas Geoffray    if (kRuntimeISA == kX86 || kRuntimeISA == kX86_64) {
10139e36931cc79ca665908db9575126881d1cfdea5aChao-ying Fu      UPDATE_CURRENT_LOCK_LEVEL(kModifyLdtLock);
10149e36931cc79ca665908db9575126881d1cfdea5aChao-ying Fu      DCHECK(modify_ldt_lock_ == nullptr);
10159e36931cc79ca665908db9575126881d1cfdea5aChao-ying Fu      modify_ldt_lock_ = new Mutex("modify_ldt lock", current_lock_level);
10169e36931cc79ca665908db9575126881d1cfdea5aChao-ying Fu    }
10179e36931cc79ca665908db9575126881d1cfdea5aChao-ying Fu
10189e36931cc79ca665908db9575126881d1cfdea5aChao-ying Fu    UPDATE_CURRENT_LOCK_LEVEL(kInternTableLock);
10199e36931cc79ca665908db9575126881d1cfdea5aChao-ying Fu    DCHECK(intern_table_lock_ == nullptr);
10209e36931cc79ca665908db9575126881d1cfdea5aChao-ying Fu    intern_table_lock_ = new Mutex("InternTable lock", current_lock_level);
10219e36931cc79ca665908db9575126881d1cfdea5aChao-ying Fu
1022a5a53efea976af505f4f849b5925d5e14c4f8e5cMathieu Chartier    UPDATE_CURRENT_LOCK_LEVEL(kReferenceProcessorLock);
1023a5a53efea976af505f4f849b5925d5e14c4f8e5cMathieu Chartier    DCHECK(reference_processor_lock_ == nullptr);
1024a5a53efea976af505f4f849b5925d5e14c4f8e5cMathieu Chartier    reference_processor_lock_ = new Mutex("ReferenceProcessor lock", current_lock_level);
1025a5a53efea976af505f4f849b5925d5e14c4f8e5cMathieu Chartier
1026a5a53efea976af505f4f849b5925d5e14c4f8e5cMathieu Chartier    UPDATE_CURRENT_LOCK_LEVEL(kReferenceQueueClearedReferencesLock);
1027a5a53efea976af505f4f849b5925d5e14c4f8e5cMathieu Chartier    DCHECK(reference_queue_cleared_references_lock_ == nullptr);
1028a5a53efea976af505f4f849b5925d5e14c4f8e5cMathieu Chartier    reference_queue_cleared_references_lock_ = new Mutex("ReferenceQueue cleared references lock", current_lock_level);
1029a5a53efea976af505f4f849b5925d5e14c4f8e5cMathieu Chartier
1030a5a53efea976af505f4f849b5925d5e14c4f8e5cMathieu Chartier    UPDATE_CURRENT_LOCK_LEVEL(kReferenceQueueWeakReferencesLock);
1031a5a53efea976af505f4f849b5925d5e14c4f8e5cMathieu Chartier    DCHECK(reference_queue_weak_references_lock_ == nullptr);
1032a5a53efea976af505f4f849b5925d5e14c4f8e5cMathieu Chartier    reference_queue_weak_references_lock_ = new Mutex("ReferenceQueue cleared references lock", current_lock_level);
1033a5a53efea976af505f4f849b5925d5e14c4f8e5cMathieu Chartier
1034a5a53efea976af505f4f849b5925d5e14c4f8e5cMathieu Chartier    UPDATE_CURRENT_LOCK_LEVEL(kReferenceQueueFinalizerReferencesLock);
1035a5a53efea976af505f4f849b5925d5e14c4f8e5cMathieu Chartier    DCHECK(reference_queue_finalizer_references_lock_ == nullptr);
1036a5a53efea976af505f4f849b5925d5e14c4f8e5cMathieu Chartier    reference_queue_finalizer_references_lock_ = new Mutex("ReferenceQueue finalizer references lock", current_lock_level);
1037a5a53efea976af505f4f849b5925d5e14c4f8e5cMathieu Chartier
1038a5a53efea976af505f4f849b5925d5e14c4f8e5cMathieu Chartier    UPDATE_CURRENT_LOCK_LEVEL(kReferenceQueuePhantomReferencesLock);
1039a5a53efea976af505f4f849b5925d5e14c4f8e5cMathieu Chartier    DCHECK(reference_queue_phantom_references_lock_ == nullptr);
1040a5a53efea976af505f4f849b5925d5e14c4f8e5cMathieu Chartier    reference_queue_phantom_references_lock_ = new Mutex("ReferenceQueue phantom references lock", current_lock_level);
1041a5a53efea976af505f4f849b5925d5e14c4f8e5cMathieu Chartier
1042a5a53efea976af505f4f849b5925d5e14c4f8e5cMathieu Chartier    UPDATE_CURRENT_LOCK_LEVEL(kReferenceQueueSoftReferencesLock);
1043a5a53efea976af505f4f849b5925d5e14c4f8e5cMathieu Chartier    DCHECK(reference_queue_soft_references_lock_ == nullptr);
1044a5a53efea976af505f4f849b5925d5e14c4f8e5cMathieu Chartier    reference_queue_soft_references_lock_ = new Mutex("ReferenceQueue soft references lock", current_lock_level);
1045a5a53efea976af505f4f849b5925d5e14c4f8e5cMathieu Chartier
10469e36931cc79ca665908db9575126881d1cfdea5aChao-ying Fu    UPDATE_CURRENT_LOCK_LEVEL(kAbortLock);
10479e36931cc79ca665908db9575126881d1cfdea5aChao-ying Fu    DCHECK(abort_lock_ == nullptr);
10489e36931cc79ca665908db9575126881d1cfdea5aChao-ying Fu    abort_lock_ = new Mutex("abort lock", current_lock_level, true);
10499e36931cc79ca665908db9575126881d1cfdea5aChao-ying Fu
10509e36931cc79ca665908db9575126881d1cfdea5aChao-ying Fu    UPDATE_CURRENT_LOCK_LEVEL(kThreadSuspendCountLock);
1051719d1a33f6569864f529e5a3fff59e7bca97aad0Ian Rogers    DCHECK(thread_suspend_count_lock_ == nullptr);
10529e36931cc79ca665908db9575126881d1cfdea5aChao-ying Fu    thread_suspend_count_lock_ = new Mutex("thread suspend count lock", current_lock_level);
10539e36931cc79ca665908db9575126881d1cfdea5aChao-ying Fu
10549e36931cc79ca665908db9575126881d1cfdea5aChao-ying Fu    UPDATE_CURRENT_LOCK_LEVEL(kUnexpectedSignalLock);
1055719d1a33f6569864f529e5a3fff59e7bca97aad0Ian Rogers    DCHECK(unexpected_signal_lock_ == nullptr);
10569e36931cc79ca665908db9575126881d1cfdea5aChao-ying Fu    unexpected_signal_lock_ = new Mutex("unexpected signal lock", current_lock_level, true);
10579e36931cc79ca665908db9575126881d1cfdea5aChao-ying Fu
10583eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi    UPDATE_CURRENT_LOCK_LEVEL(kMemMapsLock);
10593eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi    DCHECK(mem_maps_lock_ == nullptr);
10603eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi    mem_maps_lock_ = new Mutex("mem maps lock", current_lock_level);
10613eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi
10629e36931cc79ca665908db9575126881d1cfdea5aChao-ying Fu    UPDATE_CURRENT_LOCK_LEVEL(kLoggingLock);
10639e36931cc79ca665908db9575126881d1cfdea5aChao-ying Fu    DCHECK(logging_lock_ == nullptr);
10649e36931cc79ca665908db9575126881d1cfdea5aChao-ying Fu    logging_lock_ = new Mutex("logging lock", current_lock_level, true);
10659e36931cc79ca665908db9575126881d1cfdea5aChao-ying Fu
10669e36931cc79ca665908db9575126881d1cfdea5aChao-ying Fu    #undef UPDATE_CURRENT_LOCK_LEVEL
106791e56692c6bd9fa1d41951ee7dc311f19461f4beMathieu Chartier
106891e56692c6bd9fa1d41951ee7dc311f19461f4beMathieu Chartier    InitConditions();
1069719d1a33f6569864f529e5a3fff59e7bca97aad0Ian Rogers  }
1070719d1a33f6569864f529e5a3fff59e7bca97aad0Ian Rogers}
1071719d1a33f6569864f529e5a3fff59e7bca97aad0Ian Rogers
107291e56692c6bd9fa1d41951ee7dc311f19461f4beMathieu Chartiervoid Locks::InitConditions() {
107391e56692c6bd9fa1d41951ee7dc311f19461f4beMathieu Chartier  thread_exit_cond_ = new ConditionVariable("thread exit condition variable", *thread_list_lock_);
107491e56692c6bd9fa1d41951ee7dc311f19461f4beMathieu Chartier}
1075719d1a33f6569864f529e5a3fff59e7bca97aad0Ian Rogers
1076e62934d85fbc2d935afdad57eeade39ecbd7440aElliott Hughes}  // namespace art
1077