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