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