From d9c4fc94fa618617f94e1de9af5f034549100753 Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Tue, 1 Oct 2013 19:45:43 -0700 Subject: Inflate contended lock word by suspending owner. Bug 6961405. Don't inflate monitors for Notify and NotifyAll. Tidy lock word, handle recursive lock case alongside unlocked case and move assembly out of line (except for ARM quick). Also handle null in out-of-line assembly as the test is quick and the enter/exit code is already a safepoint. To gain ownership of a monitor on behalf of another thread, monitor contenders must not hold the monitor_lock_, so they wait on a condition variable. Reduce size of per mutex contention log. Be consistent in calling thin lock thread ids just thread ids. Fix potential thread death races caused by the use of FindThreadByThreadId, make it invariant that returned threads are either self or suspended now. Code size reduction on ARM boot.oat 0.2%. Old nexus 7 speedup 0.25%, new nexus 7 speedup 1.4%, nexus 10 speedup 2.24%, nexus 4 speedup 2.09% on DeltaBlue. Change-Id: Id52558b914f160d9c8578fdd7fc8199a9598576a --- runtime/base/mutex.cc | 17 +++++++++-------- runtime/base/mutex.h | 2 +- 2 files changed, 10 insertions(+), 9 deletions(-) (limited to 'runtime/base') diff --git a/runtime/base/mutex.cc b/runtime/base/mutex.cc index b048bbb..249f031 100644 --- a/runtime/base/mutex.cc +++ b/runtime/base/mutex.cc @@ -54,17 +54,17 @@ struct AllMutexData { std::set* all_mutexes; AllMutexData() : all_mutexes(NULL) {} }; -static struct AllMutexData all_mutex_data[kAllMutexDataSize]; +static struct AllMutexData gAllMutexData[kAllMutexDataSize]; class ScopedAllMutexesLock { public: explicit ScopedAllMutexesLock(const BaseMutex* mutex) : mutex_(mutex) { - while (!all_mutex_data->all_mutexes_guard.compare_and_swap(0, reinterpret_cast(mutex))) { + while (!gAllMutexData->all_mutexes_guard.compare_and_swap(0, reinterpret_cast(mutex))) { NanoSleep(100); } } ~ScopedAllMutexesLock() { - while (!all_mutex_data->all_mutexes_guard.compare_and_swap(reinterpret_cast(mutex_), 0)) { + while (!gAllMutexData->all_mutexes_guard.compare_and_swap(reinterpret_cast(mutex_), 0)) { NanoSleep(100); } } @@ -75,7 +75,7 @@ class ScopedAllMutexesLock { BaseMutex::BaseMutex(const char* name, LockLevel level) : level_(level), name_(name) { if (kLogLockContentions) { ScopedAllMutexesLock mu(this); - std::set** all_mutexes_ptr = &all_mutex_data->all_mutexes; + std::set** all_mutexes_ptr = &gAllMutexData->all_mutexes; if (*all_mutexes_ptr == NULL) { // We leak the global set of all mutexes to avoid ordering issues in global variable // construction/destruction. @@ -88,7 +88,7 @@ BaseMutex::BaseMutex(const char* name, LockLevel level) : level_(level), name_(n BaseMutex::~BaseMutex() { if (kLogLockContentions) { ScopedAllMutexesLock mu(this); - all_mutex_data->all_mutexes->erase(this); + gAllMutexData->all_mutexes->erase(this); } } @@ -96,13 +96,13 @@ void BaseMutex::DumpAll(std::ostream& os) { if (kLogLockContentions) { os << "Mutex logging:\n"; ScopedAllMutexesLock mu(reinterpret_cast(-1)); - std::set* all_mutexes = all_mutex_data->all_mutexes; + std::set* all_mutexes = gAllMutexData->all_mutexes; if (all_mutexes == NULL) { // No mutexes have been created yet during at startup. return; } typedef std::set::const_iterator It; - os << "(Contented)\n"; + os << "(Contended)\n"; for (It it = all_mutexes->begin(); it != all_mutexes->end(); ++it) { BaseMutex* mutex = *it; if (mutex->HasEverContended()) { @@ -127,7 +127,8 @@ void BaseMutex::CheckSafeToWait(Thread* self) { return; } if (kDebugLocking) { - CHECK(self->GetHeldMutex(level_) == this) << "Waiting on unacquired mutex: " << name_; + CHECK(self->GetHeldMutex(level_) == this || level_ == kMonitorLock) + << "Waiting on unacquired mutex: " << name_; bool bad_mutexes_held = false; for (int i = kLockLevelCount - 1; i >= 0; --i) { if (i != level_) { diff --git a/runtime/base/mutex.h b/runtime/base/mutex.h index ee37388..feb8a6c 100644 --- a/runtime/base/mutex.h +++ b/runtime/base/mutex.h @@ -58,7 +58,7 @@ const bool kLogLockContentions = false; // futex. const bool kLogLockContentions = false; #endif -const size_t kContentionLogSize = 64; +const size_t kContentionLogSize = 4; const size_t kContentionLogDataSize = kLogLockContentions ? 1 : 0; const size_t kAllMutexDataSize = kLogLockContentions ? 1 : 0; -- cgit v1.1