Home | History | Annotate | Download | only in base
      1 /*
      2  * Copyright (C) 2011 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 #include "mutex.h"
     18 
     19 #include <errno.h>
     20 #include <sys/time.h>
     21 
     22 #include "atomic.h"
     23 #include "base/logging.h"
     24 #include "base/time_utils.h"
     25 #include "base/systrace.h"
     26 #include "base/value_object.h"
     27 #include "mutex-inl.h"
     28 #include "runtime.h"
     29 #include "scoped_thread_state_change.h"
     30 #include "thread-inl.h"
     31 
     32 namespace art {
     33 
     34 Mutex* Locks::abort_lock_ = nullptr;
     35 Mutex* Locks::alloc_tracker_lock_ = nullptr;
     36 Mutex* Locks::allocated_monitor_ids_lock_ = nullptr;
     37 Mutex* Locks::allocated_thread_ids_lock_ = nullptr;
     38 ReaderWriterMutex* Locks::breakpoint_lock_ = nullptr;
     39 ReaderWriterMutex* Locks::classlinker_classes_lock_ = nullptr;
     40 Mutex* Locks::deoptimization_lock_ = nullptr;
     41 ReaderWriterMutex* Locks::heap_bitmap_lock_ = nullptr;
     42 Mutex* Locks::instrument_entrypoints_lock_ = nullptr;
     43 Mutex* Locks::intern_table_lock_ = nullptr;
     44 Mutex* Locks::interpreter_string_init_map_lock_ = nullptr;
     45 Mutex* Locks::jni_libraries_lock_ = nullptr;
     46 Mutex* Locks::logging_lock_ = nullptr;
     47 Mutex* Locks::mem_maps_lock_ = nullptr;
     48 Mutex* Locks::modify_ldt_lock_ = nullptr;
     49 MutatorMutex* Locks::mutator_lock_ = nullptr;
     50 Mutex* Locks::profiler_lock_ = nullptr;
     51 ReaderWriterMutex* Locks::oat_file_manager_lock_ = nullptr;
     52 Mutex* Locks::host_dlopen_handles_lock_ = nullptr;
     53 Mutex* Locks::reference_processor_lock_ = nullptr;
     54 Mutex* Locks::reference_queue_cleared_references_lock_ = nullptr;
     55 Mutex* Locks::reference_queue_finalizer_references_lock_ = nullptr;
     56 Mutex* Locks::reference_queue_phantom_references_lock_ = nullptr;
     57 Mutex* Locks::reference_queue_soft_references_lock_ = nullptr;
     58 Mutex* Locks::reference_queue_weak_references_lock_ = nullptr;
     59 Mutex* Locks::runtime_shutdown_lock_ = nullptr;
     60 Mutex* Locks::thread_list_lock_ = nullptr;
     61 ConditionVariable* Locks::thread_exit_cond_ = nullptr;
     62 Mutex* Locks::thread_suspend_count_lock_ = nullptr;
     63 Mutex* Locks::trace_lock_ = nullptr;
     64 Mutex* Locks::unexpected_signal_lock_ = nullptr;
     65 Mutex* Locks::lambda_table_lock_ = nullptr;
     66 Uninterruptible Roles::uninterruptible_;
     67 
     68 struct AllMutexData {
     69   // A guard for all_mutexes_ that's not a mutex (Mutexes must CAS to acquire and busy wait).
     70   Atomic<const BaseMutex*> all_mutexes_guard;
     71   // All created mutexes guarded by all_mutexes_guard_.
     72   std::set<BaseMutex*>* all_mutexes;
     73   AllMutexData() : all_mutexes(nullptr) {}
     74 };
     75 static struct AllMutexData gAllMutexData[kAllMutexDataSize];
     76 
     77 #if ART_USE_FUTEXES
     78 static bool ComputeRelativeTimeSpec(timespec* result_ts, const timespec& lhs, const timespec& rhs) {
     79   const int32_t one_sec = 1000 * 1000 * 1000;  // one second in nanoseconds.
     80   result_ts->tv_sec = lhs.tv_sec - rhs.tv_sec;
     81   result_ts->tv_nsec = lhs.tv_nsec - rhs.tv_nsec;
     82   if (result_ts->tv_nsec < 0) {
     83     result_ts->tv_sec--;
     84     result_ts->tv_nsec += one_sec;
     85   } else if (result_ts->tv_nsec > one_sec) {
     86     result_ts->tv_sec++;
     87     result_ts->tv_nsec -= one_sec;
     88   }
     89   return result_ts->tv_sec < 0;
     90 }
     91 #endif
     92 
     93 class ScopedAllMutexesLock FINAL {
     94  public:
     95   explicit ScopedAllMutexesLock(const BaseMutex* mutex) : mutex_(mutex) {
     96     while (!gAllMutexData->all_mutexes_guard.CompareExchangeWeakAcquire(0, mutex)) {
     97       NanoSleep(100);
     98     }
     99   }
    100 
    101   ~ScopedAllMutexesLock() {
    102 #if !defined(__clang__)
    103     // TODO: remove this workaround target GCC/libc++/bionic bug "invalid failure memory model".
    104     while (!gAllMutexData->all_mutexes_guard.CompareExchangeWeakSequentiallyConsistent(mutex_, 0)) {
    105 #else
    106     while (!gAllMutexData->all_mutexes_guard.CompareExchangeWeakRelease(mutex_, 0)) {
    107 #endif
    108       NanoSleep(100);
    109     }
    110   }
    111 
    112  private:
    113   const BaseMutex* const mutex_;
    114 };
    115 
    116 // Scoped class that generates events at the beginning and end of lock contention.
    117 class ScopedContentionRecorder FINAL : public ValueObject {
    118  public:
    119   ScopedContentionRecorder(BaseMutex* mutex, uint64_t blocked_tid, uint64_t owner_tid)
    120       : mutex_(kLogLockContentions ? mutex : nullptr),
    121         blocked_tid_(kLogLockContentions ? blocked_tid : 0),
    122         owner_tid_(kLogLockContentions ? owner_tid : 0),
    123         start_nano_time_(kLogLockContentions ? NanoTime() : 0) {
    124     if (ATRACE_ENABLED()) {
    125       std::string msg = StringPrintf("Lock contention on %s (owner tid: %" PRIu64 ")",
    126                                      mutex->GetName(), owner_tid);
    127       ATRACE_BEGIN(msg.c_str());
    128     }
    129   }
    130 
    131   ~ScopedContentionRecorder() {
    132     ATRACE_END();
    133     if (kLogLockContentions) {
    134       uint64_t end_nano_time = NanoTime();
    135       mutex_->RecordContention(blocked_tid_, owner_tid_, end_nano_time - start_nano_time_);
    136     }
    137   }
    138 
    139  private:
    140   BaseMutex* const mutex_;
    141   const uint64_t blocked_tid_;
    142   const uint64_t owner_tid_;
    143   const uint64_t start_nano_time_;
    144 };
    145 
    146 BaseMutex::BaseMutex(const char* name, LockLevel level) : level_(level), name_(name) {
    147   if (kLogLockContentions) {
    148     ScopedAllMutexesLock mu(this);
    149     std::set<BaseMutex*>** all_mutexes_ptr = &gAllMutexData->all_mutexes;
    150     if (*all_mutexes_ptr == nullptr) {
    151       // We leak the global set of all mutexes to avoid ordering issues in global variable
    152       // construction/destruction.
    153       *all_mutexes_ptr = new std::set<BaseMutex*>();
    154     }
    155     (*all_mutexes_ptr)->insert(this);
    156   }
    157 }
    158 
    159 BaseMutex::~BaseMutex() {
    160   if (kLogLockContentions) {
    161     ScopedAllMutexesLock mu(this);
    162     gAllMutexData->all_mutexes->erase(this);
    163   }
    164 }
    165 
    166 void BaseMutex::DumpAll(std::ostream& os) {
    167   if (kLogLockContentions) {
    168     os << "Mutex logging:\n";
    169     ScopedAllMutexesLock mu(reinterpret_cast<const BaseMutex*>(-1));
    170     std::set<BaseMutex*>* all_mutexes = gAllMutexData->all_mutexes;
    171     if (all_mutexes == nullptr) {
    172       // No mutexes have been created yet during at startup.
    173       return;
    174     }
    175     typedef std::set<BaseMutex*>::const_iterator It;
    176     os << "(Contended)\n";
    177     for (It it = all_mutexes->begin(); it != all_mutexes->end(); ++it) {
    178       BaseMutex* mutex = *it;
    179       if (mutex->HasEverContended()) {
    180         mutex->Dump(os);
    181         os << "\n";
    182       }
    183     }
    184     os << "(Never contented)\n";
    185     for (It it = all_mutexes->begin(); it != all_mutexes->end(); ++it) {
    186       BaseMutex* mutex = *it;
    187       if (!mutex->HasEverContended()) {
    188         mutex->Dump(os);
    189         os << "\n";
    190       }
    191     }
    192   }
    193 }
    194 
    195 void BaseMutex::CheckSafeToWait(Thread* self) {
    196   if (self == nullptr) {
    197     CheckUnattachedThread(level_);
    198     return;
    199   }
    200   if (kDebugLocking) {
    201     CHECK(self->GetHeldMutex(level_) == this || level_ == kMonitorLock)
    202         << "Waiting on unacquired mutex: " << name_;
    203     bool bad_mutexes_held = false;
    204     for (int i = kLockLevelCount - 1; i >= 0; --i) {
    205       if (i != level_) {
    206         BaseMutex* held_mutex = self->GetHeldMutex(static_cast<LockLevel>(i));
    207         // We expect waits to happen while holding the thread list suspend thread lock.
    208         if (held_mutex != nullptr) {
    209           LOG(ERROR) << "Holding \"" << held_mutex->name_ << "\" "
    210                      << "(level " << LockLevel(i) << ") while performing wait on "
    211                      << "\"" << name_ << "\" (level " << level_ << ")";
    212           bad_mutexes_held = true;
    213         }
    214       }
    215     }
    216     if (gAborting == 0) {  // Avoid recursive aborts.
    217       CHECK(!bad_mutexes_held);
    218     }
    219   }
    220 }
    221 
    222 void BaseMutex::ContentionLogData::AddToWaitTime(uint64_t value) {
    223   if (kLogLockContentions) {
    224     // Atomically add value to wait_time.
    225     wait_time.FetchAndAddSequentiallyConsistent(value);
    226   }
    227 }
    228 
    229 void BaseMutex::RecordContention(uint64_t blocked_tid,
    230                                  uint64_t owner_tid,
    231                                  uint64_t nano_time_blocked) {
    232   if (kLogLockContentions) {
    233     ContentionLogData* data = contention_log_data_;
    234     ++(data->contention_count);
    235     data->AddToWaitTime(nano_time_blocked);
    236     ContentionLogEntry* log = data->contention_log;
    237     // This code is intentionally racy as it is only used for diagnostics.
    238     uint32_t slot = data->cur_content_log_entry.LoadRelaxed();
    239     if (log[slot].blocked_tid == blocked_tid &&
    240         log[slot].owner_tid == blocked_tid) {
    241       ++log[slot].count;
    242     } else {
    243       uint32_t new_slot;
    244       do {
    245         slot = data->cur_content_log_entry.LoadRelaxed();
    246         new_slot = (slot + 1) % kContentionLogSize;
    247       } while (!data->cur_content_log_entry.CompareExchangeWeakRelaxed(slot, new_slot));
    248       log[new_slot].blocked_tid = blocked_tid;
    249       log[new_slot].owner_tid = owner_tid;
    250       log[new_slot].count.StoreRelaxed(1);
    251     }
    252   }
    253 }
    254 
    255 void BaseMutex::DumpContention(std::ostream& os) const {
    256   if (kLogLockContentions) {
    257     const ContentionLogData* data = contention_log_data_;
    258     const ContentionLogEntry* log = data->contention_log;
    259     uint64_t wait_time = data->wait_time.LoadRelaxed();
    260     uint32_t contention_count = data->contention_count.LoadRelaxed();
    261     if (contention_count == 0) {
    262       os << "never contended";
    263     } else {
    264       os << "contended " << contention_count
    265          << " total wait of contender " << PrettyDuration(wait_time)
    266          << " average " << PrettyDuration(wait_time / contention_count);
    267       SafeMap<uint64_t, size_t> most_common_blocker;
    268       SafeMap<uint64_t, size_t> most_common_blocked;
    269       for (size_t i = 0; i < kContentionLogSize; ++i) {
    270         uint64_t blocked_tid = log[i].blocked_tid;
    271         uint64_t owner_tid = log[i].owner_tid;
    272         uint32_t count = log[i].count.LoadRelaxed();
    273         if (count > 0) {
    274           auto it = most_common_blocked.find(blocked_tid);
    275           if (it != most_common_blocked.end()) {
    276             most_common_blocked.Overwrite(blocked_tid, it->second + count);
    277           } else {
    278             most_common_blocked.Put(blocked_tid, count);
    279           }
    280           it = most_common_blocker.find(owner_tid);
    281           if (it != most_common_blocker.end()) {
    282             most_common_blocker.Overwrite(owner_tid, it->second + count);
    283           } else {
    284             most_common_blocker.Put(owner_tid, count);
    285           }
    286         }
    287       }
    288       uint64_t max_tid = 0;
    289       size_t max_tid_count = 0;
    290       for (const auto& pair : most_common_blocked) {
    291         if (pair.second > max_tid_count) {
    292           max_tid = pair.first;
    293           max_tid_count = pair.second;
    294         }
    295       }
    296       if (max_tid != 0) {
    297         os << " sample shows most blocked tid=" << max_tid;
    298       }
    299       max_tid = 0;
    300       max_tid_count = 0;
    301       for (const auto& pair : most_common_blocker) {
    302         if (pair.second > max_tid_count) {
    303           max_tid = pair.first;
    304           max_tid_count = pair.second;
    305         }
    306       }
    307       if (max_tid != 0) {
    308         os << " sample shows tid=" << max_tid << " owning during this time";
    309       }
    310     }
    311   }
    312 }
    313 
    314 
    315 Mutex::Mutex(const char* name, LockLevel level, bool recursive)
    316     : BaseMutex(name, level), recursive_(recursive), recursion_count_(0) {
    317 #if ART_USE_FUTEXES
    318   DCHECK_EQ(0, state_.LoadRelaxed());
    319   DCHECK_EQ(0, num_contenders_.LoadRelaxed());
    320 #else
    321   CHECK_MUTEX_CALL(pthread_mutex_init, (&mutex_, nullptr));
    322 #endif
    323   exclusive_owner_ = 0;
    324 }
    325 
    326 // Helper to ignore the lock requirement.
    327 static bool IsShuttingDown() NO_THREAD_SAFETY_ANALYSIS {
    328   Runtime* runtime = Runtime::Current();
    329   return runtime == nullptr || runtime->IsShuttingDownLocked();
    330 }
    331 
    332 Mutex::~Mutex() {
    333   bool shutting_down = IsShuttingDown();
    334 #if ART_USE_FUTEXES
    335   if (state_.LoadRelaxed() != 0) {
    336     LOG(shutting_down ? WARNING : FATAL) << "destroying mutex with owner: " << exclusive_owner_;
    337   } else {
    338     if (exclusive_owner_ != 0) {
    339       LOG(shutting_down ? WARNING : FATAL) << "unexpectedly found an owner on unlocked mutex "
    340                                            << name_;
    341     }
    342     if (num_contenders_.LoadSequentiallyConsistent() != 0) {
    343       LOG(shutting_down ? WARNING : FATAL) << "unexpectedly found a contender on mutex " << name_;
    344     }
    345   }
    346 #else
    347   // We can't use CHECK_MUTEX_CALL here because on shutdown a suspended daemon thread
    348   // may still be using locks.
    349   int rc = pthread_mutex_destroy(&mutex_);
    350   if (rc != 0) {
    351     errno = rc;
    352     // TODO: should we just not log at all if shutting down? this could be the logging mutex!
    353     MutexLock mu(Thread::Current(), *Locks::runtime_shutdown_lock_);
    354     PLOG(shutting_down ? WARNING : FATAL) << "pthread_mutex_destroy failed for " << name_;
    355   }
    356 #endif
    357 }
    358 
    359 void Mutex::ExclusiveLock(Thread* self) {
    360   DCHECK(self == nullptr || self == Thread::Current());
    361   if (kDebugLocking && !recursive_) {
    362     AssertNotHeld(self);
    363   }
    364   if (!recursive_ || !IsExclusiveHeld(self)) {
    365 #if ART_USE_FUTEXES
    366     bool done = false;
    367     do {
    368       int32_t cur_state = state_.LoadRelaxed();
    369       if (LIKELY(cur_state == 0)) {
    370         // Change state from 0 to 1 and impose load/store ordering appropriate for lock acquisition.
    371         done = state_.CompareExchangeWeakAcquire(0 /* cur_state */, 1 /* new state */);
    372       } else {
    373         // Failed to acquire, hang up.
    374         ScopedContentionRecorder scr(this, SafeGetTid(self), GetExclusiveOwnerTid());
    375         num_contenders_++;
    376         if (futex(state_.Address(), FUTEX_WAIT, 1, nullptr, nullptr, 0) != 0) {
    377           // EAGAIN and EINTR both indicate a spurious failure, try again from the beginning.
    378           // We don't use TEMP_FAILURE_RETRY so we can intentionally retry to acquire the lock.
    379           if ((errno != EAGAIN) && (errno != EINTR)) {
    380             PLOG(FATAL) << "futex wait failed for " << name_;
    381           }
    382         }
    383         num_contenders_--;
    384       }
    385     } while (!done);
    386     DCHECK_EQ(state_.LoadRelaxed(), 1);
    387 #else
    388     CHECK_MUTEX_CALL(pthread_mutex_lock, (&mutex_));
    389 #endif
    390     DCHECK_EQ(exclusive_owner_, 0U);
    391     exclusive_owner_ = SafeGetTid(self);
    392     RegisterAsLocked(self);
    393   }
    394   recursion_count_++;
    395   if (kDebugLocking) {
    396     CHECK(recursion_count_ == 1 || recursive_) << "Unexpected recursion count on mutex: "
    397         << name_ << " " << recursion_count_;
    398     AssertHeld(self);
    399   }
    400 }
    401 
    402 bool Mutex::ExclusiveTryLock(Thread* self) {
    403   DCHECK(self == nullptr || self == Thread::Current());
    404   if (kDebugLocking && !recursive_) {
    405     AssertNotHeld(self);
    406   }
    407   if (!recursive_ || !IsExclusiveHeld(self)) {
    408 #if ART_USE_FUTEXES
    409     bool done = false;
    410     do {
    411       int32_t cur_state = state_.LoadRelaxed();
    412       if (cur_state == 0) {
    413         // Change state from 0 to 1 and impose load/store ordering appropriate for lock acquisition.
    414         done = state_.CompareExchangeWeakAcquire(0 /* cur_state */, 1 /* new state */);
    415       } else {
    416         return false;
    417       }
    418     } while (!done);
    419     DCHECK_EQ(state_.LoadRelaxed(), 1);
    420 #else
    421     int result = pthread_mutex_trylock(&mutex_);
    422     if (result == EBUSY) {
    423       return false;
    424     }
    425     if (result != 0) {
    426       errno = result;
    427       PLOG(FATAL) << "pthread_mutex_trylock failed for " << name_;
    428     }
    429 #endif
    430     DCHECK_EQ(exclusive_owner_, 0U);
    431     exclusive_owner_ = SafeGetTid(self);
    432     RegisterAsLocked(self);
    433   }
    434   recursion_count_++;
    435   if (kDebugLocking) {
    436     CHECK(recursion_count_ == 1 || recursive_) << "Unexpected recursion count on mutex: "
    437         << name_ << " " << recursion_count_;
    438     AssertHeld(self);
    439   }
    440   return true;
    441 }
    442 
    443 void Mutex::ExclusiveUnlock(Thread* self) {
    444   if (kIsDebugBuild && self != nullptr && self != Thread::Current()) {
    445     std::string name1 = "<null>";
    446     std::string name2 = "<null>";
    447     if (self != nullptr) {
    448       self->GetThreadName(name1);
    449     }
    450     if (Thread::Current() != nullptr) {
    451       Thread::Current()->GetThreadName(name2);
    452     }
    453     LOG(FATAL) << GetName() << " level=" << level_ << " self=" << name1
    454                << " Thread::Current()=" << name2;
    455   }
    456   AssertHeld(self);
    457   DCHECK_NE(exclusive_owner_, 0U);
    458   recursion_count_--;
    459   if (!recursive_ || recursion_count_ == 0) {
    460     if (kDebugLocking) {
    461       CHECK(recursion_count_ == 0 || recursive_) << "Unexpected recursion count on mutex: "
    462           << name_ << " " << recursion_count_;
    463     }
    464     RegisterAsUnlocked(self);
    465 #if ART_USE_FUTEXES
    466     bool done = false;
    467     do {
    468       int32_t cur_state = state_.LoadRelaxed();
    469       if (LIKELY(cur_state == 1)) {
    470         // We're no longer the owner.
    471         exclusive_owner_ = 0;
    472         // Change state to 0 and impose load/store ordering appropriate for lock release.
    473         // Note, the relaxed loads below musn't reorder before the CompareExchange.
    474         // TODO: the ordering here is non-trivial as state is split across 3 fields, fix by placing
    475         // a status bit into the state on contention.
    476         done =  state_.CompareExchangeWeakSequentiallyConsistent(cur_state, 0 /* new state */);
    477         if (LIKELY(done)) {  // Spurious fail?
    478           // Wake a contender.
    479           if (UNLIKELY(num_contenders_.LoadRelaxed() > 0)) {
    480             futex(state_.Address(), FUTEX_WAKE, 1, nullptr, nullptr, 0);
    481           }
    482         }
    483       } else {
    484         // Logging acquires the logging lock, avoid infinite recursion in that case.
    485         if (this != Locks::logging_lock_) {
    486           LOG(FATAL) << "Unexpected state_ in unlock " << cur_state << " for " << name_;
    487         } else {
    488           LogMessage::LogLine(__FILE__, __LINE__, INTERNAL_FATAL,
    489                               StringPrintf("Unexpected state_ %d in unlock for %s",
    490                                            cur_state, name_).c_str());
    491           _exit(1);
    492         }
    493       }
    494     } while (!done);
    495 #else
    496     exclusive_owner_ = 0;
    497     CHECK_MUTEX_CALL(pthread_mutex_unlock, (&mutex_));
    498 #endif
    499   }
    500 }
    501 
    502 void Mutex::Dump(std::ostream& os) const {
    503   os << (recursive_ ? "recursive " : "non-recursive ")
    504       << name_
    505       << " level=" << static_cast<int>(level_)
    506       << " rec=" << recursion_count_
    507       << " owner=" << GetExclusiveOwnerTid() << " ";
    508   DumpContention(os);
    509 }
    510 
    511 std::ostream& operator<<(std::ostream& os, const Mutex& mu) {
    512   mu.Dump(os);
    513   return os;
    514 }
    515 
    516 ReaderWriterMutex::ReaderWriterMutex(const char* name, LockLevel level)
    517     : BaseMutex(name, level)
    518 #if ART_USE_FUTEXES
    519     , state_(0), num_pending_readers_(0), num_pending_writers_(0)
    520 #endif
    521 {  // NOLINT(whitespace/braces)
    522 #if !ART_USE_FUTEXES
    523   CHECK_MUTEX_CALL(pthread_rwlock_init, (&rwlock_, nullptr));
    524 #endif
    525   exclusive_owner_ = 0;
    526 }
    527 
    528 ReaderWriterMutex::~ReaderWriterMutex() {
    529 #if ART_USE_FUTEXES
    530   CHECK_EQ(state_.LoadRelaxed(), 0);
    531   CHECK_EQ(exclusive_owner_, 0U);
    532   CHECK_EQ(num_pending_readers_.LoadRelaxed(), 0);
    533   CHECK_EQ(num_pending_writers_.LoadRelaxed(), 0);
    534 #else
    535   // We can't use CHECK_MUTEX_CALL here because on shutdown a suspended daemon thread
    536   // may still be using locks.
    537   int rc = pthread_rwlock_destroy(&rwlock_);
    538   if (rc != 0) {
    539     errno = rc;
    540     // TODO: should we just not log at all if shutting down? this could be the logging mutex!
    541     MutexLock mu(Thread::Current(), *Locks::runtime_shutdown_lock_);
    542     Runtime* runtime = Runtime::Current();
    543     bool shutting_down = runtime == nullptr || runtime->IsShuttingDownLocked();
    544     PLOG(shutting_down ? WARNING : FATAL) << "pthread_rwlock_destroy failed for " << name_;
    545   }
    546 #endif
    547 }
    548 
    549 void ReaderWriterMutex::ExclusiveLock(Thread* self) {
    550   DCHECK(self == nullptr || self == Thread::Current());
    551   AssertNotExclusiveHeld(self);
    552 #if ART_USE_FUTEXES
    553   bool done = false;
    554   do {
    555     int32_t cur_state = state_.LoadRelaxed();
    556     if (LIKELY(cur_state == 0)) {
    557       // Change state from 0 to -1 and impose load/store ordering appropriate for lock acquisition.
    558       done =  state_.CompareExchangeWeakAcquire(0 /* cur_state*/, -1 /* new state */);
    559     } else {
    560       // Failed to acquire, hang up.
    561       ScopedContentionRecorder scr(this, SafeGetTid(self), GetExclusiveOwnerTid());
    562       ++num_pending_writers_;
    563       if (futex(state_.Address(), FUTEX_WAIT, cur_state, nullptr, nullptr, 0) != 0) {
    564         // EAGAIN and EINTR both indicate a spurious failure, try again from the beginning.
    565         // We don't use TEMP_FAILURE_RETRY so we can intentionally retry to acquire the lock.
    566         if ((errno != EAGAIN) && (errno != EINTR)) {
    567           PLOG(FATAL) << "futex wait failed for " << name_;
    568         }
    569       }
    570       --num_pending_writers_;
    571     }
    572   } while (!done);
    573   DCHECK_EQ(state_.LoadRelaxed(), -1);
    574 #else
    575   CHECK_MUTEX_CALL(pthread_rwlock_wrlock, (&rwlock_));
    576 #endif
    577   DCHECK_EQ(exclusive_owner_, 0U);
    578   exclusive_owner_ = SafeGetTid(self);
    579   RegisterAsLocked(self);
    580   AssertExclusiveHeld(self);
    581 }
    582 
    583 void ReaderWriterMutex::ExclusiveUnlock(Thread* self) {
    584   DCHECK(self == nullptr || self == Thread::Current());
    585   AssertExclusiveHeld(self);
    586   RegisterAsUnlocked(self);
    587   DCHECK_NE(exclusive_owner_, 0U);
    588 #if ART_USE_FUTEXES
    589   bool done = false;
    590   do {
    591     int32_t cur_state = state_.LoadRelaxed();
    592     if (LIKELY(cur_state == -1)) {
    593       // We're no longer the owner.
    594       exclusive_owner_ = 0;
    595       // Change state from -1 to 0 and impose load/store ordering appropriate for lock release.
    596       // Note, the relaxed loads below musn't reorder before the CompareExchange.
    597       // TODO: the ordering here is non-trivial as state is split across 3 fields, fix by placing
    598       // a status bit into the state on contention.
    599       done =  state_.CompareExchangeWeakSequentiallyConsistent(-1 /* cur_state*/, 0 /* new state */);
    600       if (LIKELY(done)) {  // Weak CAS may fail spuriously.
    601         // Wake any waiters.
    602         if (UNLIKELY(num_pending_readers_.LoadRelaxed() > 0 ||
    603                      num_pending_writers_.LoadRelaxed() > 0)) {
    604           futex(state_.Address(), FUTEX_WAKE, -1, nullptr, nullptr, 0);
    605         }
    606       }
    607     } else {
    608       LOG(FATAL) << "Unexpected state_:" << cur_state << " for " << name_;
    609     }
    610   } while (!done);
    611 #else
    612   exclusive_owner_ = 0;
    613   CHECK_MUTEX_CALL(pthread_rwlock_unlock, (&rwlock_));
    614 #endif
    615 }
    616 
    617 #if HAVE_TIMED_RWLOCK
    618 bool ReaderWriterMutex::ExclusiveLockWithTimeout(Thread* self, int64_t ms, int32_t ns) {
    619   DCHECK(self == nullptr || self == Thread::Current());
    620 #if ART_USE_FUTEXES
    621   bool done = false;
    622   timespec end_abs_ts;
    623   InitTimeSpec(true, CLOCK_MONOTONIC, ms, ns, &end_abs_ts);
    624   do {
    625     int32_t cur_state = state_.LoadRelaxed();
    626     if (cur_state == 0) {
    627       // Change state from 0 to -1 and impose load/store ordering appropriate for lock acquisition.
    628       done =  state_.CompareExchangeWeakAcquire(0 /* cur_state */, -1 /* new state */);
    629     } else {
    630       // Failed to acquire, hang up.
    631       timespec now_abs_ts;
    632       InitTimeSpec(true, CLOCK_MONOTONIC, 0, 0, &now_abs_ts);
    633       timespec rel_ts;
    634       if (ComputeRelativeTimeSpec(&rel_ts, end_abs_ts, now_abs_ts)) {
    635         return false;  // Timed out.
    636       }
    637       ScopedContentionRecorder scr(this, SafeGetTid(self), GetExclusiveOwnerTid());
    638       ++num_pending_writers_;
    639       if (futex(state_.Address(), FUTEX_WAIT, cur_state, &rel_ts, nullptr, 0) != 0) {
    640         if (errno == ETIMEDOUT) {
    641           --num_pending_writers_;
    642           return false;  // Timed out.
    643         } else if ((errno != EAGAIN) && (errno != EINTR)) {
    644           // EAGAIN and EINTR both indicate a spurious failure,
    645           // recompute the relative time out from now and try again.
    646           // We don't use TEMP_FAILURE_RETRY so we can recompute rel_ts;
    647           PLOG(FATAL) << "timed futex wait failed for " << name_;
    648         }
    649       }
    650       --num_pending_writers_;
    651     }
    652   } while (!done);
    653 #else
    654   timespec ts;
    655   InitTimeSpec(true, CLOCK_REALTIME, ms, ns, &ts);
    656   int result = pthread_rwlock_timedwrlock(&rwlock_, &ts);
    657   if (result == ETIMEDOUT) {
    658     return false;
    659   }
    660   if (result != 0) {
    661     errno = result;
    662     PLOG(FATAL) << "pthread_rwlock_timedwrlock failed for " << name_;
    663   }
    664 #endif
    665   exclusive_owner_ = SafeGetTid(self);
    666   RegisterAsLocked(self);
    667   AssertSharedHeld(self);
    668   return true;
    669 }
    670 #endif
    671 
    672 #if ART_USE_FUTEXES
    673 void ReaderWriterMutex::HandleSharedLockContention(Thread* self, int32_t cur_state) {
    674   // Owner holds it exclusively, hang up.
    675   ScopedContentionRecorder scr(this, GetExclusiveOwnerTid(), SafeGetTid(self));
    676   ++num_pending_readers_;
    677   if (futex(state_.Address(), FUTEX_WAIT, cur_state, nullptr, nullptr, 0) != 0) {
    678     if (errno != EAGAIN) {
    679       PLOG(FATAL) << "futex wait failed for " << name_;
    680     }
    681   }
    682   --num_pending_readers_;
    683 }
    684 #endif
    685 
    686 bool ReaderWriterMutex::SharedTryLock(Thread* self) {
    687   DCHECK(self == nullptr || self == Thread::Current());
    688 #if ART_USE_FUTEXES
    689   bool done = false;
    690   do {
    691     int32_t cur_state = state_.LoadRelaxed();
    692     if (cur_state >= 0) {
    693       // Add as an extra reader and impose load/store ordering appropriate for lock acquisition.
    694       done =  state_.CompareExchangeWeakAcquire(cur_state, cur_state + 1);
    695     } else {
    696       // Owner holds it exclusively.
    697       return false;
    698     }
    699   } while (!done);
    700 #else
    701   int result = pthread_rwlock_tryrdlock(&rwlock_);
    702   if (result == EBUSY) {
    703     return false;
    704   }
    705   if (result != 0) {
    706     errno = result;
    707     PLOG(FATAL) << "pthread_mutex_trylock failed for " << name_;
    708   }
    709 #endif
    710   RegisterAsLocked(self);
    711   AssertSharedHeld(self);
    712   return true;
    713 }
    714 
    715 bool ReaderWriterMutex::IsSharedHeld(const Thread* self) const {
    716   DCHECK(self == nullptr || self == Thread::Current());
    717   bool result;
    718   if (UNLIKELY(self == nullptr)) {  // Handle unattached threads.
    719     result = IsExclusiveHeld(self);  // TODO: a better best effort here.
    720   } else {
    721     result = (self->GetHeldMutex(level_) == this);
    722   }
    723   return result;
    724 }
    725 
    726 void ReaderWriterMutex::Dump(std::ostream& os) const {
    727   os << name_
    728       << " level=" << static_cast<int>(level_)
    729       << " owner=" << GetExclusiveOwnerTid()
    730 #if ART_USE_FUTEXES
    731       << " state=" << state_.LoadSequentiallyConsistent()
    732       << " num_pending_writers=" << num_pending_writers_.LoadSequentiallyConsistent()
    733       << " num_pending_readers=" << num_pending_readers_.LoadSequentiallyConsistent()
    734 #endif
    735       << " ";
    736   DumpContention(os);
    737 }
    738 
    739 std::ostream& operator<<(std::ostream& os, const ReaderWriterMutex& mu) {
    740   mu.Dump(os);
    741   return os;
    742 }
    743 
    744 std::ostream& operator<<(std::ostream& os, const MutatorMutex& mu) {
    745   mu.Dump(os);
    746   return os;
    747 }
    748 
    749 ConditionVariable::ConditionVariable(const char* name, Mutex& guard)
    750     : name_(name), guard_(guard) {
    751 #if ART_USE_FUTEXES
    752   DCHECK_EQ(0, sequence_.LoadRelaxed());
    753   num_waiters_ = 0;
    754 #else
    755   pthread_condattr_t cond_attrs;
    756   CHECK_MUTEX_CALL(pthread_condattr_init, (&cond_attrs));
    757 #if !defined(__APPLE__)
    758   // Apple doesn't have CLOCK_MONOTONIC or pthread_condattr_setclock.
    759   CHECK_MUTEX_CALL(pthread_condattr_setclock, (&cond_attrs, CLOCK_MONOTONIC));
    760 #endif
    761   CHECK_MUTEX_CALL(pthread_cond_init, (&cond_, &cond_attrs));
    762 #endif
    763 }
    764 
    765 ConditionVariable::~ConditionVariable() {
    766 #if ART_USE_FUTEXES
    767   if (num_waiters_!= 0) {
    768     Runtime* runtime = Runtime::Current();
    769     bool shutting_down = runtime == nullptr || runtime->IsShuttingDown(Thread::Current());
    770     LOG(shutting_down ? WARNING : FATAL) << "ConditionVariable::~ConditionVariable for " << name_
    771         << " called with " << num_waiters_ << " waiters.";
    772   }
    773 #else
    774   // We can't use CHECK_MUTEX_CALL here because on shutdown a suspended daemon thread
    775   // may still be using condition variables.
    776   int rc = pthread_cond_destroy(&cond_);
    777   if (rc != 0) {
    778     errno = rc;
    779     MutexLock mu(Thread::Current(), *Locks::runtime_shutdown_lock_);
    780     Runtime* runtime = Runtime::Current();
    781     bool shutting_down = (runtime == nullptr) || runtime->IsShuttingDownLocked();
    782     PLOG(shutting_down ? WARNING : FATAL) << "pthread_cond_destroy failed for " << name_;
    783   }
    784 #endif
    785 }
    786 
    787 void ConditionVariable::Broadcast(Thread* self) {
    788   DCHECK(self == nullptr || self == Thread::Current());
    789   // TODO: enable below, there's a race in thread creation that causes false failures currently.
    790   // guard_.AssertExclusiveHeld(self);
    791   DCHECK_EQ(guard_.GetExclusiveOwnerTid(), SafeGetTid(self));
    792 #if ART_USE_FUTEXES
    793   if (num_waiters_ > 0) {
    794     sequence_++;  // Indicate the broadcast occurred.
    795     bool done = false;
    796     do {
    797       int32_t cur_sequence = sequence_.LoadRelaxed();
    798       // Requeue waiters onto mutex. The waiter holds the contender count on the mutex high ensuring
    799       // mutex unlocks will awaken the requeued waiter thread.
    800       done = futex(sequence_.Address(), FUTEX_CMP_REQUEUE, 0,
    801                    reinterpret_cast<const timespec*>(std::numeric_limits<int32_t>::max()),
    802                    guard_.state_.Address(), cur_sequence) != -1;
    803       if (!done) {
    804         if (errno != EAGAIN) {
    805           PLOG(FATAL) << "futex cmp requeue failed for " << name_;
    806         }
    807       }
    808     } while (!done);
    809   }
    810 #else
    811   CHECK_MUTEX_CALL(pthread_cond_broadcast, (&cond_));
    812 #endif
    813 }
    814 
    815 void ConditionVariable::Signal(Thread* self) {
    816   DCHECK(self == nullptr || self == Thread::Current());
    817   guard_.AssertExclusiveHeld(self);
    818 #if ART_USE_FUTEXES
    819   if (num_waiters_ > 0) {
    820     sequence_++;  // Indicate a signal occurred.
    821     // Futex wake 1 waiter who will then come and in contend on mutex. It'd be nice to requeue them
    822     // to avoid this, however, requeueing can only move all waiters.
    823     int num_woken = futex(sequence_.Address(), FUTEX_WAKE, 1, nullptr, nullptr, 0);
    824     // Check something was woken or else we changed sequence_ before they had chance to wait.
    825     CHECK((num_woken == 0) || (num_woken == 1));
    826   }
    827 #else
    828   CHECK_MUTEX_CALL(pthread_cond_signal, (&cond_));
    829 #endif
    830 }
    831 
    832 void ConditionVariable::Wait(Thread* self) {
    833   guard_.CheckSafeToWait(self);
    834   WaitHoldingLocks(self);
    835 }
    836 
    837 void ConditionVariable::WaitHoldingLocks(Thread* self) {
    838   DCHECK(self == nullptr || self == Thread::Current());
    839   guard_.AssertExclusiveHeld(self);
    840   unsigned int old_recursion_count = guard_.recursion_count_;
    841 #if ART_USE_FUTEXES
    842   num_waiters_++;
    843   // Ensure the Mutex is contended so that requeued threads are awoken.
    844   guard_.num_contenders_++;
    845   guard_.recursion_count_ = 1;
    846   int32_t cur_sequence = sequence_.LoadRelaxed();
    847   guard_.ExclusiveUnlock(self);
    848   if (futex(sequence_.Address(), FUTEX_WAIT, cur_sequence, nullptr, nullptr, 0) != 0) {
    849     // Futex failed, check it is an expected error.
    850     // EAGAIN == EWOULDBLK, so we let the caller try again.
    851     // EINTR implies a signal was sent to this thread.
    852     if ((errno != EINTR) && (errno != EAGAIN)) {
    853       PLOG(FATAL) << "futex wait failed for " << name_;
    854     }
    855   }
    856   if (self != nullptr) {
    857     JNIEnvExt* const env = self->GetJniEnv();
    858     if (UNLIKELY(env != nullptr && env->runtime_deleted)) {
    859       CHECK(self->IsDaemon());
    860       // If the runtime has been deleted, then we cannot proceed. Just sleep forever. This may
    861       // occur for user daemon threads that get a spurious wakeup. This occurs for test 132 with
    862       // --host and --gdb.
    863       // After we wake up, the runtime may have been shutdown, which means that this condition may
    864       // have been deleted. It is not safe to retry the wait.
    865       SleepForever();
    866     }
    867   }
    868   guard_.ExclusiveLock(self);
    869   CHECK_GE(num_waiters_, 0);
    870   num_waiters_--;
    871   // We awoke and so no longer require awakes from the guard_'s unlock.
    872   CHECK_GE(guard_.num_contenders_.LoadRelaxed(), 0);
    873   guard_.num_contenders_--;
    874 #else
    875   uint64_t old_owner = guard_.exclusive_owner_;
    876   guard_.exclusive_owner_ = 0;
    877   guard_.recursion_count_ = 0;
    878   CHECK_MUTEX_CALL(pthread_cond_wait, (&cond_, &guard_.mutex_));
    879   guard_.exclusive_owner_ = old_owner;
    880 #endif
    881   guard_.recursion_count_ = old_recursion_count;
    882 }
    883 
    884 bool ConditionVariable::TimedWait(Thread* self, int64_t ms, int32_t ns) {
    885   DCHECK(self == nullptr || self == Thread::Current());
    886   bool timed_out = false;
    887   guard_.AssertExclusiveHeld(self);
    888   guard_.CheckSafeToWait(self);
    889   unsigned int old_recursion_count = guard_.recursion_count_;
    890 #if ART_USE_FUTEXES
    891   timespec rel_ts;
    892   InitTimeSpec(false, CLOCK_REALTIME, ms, ns, &rel_ts);
    893   num_waiters_++;
    894   // Ensure the Mutex is contended so that requeued threads are awoken.
    895   guard_.num_contenders_++;
    896   guard_.recursion_count_ = 1;
    897   int32_t cur_sequence = sequence_.LoadRelaxed();
    898   guard_.ExclusiveUnlock(self);
    899   if (futex(sequence_.Address(), FUTEX_WAIT, cur_sequence, &rel_ts, nullptr, 0) != 0) {
    900     if (errno == ETIMEDOUT) {
    901       // Timed out we're done.
    902       timed_out = true;
    903     } else if ((errno == EAGAIN) || (errno == EINTR)) {
    904       // A signal or ConditionVariable::Signal/Broadcast has come in.
    905     } else {
    906       PLOG(FATAL) << "timed futex wait failed for " << name_;
    907     }
    908   }
    909   guard_.ExclusiveLock(self);
    910   CHECK_GE(num_waiters_, 0);
    911   num_waiters_--;
    912   // We awoke and so no longer require awakes from the guard_'s unlock.
    913   CHECK_GE(guard_.num_contenders_.LoadRelaxed(), 0);
    914   guard_.num_contenders_--;
    915 #else
    916 #if !defined(__APPLE__)
    917   int clock = CLOCK_MONOTONIC;
    918 #else
    919   int clock = CLOCK_REALTIME;
    920 #endif
    921   uint64_t old_owner = guard_.exclusive_owner_;
    922   guard_.exclusive_owner_ = 0;
    923   guard_.recursion_count_ = 0;
    924   timespec ts;
    925   InitTimeSpec(true, clock, ms, ns, &ts);
    926   int rc = TEMP_FAILURE_RETRY(pthread_cond_timedwait(&cond_, &guard_.mutex_, &ts));
    927   if (rc == ETIMEDOUT) {
    928     timed_out = true;
    929   } else if (rc != 0) {
    930     errno = rc;
    931     PLOG(FATAL) << "TimedWait failed for " << name_;
    932   }
    933   guard_.exclusive_owner_ = old_owner;
    934 #endif
    935   guard_.recursion_count_ = old_recursion_count;
    936   return timed_out;
    937 }
    938 
    939 void Locks::Init() {
    940   if (logging_lock_ != nullptr) {
    941     // Already initialized.
    942     if (kRuntimeISA == kX86 || kRuntimeISA == kX86_64) {
    943       DCHECK(modify_ldt_lock_ != nullptr);
    944     } else {
    945       DCHECK(modify_ldt_lock_ == nullptr);
    946     }
    947     DCHECK(abort_lock_ != nullptr);
    948     DCHECK(alloc_tracker_lock_ != nullptr);
    949     DCHECK(allocated_monitor_ids_lock_ != nullptr);
    950     DCHECK(allocated_thread_ids_lock_ != nullptr);
    951     DCHECK(breakpoint_lock_ != nullptr);
    952     DCHECK(classlinker_classes_lock_ != nullptr);
    953     DCHECK(deoptimization_lock_ != nullptr);
    954     DCHECK(heap_bitmap_lock_ != nullptr);
    955     DCHECK(oat_file_manager_lock_ != nullptr);
    956     DCHECK(host_dlopen_handles_lock_ != nullptr);
    957     DCHECK(intern_table_lock_ != nullptr);
    958     DCHECK(jni_libraries_lock_ != nullptr);
    959     DCHECK(logging_lock_ != nullptr);
    960     DCHECK(mutator_lock_ != nullptr);
    961     DCHECK(profiler_lock_ != nullptr);
    962     DCHECK(thread_list_lock_ != nullptr);
    963     DCHECK(thread_suspend_count_lock_ != nullptr);
    964     DCHECK(trace_lock_ != nullptr);
    965     DCHECK(unexpected_signal_lock_ != nullptr);
    966     DCHECK(lambda_table_lock_ != nullptr);
    967   } else {
    968     // Create global locks in level order from highest lock level to lowest.
    969     LockLevel current_lock_level = kInstrumentEntrypointsLock;
    970     DCHECK(instrument_entrypoints_lock_ == nullptr);
    971     instrument_entrypoints_lock_ = new Mutex("instrument entrypoint lock", current_lock_level);
    972 
    973     #define UPDATE_CURRENT_LOCK_LEVEL(new_level) \
    974       if (new_level >= current_lock_level) { \
    975         /* Do not use CHECKs or FATAL here, abort_lock_ is not setup yet. */ \
    976         fprintf(stderr, "New local level %d is not less than current level %d\n", \
    977                 new_level, current_lock_level); \
    978         exit(1); \
    979       } \
    980       current_lock_level = new_level;
    981 
    982     UPDATE_CURRENT_LOCK_LEVEL(kMutatorLock);
    983     DCHECK(mutator_lock_ == nullptr);
    984     mutator_lock_ = new MutatorMutex("mutator lock", current_lock_level);
    985 
    986     UPDATE_CURRENT_LOCK_LEVEL(kHeapBitmapLock);
    987     DCHECK(heap_bitmap_lock_ == nullptr);
    988     heap_bitmap_lock_ = new ReaderWriterMutex("heap bitmap lock", current_lock_level);
    989 
    990     UPDATE_CURRENT_LOCK_LEVEL(kTraceLock);
    991     DCHECK(trace_lock_ == nullptr);
    992     trace_lock_ = new Mutex("trace lock", current_lock_level);
    993 
    994     UPDATE_CURRENT_LOCK_LEVEL(kRuntimeShutdownLock);
    995     DCHECK(runtime_shutdown_lock_ == nullptr);
    996     runtime_shutdown_lock_ = new Mutex("runtime shutdown lock", current_lock_level);
    997 
    998     UPDATE_CURRENT_LOCK_LEVEL(kProfilerLock);
    999     DCHECK(profiler_lock_ == nullptr);
   1000     profiler_lock_ = new Mutex("profiler lock", current_lock_level);
   1001 
   1002     UPDATE_CURRENT_LOCK_LEVEL(kDeoptimizationLock);
   1003     DCHECK(deoptimization_lock_ == nullptr);
   1004     deoptimization_lock_ = new Mutex("Deoptimization lock", current_lock_level);
   1005 
   1006     UPDATE_CURRENT_LOCK_LEVEL(kAllocTrackerLock);
   1007     DCHECK(alloc_tracker_lock_ == nullptr);
   1008     alloc_tracker_lock_ = new Mutex("AllocTracker lock", current_lock_level);
   1009 
   1010     UPDATE_CURRENT_LOCK_LEVEL(kThreadListLock);
   1011     DCHECK(thread_list_lock_ == nullptr);
   1012     thread_list_lock_ = new Mutex("thread list lock", current_lock_level);
   1013 
   1014     UPDATE_CURRENT_LOCK_LEVEL(kJniLoadLibraryLock);
   1015     DCHECK(jni_libraries_lock_ == nullptr);
   1016     jni_libraries_lock_ = new Mutex("JNI shared libraries map lock", current_lock_level);
   1017 
   1018     UPDATE_CURRENT_LOCK_LEVEL(kBreakpointLock);
   1019     DCHECK(breakpoint_lock_ == nullptr);
   1020     breakpoint_lock_ = new ReaderWriterMutex("breakpoint lock", current_lock_level);
   1021 
   1022     UPDATE_CURRENT_LOCK_LEVEL(kClassLinkerClassesLock);
   1023     DCHECK(classlinker_classes_lock_ == nullptr);
   1024     classlinker_classes_lock_ = new ReaderWriterMutex("ClassLinker classes lock",
   1025                                                       current_lock_level);
   1026 
   1027     UPDATE_CURRENT_LOCK_LEVEL(kMonitorPoolLock);
   1028     DCHECK(allocated_monitor_ids_lock_ == nullptr);
   1029     allocated_monitor_ids_lock_ =  new Mutex("allocated monitor ids lock", current_lock_level);
   1030 
   1031     UPDATE_CURRENT_LOCK_LEVEL(kAllocatedThreadIdsLock);
   1032     DCHECK(allocated_thread_ids_lock_ == nullptr);
   1033     allocated_thread_ids_lock_ =  new Mutex("allocated thread ids lock", current_lock_level);
   1034 
   1035     if (kRuntimeISA == kX86 || kRuntimeISA == kX86_64) {
   1036       UPDATE_CURRENT_LOCK_LEVEL(kModifyLdtLock);
   1037       DCHECK(modify_ldt_lock_ == nullptr);
   1038       modify_ldt_lock_ = new Mutex("modify_ldt lock", current_lock_level);
   1039     }
   1040 
   1041     UPDATE_CURRENT_LOCK_LEVEL(kOatFileManagerLock);
   1042     DCHECK(oat_file_manager_lock_ == nullptr);
   1043     oat_file_manager_lock_ = new ReaderWriterMutex("OatFile manager lock", current_lock_level);
   1044 
   1045     UPDATE_CURRENT_LOCK_LEVEL(kHostDlOpenHandlesLock);
   1046     DCHECK(host_dlopen_handles_lock_ == nullptr);
   1047     host_dlopen_handles_lock_ = new Mutex("host dlopen handles lock", current_lock_level);
   1048 
   1049     UPDATE_CURRENT_LOCK_LEVEL(kInternTableLock);
   1050     DCHECK(intern_table_lock_ == nullptr);
   1051     intern_table_lock_ = new Mutex("InternTable lock", current_lock_level);
   1052 
   1053     UPDATE_CURRENT_LOCK_LEVEL(kReferenceProcessorLock);
   1054     DCHECK(reference_processor_lock_ == nullptr);
   1055     reference_processor_lock_ = new Mutex("ReferenceProcessor lock", current_lock_level);
   1056 
   1057     UPDATE_CURRENT_LOCK_LEVEL(kReferenceQueueClearedReferencesLock);
   1058     DCHECK(reference_queue_cleared_references_lock_ == nullptr);
   1059     reference_queue_cleared_references_lock_ = new Mutex("ReferenceQueue cleared references lock", current_lock_level);
   1060 
   1061     UPDATE_CURRENT_LOCK_LEVEL(kReferenceQueueWeakReferencesLock);
   1062     DCHECK(reference_queue_weak_references_lock_ == nullptr);
   1063     reference_queue_weak_references_lock_ = new Mutex("ReferenceQueue cleared references lock", current_lock_level);
   1064 
   1065     UPDATE_CURRENT_LOCK_LEVEL(kReferenceQueueFinalizerReferencesLock);
   1066     DCHECK(reference_queue_finalizer_references_lock_ == nullptr);
   1067     reference_queue_finalizer_references_lock_ = new Mutex("ReferenceQueue finalizer references lock", current_lock_level);
   1068 
   1069     UPDATE_CURRENT_LOCK_LEVEL(kReferenceQueuePhantomReferencesLock);
   1070     DCHECK(reference_queue_phantom_references_lock_ == nullptr);
   1071     reference_queue_phantom_references_lock_ = new Mutex("ReferenceQueue phantom references lock", current_lock_level);
   1072 
   1073     UPDATE_CURRENT_LOCK_LEVEL(kReferenceQueueSoftReferencesLock);
   1074     DCHECK(reference_queue_soft_references_lock_ == nullptr);
   1075     reference_queue_soft_references_lock_ = new Mutex("ReferenceQueue soft references lock", current_lock_level);
   1076 
   1077     UPDATE_CURRENT_LOCK_LEVEL(kLambdaTableLock);
   1078     DCHECK(lambda_table_lock_ == nullptr);
   1079     lambda_table_lock_ = new Mutex("lambda table lock", current_lock_level);
   1080 
   1081     UPDATE_CURRENT_LOCK_LEVEL(kAbortLock);
   1082     DCHECK(abort_lock_ == nullptr);
   1083     abort_lock_ = new Mutex("abort lock", current_lock_level, true);
   1084 
   1085     UPDATE_CURRENT_LOCK_LEVEL(kThreadSuspendCountLock);
   1086     DCHECK(thread_suspend_count_lock_ == nullptr);
   1087     thread_suspend_count_lock_ = new Mutex("thread suspend count lock", current_lock_level);
   1088 
   1089     UPDATE_CURRENT_LOCK_LEVEL(kUnexpectedSignalLock);
   1090     DCHECK(unexpected_signal_lock_ == nullptr);
   1091     unexpected_signal_lock_ = new Mutex("unexpected signal lock", current_lock_level, true);
   1092 
   1093     UPDATE_CURRENT_LOCK_LEVEL(kMemMapsLock);
   1094     DCHECK(mem_maps_lock_ == nullptr);
   1095     mem_maps_lock_ = new Mutex("mem maps lock", current_lock_level);
   1096 
   1097     UPDATE_CURRENT_LOCK_LEVEL(kLoggingLock);
   1098     DCHECK(logging_lock_ == nullptr);
   1099     logging_lock_ = new Mutex("logging lock", current_lock_level, true);
   1100 
   1101     #undef UPDATE_CURRENT_LOCK_LEVEL
   1102 
   1103     InitConditions();
   1104   }
   1105 }
   1106 
   1107 void Locks::InitConditions() {
   1108   thread_exit_cond_ = new ConditionVariable("thread exit condition variable", *thread_list_lock_);
   1109 }
   1110 
   1111 }  // namespace art
   1112