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