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