| Elliott Hughes | 5f79133 | 2011-09-15 17:45:30 -0700 | [diff] [blame] | 1 | /* | 
 | 2 |  * Copyright (C) 2008 The Android Open Source Project | 
 | 3 |  * | 
 | 4 |  * Licensed under the Apache License, Version 2.0 (the "License"); | 
 | 5 |  * you may not use this file except in compliance with the License. | 
 | 6 |  * You may obtain a copy of the License at | 
 | 7 |  * | 
 | 8 |  *      http://www.apache.org/licenses/LICENSE-2.0 | 
 | 9 |  * | 
 | 10 |  * Unless required by applicable law or agreed to in writing, software | 
 | 11 |  * distributed under the License is distributed on an "AS IS" BASIS, | 
 | 12 |  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 
 | 13 |  * See the License for the specific language governing permissions and | 
 | 14 |  * limitations under the License. | 
 | 15 |  */ | 
 | 16 |  | 
| Elliott Hughes | 54e7df1 | 2011-09-16 11:47:04 -0700 | [diff] [blame] | 17 | #include "monitor.h" | 
| Elliott Hughes | 5f79133 | 2011-09-15 17:45:30 -0700 | [diff] [blame] | 18 |  | 
| Elliott Hughes | 08fc03a | 2012-06-26 17:34:00 -0700 | [diff] [blame] | 19 | #include <vector> | 
 | 20 |  | 
| Andreas Gampe | 46ee31b | 2016-12-14 10:11:49 -0800 | [diff] [blame] | 21 | #include "android-base/stringprintf.h" | 
 | 22 |  | 
| Mathieu Chartier | e401d14 | 2015-04-22 13:56:20 -0700 | [diff] [blame] | 23 | #include "art_method-inl.h" | 
| Elliott Hughes | 76b6167 | 2012-12-12 17:47:30 -0800 | [diff] [blame] | 24 | #include "base/mutex.h" | 
| Elliott Hughes | 1aa246d | 2012-12-13 09:29:36 -0800 | [diff] [blame] | 25 | #include "base/stl_util.h" | 
| Mathieu Chartier | 32ce2ad | 2016-03-04 14:58:03 -0800 | [diff] [blame] | 26 | #include "base/systrace.h" | 
| Vladimir Marko | 80afd02 | 2015-05-19 18:08:00 +0100 | [diff] [blame] | 27 | #include "base/time_utils.h" | 
| jeffhao | 33dc771 | 2011-11-09 17:54:24 -0800 | [diff] [blame] | 28 | #include "class_linker.h" | 
| Ian Rogers | 4f6ad8a | 2013-03-18 15:27:28 -0700 | [diff] [blame] | 29 | #include "dex_file-inl.h" | 
| Sebastien Hertz | 0f7c933 | 2015-11-05 15:57:30 +0100 | [diff] [blame] | 30 | #include "dex_instruction-inl.h" | 
| Ian Rogers | d9c4fc9 | 2013-10-01 19:45:43 -0700 | [diff] [blame] | 31 | #include "lock_word-inl.h" | 
| Ian Rogers | 4f6ad8a | 2013-03-18 15:27:28 -0700 | [diff] [blame] | 32 | #include "mirror/class-inl.h" | 
| Ian Rogers | 05f3057 | 2013-02-20 12:13:11 -0800 | [diff] [blame] | 33 | #include "mirror/object-inl.h" | 
| Mathieu Chartier | 0795f23 | 2016-09-27 18:43:30 -0700 | [diff] [blame] | 34 | #include "scoped_thread_state_change-inl.h" | 
| Elliott Hughes | 5f79133 | 2011-09-15 17:45:30 -0700 | [diff] [blame] | 35 | #include "thread.h" | 
| Elliott Hughes | 8e4aac5 | 2011-09-26 17:03:36 -0700 | [diff] [blame] | 36 | #include "thread_list.h" | 
| Elliott Hughes | 08fc03a | 2012-06-26 17:34:00 -0700 | [diff] [blame] | 37 | #include "verifier/method_verifier.h" | 
| Elliott Hughes | 044288f | 2012-06-25 14:46:39 -0700 | [diff] [blame] | 38 | #include "well_known_classes.h" | 
| Elliott Hughes | 5f79133 | 2011-09-15 17:45:30 -0700 | [diff] [blame] | 39 |  | 
 | 40 | namespace art { | 
 | 41 |  | 
| Andreas Gampe | 46ee31b | 2016-12-14 10:11:49 -0800 | [diff] [blame] | 42 | using android::base::StringPrintf; | 
 | 43 |  | 
| Mathieu Chartier | b9001ab | 2014-10-03 13:28:46 -0700 | [diff] [blame] | 44 | static constexpr uint64_t kLongWaitMs = 100; | 
 | 45 |  | 
| Elliott Hughes | 5f79133 | 2011-09-15 17:45:30 -0700 | [diff] [blame] | 46 | /* | 
| Ian Rogers | d9c4fc9 | 2013-10-01 19:45:43 -0700 | [diff] [blame] | 47 |  * Every Object has a monitor associated with it, but not every Object is actually locked.  Even | 
 | 48 |  * the ones that are locked do not need a full-fledged monitor until a) there is actual contention | 
 | 49 |  * or b) wait() is called on the Object. | 
| Elliott Hughes | 5f79133 | 2011-09-15 17:45:30 -0700 | [diff] [blame] | 50 |  * | 
| Ian Rogers | d9c4fc9 | 2013-10-01 19:45:43 -0700 | [diff] [blame] | 51 |  * For Android, we have implemented a scheme similar to the one described in Bacon et al.'s | 
 | 52 |  * "Thin locks: featherweight synchronization for Java" (ACM 1998).  Things are even easier for us, | 
 | 53 |  * though, because we have a full 32 bits to work with. | 
| Elliott Hughes | 5f79133 | 2011-09-15 17:45:30 -0700 | [diff] [blame] | 54 |  * | 
| Ian Rogers | d9c4fc9 | 2013-10-01 19:45:43 -0700 | [diff] [blame] | 55 |  * The two states of an Object's lock are referred to as "thin" and "fat".  A lock may transition | 
 | 56 |  * from the "thin" state to the "fat" state and this transition is referred to as inflation. Once | 
 | 57 |  * a lock has been inflated it remains in the "fat" state indefinitely. | 
| Elliott Hughes | 5f79133 | 2011-09-15 17:45:30 -0700 | [diff] [blame] | 58 |  * | 
| Ian Rogers | d9c4fc9 | 2013-10-01 19:45:43 -0700 | [diff] [blame] | 59 |  * The lock value itself is stored in mirror::Object::monitor_ and the representation is described | 
 | 60 |  * in the LockWord value type. | 
| Elliott Hughes | 54e7df1 | 2011-09-16 11:47:04 -0700 | [diff] [blame] | 61 |  * | 
| Elliott Hughes | 5f79133 | 2011-09-15 17:45:30 -0700 | [diff] [blame] | 62 |  * Monitors provide: | 
 | 63 |  *  - mutually exclusive access to resources | 
 | 64 |  *  - a way for multiple threads to wait for notification | 
 | 65 |  * | 
 | 66 |  * In effect, they fill the role of both mutexes and condition variables. | 
 | 67 |  * | 
| Ian Rogers | d9c4fc9 | 2013-10-01 19:45:43 -0700 | [diff] [blame] | 68 |  * Only one thread can own the monitor at any time.  There may be several threads waiting on it | 
 | 69 |  * (the wait call unlocks it).  One or more waiting threads may be getting interrupted or notified | 
 | 70 |  * at any given time. | 
| Elliott Hughes | 5f79133 | 2011-09-15 17:45:30 -0700 | [diff] [blame] | 71 |  */ | 
| Elliott Hughes | 54e7df1 | 2011-09-16 11:47:04 -0700 | [diff] [blame] | 72 |  | 
| Elliott Hughes | fc86162 | 2011-10-17 17:57:47 -0700 | [diff] [blame] | 73 | uint32_t Monitor::lock_profiling_threshold_ = 0; | 
| Elliott Hughes | 32d6e1e | 2011-10-11 14:47:44 -0700 | [diff] [blame] | 74 |  | 
| Calin Juravle | b2771b4 | 2016-04-07 17:09:25 +0100 | [diff] [blame] | 75 | void Monitor::Init(uint32_t lock_profiling_threshold) { | 
| Elliott Hughes | fc86162 | 2011-10-17 17:57:47 -0700 | [diff] [blame] | 76 |   lock_profiling_threshold_ = lock_profiling_threshold; | 
| Elliott Hughes | 32d6e1e | 2011-10-11 14:47:44 -0700 | [diff] [blame] | 77 | } | 
 | 78 |  | 
| Ian Rogers | ef7d42f | 2014-01-06 12:55:46 -0800 | [diff] [blame] | 79 | Monitor::Monitor(Thread* self, Thread* owner, mirror::Object* obj, int32_t hash_code) | 
| Ian Rogers | 00f7d0e | 2012-07-19 15:28:27 -0700 | [diff] [blame] | 80 |     : monitor_lock_("a monitor lock", kMonitorLock), | 
| Ian Rogers | d9c4fc9 | 2013-10-01 19:45:43 -0700 | [diff] [blame] | 81 |       monitor_contenders_("monitor contenders", monitor_lock_), | 
| Mathieu Chartier | 46bc778 | 2013-11-12 17:03:02 -0800 | [diff] [blame] | 82 |       num_waiters_(0), | 
| Ian Rogers | 00f7d0e | 2012-07-19 15:28:27 -0700 | [diff] [blame] | 83 |       owner_(owner), | 
| Elliott Hughes | 5f79133 | 2011-09-15 17:45:30 -0700 | [diff] [blame] | 84 |       lock_count_(0), | 
| Hiroshi Yamauchi | 94f7b49 | 2014-07-22 18:08:23 -0700 | [diff] [blame] | 85 |       obj_(GcRoot<mirror::Object>(obj)), | 
| Mathieu Chartier | 2cebb24 | 2015-04-21 16:50:40 -0700 | [diff] [blame] | 86 |       wait_set_(nullptr), | 
| Mathieu Chartier | ad2541a | 2013-10-25 10:05:23 -0700 | [diff] [blame] | 87 |       hash_code_(hash_code), | 
| Mathieu Chartier | 2cebb24 | 2015-04-21 16:50:40 -0700 | [diff] [blame] | 88 |       locking_method_(nullptr), | 
| Ian Rogers | ef7d42f | 2014-01-06 12:55:46 -0800 | [diff] [blame] | 89 |       locking_dex_pc_(0), | 
| Andreas Gampe | 7424081 | 2014-04-17 10:35:09 -0700 | [diff] [blame] | 90 |       monitor_id_(MonitorPool::ComputeMonitorId(this, self)) { | 
 | 91 | #ifdef __LP64__ | 
 | 92 |   DCHECK(false) << "Should not be reached in 64b"; | 
 | 93 |   next_free_ = nullptr; | 
 | 94 | #endif | 
 | 95 |   // We should only inflate a lock if the owner is ourselves or suspended. This avoids a race | 
 | 96 |   // with the owner unlocking the thin-lock. | 
 | 97 |   CHECK(owner == nullptr || owner == self || owner->IsSuspended()); | 
 | 98 |   // The identity hash code is set for the life time of the monitor. | 
 | 99 | } | 
 | 100 |  | 
 | 101 | Monitor::Monitor(Thread* self, Thread* owner, mirror::Object* obj, int32_t hash_code, | 
 | 102 |                  MonitorId id) | 
 | 103 |     : monitor_lock_("a monitor lock", kMonitorLock), | 
 | 104 |       monitor_contenders_("monitor contenders", monitor_lock_), | 
 | 105 |       num_waiters_(0), | 
 | 106 |       owner_(owner), | 
 | 107 |       lock_count_(0), | 
| Hiroshi Yamauchi | 94f7b49 | 2014-07-22 18:08:23 -0700 | [diff] [blame] | 108 |       obj_(GcRoot<mirror::Object>(obj)), | 
| Mathieu Chartier | 2cebb24 | 2015-04-21 16:50:40 -0700 | [diff] [blame] | 109 |       wait_set_(nullptr), | 
| Andreas Gampe | 7424081 | 2014-04-17 10:35:09 -0700 | [diff] [blame] | 110 |       hash_code_(hash_code), | 
| Mathieu Chartier | 2cebb24 | 2015-04-21 16:50:40 -0700 | [diff] [blame] | 111 |       locking_method_(nullptr), | 
| Andreas Gampe | 7424081 | 2014-04-17 10:35:09 -0700 | [diff] [blame] | 112 |       locking_dex_pc_(0), | 
 | 113 |       monitor_id_(id) { | 
 | 114 | #ifdef __LP64__ | 
 | 115 |   next_free_ = nullptr; | 
 | 116 | #endif | 
| Ian Rogers | d9c4fc9 | 2013-10-01 19:45:43 -0700 | [diff] [blame] | 117 |   // We should only inflate a lock if the owner is ourselves or suspended. This avoids a race | 
 | 118 |   // with the owner unlocking the thin-lock. | 
| Ian Rogers | ef7d42f | 2014-01-06 12:55:46 -0800 | [diff] [blame] | 119 |   CHECK(owner == nullptr || owner == self || owner->IsSuspended()); | 
| Mathieu Chartier | ad2541a | 2013-10-25 10:05:23 -0700 | [diff] [blame] | 120 |   // The identity hash code is set for the life time of the monitor. | 
| Ian Rogers | d9c4fc9 | 2013-10-01 19:45:43 -0700 | [diff] [blame] | 121 | } | 
 | 122 |  | 
| Mathieu Chartier | 4e6a31e | 2013-10-31 10:35:05 -0700 | [diff] [blame] | 123 | int32_t Monitor::GetHashCode() { | 
 | 124 |   while (!HasHashCode()) { | 
| Ian Rogers | 3e5cf30 | 2014-05-20 16:40:37 -0700 | [diff] [blame] | 125 |     if (hash_code_.CompareExchangeWeakRelaxed(0, mirror::Object::GenerateIdentityHashCode())) { | 
| Mathieu Chartier | 4e6a31e | 2013-10-31 10:35:05 -0700 | [diff] [blame] | 126 |       break; | 
 | 127 |     } | 
 | 128 |   } | 
 | 129 |   DCHECK(HasHashCode()); | 
| Ian Rogers | 3e5cf30 | 2014-05-20 16:40:37 -0700 | [diff] [blame] | 130 |   return hash_code_.LoadRelaxed(); | 
| Mathieu Chartier | 4e6a31e | 2013-10-31 10:35:05 -0700 | [diff] [blame] | 131 | } | 
 | 132 |  | 
| Ian Rogers | d9c4fc9 | 2013-10-01 19:45:43 -0700 | [diff] [blame] | 133 | bool Monitor::Install(Thread* self) { | 
 | 134 |   MutexLock mu(self, monitor_lock_);  // Uncontended mutex acquisition as monitor isn't yet public. | 
| Mathieu Chartier | ad2541a | 2013-10-25 10:05:23 -0700 | [diff] [blame] | 135 |   CHECK(owner_ == nullptr || owner_ == self || owner_->IsSuspended()); | 
| Ian Rogers | 00f7d0e | 2012-07-19 15:28:27 -0700 | [diff] [blame] | 136 |   // Propagate the lock state. | 
| Hiroshi Yamauchi | 4cba0d9 | 2014-05-21 21:10:23 -0700 | [diff] [blame] | 137 |   LockWord lw(GetObject()->GetLockWord(false)); | 
| Mathieu Chartier | ad2541a | 2013-10-25 10:05:23 -0700 | [diff] [blame] | 138 |   switch (lw.GetState()) { | 
 | 139 |     case LockWord::kThinLocked: { | 
 | 140 |       CHECK_EQ(owner_->GetThreadId(), lw.ThinLockOwner()); | 
 | 141 |       lock_count_ = lw.ThinLockCount(); | 
 | 142 |       break; | 
 | 143 |     } | 
 | 144 |     case LockWord::kHashCode: { | 
| Ian Rogers | 3e5cf30 | 2014-05-20 16:40:37 -0700 | [diff] [blame] | 145 |       CHECK_EQ(hash_code_.LoadRelaxed(), static_cast<int32_t>(lw.GetHashCode())); | 
| Mathieu Chartier | ad2541a | 2013-10-25 10:05:23 -0700 | [diff] [blame] | 146 |       break; | 
 | 147 |     } | 
 | 148 |     case LockWord::kFatLocked: { | 
 | 149 |       // The owner_ is suspended but another thread beat us to install a monitor. | 
 | 150 |       return false; | 
 | 151 |     } | 
 | 152 |     case LockWord::kUnlocked: { | 
 | 153 |       LOG(FATAL) << "Inflating unlocked lock word"; | 
 | 154 |       break; | 
 | 155 |     } | 
| Mathieu Chartier | 590fee9 | 2013-09-13 13:46:47 -0700 | [diff] [blame] | 156 |     default: { | 
 | 157 |       LOG(FATAL) << "Invalid monitor state " << lw.GetState(); | 
 | 158 |       return false; | 
 | 159 |     } | 
| Ian Rogers | 00f7d0e | 2012-07-19 15:28:27 -0700 | [diff] [blame] | 160 |   } | 
| Mathieu Chartier | 36a270a | 2016-07-28 18:08:51 -0700 | [diff] [blame] | 161 |   LockWord fat(this, lw.GCState()); | 
| Ian Rogers | d9c4fc9 | 2013-10-01 19:45:43 -0700 | [diff] [blame] | 162 |   // Publish the updated lock word, which may race with other threads. | 
| Hans Boehm | b3da36c | 2016-12-15 13:12:59 -0800 | [diff] [blame] | 163 |   bool success = GetObject()->CasLockWordWeakRelease(lw, fat); | 
| Ian Rogers | d9c4fc9 | 2013-10-01 19:45:43 -0700 | [diff] [blame] | 164 |   // Lock profiling. | 
| Mathieu Chartier | 9728f91 | 2013-10-30 09:45:13 -0700 | [diff] [blame] | 165 |   if (success && owner_ != nullptr && lock_profiling_threshold_ != 0) { | 
| Andreas Gampe | 6ec8ebd | 2014-07-25 13:36:56 -0700 | [diff] [blame] | 166 |     // Do not abort on dex pc errors. This can easily happen when we want to dump a stack trace on | 
 | 167 |     // abort. | 
 | 168 |     locking_method_ = owner_->GetCurrentMethod(&locking_dex_pc_, false); | 
| Ian Rogers | d9c4fc9 | 2013-10-01 19:45:43 -0700 | [diff] [blame] | 169 |   } | 
 | 170 |   return success; | 
| Elliott Hughes | 5f79133 | 2011-09-15 17:45:30 -0700 | [diff] [blame] | 171 | } | 
 | 172 |  | 
 | 173 | Monitor::~Monitor() { | 
| Mathieu Chartier | 590fee9 | 2013-09-13 13:46:47 -0700 | [diff] [blame] | 174 |   // Deflated monitors have a null object. | 
| Elliott Hughes | 5f79133 | 2011-09-15 17:45:30 -0700 | [diff] [blame] | 175 | } | 
 | 176 |  | 
| Elliott Hughes | 5f79133 | 2011-09-15 17:45:30 -0700 | [diff] [blame] | 177 | void Monitor::AppendToWaitSet(Thread* thread) { | 
 | 178 |   DCHECK(owner_ == Thread::Current()); | 
| Mathieu Chartier | 2cebb24 | 2015-04-21 16:50:40 -0700 | [diff] [blame] | 179 |   DCHECK(thread != nullptr); | 
| Ian Rogers | dd7624d | 2014-03-14 17:43:00 -0700 | [diff] [blame] | 180 |   DCHECK(thread->GetWaitNext() == nullptr) << thread->GetWaitNext(); | 
| Mathieu Chartier | 2cebb24 | 2015-04-21 16:50:40 -0700 | [diff] [blame] | 181 |   if (wait_set_ == nullptr) { | 
| Elliott Hughes | 5f79133 | 2011-09-15 17:45:30 -0700 | [diff] [blame] | 182 |     wait_set_ = thread; | 
 | 183 |     return; | 
 | 184 |   } | 
 | 185 |  | 
 | 186 |   // push_back. | 
 | 187 |   Thread* t = wait_set_; | 
| Ian Rogers | dd7624d | 2014-03-14 17:43:00 -0700 | [diff] [blame] | 188 |   while (t->GetWaitNext() != nullptr) { | 
 | 189 |     t = t->GetWaitNext(); | 
| Elliott Hughes | 5f79133 | 2011-09-15 17:45:30 -0700 | [diff] [blame] | 190 |   } | 
| Ian Rogers | dd7624d | 2014-03-14 17:43:00 -0700 | [diff] [blame] | 191 |   t->SetWaitNext(thread); | 
| Elliott Hughes | 5f79133 | 2011-09-15 17:45:30 -0700 | [diff] [blame] | 192 | } | 
 | 193 |  | 
| Elliott Hughes | 5f79133 | 2011-09-15 17:45:30 -0700 | [diff] [blame] | 194 | void Monitor::RemoveFromWaitSet(Thread *thread) { | 
 | 195 |   DCHECK(owner_ == Thread::Current()); | 
| Mathieu Chartier | 2cebb24 | 2015-04-21 16:50:40 -0700 | [diff] [blame] | 196 |   DCHECK(thread != nullptr); | 
 | 197 |   if (wait_set_ == nullptr) { | 
| Elliott Hughes | 5f79133 | 2011-09-15 17:45:30 -0700 | [diff] [blame] | 198 |     return; | 
 | 199 |   } | 
 | 200 |   if (wait_set_ == thread) { | 
| Ian Rogers | dd7624d | 2014-03-14 17:43:00 -0700 | [diff] [blame] | 201 |     wait_set_ = thread->GetWaitNext(); | 
 | 202 |     thread->SetWaitNext(nullptr); | 
| Elliott Hughes | 5f79133 | 2011-09-15 17:45:30 -0700 | [diff] [blame] | 203 |     return; | 
 | 204 |   } | 
 | 205 |  | 
 | 206 |   Thread* t = wait_set_; | 
| Mathieu Chartier | 2cebb24 | 2015-04-21 16:50:40 -0700 | [diff] [blame] | 207 |   while (t->GetWaitNext() != nullptr) { | 
| Ian Rogers | dd7624d | 2014-03-14 17:43:00 -0700 | [diff] [blame] | 208 |     if (t->GetWaitNext() == thread) { | 
 | 209 |       t->SetWaitNext(thread->GetWaitNext()); | 
 | 210 |       thread->SetWaitNext(nullptr); | 
| Elliott Hughes | 5f79133 | 2011-09-15 17:45:30 -0700 | [diff] [blame] | 211 |       return; | 
 | 212 |     } | 
| Ian Rogers | dd7624d | 2014-03-14 17:43:00 -0700 | [diff] [blame] | 213 |     t = t->GetWaitNext(); | 
| Elliott Hughes | 5f79133 | 2011-09-15 17:45:30 -0700 | [diff] [blame] | 214 |   } | 
 | 215 | } | 
 | 216 |  | 
| Mathieu Chartier | 6aa3df9 | 2013-09-17 15:17:28 -0700 | [diff] [blame] | 217 | void Monitor::SetObject(mirror::Object* object) { | 
| Hiroshi Yamauchi | 94f7b49 | 2014-07-22 18:08:23 -0700 | [diff] [blame] | 218 |   obj_ = GcRoot<mirror::Object>(object); | 
| Mathieu Chartier | 6aa3df9 | 2013-09-17 15:17:28 -0700 | [diff] [blame] | 219 | } | 
 | 220 |  | 
| Andreas Gampe | c7ed09b | 2016-04-25 20:08:55 -0700 | [diff] [blame] | 221 | // Note: Adapted from CurrentMethodVisitor in thread.cc. We must not resolve here. | 
 | 222 |  | 
 | 223 | struct NthCallerWithDexPcVisitor FINAL : public StackVisitor { | 
 | 224 |   explicit NthCallerWithDexPcVisitor(Thread* thread, size_t frame) | 
| Andreas Gampe | bdf7f1c | 2016-08-30 16:38:47 -0700 | [diff] [blame] | 225 |       REQUIRES_SHARED(Locks::mutator_lock_) | 
| Nicolas Geoffray | c6df1e3 | 2016-07-04 10:15:47 +0100 | [diff] [blame] | 226 |       : StackVisitor(thread, nullptr, StackVisitor::StackWalkKind::kIncludeInlinedFrames), | 
| Andreas Gampe | c7ed09b | 2016-04-25 20:08:55 -0700 | [diff] [blame] | 227 |         method_(nullptr), | 
 | 228 |         dex_pc_(0), | 
 | 229 |         current_frame_number_(0), | 
 | 230 |         wanted_frame_number_(frame) {} | 
| Andreas Gampe | bdf7f1c | 2016-08-30 16:38:47 -0700 | [diff] [blame] | 231 |   bool VisitFrame() OVERRIDE REQUIRES_SHARED(Locks::mutator_lock_) { | 
| Andreas Gampe | c7ed09b | 2016-04-25 20:08:55 -0700 | [diff] [blame] | 232 |     ArtMethod* m = GetMethod(); | 
 | 233 |     if (m == nullptr || m->IsRuntimeMethod()) { | 
 | 234 |       // Runtime method, upcall, or resolution issue. Skip. | 
 | 235 |       return true; | 
 | 236 |     } | 
 | 237 |  | 
 | 238 |     // Is this the requested frame? | 
 | 239 |     if (current_frame_number_ == wanted_frame_number_) { | 
 | 240 |       method_ = m; | 
 | 241 |       dex_pc_ = GetDexPc(false /* abort_on_error*/); | 
 | 242 |       return false; | 
 | 243 |     } | 
 | 244 |  | 
 | 245 |     // Look for more. | 
 | 246 |     current_frame_number_++; | 
 | 247 |     return true; | 
 | 248 |   } | 
 | 249 |  | 
 | 250 |   ArtMethod* method_; | 
 | 251 |   uint32_t dex_pc_; | 
 | 252 |  | 
 | 253 |  private: | 
 | 254 |   size_t current_frame_number_; | 
 | 255 |   const size_t wanted_frame_number_; | 
 | 256 | }; | 
 | 257 |  | 
 | 258 | // This function is inlined and just helps to not have the VLOG and ATRACE check at all the | 
 | 259 | // potential tracing points. | 
 | 260 | void Monitor::AtraceMonitorLock(Thread* self, mirror::Object* obj, bool is_wait) { | 
 | 261 |   if (UNLIKELY(VLOG_IS_ON(systrace_lock_logging) && ATRACE_ENABLED())) { | 
 | 262 |     AtraceMonitorLockImpl(self, obj, is_wait); | 
 | 263 |   } | 
 | 264 | } | 
 | 265 |  | 
 | 266 | void Monitor::AtraceMonitorLockImpl(Thread* self, mirror::Object* obj, bool is_wait) { | 
 | 267 |   // Wait() requires a deeper call stack to be useful. Otherwise you'll see "Waiting at | 
 | 268 |   // Object.java". Assume that we'll wait a nontrivial amount, so it's OK to do a longer | 
 | 269 |   // stack walk than if !is_wait. | 
 | 270 |   NthCallerWithDexPcVisitor visitor(self, is_wait ? 1U : 0U); | 
 | 271 |   visitor.WalkStack(false); | 
 | 272 |   const char* prefix = is_wait ? "Waiting on " : "Locking "; | 
 | 273 |  | 
 | 274 |   const char* filename; | 
 | 275 |   int32_t line_number; | 
 | 276 |   TranslateLocation(visitor.method_, visitor.dex_pc_, &filename, &line_number); | 
 | 277 |  | 
 | 278 |   // It would be nice to have a stable "ID" for the object here. However, the only stable thing | 
 | 279 |   // would be the identity hashcode. But we cannot use IdentityHashcode here: For one, there are | 
 | 280 |   // times when it is unsafe to make that call (see stack dumping for an explanation). More | 
 | 281 |   // importantly, we would have to give up on thin-locking when adding systrace locks, as the | 
 | 282 |   // identity hashcode is stored in the lockword normally (so can't be used with thin-locks). | 
 | 283 |   // | 
 | 284 |   // Because of thin-locks we also cannot use the monitor id (as there is no monitor). Monitor ids | 
 | 285 |   // also do not have to be stable, as the monitor may be deflated. | 
 | 286 |   std::string tmp = StringPrintf("%s %d at %s:%d", | 
 | 287 |       prefix, | 
 | 288 |       (obj == nullptr ? -1 : static_cast<int32_t>(reinterpret_cast<uintptr_t>(obj))), | 
 | 289 |       (filename != nullptr ? filename : "null"), | 
 | 290 |       line_number); | 
 | 291 |   ATRACE_BEGIN(tmp.c_str()); | 
 | 292 | } | 
 | 293 |  | 
 | 294 | void Monitor::AtraceMonitorUnlock() { | 
 | 295 |   if (UNLIKELY(VLOG_IS_ON(systrace_lock_logging))) { | 
 | 296 |     ATRACE_END(); | 
 | 297 |   } | 
 | 298 | } | 
 | 299 |  | 
| Mathieu Chartier | 0ffdc9c | 2016-04-19 13:46:03 -0700 | [diff] [blame] | 300 | std::string Monitor::PrettyContentionInfo(const std::string& owner_name, | 
 | 301 |                                           pid_t owner_tid, | 
| Mathieu Chartier | 74b3c8f | 2016-04-15 19:11:45 -0700 | [diff] [blame] | 302 |                                           ArtMethod* owners_method, | 
 | 303 |                                           uint32_t owners_dex_pc, | 
 | 304 |                                           size_t num_waiters) { | 
| Hiroshi Yamauchi | 71cd68d | 2017-01-25 18:28:12 -0800 | [diff] [blame] | 305 |   Locks::mutator_lock_->AssertSharedHeld(Thread::Current()); | 
| Mathieu Chartier | 74b3c8f | 2016-04-15 19:11:45 -0700 | [diff] [blame] | 306 |   const char* owners_filename; | 
| Goran Jakovljevic | 49c882b | 2016-04-19 10:27:21 +0200 | [diff] [blame] | 307 |   int32_t owners_line_number = 0; | 
| Mathieu Chartier | 74b3c8f | 2016-04-15 19:11:45 -0700 | [diff] [blame] | 308 |   if (owners_method != nullptr) { | 
 | 309 |     TranslateLocation(owners_method, owners_dex_pc, &owners_filename, &owners_line_number); | 
 | 310 |   } | 
 | 311 |   std::ostringstream oss; | 
| Mathieu Chartier | 0ffdc9c | 2016-04-19 13:46:03 -0700 | [diff] [blame] | 312 |   oss << "monitor contention with owner " << owner_name << " (" << owner_tid << ")"; | 
| Mathieu Chartier | 74b3c8f | 2016-04-15 19:11:45 -0700 | [diff] [blame] | 313 |   if (owners_method != nullptr) { | 
| David Sehr | 709b070 | 2016-10-13 09:12:37 -0700 | [diff] [blame] | 314 |     oss << " at " << owners_method->PrettyMethod(); | 
| Mathieu Chartier | 36891fe | 2016-04-28 17:21:08 -0700 | [diff] [blame] | 315 |     oss << "(" << owners_filename << ":" << owners_line_number << ")"; | 
| Mathieu Chartier | 74b3c8f | 2016-04-15 19:11:45 -0700 | [diff] [blame] | 316 |   } | 
 | 317 |   oss << " waiters=" << num_waiters; | 
 | 318 |   return oss.str(); | 
 | 319 | } | 
 | 320 |  | 
| Mathieu Chartier | 4b0ef1c | 2016-07-29 16:26:01 -0700 | [diff] [blame] | 321 | bool Monitor::TryLockLocked(Thread* self) { | 
 | 322 |   if (owner_ == nullptr) {  // Unowned. | 
 | 323 |     owner_ = self; | 
 | 324 |     CHECK_EQ(lock_count_, 0); | 
 | 325 |     // When debugging, save the current monitor holder for future | 
 | 326 |     // acquisition failures to use in sampled logging. | 
 | 327 |     if (lock_profiling_threshold_ != 0) { | 
 | 328 |       locking_method_ = self->GetCurrentMethod(&locking_dex_pc_); | 
 | 329 |     } | 
 | 330 |   } else if (owner_ == self) {  // Recursive. | 
 | 331 |     lock_count_++; | 
 | 332 |   } else { | 
 | 333 |     return false; | 
 | 334 |   } | 
 | 335 |   AtraceMonitorLock(self, GetObject(), false /* is_wait */); | 
 | 336 |   return true; | 
 | 337 | } | 
 | 338 |  | 
 | 339 | bool Monitor::TryLock(Thread* self) { | 
 | 340 |   MutexLock mu(self, monitor_lock_); | 
 | 341 |   return TryLockLocked(self); | 
 | 342 | } | 
 | 343 |  | 
| Elliott Hughes | 5f79133 | 2011-09-15 17:45:30 -0700 | [diff] [blame] | 344 | void Monitor::Lock(Thread* self) { | 
| Ian Rogers | d9c4fc9 | 2013-10-01 19:45:43 -0700 | [diff] [blame] | 345 |   MutexLock mu(self, monitor_lock_); | 
 | 346 |   while (true) { | 
| Mathieu Chartier | 4b0ef1c | 2016-07-29 16:26:01 -0700 | [diff] [blame] | 347 |     if (TryLockLocked(self)) { | 
 | 348 |       return; | 
| Ian Rogers | d9c4fc9 | 2013-10-01 19:45:43 -0700 | [diff] [blame] | 349 |     } | 
 | 350 |     // Contended. | 
 | 351 |     const bool log_contention = (lock_profiling_threshold_ != 0); | 
| Xin Guan | b894a19 | 2014-08-22 11:55:37 -0500 | [diff] [blame] | 352 |     uint64_t wait_start_ms = log_contention ? MilliTime() : 0; | 
| Mathieu Chartier | e401d14 | 2015-04-22 13:56:20 -0700 | [diff] [blame] | 353 |     ArtMethod* owners_method = locking_method_; | 
| Ian Rogers | d9c4fc9 | 2013-10-01 19:45:43 -0700 | [diff] [blame] | 354 |     uint32_t owners_dex_pc = locking_dex_pc_; | 
| Mathieu Chartier | 440e4ce | 2014-03-31 16:36:35 -0700 | [diff] [blame] | 355 |     // Do this before releasing the lock so that we don't get deflated. | 
| Mathieu Chartier | b9001ab | 2014-10-03 13:28:46 -0700 | [diff] [blame] | 356 |     size_t num_waiters = num_waiters_; | 
| Mathieu Chartier | 440e4ce | 2014-03-31 16:36:35 -0700 | [diff] [blame] | 357 |     ++num_waiters_; | 
| Andreas Gampe | 2702d56 | 2017-02-06 09:48:00 -0800 | [diff] [blame] | 358 |  | 
 | 359 |     // If systrace logging is enabled, first look at the lock owner. Acquiring the monitor's | 
 | 360 |     // lock and then re-acquiring the mutator lock can deadlock. | 
 | 361 |     bool started_trace = false; | 
 | 362 |     if (ATRACE_ENABLED()) { | 
 | 363 |       if (owner_ != nullptr) {  // Did the owner_ give the lock up? | 
 | 364 |         std::ostringstream oss; | 
 | 365 |         std::string name; | 
 | 366 |         owner_->GetThreadName(name); | 
 | 367 |         oss << PrettyContentionInfo(name, | 
 | 368 |                                     owner_->GetTid(), | 
 | 369 |                                     owners_method, | 
 | 370 |                                     owners_dex_pc, | 
 | 371 |                                     num_waiters); | 
 | 372 |         // Add info for contending thread. | 
 | 373 |         uint32_t pc; | 
 | 374 |         ArtMethod* m = self->GetCurrentMethod(&pc); | 
 | 375 |         const char* filename; | 
 | 376 |         int32_t line_number; | 
 | 377 |         TranslateLocation(m, pc, &filename, &line_number); | 
 | 378 |         oss << " blocking from " | 
 | 379 |             << ArtMethod::PrettyMethod(m) << "(" << (filename != nullptr ? filename : "null") | 
 | 380 |             << ":" << line_number << ")"; | 
 | 381 |         ATRACE_BEGIN(oss.str().c_str()); | 
 | 382 |         started_trace = true; | 
 | 383 |       } | 
 | 384 |     } | 
 | 385 |  | 
| Ian Rogers | d9c4fc9 | 2013-10-01 19:45:43 -0700 | [diff] [blame] | 386 |     monitor_lock_.Unlock(self);  // Let go of locks in order. | 
| Mathieu Chartier | a6e7f08 | 2014-05-22 14:43:37 -0700 | [diff] [blame] | 387 |     self->SetMonitorEnterObject(GetObject()); | 
| Elliott Hughes | 5f79133 | 2011-09-15 17:45:30 -0700 | [diff] [blame] | 388 |     { | 
| Hiroshi Yamauchi | 71cd68d | 2017-01-25 18:28:12 -0800 | [diff] [blame] | 389 |       ScopedThreadSuspension tsc(self, kBlocked);  // Change to blocked and give up mutator_lock_. | 
| Andreas Gampe | 2702d56 | 2017-02-06 09:48:00 -0800 | [diff] [blame] | 390 |       uint32_t original_owner_thread_id = 0u; | 
| Mathieu Chartier | 61b3cd4 | 2016-04-18 11:43:29 -0700 | [diff] [blame] | 391 |       { | 
 | 392 |         // Reacquire monitor_lock_ without mutator_lock_ for Wait. | 
 | 393 |         MutexLock mu2(self, monitor_lock_); | 
 | 394 |         if (owner_ != nullptr) {  // Did the owner_ give the lock up? | 
 | 395 |           original_owner_thread_id = owner_->GetThreadId(); | 
| Mathieu Chartier | 61b3cd4 | 2016-04-18 11:43:29 -0700 | [diff] [blame] | 396 |           monitor_contenders_.Wait(self);  // Still contended so wait. | 
| Mathieu Chartier | f0dc8b5 | 2014-12-17 10:13:30 -0800 | [diff] [blame] | 397 |         } | 
| Mathieu Chartier | 61b3cd4 | 2016-04-18 11:43:29 -0700 | [diff] [blame] | 398 |       } | 
 | 399 |       if (original_owner_thread_id != 0u) { | 
| Ian Rogers | d9c4fc9 | 2013-10-01 19:45:43 -0700 | [diff] [blame] | 400 |         // Woken from contention. | 
 | 401 |         if (log_contention) { | 
| Mathieu Chartier | 0ffdc9c | 2016-04-19 13:46:03 -0700 | [diff] [blame] | 402 |           uint32_t original_owner_tid = 0; | 
 | 403 |           std::string original_owner_name; | 
 | 404 |           { | 
 | 405 |             MutexLock mu2(Thread::Current(), *Locks::thread_list_lock_); | 
 | 406 |             // Re-find the owner in case the thread got killed. | 
 | 407 |             Thread* original_owner = Runtime::Current()->GetThreadList()->FindThreadByThreadId( | 
 | 408 |                 original_owner_thread_id); | 
 | 409 |             // Do not do any work that requires the mutator lock. | 
 | 410 |             if (original_owner != nullptr) { | 
 | 411 |               original_owner_tid = original_owner->GetTid(); | 
 | 412 |               original_owner->GetThreadName(original_owner_name); | 
 | 413 |             } | 
 | 414 |           } | 
 | 415 |  | 
 | 416 |           if (original_owner_tid != 0u) { | 
| Mathieu Chartier | 61b3cd4 | 2016-04-18 11:43:29 -0700 | [diff] [blame] | 417 |             uint64_t wait_ms = MilliTime() - wait_start_ms; | 
 | 418 |             uint32_t sample_percent; | 
 | 419 |             if (wait_ms >= lock_profiling_threshold_) { | 
 | 420 |               sample_percent = 100; | 
 | 421 |             } else { | 
 | 422 |               sample_percent = 100 * wait_ms / lock_profiling_threshold_; | 
| Mathieu Chartier | 74b3c8f | 2016-04-15 19:11:45 -0700 | [diff] [blame] | 423 |             } | 
| Mathieu Chartier | 61b3cd4 | 2016-04-18 11:43:29 -0700 | [diff] [blame] | 424 |             if (sample_percent != 0 && (static_cast<uint32_t>(rand() % 100) < sample_percent)) { | 
| Hiroshi Yamauchi | 71cd68d | 2017-01-25 18:28:12 -0800 | [diff] [blame] | 425 |               // Reacquire mutator_lock_ for logging. | 
 | 426 |               ScopedObjectAccess soa(self); | 
| Mathieu Chartier | 61b3cd4 | 2016-04-18 11:43:29 -0700 | [diff] [blame] | 427 |               if (wait_ms > kLongWaitMs && owners_method != nullptr) { | 
| Mathieu Chartier | 36891fe | 2016-04-28 17:21:08 -0700 | [diff] [blame] | 428 |                 uint32_t pc; | 
 | 429 |                 ArtMethod* m = self->GetCurrentMethod(&pc); | 
| Mathieu Chartier | 61b3cd4 | 2016-04-18 11:43:29 -0700 | [diff] [blame] | 430 |                 // TODO: We should maybe check that original_owner is still a live thread. | 
 | 431 |                 LOG(WARNING) << "Long " | 
| Mathieu Chartier | 0ffdc9c | 2016-04-19 13:46:03 -0700 | [diff] [blame] | 432 |                     << PrettyContentionInfo(original_owner_name, | 
 | 433 |                                             original_owner_tid, | 
| Mathieu Chartier | 61b3cd4 | 2016-04-18 11:43:29 -0700 | [diff] [blame] | 434 |                                             owners_method, | 
 | 435 |                                             owners_dex_pc, | 
 | 436 |                                             num_waiters) | 
| David Sehr | 709b070 | 2016-10-13 09:12:37 -0700 | [diff] [blame] | 437 |                     << " in " << ArtMethod::PrettyMethod(m) << " for " | 
 | 438 |                     << PrettyDuration(MsToNs(wait_ms)); | 
| Mathieu Chartier | 61b3cd4 | 2016-04-18 11:43:29 -0700 | [diff] [blame] | 439 |               } | 
 | 440 |               const char* owners_filename; | 
 | 441 |               int32_t owners_line_number; | 
 | 442 |               TranslateLocation(owners_method, | 
 | 443 |                                 owners_dex_pc, | 
 | 444 |                                 &owners_filename, | 
 | 445 |                                 &owners_line_number); | 
 | 446 |               LogContentionEvent(self, | 
 | 447 |                                  wait_ms, | 
 | 448 |                                  sample_percent, | 
 | 449 |                                  owners_filename, | 
 | 450 |                                  owners_line_number); | 
 | 451 |             } | 
| Ian Rogers | d9c4fc9 | 2013-10-01 19:45:43 -0700 | [diff] [blame] | 452 |           } | 
 | 453 |         } | 
| Elliott Hughes | fc86162 | 2011-10-17 17:57:47 -0700 | [diff] [blame] | 454 |       } | 
| Elliott Hughes | 5f79133 | 2011-09-15 17:45:30 -0700 | [diff] [blame] | 455 |     } | 
| Andreas Gampe | 2702d56 | 2017-02-06 09:48:00 -0800 | [diff] [blame] | 456 |     if (started_trace) { | 
 | 457 |       ATRACE_END(); | 
 | 458 |     } | 
| Mathieu Chartier | a6e7f08 | 2014-05-22 14:43:37 -0700 | [diff] [blame] | 459 |     self->SetMonitorEnterObject(nullptr); | 
| Ian Rogers | d9c4fc9 | 2013-10-01 19:45:43 -0700 | [diff] [blame] | 460 |     monitor_lock_.Lock(self);  // Reacquire locks in order. | 
| Mathieu Chartier | 440e4ce | 2014-03-31 16:36:35 -0700 | [diff] [blame] | 461 |     --num_waiters_; | 
| Elliott Hughes | fc86162 | 2011-10-17 17:57:47 -0700 | [diff] [blame] | 462 |   } | 
| Elliott Hughes | 5f79133 | 2011-09-15 17:45:30 -0700 | [diff] [blame] | 463 | } | 
 | 464 |  | 
| Ian Rogers | 6d0b13e | 2012-02-07 09:25:29 -0800 | [diff] [blame] | 465 | static void ThrowIllegalMonitorStateExceptionF(const char* fmt, ...) | 
 | 466 |                                               __attribute__((format(printf, 1, 2))); | 
 | 467 |  | 
| Ian Rogers | 00f7d0e | 2012-07-19 15:28:27 -0700 | [diff] [blame] | 468 | static void ThrowIllegalMonitorStateExceptionF(const char* fmt, ...) | 
| Andreas Gampe | bdf7f1c | 2016-08-30 16:38:47 -0700 | [diff] [blame] | 469 |     REQUIRES_SHARED(Locks::mutator_lock_) { | 
| Ian Rogers | 6d0b13e | 2012-02-07 09:25:29 -0800 | [diff] [blame] | 470 |   va_list args; | 
 | 471 |   va_start(args, fmt); | 
| Ian Rogers | 62d6c77 | 2013-02-27 08:32:07 -0800 | [diff] [blame] | 472 |   Thread* self = Thread::Current(); | 
| Nicolas Geoffray | 0aa50ce | 2015-03-10 11:03:29 +0000 | [diff] [blame] | 473 |   self->ThrowNewExceptionV("Ljava/lang/IllegalMonitorStateException;", fmt, args); | 
| Ian Rogers | d9c4fc9 | 2013-10-01 19:45:43 -0700 | [diff] [blame] | 474 |   if (!Runtime::Current()->IsStarted() || VLOG_IS_ON(monitor)) { | 
| Brian Carlstrom | 64277f3 | 2012-03-26 23:53:34 -0700 | [diff] [blame] | 475 |     std::ostringstream ss; | 
| Ian Rogers | 62d6c77 | 2013-02-27 08:32:07 -0800 | [diff] [blame] | 476 |     self->Dump(ss); | 
| Andreas Gampe | 3fec9ac | 2016-09-13 10:47:28 -0700 | [diff] [blame] | 477 |     LOG(Runtime::Current()->IsStarted() ? ::android::base::INFO : ::android::base::ERROR) | 
| Nicolas Geoffray | 14691c5 | 2015-03-05 10:40:17 +0000 | [diff] [blame] | 478 |         << self->GetException()->Dump() << "\n" << ss.str(); | 
| Brian Carlstrom | 64277f3 | 2012-03-26 23:53:34 -0700 | [diff] [blame] | 479 |   } | 
| Ian Rogers | 6d0b13e | 2012-02-07 09:25:29 -0800 | [diff] [blame] | 480 |   va_end(args); | 
 | 481 | } | 
 | 482 |  | 
| Elliott Hughes | d423741 | 2012-02-21 11:24:45 -0800 | [diff] [blame] | 483 | static std::string ThreadToString(Thread* thread) { | 
| Mathieu Chartier | 2cebb24 | 2015-04-21 16:50:40 -0700 | [diff] [blame] | 484 |   if (thread == nullptr) { | 
 | 485 |     return "nullptr"; | 
| Elliott Hughes | d423741 | 2012-02-21 11:24:45 -0800 | [diff] [blame] | 486 |   } | 
 | 487 |   std::ostringstream oss; | 
 | 488 |   // TODO: alternatively, we could just return the thread's name. | 
 | 489 |   oss << *thread; | 
 | 490 |   return oss.str(); | 
 | 491 | } | 
 | 492 |  | 
| Mathieu Chartier | 61b3cd4 | 2016-04-18 11:43:29 -0700 | [diff] [blame] | 493 | void Monitor::FailedUnlock(mirror::Object* o, | 
 | 494 |                            uint32_t expected_owner_thread_id, | 
 | 495 |                            uint32_t found_owner_thread_id, | 
| Elliott Hughes | ffb465f | 2012-03-01 18:46:05 -0800 | [diff] [blame] | 496 |                            Monitor* monitor) { | 
| Mathieu Chartier | 61b3cd4 | 2016-04-18 11:43:29 -0700 | [diff] [blame] | 497 |   // Acquire thread list lock so threads won't disappear from under us. | 
| Elliott Hughes | ffb465f | 2012-03-01 18:46:05 -0800 | [diff] [blame] | 498 |   std::string current_owner_string; | 
 | 499 |   std::string expected_owner_string; | 
 | 500 |   std::string found_owner_string; | 
| Mathieu Chartier | 61b3cd4 | 2016-04-18 11:43:29 -0700 | [diff] [blame] | 501 |   uint32_t current_owner_thread_id = 0u; | 
| Elliott Hughes | ffb465f | 2012-03-01 18:46:05 -0800 | [diff] [blame] | 502 |   { | 
| Ian Rogers | 50b35e2 | 2012-10-04 10:09:15 -0700 | [diff] [blame] | 503 |     MutexLock mu(Thread::Current(), *Locks::thread_list_lock_); | 
| Mathieu Chartier | 61b3cd4 | 2016-04-18 11:43:29 -0700 | [diff] [blame] | 504 |     ThreadList* const thread_list = Runtime::Current()->GetThreadList(); | 
 | 505 |     Thread* expected_owner = thread_list->FindThreadByThreadId(expected_owner_thread_id); | 
 | 506 |     Thread* found_owner = thread_list->FindThreadByThreadId(found_owner_thread_id); | 
 | 507 |  | 
| Elliott Hughes | ffb465f | 2012-03-01 18:46:05 -0800 | [diff] [blame] | 508 |     // Re-read owner now that we hold lock. | 
| Mathieu Chartier | 61b3cd4 | 2016-04-18 11:43:29 -0700 | [diff] [blame] | 509 |     Thread* current_owner = (monitor != nullptr) ? monitor->GetOwner() : nullptr; | 
 | 510 |     if (current_owner != nullptr) { | 
 | 511 |       current_owner_thread_id = current_owner->GetThreadId(); | 
 | 512 |     } | 
| Elliott Hughes | ffb465f | 2012-03-01 18:46:05 -0800 | [diff] [blame] | 513 |     // Get short descriptions of the threads involved. | 
 | 514 |     current_owner_string = ThreadToString(current_owner); | 
| Mathieu Chartier | 61b3cd4 | 2016-04-18 11:43:29 -0700 | [diff] [blame] | 515 |     expected_owner_string = expected_owner != nullptr ? ThreadToString(expected_owner) : "unnamed"; | 
 | 516 |     found_owner_string = found_owner != nullptr ? ThreadToString(found_owner) : "unnamed"; | 
| Elliott Hughes | ffb465f | 2012-03-01 18:46:05 -0800 | [diff] [blame] | 517 |   } | 
| Mathieu Chartier | 61b3cd4 | 2016-04-18 11:43:29 -0700 | [diff] [blame] | 518 |  | 
 | 519 |   if (current_owner_thread_id == 0u) { | 
 | 520 |     if (found_owner_thread_id == 0u) { | 
| Ian Rogers | 6d0b13e | 2012-02-07 09:25:29 -0800 | [diff] [blame] | 521 |       ThrowIllegalMonitorStateExceptionF("unlock of unowned monitor on object of type '%s'" | 
 | 522 |                                          " on thread '%s'", | 
| David Sehr | 709b070 | 2016-10-13 09:12:37 -0700 | [diff] [blame] | 523 |                                          mirror::Object::PrettyTypeOf(o).c_str(), | 
| Elliott Hughes | ffb465f | 2012-03-01 18:46:05 -0800 | [diff] [blame] | 524 |                                          expected_owner_string.c_str()); | 
| Ian Rogers | 6d0b13e | 2012-02-07 09:25:29 -0800 | [diff] [blame] | 525 |     } else { | 
 | 526 |       // Race: the original read found an owner but now there is none | 
| Ian Rogers | 6d0b13e | 2012-02-07 09:25:29 -0800 | [diff] [blame] | 527 |       ThrowIllegalMonitorStateExceptionF("unlock of monitor owned by '%s' on object of type '%s'" | 
 | 528 |                                          " (where now the monitor appears unowned) on thread '%s'", | 
| Elliott Hughes | ffb465f | 2012-03-01 18:46:05 -0800 | [diff] [blame] | 529 |                                          found_owner_string.c_str(), | 
| David Sehr | 709b070 | 2016-10-13 09:12:37 -0700 | [diff] [blame] | 530 |                                          mirror::Object::PrettyTypeOf(o).c_str(), | 
| Elliott Hughes | ffb465f | 2012-03-01 18:46:05 -0800 | [diff] [blame] | 531 |                                          expected_owner_string.c_str()); | 
| Ian Rogers | 6d0b13e | 2012-02-07 09:25:29 -0800 | [diff] [blame] | 532 |     } | 
 | 533 |   } else { | 
| Mathieu Chartier | 61b3cd4 | 2016-04-18 11:43:29 -0700 | [diff] [blame] | 534 |     if (found_owner_thread_id == 0u) { | 
| Ian Rogers | 6d0b13e | 2012-02-07 09:25:29 -0800 | [diff] [blame] | 535 |       // Race: originally there was no owner, there is now | 
 | 536 |       ThrowIllegalMonitorStateExceptionF("unlock of monitor owned by '%s' on object of type '%s'" | 
 | 537 |                                          " (originally believed to be unowned) on thread '%s'", | 
| Elliott Hughes | ffb465f | 2012-03-01 18:46:05 -0800 | [diff] [blame] | 538 |                                          current_owner_string.c_str(), | 
| David Sehr | 709b070 | 2016-10-13 09:12:37 -0700 | [diff] [blame] | 539 |                                          mirror::Object::PrettyTypeOf(o).c_str(), | 
| Elliott Hughes | ffb465f | 2012-03-01 18:46:05 -0800 | [diff] [blame] | 540 |                                          expected_owner_string.c_str()); | 
| Ian Rogers | 6d0b13e | 2012-02-07 09:25:29 -0800 | [diff] [blame] | 541 |     } else { | 
| Mathieu Chartier | 61b3cd4 | 2016-04-18 11:43:29 -0700 | [diff] [blame] | 542 |       if (found_owner_thread_id != current_owner_thread_id) { | 
| Ian Rogers | 6d0b13e | 2012-02-07 09:25:29 -0800 | [diff] [blame] | 543 |         // Race: originally found and current owner have changed | 
| Ian Rogers | 6d0b13e | 2012-02-07 09:25:29 -0800 | [diff] [blame] | 544 |         ThrowIllegalMonitorStateExceptionF("unlock of monitor originally owned by '%s' (now" | 
 | 545 |                                            " owned by '%s') on object of type '%s' on thread '%s'", | 
| Elliott Hughes | ffb465f | 2012-03-01 18:46:05 -0800 | [diff] [blame] | 546 |                                            found_owner_string.c_str(), | 
 | 547 |                                            current_owner_string.c_str(), | 
| David Sehr | 709b070 | 2016-10-13 09:12:37 -0700 | [diff] [blame] | 548 |                                            mirror::Object::PrettyTypeOf(o).c_str(), | 
| Elliott Hughes | ffb465f | 2012-03-01 18:46:05 -0800 | [diff] [blame] | 549 |                                            expected_owner_string.c_str()); | 
| Ian Rogers | 6d0b13e | 2012-02-07 09:25:29 -0800 | [diff] [blame] | 550 |       } else { | 
 | 551 |         ThrowIllegalMonitorStateExceptionF("unlock of monitor owned by '%s' on object of type '%s'" | 
 | 552 |                                            " on thread '%s", | 
| Elliott Hughes | ffb465f | 2012-03-01 18:46:05 -0800 | [diff] [blame] | 553 |                                            current_owner_string.c_str(), | 
| David Sehr | 709b070 | 2016-10-13 09:12:37 -0700 | [diff] [blame] | 554 |                                            mirror::Object::PrettyTypeOf(o).c_str(), | 
| Elliott Hughes | ffb465f | 2012-03-01 18:46:05 -0800 | [diff] [blame] | 555 |                                            expected_owner_string.c_str()); | 
| Ian Rogers | 6d0b13e | 2012-02-07 09:25:29 -0800 | [diff] [blame] | 556 |       } | 
 | 557 |     } | 
 | 558 |   } | 
| Elliott Hughes | 5f79133 | 2011-09-15 17:45:30 -0700 | [diff] [blame] | 559 | } | 
 | 560 |  | 
| Ian Rogers | d9c4fc9 | 2013-10-01 19:45:43 -0700 | [diff] [blame] | 561 | bool Monitor::Unlock(Thread* self) { | 
| Mathieu Chartier | 2cebb24 | 2015-04-21 16:50:40 -0700 | [diff] [blame] | 562 |   DCHECK(self != nullptr); | 
| Mathieu Chartier | 0ffdc9c | 2016-04-19 13:46:03 -0700 | [diff] [blame] | 563 |   uint32_t owner_thread_id = 0u; | 
| Mathieu Chartier | 61b3cd4 | 2016-04-18 11:43:29 -0700 | [diff] [blame] | 564 |   { | 
 | 565 |     MutexLock mu(self, monitor_lock_); | 
 | 566 |     Thread* owner = owner_; | 
| Mathieu Chartier | 0ffdc9c | 2016-04-19 13:46:03 -0700 | [diff] [blame] | 567 |     if (owner != nullptr) { | 
 | 568 |       owner_thread_id = owner->GetThreadId(); | 
 | 569 |     } | 
| Mathieu Chartier | 61b3cd4 | 2016-04-18 11:43:29 -0700 | [diff] [blame] | 570 |     if (owner == self) { | 
 | 571 |       // We own the monitor, so nobody else can be in here. | 
| Andreas Gampe | c7ed09b | 2016-04-25 20:08:55 -0700 | [diff] [blame] | 572 |       AtraceMonitorUnlock(); | 
| Mathieu Chartier | 61b3cd4 | 2016-04-18 11:43:29 -0700 | [diff] [blame] | 573 |       if (lock_count_ == 0) { | 
 | 574 |         owner_ = nullptr; | 
 | 575 |         locking_method_ = nullptr; | 
 | 576 |         locking_dex_pc_ = 0; | 
 | 577 |         // Wake a contender. | 
 | 578 |         monitor_contenders_.Signal(self); | 
 | 579 |       } else { | 
 | 580 |         --lock_count_; | 
 | 581 |       } | 
 | 582 |       return true; | 
| Elliott Hughes | 5f79133 | 2011-09-15 17:45:30 -0700 | [diff] [blame] | 583 |     } | 
| Elliott Hughes | 5f79133 | 2011-09-15 17:45:30 -0700 | [diff] [blame] | 584 |   } | 
| Mathieu Chartier | 61b3cd4 | 2016-04-18 11:43:29 -0700 | [diff] [blame] | 585 |   // We don't own this, so we're not allowed to unlock it. | 
 | 586 |   // The JNI spec says that we should throw IllegalMonitorStateException in this case. | 
 | 587 |   FailedUnlock(GetObject(), self->GetThreadId(), owner_thread_id, this); | 
 | 588 |   return false; | 
| Elliott Hughes | 5f79133 | 2011-09-15 17:45:30 -0700 | [diff] [blame] | 589 | } | 
 | 590 |  | 
| Elliott Hughes | 4cd121e | 2013-01-07 17:35:41 -0800 | [diff] [blame] | 591 | void Monitor::Wait(Thread* self, int64_t ms, int32_t ns, | 
 | 592 |                    bool interruptShouldThrow, ThreadState why) { | 
| Mathieu Chartier | 2cebb24 | 2015-04-21 16:50:40 -0700 | [diff] [blame] | 593 |   DCHECK(self != nullptr); | 
| Elliott Hughes | 4cd121e | 2013-01-07 17:35:41 -0800 | [diff] [blame] | 594 |   DCHECK(why == kTimedWaiting || why == kWaiting || why == kSleeping); | 
| Elliott Hughes | 5f79133 | 2011-09-15 17:45:30 -0700 | [diff] [blame] | 595 |  | 
| Ian Rogers | d9c4fc9 | 2013-10-01 19:45:43 -0700 | [diff] [blame] | 596 |   monitor_lock_.Lock(self); | 
 | 597 |  | 
| Elliott Hughes | 5f79133 | 2011-09-15 17:45:30 -0700 | [diff] [blame] | 598 |   // Make sure that we hold the lock. | 
 | 599 |   if (owner_ != self) { | 
| Ian Rogers | d9c4fc9 | 2013-10-01 19:45:43 -0700 | [diff] [blame] | 600 |     monitor_lock_.Unlock(self); | 
| Elena Sayapina | 1af6a1f | 2014-06-20 16:58:37 +0700 | [diff] [blame] | 601 |     ThrowIllegalMonitorStateExceptionF("object not locked by thread before wait()"); | 
| Elliott Hughes | 5f79133 | 2011-09-15 17:45:30 -0700 | [diff] [blame] | 602 |     return; | 
 | 603 |   } | 
| Elliott Hughes | 4cd121e | 2013-01-07 17:35:41 -0800 | [diff] [blame] | 604 |  | 
| Elliott Hughes | df42c48 | 2013-01-09 12:49:02 -0800 | [diff] [blame] | 605 |   // We need to turn a zero-length timed wait into a regular wait because | 
 | 606 |   // Object.wait(0, 0) is defined as Object.wait(0), which is defined as Object.wait(). | 
 | 607 |   if (why == kTimedWaiting && (ms == 0 && ns == 0)) { | 
 | 608 |     why = kWaiting; | 
 | 609 |   } | 
 | 610 |  | 
| Elliott Hughes | 5f79133 | 2011-09-15 17:45:30 -0700 | [diff] [blame] | 611 |   // Enforce the timeout range. | 
 | 612 |   if (ms < 0 || ns < 0 || ns > 999999) { | 
| Elena Sayapina | 1af6a1f | 2014-06-20 16:58:37 +0700 | [diff] [blame] | 613 |     monitor_lock_.Unlock(self); | 
| Nicolas Geoffray | 0aa50ce | 2015-03-10 11:03:29 +0000 | [diff] [blame] | 614 |     self->ThrowNewExceptionF("Ljava/lang/IllegalArgumentException;", | 
| Ian Rogers | ef7d42f | 2014-01-06 12:55:46 -0800 | [diff] [blame] | 615 |                              "timeout arguments out of range: ms=%" PRId64 " ns=%d", ms, ns); | 
| Elliott Hughes | 5f79133 | 2011-09-15 17:45:30 -0700 | [diff] [blame] | 616 |     return; | 
 | 617 |   } | 
 | 618 |  | 
| Elliott Hughes | 5f79133 | 2011-09-15 17:45:30 -0700 | [diff] [blame] | 619 |   /* | 
 | 620 |    * Add ourselves to the set of threads waiting on this monitor, and | 
 | 621 |    * release our hold.  We need to let it go even if we're a few levels | 
 | 622 |    * deep in a recursive lock, and we need to restore that later. | 
 | 623 |    * | 
 | 624 |    * We append to the wait set ahead of clearing the count and owner | 
 | 625 |    * fields so the subroutine can check that the calling thread owns | 
 | 626 |    * the monitor.  Aside from that, the order of member updates is | 
 | 627 |    * not order sensitive as we hold the pthread mutex. | 
 | 628 |    */ | 
 | 629 |   AppendToWaitSet(self); | 
| Mathieu Chartier | 440e4ce | 2014-03-31 16:36:35 -0700 | [diff] [blame] | 630 |   ++num_waiters_; | 
| Ian Rogers | 0399dde | 2012-06-06 17:09:28 -0700 | [diff] [blame] | 631 |   int prev_lock_count = lock_count_; | 
| Elliott Hughes | 5f79133 | 2011-09-15 17:45:30 -0700 | [diff] [blame] | 632 |   lock_count_ = 0; | 
| Mathieu Chartier | 2cebb24 | 2015-04-21 16:50:40 -0700 | [diff] [blame] | 633 |   owner_ = nullptr; | 
| Mathieu Chartier | e401d14 | 2015-04-22 13:56:20 -0700 | [diff] [blame] | 634 |   ArtMethod* saved_method = locking_method_; | 
| Mathieu Chartier | 2cebb24 | 2015-04-21 16:50:40 -0700 | [diff] [blame] | 635 |   locking_method_ = nullptr; | 
| Ian Rogers | 0399dde | 2012-06-06 17:09:28 -0700 | [diff] [blame] | 636 |   uintptr_t saved_dex_pc = locking_dex_pc_; | 
 | 637 |   locking_dex_pc_ = 0; | 
| Elliott Hughes | 5f79133 | 2011-09-15 17:45:30 -0700 | [diff] [blame] | 638 |  | 
| Andreas Gampe | c7ed09b | 2016-04-25 20:08:55 -0700 | [diff] [blame] | 639 |   AtraceMonitorUnlock();  // For the implict Unlock() just above. This will only end the deepest | 
 | 640 |                           // nesting, but that is enough for the visualization, and corresponds to | 
 | 641 |                           // the single Lock() we do afterwards. | 
 | 642 |   AtraceMonitorLock(self, GetObject(), true /* is_wait */); | 
 | 643 |  | 
| Elliott Hughes | b4e94fd | 2013-01-08 14:41:26 -0800 | [diff] [blame] | 644 |   bool was_interrupted = false; | 
| Ian Rogers | 00f7d0e | 2012-07-19 15:28:27 -0700 | [diff] [blame] | 645 |   { | 
| Mathieu Chartier | f1d666e | 2015-09-03 16:13:34 -0700 | [diff] [blame] | 646 |     // Update thread state. If the GC wakes up, it'll ignore us, knowing | 
 | 647 |     // that we won't touch any references in this state, and we'll check | 
 | 648 |     // our suspend mode before we transition out. | 
 | 649 |     ScopedThreadSuspension sts(self, why); | 
 | 650 |  | 
| Ian Rogers | 00f7d0e | 2012-07-19 15:28:27 -0700 | [diff] [blame] | 651 |     // Pseudo-atomically wait on self's wait_cond_ and release the monitor lock. | 
| Ian Rogers | dd7624d | 2014-03-14 17:43:00 -0700 | [diff] [blame] | 652 |     MutexLock mu(self, *self->GetWaitMutex()); | 
| Ian Rogers | 00f7d0e | 2012-07-19 15:28:27 -0700 | [diff] [blame] | 653 |  | 
 | 654 |     // Set wait_monitor_ to the monitor object we will be waiting on. When wait_monitor_ is | 
| Mathieu Chartier | 2cebb24 | 2015-04-21 16:50:40 -0700 | [diff] [blame] | 655 |     // non-null a notifying or interrupting thread must signal the thread's wait_cond_ to wake it | 
| Ian Rogers | 00f7d0e | 2012-07-19 15:28:27 -0700 | [diff] [blame] | 656 |     // up. | 
| Ian Rogers | dd7624d | 2014-03-14 17:43:00 -0700 | [diff] [blame] | 657 |     DCHECK(self->GetWaitMonitor() == nullptr); | 
 | 658 |     self->SetWaitMonitor(this); | 
| Ian Rogers | 00f7d0e | 2012-07-19 15:28:27 -0700 | [diff] [blame] | 659 |  | 
 | 660 |     // Release the monitor lock. | 
| Ian Rogers | d9c4fc9 | 2013-10-01 19:45:43 -0700 | [diff] [blame] | 661 |     monitor_contenders_.Signal(self); | 
 | 662 |     monitor_lock_.Unlock(self); | 
| Ian Rogers | 00f7d0e | 2012-07-19 15:28:27 -0700 | [diff] [blame] | 663 |  | 
| Elliott Hughes | b4e94fd | 2013-01-08 14:41:26 -0800 | [diff] [blame] | 664 |     // Handle the case where the thread was interrupted before we called wait(). | 
| Nicolas Geoffray | 365719c | 2017-03-08 13:11:50 +0000 | [diff] [blame^] | 665 |     if (self->IsInterrupted()) { | 
| Elliott Hughes | b4e94fd | 2013-01-08 14:41:26 -0800 | [diff] [blame] | 666 |       was_interrupted = true; | 
| Ian Rogers | 00f7d0e | 2012-07-19 15:28:27 -0700 | [diff] [blame] | 667 |     } else { | 
 | 668 |       // Wait for a notification or a timeout to occur. | 
| Elliott Hughes | 4cd121e | 2013-01-07 17:35:41 -0800 | [diff] [blame] | 669 |       if (why == kWaiting) { | 
| Ian Rogers | dd7624d | 2014-03-14 17:43:00 -0700 | [diff] [blame] | 670 |         self->GetWaitConditionVariable()->Wait(self); | 
| Ian Rogers | 00f7d0e | 2012-07-19 15:28:27 -0700 | [diff] [blame] | 671 |       } else { | 
| Elliott Hughes | 4cd121e | 2013-01-07 17:35:41 -0800 | [diff] [blame] | 672 |         DCHECK(why == kTimedWaiting || why == kSleeping) << why; | 
| Ian Rogers | dd7624d | 2014-03-14 17:43:00 -0700 | [diff] [blame] | 673 |         self->GetWaitConditionVariable()->TimedWait(self, ms, ns); | 
| Ian Rogers | 00f7d0e | 2012-07-19 15:28:27 -0700 | [diff] [blame] | 674 |       } | 
| Nicolas Geoffray | 365719c | 2017-03-08 13:11:50 +0000 | [diff] [blame^] | 675 |       was_interrupted = self->IsInterrupted(); | 
| Ian Rogers | 00f7d0e | 2012-07-19 15:28:27 -0700 | [diff] [blame] | 676 |     } | 
| Elliott Hughes | 5f79133 | 2011-09-15 17:45:30 -0700 | [diff] [blame] | 677 |   } | 
 | 678 |  | 
| Elliott Hughes | b4e94fd | 2013-01-08 14:41:26 -0800 | [diff] [blame] | 679 |   { | 
 | 680 |     // We reset the thread's wait_monitor_ field after transitioning back to runnable so | 
 | 681 |     // that a thread in a waiting/sleeping state has a non-null wait_monitor_ for debugging | 
 | 682 |     // and diagnostic purposes. (If you reset this earlier, stack dumps will claim that threads | 
 | 683 |     // are waiting on "null".) | 
| Ian Rogers | dd7624d | 2014-03-14 17:43:00 -0700 | [diff] [blame] | 684 |     MutexLock mu(self, *self->GetWaitMutex()); | 
 | 685 |     DCHECK(self->GetWaitMonitor() != nullptr); | 
 | 686 |     self->SetWaitMonitor(nullptr); | 
| Elliott Hughes | b4e94fd | 2013-01-08 14:41:26 -0800 | [diff] [blame] | 687 |   } | 
 | 688 |  | 
| Mathieu Chartier | daed5d8 | 2016-03-10 10:49:35 -0800 | [diff] [blame] | 689 |   // Allocate the interrupted exception not holding the monitor lock since it may cause a GC. | 
 | 690 |   // If the GC requires acquiring the monitor for enqueuing cleared references, this would | 
 | 691 |   // cause a deadlock if the monitor is held. | 
 | 692 |   if (was_interrupted && interruptShouldThrow) { | 
 | 693 |     /* | 
 | 694 |      * We were interrupted while waiting, or somebody interrupted an | 
 | 695 |      * un-interruptible thread earlier and we're bailing out immediately. | 
 | 696 |      * | 
 | 697 |      * The doc sayeth: "The interrupted status of the current thread is | 
 | 698 |      * cleared when this exception is thrown." | 
 | 699 |      */ | 
| Nicolas Geoffray | 365719c | 2017-03-08 13:11:50 +0000 | [diff] [blame^] | 700 |     self->SetInterrupted(false); | 
| Mathieu Chartier | daed5d8 | 2016-03-10 10:49:35 -0800 | [diff] [blame] | 701 |     self->ThrowNewException("Ljava/lang/InterruptedException;", nullptr); | 
 | 702 |   } | 
 | 703 |  | 
| Andreas Gampe | c7ed09b | 2016-04-25 20:08:55 -0700 | [diff] [blame] | 704 |   AtraceMonitorUnlock();  // End Wait(). | 
 | 705 |  | 
| Ian Rogers | d9c4fc9 | 2013-10-01 19:45:43 -0700 | [diff] [blame] | 706 |   // Re-acquire the monitor and lock. | 
| Elliott Hughes | 5f79133 | 2011-09-15 17:45:30 -0700 | [diff] [blame] | 707 |   Lock(self); | 
| Ian Rogers | d9c4fc9 | 2013-10-01 19:45:43 -0700 | [diff] [blame] | 708 |   monitor_lock_.Lock(self); | 
| Ian Rogers | dd7624d | 2014-03-14 17:43:00 -0700 | [diff] [blame] | 709 |   self->GetWaitMutex()->AssertNotHeld(self); | 
| Ian Rogers | 00f7d0e | 2012-07-19 15:28:27 -0700 | [diff] [blame] | 710 |  | 
| Elliott Hughes | 5f79133 | 2011-09-15 17:45:30 -0700 | [diff] [blame] | 711 |   /* | 
 | 712 |    * We remove our thread from wait set after restoring the count | 
 | 713 |    * and owner fields so the subroutine can check that the calling | 
 | 714 |    * thread owns the monitor. Aside from that, the order of member | 
 | 715 |    * updates is not order sensitive as we hold the pthread mutex. | 
 | 716 |    */ | 
 | 717 |   owner_ = self; | 
| Ian Rogers | 0399dde | 2012-06-06 17:09:28 -0700 | [diff] [blame] | 718 |   lock_count_ = prev_lock_count; | 
 | 719 |   locking_method_ = saved_method; | 
 | 720 |   locking_dex_pc_ = saved_dex_pc; | 
| Mathieu Chartier | 440e4ce | 2014-03-31 16:36:35 -0700 | [diff] [blame] | 721 |   --num_waiters_; | 
| Elliott Hughes | 5f79133 | 2011-09-15 17:45:30 -0700 | [diff] [blame] | 722 |   RemoveFromWaitSet(self); | 
 | 723 |  | 
| Elena Sayapina | 1af6a1f | 2014-06-20 16:58:37 +0700 | [diff] [blame] | 724 |   monitor_lock_.Unlock(self); | 
| Elliott Hughes | 5f79133 | 2011-09-15 17:45:30 -0700 | [diff] [blame] | 725 | } | 
 | 726 |  | 
 | 727 | void Monitor::Notify(Thread* self) { | 
| Mathieu Chartier | 2cebb24 | 2015-04-21 16:50:40 -0700 | [diff] [blame] | 728 |   DCHECK(self != nullptr); | 
| Ian Rogers | d9c4fc9 | 2013-10-01 19:45:43 -0700 | [diff] [blame] | 729 |   MutexLock mu(self, monitor_lock_); | 
| Elliott Hughes | 5f79133 | 2011-09-15 17:45:30 -0700 | [diff] [blame] | 730 |   // Make sure that we hold the lock. | 
 | 731 |   if (owner_ != self) { | 
| Ian Rogers | 6d0b13e | 2012-02-07 09:25:29 -0800 | [diff] [blame] | 732 |     ThrowIllegalMonitorStateExceptionF("object not locked by thread before notify()"); | 
| Elliott Hughes | 5f79133 | 2011-09-15 17:45:30 -0700 | [diff] [blame] | 733 |     return; | 
 | 734 |   } | 
 | 735 |   // Signal the first waiting thread in the wait set. | 
| Mathieu Chartier | 2cebb24 | 2015-04-21 16:50:40 -0700 | [diff] [blame] | 736 |   while (wait_set_ != nullptr) { | 
| Elliott Hughes | 5f79133 | 2011-09-15 17:45:30 -0700 | [diff] [blame] | 737 |     Thread* thread = wait_set_; | 
| Ian Rogers | dd7624d | 2014-03-14 17:43:00 -0700 | [diff] [blame] | 738 |     wait_set_ = thread->GetWaitNext(); | 
 | 739 |     thread->SetWaitNext(nullptr); | 
| Elliott Hughes | 5f79133 | 2011-09-15 17:45:30 -0700 | [diff] [blame] | 740 |  | 
 | 741 |     // Check to see if the thread is still waiting. | 
| Andreas Gampe | 277ccbd | 2014-11-03 21:36:10 -0800 | [diff] [blame] | 742 |     MutexLock wait_mu(self, *thread->GetWaitMutex()); | 
| Ian Rogers | dd7624d | 2014-03-14 17:43:00 -0700 | [diff] [blame] | 743 |     if (thread->GetWaitMonitor() != nullptr) { | 
 | 744 |       thread->GetWaitConditionVariable()->Signal(self); | 
| Elliott Hughes | 5f79133 | 2011-09-15 17:45:30 -0700 | [diff] [blame] | 745 |       return; | 
 | 746 |     } | 
 | 747 |   } | 
 | 748 | } | 
 | 749 |  | 
 | 750 | void Monitor::NotifyAll(Thread* self) { | 
| Mathieu Chartier | 2cebb24 | 2015-04-21 16:50:40 -0700 | [diff] [blame] | 751 |   DCHECK(self != nullptr); | 
| Ian Rogers | d9c4fc9 | 2013-10-01 19:45:43 -0700 | [diff] [blame] | 752 |   MutexLock mu(self, monitor_lock_); | 
| Elliott Hughes | 5f79133 | 2011-09-15 17:45:30 -0700 | [diff] [blame] | 753 |   // Make sure that we hold the lock. | 
 | 754 |   if (owner_ != self) { | 
| Ian Rogers | 6d0b13e | 2012-02-07 09:25:29 -0800 | [diff] [blame] | 755 |     ThrowIllegalMonitorStateExceptionF("object not locked by thread before notifyAll()"); | 
| Elliott Hughes | 5f79133 | 2011-09-15 17:45:30 -0700 | [diff] [blame] | 756 |     return; | 
 | 757 |   } | 
 | 758 |   // Signal all threads in the wait set. | 
| Mathieu Chartier | 2cebb24 | 2015-04-21 16:50:40 -0700 | [diff] [blame] | 759 |   while (wait_set_ != nullptr) { | 
| Elliott Hughes | 5f79133 | 2011-09-15 17:45:30 -0700 | [diff] [blame] | 760 |     Thread* thread = wait_set_; | 
| Ian Rogers | dd7624d | 2014-03-14 17:43:00 -0700 | [diff] [blame] | 761 |     wait_set_ = thread->GetWaitNext(); | 
 | 762 |     thread->SetWaitNext(nullptr); | 
| Elliott Hughes | 5f79133 | 2011-09-15 17:45:30 -0700 | [diff] [blame] | 763 |     thread->Notify(); | 
 | 764 |   } | 
 | 765 | } | 
 | 766 |  | 
| Mathieu Chartier | 590fee9 | 2013-09-13 13:46:47 -0700 | [diff] [blame] | 767 | bool Monitor::Deflate(Thread* self, mirror::Object* obj) { | 
 | 768 |   DCHECK(obj != nullptr); | 
| Mathieu Chartier | 4d7f61d | 2014-04-17 14:43:39 -0700 | [diff] [blame] | 769 |   // Don't need volatile since we only deflate with mutators suspended. | 
 | 770 |   LockWord lw(obj->GetLockWord(false)); | 
| Mathieu Chartier | 590fee9 | 2013-09-13 13:46:47 -0700 | [diff] [blame] | 771 |   // If the lock isn't an inflated monitor, then we don't need to deflate anything. | 
 | 772 |   if (lw.GetState() == LockWord::kFatLocked) { | 
 | 773 |     Monitor* monitor = lw.FatLockMonitor(); | 
| Mathieu Chartier | 440e4ce | 2014-03-31 16:36:35 -0700 | [diff] [blame] | 774 |     DCHECK(monitor != nullptr); | 
| Mathieu Chartier | 590fee9 | 2013-09-13 13:46:47 -0700 | [diff] [blame] | 775 |     MutexLock mu(self, monitor->monitor_lock_); | 
| Mathieu Chartier | 440e4ce | 2014-03-31 16:36:35 -0700 | [diff] [blame] | 776 |     // Can't deflate if we have anybody waiting on the CV. | 
 | 777 |     if (monitor->num_waiters_ > 0) { | 
 | 778 |       return false; | 
 | 779 |     } | 
| Mathieu Chartier | 590fee9 | 2013-09-13 13:46:47 -0700 | [diff] [blame] | 780 |     Thread* owner = monitor->owner_; | 
 | 781 |     if (owner != nullptr) { | 
 | 782 |       // Can't deflate if we are locked and have a hash code. | 
 | 783 |       if (monitor->HasHashCode()) { | 
 | 784 |         return false; | 
 | 785 |       } | 
 | 786 |       // Can't deflate if our lock count is too high. | 
| Mathieu Chartier | 1cf194f | 2016-11-01 20:13:24 -0700 | [diff] [blame] | 787 |       if (static_cast<uint32_t>(monitor->lock_count_) > LockWord::kThinLockMaxCount) { | 
| Mathieu Chartier | 590fee9 | 2013-09-13 13:46:47 -0700 | [diff] [blame] | 788 |         return false; | 
 | 789 |       } | 
| Mathieu Chartier | 590fee9 | 2013-09-13 13:46:47 -0700 | [diff] [blame] | 790 |       // Deflate to a thin lock. | 
| Mathieu Chartier | 36a270a | 2016-07-28 18:08:51 -0700 | [diff] [blame] | 791 |       LockWord new_lw = LockWord::FromThinLockId(owner->GetThreadId(), | 
 | 792 |                                                  monitor->lock_count_, | 
 | 793 |                                                  lw.GCState()); | 
| Hiroshi Yamauchi | e15ea08 | 2015-02-09 17:11:42 -0800 | [diff] [blame] | 794 |       // Assume no concurrent read barrier state changes as mutators are suspended. | 
 | 795 |       obj->SetLockWord(new_lw, false); | 
| Mathieu Chartier | 4d7f61d | 2014-04-17 14:43:39 -0700 | [diff] [blame] | 796 |       VLOG(monitor) << "Deflated " << obj << " to thin lock " << owner->GetTid() << " / " | 
 | 797 |           << monitor->lock_count_; | 
| Mathieu Chartier | 590fee9 | 2013-09-13 13:46:47 -0700 | [diff] [blame] | 798 |     } else if (monitor->HasHashCode()) { | 
| Mathieu Chartier | 36a270a | 2016-07-28 18:08:51 -0700 | [diff] [blame] | 799 |       LockWord new_lw = LockWord::FromHashCode(monitor->GetHashCode(), lw.GCState()); | 
| Hiroshi Yamauchi | e15ea08 | 2015-02-09 17:11:42 -0800 | [diff] [blame] | 800 |       // Assume no concurrent read barrier state changes as mutators are suspended. | 
 | 801 |       obj->SetLockWord(new_lw, false); | 
| Mathieu Chartier | 440e4ce | 2014-03-31 16:36:35 -0700 | [diff] [blame] | 802 |       VLOG(monitor) << "Deflated " << obj << " to hash monitor " << monitor->GetHashCode(); | 
| Mathieu Chartier | 590fee9 | 2013-09-13 13:46:47 -0700 | [diff] [blame] | 803 |     } else { | 
 | 804 |       // No lock and no hash, just put an empty lock word inside the object. | 
| Mathieu Chartier | 36a270a | 2016-07-28 18:08:51 -0700 | [diff] [blame] | 805 |       LockWord new_lw = LockWord::FromDefault(lw.GCState()); | 
| Hiroshi Yamauchi | e15ea08 | 2015-02-09 17:11:42 -0800 | [diff] [blame] | 806 |       // Assume no concurrent read barrier state changes as mutators are suspended. | 
 | 807 |       obj->SetLockWord(new_lw, false); | 
| Mathieu Chartier | 440e4ce | 2014-03-31 16:36:35 -0700 | [diff] [blame] | 808 |       VLOG(monitor) << "Deflated" << obj << " to empty lock word"; | 
| Mathieu Chartier | 590fee9 | 2013-09-13 13:46:47 -0700 | [diff] [blame] | 809 |     } | 
| Mathieu Chartier | 2cebb24 | 2015-04-21 16:50:40 -0700 | [diff] [blame] | 810 |     // The monitor is deflated, mark the object as null so that we know to delete it during the | 
| Mathieu Chartier | 590fee9 | 2013-09-13 13:46:47 -0700 | [diff] [blame] | 811 |     // next GC. | 
| Hiroshi Yamauchi | 94f7b49 | 2014-07-22 18:08:23 -0700 | [diff] [blame] | 812 |     monitor->obj_ = GcRoot<mirror::Object>(nullptr); | 
| Mathieu Chartier | 590fee9 | 2013-09-13 13:46:47 -0700 | [diff] [blame] | 813 |   } | 
 | 814 |   return true; | 
 | 815 | } | 
 | 816 |  | 
| Mathieu Chartier | ad2541a | 2013-10-25 10:05:23 -0700 | [diff] [blame] | 817 | void Monitor::Inflate(Thread* self, Thread* owner, mirror::Object* obj, int32_t hash_code) { | 
| Andreas Gampe | 7424081 | 2014-04-17 10:35:09 -0700 | [diff] [blame] | 818 |   DCHECK(self != nullptr); | 
 | 819 |   DCHECK(obj != nullptr); | 
| Elliott Hughes | 5f79133 | 2011-09-15 17:45:30 -0700 | [diff] [blame] | 820 |   // Allocate and acquire a new monitor. | 
| Andreas Gampe | 7424081 | 2014-04-17 10:35:09 -0700 | [diff] [blame] | 821 |   Monitor* m = MonitorPool::CreateMonitor(self, owner, obj, hash_code); | 
 | 822 |   DCHECK(m != nullptr); | 
| Ian Rogers | d9c4fc9 | 2013-10-01 19:45:43 -0700 | [diff] [blame] | 823 |   if (m->Install(self)) { | 
| Haifeng Li | 86ab791 | 2014-05-16 10:47:59 +0800 | [diff] [blame] | 824 |     if (owner != nullptr) { | 
 | 825 |       VLOG(monitor) << "monitor: thread" << owner->GetThreadId() | 
| Andreas Gampe | 7424081 | 2014-04-17 10:35:09 -0700 | [diff] [blame] | 826 |           << " created monitor " << m << " for object " << obj; | 
| Haifeng Li | 86ab791 | 2014-05-16 10:47:59 +0800 | [diff] [blame] | 827 |     } else { | 
 | 828 |       VLOG(monitor) << "monitor: Inflate with hashcode " << hash_code | 
| Andreas Gampe | 7424081 | 2014-04-17 10:35:09 -0700 | [diff] [blame] | 829 |           << " created monitor " << m << " for object " << obj; | 
| Haifeng Li | 86ab791 | 2014-05-16 10:47:59 +0800 | [diff] [blame] | 830 |     } | 
| Andreas Gampe | 7424081 | 2014-04-17 10:35:09 -0700 | [diff] [blame] | 831 |     Runtime::Current()->GetMonitorList()->Add(m); | 
| Mathieu Chartier | 4d7f61d | 2014-04-17 14:43:39 -0700 | [diff] [blame] | 832 |     CHECK_EQ(obj->GetLockWord(true).GetState(), LockWord::kFatLocked); | 
| Andreas Gampe | 7424081 | 2014-04-17 10:35:09 -0700 | [diff] [blame] | 833 |   } else { | 
 | 834 |     MonitorPool::ReleaseMonitor(self, m); | 
| Ian Rogers | d9c4fc9 | 2013-10-01 19:45:43 -0700 | [diff] [blame] | 835 |   } | 
| Mathieu Chartier | ad2541a | 2013-10-25 10:05:23 -0700 | [diff] [blame] | 836 | } | 
 | 837 |  | 
| Mathieu Chartier | 0cd8135 | 2014-05-22 16:48:55 -0700 | [diff] [blame] | 838 | void Monitor::InflateThinLocked(Thread* self, Handle<mirror::Object> obj, LockWord lock_word, | 
| Mathieu Chartier | ad2541a | 2013-10-25 10:05:23 -0700 | [diff] [blame] | 839 |                                 uint32_t hash_code) { | 
 | 840 |   DCHECK_EQ(lock_word.GetState(), LockWord::kThinLocked); | 
 | 841 |   uint32_t owner_thread_id = lock_word.ThinLockOwner(); | 
 | 842 |   if (owner_thread_id == self->GetThreadId()) { | 
 | 843 |     // We own the monitor, we can easily inflate it. | 
| Mathieu Chartier | eb8167a | 2014-05-07 15:43:14 -0700 | [diff] [blame] | 844 |     Inflate(self, self, obj.Get(), hash_code); | 
| Mathieu Chartier | ad2541a | 2013-10-25 10:05:23 -0700 | [diff] [blame] | 845 |   } else { | 
 | 846 |     ThreadList* thread_list = Runtime::Current()->GetThreadList(); | 
 | 847 |     // Suspend the owner, inflate. First change to blocked and give up mutator_lock_. | 
| Mathieu Chartier | eb8167a | 2014-05-07 15:43:14 -0700 | [diff] [blame] | 848 |     self->SetMonitorEnterObject(obj.Get()); | 
| Mathieu Chartier | a1ee14f | 2014-05-14 16:51:03 -0700 | [diff] [blame] | 849 |     bool timed_out; | 
| Mathieu Chartier | f1d666e | 2015-09-03 16:13:34 -0700 | [diff] [blame] | 850 |     Thread* owner; | 
 | 851 |     { | 
 | 852 |       ScopedThreadSuspension sts(self, kBlocked); | 
 | 853 |       owner = thread_list->SuspendThreadByThreadId(owner_thread_id, false, &timed_out); | 
 | 854 |     } | 
| Mathieu Chartier | a1ee14f | 2014-05-14 16:51:03 -0700 | [diff] [blame] | 855 |     if (owner != nullptr) { | 
 | 856 |       // We succeeded in suspending the thread, check the lock's status didn't change. | 
 | 857 |       lock_word = obj->GetLockWord(true); | 
 | 858 |       if (lock_word.GetState() == LockWord::kThinLocked && | 
 | 859 |           lock_word.ThinLockOwner() == owner_thread_id) { | 
 | 860 |         // Go ahead and inflate the lock. | 
 | 861 |         Inflate(self, owner, obj.Get(), hash_code); | 
| Mathieu Chartier | ad2541a | 2013-10-25 10:05:23 -0700 | [diff] [blame] | 862 |       } | 
| Mathieu Chartier | a1ee14f | 2014-05-14 16:51:03 -0700 | [diff] [blame] | 863 |       thread_list->Resume(owner, false); | 
| Mathieu Chartier | ad2541a | 2013-10-25 10:05:23 -0700 | [diff] [blame] | 864 |     } | 
| Ian Rogers | dd7624d | 2014-03-14 17:43:00 -0700 | [diff] [blame] | 865 |     self->SetMonitorEnterObject(nullptr); | 
| Mathieu Chartier | ad2541a | 2013-10-25 10:05:23 -0700 | [diff] [blame] | 866 |   } | 
| Elliott Hughes | 5f79133 | 2011-09-15 17:45:30 -0700 | [diff] [blame] | 867 | } | 
 | 868 |  | 
| Ian Rogers | 719d1a3 | 2014-03-06 12:13:39 -0800 | [diff] [blame] | 869 | // Fool annotalysis into thinking that the lock on obj is acquired. | 
 | 870 | static mirror::Object* FakeLock(mirror::Object* obj) | 
 | 871 |     EXCLUSIVE_LOCK_FUNCTION(obj) NO_THREAD_SAFETY_ANALYSIS { | 
 | 872 |   return obj; | 
 | 873 | } | 
 | 874 |  | 
 | 875 | // Fool annotalysis into thinking that the lock on obj is release. | 
 | 876 | static mirror::Object* FakeUnlock(mirror::Object* obj) | 
 | 877 |     UNLOCK_FUNCTION(obj) NO_THREAD_SAFETY_ANALYSIS { | 
 | 878 |   return obj; | 
 | 879 | } | 
 | 880 |  | 
| Mathieu Chartier | 4b0ef1c | 2016-07-29 16:26:01 -0700 | [diff] [blame] | 881 | mirror::Object* Monitor::MonitorEnter(Thread* self, mirror::Object* obj, bool trylock) { | 
| Mathieu Chartier | 2cebb24 | 2015-04-21 16:50:40 -0700 | [diff] [blame] | 882 |   DCHECK(self != nullptr); | 
 | 883 |   DCHECK(obj != nullptr); | 
| Mathieu Chartier | 2d096c9 | 2015-10-12 16:18:20 -0700 | [diff] [blame] | 884 |   self->AssertThreadSuspensionIsAllowable(); | 
| Ian Rogers | 719d1a3 | 2014-03-06 12:13:39 -0800 | [diff] [blame] | 885 |   obj = FakeLock(obj); | 
| Ian Rogers | d9c4fc9 | 2013-10-01 19:45:43 -0700 | [diff] [blame] | 886 |   uint32_t thread_id = self->GetThreadId(); | 
 | 887 |   size_t contention_count = 0; | 
| Mathieu Chartier | eb8167a | 2014-05-07 15:43:14 -0700 | [diff] [blame] | 888 |   StackHandleScope<1> hs(self); | 
 | 889 |   Handle<mirror::Object> h_obj(hs.NewHandle(obj)); | 
| Ian Rogers | d9c4fc9 | 2013-10-01 19:45:43 -0700 | [diff] [blame] | 890 |   while (true) { | 
| Hans Boehm | b3da36c | 2016-12-15 13:12:59 -0800 | [diff] [blame] | 891 |     // We initially read the lockword with ordinary Java/relaxed semantics. When stronger | 
 | 892 |     // semantics are needed, we address it below. Since GetLockWord bottoms out to a relaxed load, | 
 | 893 |     // we can fix it later, in an infrequently executed case, with a fence. | 
 | 894 |     LockWord lock_word = h_obj->GetLockWord(false); | 
| Ian Rogers | d9c4fc9 | 2013-10-01 19:45:43 -0700 | [diff] [blame] | 895 |     switch (lock_word.GetState()) { | 
 | 896 |       case LockWord::kUnlocked: { | 
| Hans Boehm | b3da36c | 2016-12-15 13:12:59 -0800 | [diff] [blame] | 897 |         // No ordering required for preceding lockword read, since we retest. | 
| Mathieu Chartier | 36a270a | 2016-07-28 18:08:51 -0700 | [diff] [blame] | 898 |         LockWord thin_locked(LockWord::FromThinLockId(thread_id, 0, lock_word.GCState())); | 
| Hans Boehm | b3da36c | 2016-12-15 13:12:59 -0800 | [diff] [blame] | 899 |         if (h_obj->CasLockWordWeakAcquire(lock_word, thin_locked)) { | 
| Andreas Gampe | c7ed09b | 2016-04-25 20:08:55 -0700 | [diff] [blame] | 900 |           AtraceMonitorLock(self, h_obj.Get(), false /* is_wait */); | 
| Mathieu Chartier | eb8167a | 2014-05-07 15:43:14 -0700 | [diff] [blame] | 901 |           return h_obj.Get();  // Success! | 
| Ian Rogers | d9c4fc9 | 2013-10-01 19:45:43 -0700 | [diff] [blame] | 902 |         } | 
 | 903 |         continue;  // Go again. | 
| Elliott Hughes | 5f79133 | 2011-09-15 17:45:30 -0700 | [diff] [blame] | 904 |       } | 
| Ian Rogers | d9c4fc9 | 2013-10-01 19:45:43 -0700 | [diff] [blame] | 905 |       case LockWord::kThinLocked: { | 
 | 906 |         uint32_t owner_thread_id = lock_word.ThinLockOwner(); | 
 | 907 |         if (owner_thread_id == thread_id) { | 
| Hans Boehm | b3da36c | 2016-12-15 13:12:59 -0800 | [diff] [blame] | 908 |           // No ordering required for initial lockword read. | 
| Ian Rogers | d9c4fc9 | 2013-10-01 19:45:43 -0700 | [diff] [blame] | 909 |           // We own the lock, increase the recursion count. | 
 | 910 |           uint32_t new_count = lock_word.ThinLockCount() + 1; | 
 | 911 |           if (LIKELY(new_count <= LockWord::kThinLockMaxCount)) { | 
| Mathieu Chartier | 36a270a | 2016-07-28 18:08:51 -0700 | [diff] [blame] | 912 |             LockWord thin_locked(LockWord::FromThinLockId(thread_id, | 
 | 913 |                                                           new_count, | 
 | 914 |                                                           lock_word.GCState())); | 
| Hans Boehm | b3da36c | 2016-12-15 13:12:59 -0800 | [diff] [blame] | 915 |             // Only this thread pays attention to the count. Thus there is no need for stronger | 
 | 916 |             // than relaxed memory ordering. | 
| Hiroshi Yamauchi | e15ea08 | 2015-02-09 17:11:42 -0800 | [diff] [blame] | 917 |             if (!kUseReadBarrier) { | 
| Hans Boehm | b3da36c | 2016-12-15 13:12:59 -0800 | [diff] [blame] | 918 |               h_obj->SetLockWord(thin_locked, false /* volatile */); | 
| Andreas Gampe | c7ed09b | 2016-04-25 20:08:55 -0700 | [diff] [blame] | 919 |               AtraceMonitorLock(self, h_obj.Get(), false /* is_wait */); | 
| Hiroshi Yamauchi | e15ea08 | 2015-02-09 17:11:42 -0800 | [diff] [blame] | 920 |               return h_obj.Get();  // Success! | 
 | 921 |             } else { | 
 | 922 |               // Use CAS to preserve the read barrier state. | 
| Hans Boehm | b3da36c | 2016-12-15 13:12:59 -0800 | [diff] [blame] | 923 |               if (h_obj->CasLockWordWeakRelaxed(lock_word, thin_locked)) { | 
| Andreas Gampe | c7ed09b | 2016-04-25 20:08:55 -0700 | [diff] [blame] | 924 |                 AtraceMonitorLock(self, h_obj.Get(), false /* is_wait */); | 
| Hiroshi Yamauchi | e15ea08 | 2015-02-09 17:11:42 -0800 | [diff] [blame] | 925 |                 return h_obj.Get();  // Success! | 
 | 926 |               } | 
 | 927 |             } | 
 | 928 |             continue;  // Go again. | 
| Elliott Hughes | 5f79133 | 2011-09-15 17:45:30 -0700 | [diff] [blame] | 929 |           } else { | 
| Ian Rogers | d9c4fc9 | 2013-10-01 19:45:43 -0700 | [diff] [blame] | 930 |             // We'd overflow the recursion count, so inflate the monitor. | 
| Mathieu Chartier | eb8167a | 2014-05-07 15:43:14 -0700 | [diff] [blame] | 931 |             InflateThinLocked(self, h_obj, lock_word, 0); | 
| Ian Rogers | d9c4fc9 | 2013-10-01 19:45:43 -0700 | [diff] [blame] | 932 |           } | 
 | 933 |         } else { | 
| Mathieu Chartier | 4b0ef1c | 2016-07-29 16:26:01 -0700 | [diff] [blame] | 934 |           if (trylock) { | 
 | 935 |             return nullptr; | 
 | 936 |           } | 
| Ian Rogers | d9c4fc9 | 2013-10-01 19:45:43 -0700 | [diff] [blame] | 937 |           // Contention. | 
 | 938 |           contention_count++; | 
| Mathieu Chartier | ad2541a | 2013-10-25 10:05:23 -0700 | [diff] [blame] | 939 |           Runtime* runtime = Runtime::Current(); | 
| Hans Boehm | b3da36c | 2016-12-15 13:12:59 -0800 | [diff] [blame] | 940 |           if (contention_count <= runtime->GetMaxSpinsBeforeThinLockInflation()) { | 
| Mathieu Chartier | b363f66 | 2014-07-16 13:28:58 -0700 | [diff] [blame] | 941 |             // TODO: Consider switching the thread state to kBlocked when we are yielding. | 
| Mathieu Chartier | 251755c | 2014-07-15 18:10:25 -0700 | [diff] [blame] | 942 |             // Use sched_yield instead of NanoSleep since NanoSleep can wait much longer than the | 
 | 943 |             // parameter you pass in. This can cause thread suspension to take excessively long | 
| Mathieu Chartier | b363f66 | 2014-07-16 13:28:58 -0700 | [diff] [blame] | 944 |             // and make long pauses. See b/16307460. | 
| Hans Boehm | b3da36c | 2016-12-15 13:12:59 -0800 | [diff] [blame] | 945 |             // TODO: We should literally spin first, without sched_yield. Sched_yield either does | 
 | 946 |             // nothing (at significant expense), or guarantees that we wait at least microseconds. | 
 | 947 |             // If the owner is running, I would expect the median lock hold time to be hundreds | 
 | 948 |             // of nanoseconds or less. | 
| Mathieu Chartier | 251755c | 2014-07-15 18:10:25 -0700 | [diff] [blame] | 949 |             sched_yield(); | 
| Ian Rogers | d9c4fc9 | 2013-10-01 19:45:43 -0700 | [diff] [blame] | 950 |           } else { | 
 | 951 |             contention_count = 0; | 
| Hans Boehm | b3da36c | 2016-12-15 13:12:59 -0800 | [diff] [blame] | 952 |             // No ordering required for initial lockword read. Install rereads it anyway. | 
| Mathieu Chartier | eb8167a | 2014-05-07 15:43:14 -0700 | [diff] [blame] | 953 |             InflateThinLocked(self, h_obj, lock_word, 0); | 
| Elliott Hughes | 5f79133 | 2011-09-15 17:45:30 -0700 | [diff] [blame] | 954 |           } | 
| Elliott Hughes | 5f79133 | 2011-09-15 17:45:30 -0700 | [diff] [blame] | 955 |         } | 
| Ian Rogers | d9c4fc9 | 2013-10-01 19:45:43 -0700 | [diff] [blame] | 956 |         continue;  // Start from the beginning. | 
| Elliott Hughes | 5f79133 | 2011-09-15 17:45:30 -0700 | [diff] [blame] | 957 |       } | 
| Ian Rogers | d9c4fc9 | 2013-10-01 19:45:43 -0700 | [diff] [blame] | 958 |       case LockWord::kFatLocked: { | 
| Hans Boehm | b3da36c | 2016-12-15 13:12:59 -0800 | [diff] [blame] | 959 |         // We should have done an acquire read of the lockword initially, to ensure | 
 | 960 |         // visibility of the monitor data structure. Use an explicit fence instead. | 
 | 961 |         QuasiAtomic::ThreadFenceAcquire(); | 
| Ian Rogers | d9c4fc9 | 2013-10-01 19:45:43 -0700 | [diff] [blame] | 962 |         Monitor* mon = lock_word.FatLockMonitor(); | 
| Mathieu Chartier | 4b0ef1c | 2016-07-29 16:26:01 -0700 | [diff] [blame] | 963 |         if (trylock) { | 
 | 964 |           return mon->TryLock(self) ? h_obj.Get() : nullptr; | 
 | 965 |         } else { | 
 | 966 |           mon->Lock(self); | 
 | 967 |           return h_obj.Get();  // Success! | 
 | 968 |         } | 
| Ian Rogers | d9c4fc9 | 2013-10-01 19:45:43 -0700 | [diff] [blame] | 969 |       } | 
| Ian Rogers | 719d1a3 | 2014-03-06 12:13:39 -0800 | [diff] [blame] | 970 |       case LockWord::kHashCode: | 
| Mathieu Chartier | ad2541a | 2013-10-25 10:05:23 -0700 | [diff] [blame] | 971 |         // Inflate with the existing hashcode. | 
| Hans Boehm | b3da36c | 2016-12-15 13:12:59 -0800 | [diff] [blame] | 972 |         // Again no ordering required for initial lockword read, since we don't rely | 
 | 973 |         // on the visibility of any prior computation. | 
| Mathieu Chartier | eb8167a | 2014-05-07 15:43:14 -0700 | [diff] [blame] | 974 |         Inflate(self, nullptr, h_obj.Get(), lock_word.GetHashCode()); | 
| Ian Rogers | 719d1a3 | 2014-03-06 12:13:39 -0800 | [diff] [blame] | 975 |         continue;  // Start from the beginning. | 
| Mathieu Chartier | 590fee9 | 2013-09-13 13:46:47 -0700 | [diff] [blame] | 976 |       default: { | 
 | 977 |         LOG(FATAL) << "Invalid monitor state " << lock_word.GetState(); | 
| Andreas Gampe | c7ed09b | 2016-04-25 20:08:55 -0700 | [diff] [blame] | 978 |         UNREACHABLE(); | 
| Mathieu Chartier | 590fee9 | 2013-09-13 13:46:47 -0700 | [diff] [blame] | 979 |       } | 
| Elliott Hughes | 5f79133 | 2011-09-15 17:45:30 -0700 | [diff] [blame] | 980 |     } | 
| Elliott Hughes | 5f79133 | 2011-09-15 17:45:30 -0700 | [diff] [blame] | 981 |   } | 
 | 982 | } | 
 | 983 |  | 
| Ian Rogers | 2dd0e2c | 2013-01-24 12:42:14 -0800 | [diff] [blame] | 984 | bool Monitor::MonitorExit(Thread* self, mirror::Object* obj) { | 
| Mathieu Chartier | 2cebb24 | 2015-04-21 16:50:40 -0700 | [diff] [blame] | 985 |   DCHECK(self != nullptr); | 
 | 986 |   DCHECK(obj != nullptr); | 
| Mathieu Chartier | 2d096c9 | 2015-10-12 16:18:20 -0700 | [diff] [blame] | 987 |   self->AssertThreadSuspensionIsAllowable(); | 
| Ian Rogers | 719d1a3 | 2014-03-06 12:13:39 -0800 | [diff] [blame] | 988 |   obj = FakeUnlock(obj); | 
| Mathieu Chartier | eb8167a | 2014-05-07 15:43:14 -0700 | [diff] [blame] | 989 |   StackHandleScope<1> hs(self); | 
 | 990 |   Handle<mirror::Object> h_obj(hs.NewHandle(obj)); | 
| Hiroshi Yamauchi | e15ea08 | 2015-02-09 17:11:42 -0800 | [diff] [blame] | 991 |   while (true) { | 
 | 992 |     LockWord lock_word = obj->GetLockWord(true); | 
 | 993 |     switch (lock_word.GetState()) { | 
 | 994 |       case LockWord::kHashCode: | 
 | 995 |         // Fall-through. | 
 | 996 |       case LockWord::kUnlocked: | 
| Mathieu Chartier | 61b3cd4 | 2016-04-18 11:43:29 -0700 | [diff] [blame] | 997 |         FailedUnlock(h_obj.Get(), self->GetThreadId(), 0u, nullptr); | 
| Ian Rogers | d9c4fc9 | 2013-10-01 19:45:43 -0700 | [diff] [blame] | 998 |         return false;  // Failure. | 
| Hiroshi Yamauchi | e15ea08 | 2015-02-09 17:11:42 -0800 | [diff] [blame] | 999 |       case LockWord::kThinLocked: { | 
 | 1000 |         uint32_t thread_id = self->GetThreadId(); | 
 | 1001 |         uint32_t owner_thread_id = lock_word.ThinLockOwner(); | 
 | 1002 |         if (owner_thread_id != thread_id) { | 
| Mathieu Chartier | 61b3cd4 | 2016-04-18 11:43:29 -0700 | [diff] [blame] | 1003 |           FailedUnlock(h_obj.Get(), thread_id, owner_thread_id, nullptr); | 
| Hiroshi Yamauchi | e15ea08 | 2015-02-09 17:11:42 -0800 | [diff] [blame] | 1004 |           return false;  // Failure. | 
| Ian Rogers | d9c4fc9 | 2013-10-01 19:45:43 -0700 | [diff] [blame] | 1005 |         } else { | 
| Hiroshi Yamauchi | e15ea08 | 2015-02-09 17:11:42 -0800 | [diff] [blame] | 1006 |           // We own the lock, decrease the recursion count. | 
 | 1007 |           LockWord new_lw = LockWord::Default(); | 
 | 1008 |           if (lock_word.ThinLockCount() != 0) { | 
 | 1009 |             uint32_t new_count = lock_word.ThinLockCount() - 1; | 
| Mathieu Chartier | 36a270a | 2016-07-28 18:08:51 -0700 | [diff] [blame] | 1010 |             new_lw = LockWord::FromThinLockId(thread_id, new_count, lock_word.GCState()); | 
| Hiroshi Yamauchi | e15ea08 | 2015-02-09 17:11:42 -0800 | [diff] [blame] | 1011 |           } else { | 
| Mathieu Chartier | 36a270a | 2016-07-28 18:08:51 -0700 | [diff] [blame] | 1012 |             new_lw = LockWord::FromDefault(lock_word.GCState()); | 
| Hiroshi Yamauchi | e15ea08 | 2015-02-09 17:11:42 -0800 | [diff] [blame] | 1013 |           } | 
 | 1014 |           if (!kUseReadBarrier) { | 
 | 1015 |             DCHECK_EQ(new_lw.ReadBarrierState(), 0U); | 
| Hans Boehm | b3da36c | 2016-12-15 13:12:59 -0800 | [diff] [blame] | 1016 |             // TODO: This really only needs memory_order_release, but we currently have | 
 | 1017 |             // no way to specify that. In fact there seem to be no legitimate uses of SetLockWord | 
 | 1018 |             // with a final argument of true. This slows down x86 and ARMv7, but probably not v8. | 
| Hiroshi Yamauchi | e15ea08 | 2015-02-09 17:11:42 -0800 | [diff] [blame] | 1019 |             h_obj->SetLockWord(new_lw, true); | 
| Andreas Gampe | 6e759ad | 2016-05-17 10:13:10 -0700 | [diff] [blame] | 1020 |             AtraceMonitorUnlock(); | 
| Hiroshi Yamauchi | e15ea08 | 2015-02-09 17:11:42 -0800 | [diff] [blame] | 1021 |             // Success! | 
 | 1022 |             return true; | 
 | 1023 |           } else { | 
 | 1024 |             // Use CAS to preserve the read barrier state. | 
| Hans Boehm | b3da36c | 2016-12-15 13:12:59 -0800 | [diff] [blame] | 1025 |             if (h_obj->CasLockWordWeakRelease(lock_word, new_lw)) { | 
| Andreas Gampe | 6e759ad | 2016-05-17 10:13:10 -0700 | [diff] [blame] | 1026 |               AtraceMonitorUnlock(); | 
| Hiroshi Yamauchi | e15ea08 | 2015-02-09 17:11:42 -0800 | [diff] [blame] | 1027 |               // Success! | 
 | 1028 |               return true; | 
 | 1029 |             } | 
 | 1030 |           } | 
 | 1031 |           continue;  // Go again. | 
| Ian Rogers | d9c4fc9 | 2013-10-01 19:45:43 -0700 | [diff] [blame] | 1032 |         } | 
| Ian Rogers | d9c4fc9 | 2013-10-01 19:45:43 -0700 | [diff] [blame] | 1033 |       } | 
| Hiroshi Yamauchi | e15ea08 | 2015-02-09 17:11:42 -0800 | [diff] [blame] | 1034 |       case LockWord::kFatLocked: { | 
 | 1035 |         Monitor* mon = lock_word.FatLockMonitor(); | 
 | 1036 |         return mon->Unlock(self); | 
 | 1037 |       } | 
 | 1038 |       default: { | 
 | 1039 |         LOG(FATAL) << "Invalid monitor state " << lock_word.GetState(); | 
 | 1040 |         return false; | 
 | 1041 |       } | 
| Mathieu Chartier | 590fee9 | 2013-09-13 13:46:47 -0700 | [diff] [blame] | 1042 |     } | 
| Elliott Hughes | 5f79133 | 2011-09-15 17:45:30 -0700 | [diff] [blame] | 1043 |   } | 
| Elliott Hughes | 5f79133 | 2011-09-15 17:45:30 -0700 | [diff] [blame] | 1044 | } | 
 | 1045 |  | 
| Ian Rogers | 2dd0e2c | 2013-01-24 12:42:14 -0800 | [diff] [blame] | 1046 | void Monitor::Wait(Thread* self, mirror::Object *obj, int64_t ms, int32_t ns, | 
| Elliott Hughes | 4cd121e | 2013-01-07 17:35:41 -0800 | [diff] [blame] | 1047 |                    bool interruptShouldThrow, ThreadState why) { | 
| Mathieu Chartier | 4d7f61d | 2014-04-17 14:43:39 -0700 | [diff] [blame] | 1048 |   DCHECK(self != nullptr); | 
 | 1049 |   DCHECK(obj != nullptr); | 
 | 1050 |   LockWord lock_word = obj->GetLockWord(true); | 
| Ian Rogers | 43c69cc | 2014-08-15 11:09:28 -0700 | [diff] [blame] | 1051 |   while (lock_word.GetState() != LockWord::kFatLocked) { | 
 | 1052 |     switch (lock_word.GetState()) { | 
 | 1053 |       case LockWord::kHashCode: | 
 | 1054 |         // Fall-through. | 
 | 1055 |       case LockWord::kUnlocked: | 
| Ian Rogers | d9c4fc9 | 2013-10-01 19:45:43 -0700 | [diff] [blame] | 1056 |         ThrowIllegalMonitorStateExceptionF("object not locked by thread before wait()"); | 
 | 1057 |         return;  // Failure. | 
| Ian Rogers | 43c69cc | 2014-08-15 11:09:28 -0700 | [diff] [blame] | 1058 |       case LockWord::kThinLocked: { | 
 | 1059 |         uint32_t thread_id = self->GetThreadId(); | 
 | 1060 |         uint32_t owner_thread_id = lock_word.ThinLockOwner(); | 
 | 1061 |         if (owner_thread_id != thread_id) { | 
 | 1062 |           ThrowIllegalMonitorStateExceptionF("object not locked by thread before wait()"); | 
 | 1063 |           return;  // Failure. | 
 | 1064 |         } else { | 
 | 1065 |           // We own the lock, inflate to enqueue ourself on the Monitor. May fail spuriously so | 
 | 1066 |           // re-load. | 
 | 1067 |           Inflate(self, self, obj, 0); | 
 | 1068 |           lock_word = obj->GetLockWord(true); | 
 | 1069 |         } | 
 | 1070 |         break; | 
| Ian Rogers | d9c4fc9 | 2013-10-01 19:45:43 -0700 | [diff] [blame] | 1071 |       } | 
| Ian Rogers | 43c69cc | 2014-08-15 11:09:28 -0700 | [diff] [blame] | 1072 |       case LockWord::kFatLocked:  // Unreachable given the loop condition above. Fall-through. | 
 | 1073 |       default: { | 
 | 1074 |         LOG(FATAL) << "Invalid monitor state " << lock_word.GetState(); | 
 | 1075 |         return; | 
 | 1076 |       } | 
| Mathieu Chartier | 590fee9 | 2013-09-13 13:46:47 -0700 | [diff] [blame] | 1077 |     } | 
| Elliott Hughes | 5f79133 | 2011-09-15 17:45:30 -0700 | [diff] [blame] | 1078 |   } | 
| Ian Rogers | d9c4fc9 | 2013-10-01 19:45:43 -0700 | [diff] [blame] | 1079 |   Monitor* mon = lock_word.FatLockMonitor(); | 
 | 1080 |   mon->Wait(self, ms, ns, interruptShouldThrow, why); | 
| Elliott Hughes | 5f79133 | 2011-09-15 17:45:30 -0700 | [diff] [blame] | 1081 | } | 
 | 1082 |  | 
| Ian Rogers | 13c479e | 2013-10-11 07:59:01 -0700 | [diff] [blame] | 1083 | void Monitor::DoNotify(Thread* self, mirror::Object* obj, bool notify_all) { | 
| Mathieu Chartier | 4d7f61d | 2014-04-17 14:43:39 -0700 | [diff] [blame] | 1084 |   DCHECK(self != nullptr); | 
 | 1085 |   DCHECK(obj != nullptr); | 
 | 1086 |   LockWord lock_word = obj->GetLockWord(true); | 
| Ian Rogers | d9c4fc9 | 2013-10-01 19:45:43 -0700 | [diff] [blame] | 1087 |   switch (lock_word.GetState()) { | 
| Mathieu Chartier | ad2541a | 2013-10-25 10:05:23 -0700 | [diff] [blame] | 1088 |     case LockWord::kHashCode: | 
 | 1089 |       // Fall-through. | 
| Ian Rogers | d9c4fc9 | 2013-10-01 19:45:43 -0700 | [diff] [blame] | 1090 |     case LockWord::kUnlocked: | 
| Ian Rogers | 6d0b13e | 2012-02-07 09:25:29 -0800 | [diff] [blame] | 1091 |       ThrowIllegalMonitorStateExceptionF("object not locked by thread before notify()"); | 
| Ian Rogers | d9c4fc9 | 2013-10-01 19:45:43 -0700 | [diff] [blame] | 1092 |       return;  // Failure. | 
 | 1093 |     case LockWord::kThinLocked: { | 
 | 1094 |       uint32_t thread_id = self->GetThreadId(); | 
 | 1095 |       uint32_t owner_thread_id = lock_word.ThinLockOwner(); | 
 | 1096 |       if (owner_thread_id != thread_id) { | 
 | 1097 |         ThrowIllegalMonitorStateExceptionF("object not locked by thread before notify()"); | 
 | 1098 |         return;  // Failure. | 
 | 1099 |       } else { | 
 | 1100 |         // We own the lock but there's no Monitor and therefore no waiters. | 
 | 1101 |         return;  // Success. | 
 | 1102 |       } | 
| Elliott Hughes | 5f79133 | 2011-09-15 17:45:30 -0700 | [diff] [blame] | 1103 |     } | 
| Ian Rogers | d9c4fc9 | 2013-10-01 19:45:43 -0700 | [diff] [blame] | 1104 |     case LockWord::kFatLocked: { | 
 | 1105 |       Monitor* mon = lock_word.FatLockMonitor(); | 
 | 1106 |       if (notify_all) { | 
 | 1107 |         mon->NotifyAll(self); | 
 | 1108 |       } else { | 
 | 1109 |         mon->Notify(self); | 
 | 1110 |       } | 
 | 1111 |       return;  // Success. | 
 | 1112 |     } | 
| Mathieu Chartier | 590fee9 | 2013-09-13 13:46:47 -0700 | [diff] [blame] | 1113 |     default: { | 
 | 1114 |       LOG(FATAL) << "Invalid monitor state " << lock_word.GetState(); | 
 | 1115 |       return; | 
 | 1116 |     } | 
| Elliott Hughes | 5f79133 | 2011-09-15 17:45:30 -0700 | [diff] [blame] | 1117 |   } | 
 | 1118 | } | 
 | 1119 |  | 
| Ian Rogers | d9c4fc9 | 2013-10-01 19:45:43 -0700 | [diff] [blame] | 1120 | uint32_t Monitor::GetLockOwnerThreadId(mirror::Object* obj) { | 
| Mathieu Chartier | 4d7f61d | 2014-04-17 14:43:39 -0700 | [diff] [blame] | 1121 |   DCHECK(obj != nullptr); | 
 | 1122 |   LockWord lock_word = obj->GetLockWord(true); | 
| Ian Rogers | d9c4fc9 | 2013-10-01 19:45:43 -0700 | [diff] [blame] | 1123 |   switch (lock_word.GetState()) { | 
| Mathieu Chartier | ad2541a | 2013-10-25 10:05:23 -0700 | [diff] [blame] | 1124 |     case LockWord::kHashCode: | 
 | 1125 |       // Fall-through. | 
| Ian Rogers | d9c4fc9 | 2013-10-01 19:45:43 -0700 | [diff] [blame] | 1126 |     case LockWord::kUnlocked: | 
 | 1127 |       return ThreadList::kInvalidThreadId; | 
 | 1128 |     case LockWord::kThinLocked: | 
 | 1129 |       return lock_word.ThinLockOwner(); | 
 | 1130 |     case LockWord::kFatLocked: { | 
 | 1131 |       Monitor* mon = lock_word.FatLockMonitor(); | 
 | 1132 |       return mon->GetOwnerThreadId(); | 
| Elliott Hughes | 5f79133 | 2011-09-15 17:45:30 -0700 | [diff] [blame] | 1133 |     } | 
| Mathieu Chartier | 590fee9 | 2013-09-13 13:46:47 -0700 | [diff] [blame] | 1134 |     default: { | 
| Ian Rogers | d9c4fc9 | 2013-10-01 19:45:43 -0700 | [diff] [blame] | 1135 |       LOG(FATAL) << "Unreachable"; | 
| Ian Rogers | 2c4257b | 2014-10-24 14:20:06 -0700 | [diff] [blame] | 1136 |       UNREACHABLE(); | 
| Mathieu Chartier | 590fee9 | 2013-09-13 13:46:47 -0700 | [diff] [blame] | 1137 |     } | 
| Elliott Hughes | 5f79133 | 2011-09-15 17:45:30 -0700 | [diff] [blame] | 1138 |   } | 
 | 1139 | } | 
 | 1140 |  | 
| Elliott Hughes | 8e4aac5 | 2011-09-26 17:03:36 -0700 | [diff] [blame] | 1141 | void Monitor::DescribeWait(std::ostream& os, const Thread* thread) { | 
| Ian Rogers | d803bc7 | 2014-04-01 15:33:03 -0700 | [diff] [blame] | 1142 |   // Determine the wait message and object we're waiting or blocked upon. | 
 | 1143 |   mirror::Object* pretty_object = nullptr; | 
 | 1144 |   const char* wait_message = nullptr; | 
| Ian Rogers | d9c4fc9 | 2013-10-01 19:45:43 -0700 | [diff] [blame] | 1145 |   uint32_t lock_owner = ThreadList::kInvalidThreadId; | 
| Ian Rogers | d803bc7 | 2014-04-01 15:33:03 -0700 | [diff] [blame] | 1146 |   ThreadState state = thread->GetState(); | 
| Elliott Hughes | b4e94fd | 2013-01-08 14:41:26 -0800 | [diff] [blame] | 1147 |   if (state == kWaiting || state == kTimedWaiting || state == kSleeping) { | 
| Ian Rogers | d803bc7 | 2014-04-01 15:33:03 -0700 | [diff] [blame] | 1148 |     wait_message = (state == kSleeping) ? "  - sleeping on " : "  - waiting on "; | 
 | 1149 |     Thread* self = Thread::Current(); | 
 | 1150 |     MutexLock mu(self, *thread->GetWaitMutex()); | 
 | 1151 |     Monitor* monitor = thread->GetWaitMonitor(); | 
 | 1152 |     if (monitor != nullptr) { | 
| Hiroshi Yamauchi | 4cba0d9 | 2014-05-21 21:10:23 -0700 | [diff] [blame] | 1153 |       pretty_object = monitor->GetObject(); | 
| Ian Rogers | 00f7d0e | 2012-07-19 15:28:27 -0700 | [diff] [blame] | 1154 |     } | 
| Elliott Hughes | 34e0696 | 2012-04-09 13:55:55 -0700 | [diff] [blame] | 1155 |   } else if (state == kBlocked) { | 
| Ian Rogers | d803bc7 | 2014-04-01 15:33:03 -0700 | [diff] [blame] | 1156 |     wait_message = "  - waiting to lock "; | 
 | 1157 |     pretty_object = thread->GetMonitorEnterObject(); | 
 | 1158 |     if (pretty_object != nullptr) { | 
| Hiroshi Yamauchi | 7b08ae4 | 2016-10-04 15:20:36 -0700 | [diff] [blame] | 1159 |       if (kUseReadBarrier && Thread::Current()->GetIsGcMarking()) { | 
 | 1160 |         // We may call Thread::Dump() in the middle of the CC thread flip and this thread's stack | 
 | 1161 |         // may have not been flipped yet and "pretty_object" may be a from-space (stale) ref, in | 
 | 1162 |         // which case the GetLockOwnerThreadId() call below will crash. So explicitly mark/forward | 
 | 1163 |         // it here. | 
 | 1164 |         pretty_object = ReadBarrier::Mark(pretty_object); | 
 | 1165 |       } | 
| Ian Rogers | d803bc7 | 2014-04-01 15:33:03 -0700 | [diff] [blame] | 1166 |       lock_owner = pretty_object->GetLockOwnerThreadId(); | 
| Elliott Hughes | 8e4aac5 | 2011-09-26 17:03:36 -0700 | [diff] [blame] | 1167 |     } | 
| Elliott Hughes | 8e4aac5 | 2011-09-26 17:03:36 -0700 | [diff] [blame] | 1168 |   } | 
| Elliott Hughes | 8e4aac5 | 2011-09-26 17:03:36 -0700 | [diff] [blame] | 1169 |  | 
| Ian Rogers | d803bc7 | 2014-04-01 15:33:03 -0700 | [diff] [blame] | 1170 |   if (wait_message != nullptr) { | 
 | 1171 |     if (pretty_object == nullptr) { | 
 | 1172 |       os << wait_message << "an unknown object"; | 
 | 1173 |     } else { | 
| Mathieu Chartier | 4d7f61d | 2014-04-17 14:43:39 -0700 | [diff] [blame] | 1174 |       if ((pretty_object->GetLockWord(true).GetState() == LockWord::kThinLocked) && | 
| Ian Rogers | d803bc7 | 2014-04-01 15:33:03 -0700 | [diff] [blame] | 1175 |           Locks::mutator_lock_->IsExclusiveHeld(Thread::Current())) { | 
 | 1176 |         // Getting the identity hashcode here would result in lock inflation and suspension of the | 
 | 1177 |         // current thread, which isn't safe if this is the only runnable thread. | 
 | 1178 |         os << wait_message << StringPrintf("<@addr=0x%" PRIxPTR "> (a %s)", | 
 | 1179 |                                            reinterpret_cast<intptr_t>(pretty_object), | 
| David Sehr | 709b070 | 2016-10-13 09:12:37 -0700 | [diff] [blame] | 1180 |                                            pretty_object->PrettyTypeOf().c_str()); | 
| Ian Rogers | d803bc7 | 2014-04-01 15:33:03 -0700 | [diff] [blame] | 1181 |       } else { | 
 | 1182 |         // - waiting on <0x6008c468> (a java.lang.Class<java.lang.ref.ReferenceQueue>) | 
| Mathieu Chartier | 4936159 | 2015-01-22 16:36:10 -0800 | [diff] [blame] | 1183 |         // Call PrettyTypeOf before IdentityHashCode since IdentityHashCode can cause thread | 
 | 1184 |         // suspension and move pretty_object. | 
| David Sehr | 709b070 | 2016-10-13 09:12:37 -0700 | [diff] [blame] | 1185 |         const std::string pretty_type(pretty_object->PrettyTypeOf()); | 
| Ian Rogers | d803bc7 | 2014-04-01 15:33:03 -0700 | [diff] [blame] | 1186 |         os << wait_message << StringPrintf("<0x%08x> (a %s)", pretty_object->IdentityHashCode(), | 
| Mathieu Chartier | 4936159 | 2015-01-22 16:36:10 -0800 | [diff] [blame] | 1187 |                                            pretty_type.c_str()); | 
| Ian Rogers | d803bc7 | 2014-04-01 15:33:03 -0700 | [diff] [blame] | 1188 |       } | 
 | 1189 |     } | 
 | 1190 |     // - waiting to lock <0x613f83d8> (a java.lang.Object) held by thread 5 | 
 | 1191 |     if (lock_owner != ThreadList::kInvalidThreadId) { | 
 | 1192 |       os << " held by thread " << lock_owner; | 
 | 1193 |     } | 
 | 1194 |     os << "\n"; | 
| Elliott Hughes | 8e4aac5 | 2011-09-26 17:03:36 -0700 | [diff] [blame] | 1195 |   } | 
| Elliott Hughes | 8e4aac5 | 2011-09-26 17:03:36 -0700 | [diff] [blame] | 1196 | } | 
 | 1197 |  | 
| Ian Rogers | 2dd0e2c | 2013-01-24 12:42:14 -0800 | [diff] [blame] | 1198 | mirror::Object* Monitor::GetContendedMonitor(Thread* thread) { | 
| Elliott Hughes | f950170 | 2013-01-11 11:22:27 -0800 | [diff] [blame] | 1199 |   // This is used to implement JDWP's ThreadReference.CurrentContendedMonitor, and has a bizarre | 
 | 1200 |   // definition of contended that includes a monitor a thread is trying to enter... | 
| Ian Rogers | dd7624d | 2014-03-14 17:43:00 -0700 | [diff] [blame] | 1201 |   mirror::Object* result = thread->GetMonitorEnterObject(); | 
| Mathieu Chartier | 2cebb24 | 2015-04-21 16:50:40 -0700 | [diff] [blame] | 1202 |   if (result == nullptr) { | 
| Ian Rogers | d9c4fc9 | 2013-10-01 19:45:43 -0700 | [diff] [blame] | 1203 |     // ...but also a monitor that the thread is waiting on. | 
| Ian Rogers | dd7624d | 2014-03-14 17:43:00 -0700 | [diff] [blame] | 1204 |     MutexLock mu(Thread::Current(), *thread->GetWaitMutex()); | 
 | 1205 |     Monitor* monitor = thread->GetWaitMonitor(); | 
| Mathieu Chartier | 2cebb24 | 2015-04-21 16:50:40 -0700 | [diff] [blame] | 1206 |     if (monitor != nullptr) { | 
| Ian Rogers | d9c4fc9 | 2013-10-01 19:45:43 -0700 | [diff] [blame] | 1207 |       result = monitor->GetObject(); | 
| Elliott Hughes | f950170 | 2013-01-11 11:22:27 -0800 | [diff] [blame] | 1208 |     } | 
 | 1209 |   } | 
| Ian Rogers | d9c4fc9 | 2013-10-01 19:45:43 -0700 | [diff] [blame] | 1210 |   return result; | 
| Elliott Hughes | f950170 | 2013-01-11 11:22:27 -0800 | [diff] [blame] | 1211 | } | 
 | 1212 |  | 
| Ian Rogers | 2dd0e2c | 2013-01-24 12:42:14 -0800 | [diff] [blame] | 1213 | void Monitor::VisitLocks(StackVisitor* stack_visitor, void (*callback)(mirror::Object*, void*), | 
| Andreas Gampe | 760172c | 2014-08-16 13:41:10 -0700 | [diff] [blame] | 1214 |                          void* callback_context, bool abort_on_failure) { | 
| Mathieu Chartier | e401d14 | 2015-04-22 13:56:20 -0700 | [diff] [blame] | 1215 |   ArtMethod* m = stack_visitor->GetMethod(); | 
| Mathieu Chartier | 2cebb24 | 2015-04-21 16:50:40 -0700 | [diff] [blame] | 1216 |   CHECK(m != nullptr); | 
| Elliott Hughes | 08fc03a | 2012-06-26 17:34:00 -0700 | [diff] [blame] | 1217 |  | 
 | 1218 |   // Native methods are an easy special case. | 
 | 1219 |   // TODO: use the JNI implementation's table of explicit MonitorEnter calls and dump those too. | 
 | 1220 |   if (m->IsNative()) { | 
 | 1221 |     if (m->IsSynchronized()) { | 
| Mathieu Chartier | e401d14 | 2015-04-22 13:56:20 -0700 | [diff] [blame] | 1222 |       mirror::Object* jni_this = | 
 | 1223 |           stack_visitor->GetCurrentHandleScope(sizeof(void*))->GetReference(0); | 
| Elliott Hughes | 4993bbc | 2013-01-10 15:41:25 -0800 | [diff] [blame] | 1224 |       callback(jni_this, callback_context); | 
| Elliott Hughes | 08fc03a | 2012-06-26 17:34:00 -0700 | [diff] [blame] | 1225 |     } | 
 | 1226 |     return; | 
 | 1227 |   } | 
 | 1228 |  | 
| jeffhao | 61f916c | 2012-10-25 17:48:51 -0700 | [diff] [blame] | 1229 |   // Proxy methods should not be synchronized. | 
 | 1230 |   if (m->IsProxyMethod()) { | 
 | 1231 |     CHECK(!m->IsSynchronized()); | 
 | 1232 |     return; | 
 | 1233 |   } | 
 | 1234 |  | 
| Elliott Hughes | 08fc03a | 2012-06-26 17:34:00 -0700 | [diff] [blame] | 1235 |   // Is there any reason to believe there's any synchronization in this method? | 
| Mathieu Chartier | bfd9a43 | 2014-05-21 17:43:44 -0700 | [diff] [blame] | 1236 |   const DexFile::CodeItem* code_item = m->GetCodeItem(); | 
| David Sehr | 709b070 | 2016-10-13 09:12:37 -0700 | [diff] [blame] | 1237 |   CHECK(code_item != nullptr) << m->PrettyMethod(); | 
| Elliott Hughes | 08fc03a | 2012-06-26 17:34:00 -0700 | [diff] [blame] | 1238 |   if (code_item->tries_size_ == 0) { | 
| Brian Carlstrom | 7934ac2 | 2013-07-26 10:54:15 -0700 | [diff] [blame] | 1239 |     return;  // No "tries" implies no synchronization, so no held locks to report. | 
| Elliott Hughes | 08fc03a | 2012-06-26 17:34:00 -0700 | [diff] [blame] | 1240 |   } | 
 | 1241 |  | 
| Andreas Gampe | 760172c | 2014-08-16 13:41:10 -0700 | [diff] [blame] | 1242 |   // Get the dex pc. If abort_on_failure is false, GetDexPc will not abort in the case it cannot | 
 | 1243 |   // find the dex pc, and instead return kDexNoIndex. Then bail out, as it indicates we have an | 
 | 1244 |   // inconsistent stack anyways. | 
 | 1245 |   uint32_t dex_pc = stack_visitor->GetDexPc(abort_on_failure); | 
 | 1246 |   if (!abort_on_failure && dex_pc == DexFile::kDexNoIndex) { | 
| David Sehr | 709b070 | 2016-10-13 09:12:37 -0700 | [diff] [blame] | 1247 |     LOG(ERROR) << "Could not find dex_pc for " << m->PrettyMethod(); | 
| Andreas Gampe | 760172c | 2014-08-16 13:41:10 -0700 | [diff] [blame] | 1248 |     return; | 
 | 1249 |   } | 
 | 1250 |  | 
| Elliott Hughes | 80537bb | 2013-01-04 16:37:26 -0800 | [diff] [blame] | 1251 |   // Ask the verifier for the dex pcs of all the monitor-enter instructions corresponding to | 
 | 1252 |   // the locks held in this stack frame. | 
 | 1253 |   std::vector<uint32_t> monitor_enter_dex_pcs; | 
| Andreas Gampe | 760172c | 2014-08-16 13:41:10 -0700 | [diff] [blame] | 1254 |   verifier::MethodVerifier::FindLocksAtDexPc(m, dex_pc, &monitor_enter_dex_pcs); | 
| Mathieu Chartier | e6a8eec | 2015-01-06 14:17:57 -0800 | [diff] [blame] | 1255 |   for (uint32_t monitor_dex_pc : monitor_enter_dex_pcs) { | 
| Elliott Hughes | 80537bb | 2013-01-04 16:37:26 -0800 | [diff] [blame] | 1256 |     // The verifier works in terms of the dex pcs of the monitor-enter instructions. | 
 | 1257 |     // We want the registers used by those instructions (so we can read the values out of them). | 
| Sebastien Hertz | 0f7c933 | 2015-11-05 15:57:30 +0100 | [diff] [blame] | 1258 |     const Instruction* monitor_enter_instruction = | 
 | 1259 |         Instruction::At(&code_item->insns_[monitor_dex_pc]); | 
| Elliott Hughes | 80537bb | 2013-01-04 16:37:26 -0800 | [diff] [blame] | 1260 |  | 
 | 1261 |     // Quick sanity check. | 
| Sebastien Hertz | 0f7c933 | 2015-11-05 15:57:30 +0100 | [diff] [blame] | 1262 |     CHECK_EQ(monitor_enter_instruction->Opcode(), Instruction::MONITOR_ENTER) | 
 | 1263 |       << "expected monitor-enter @" << monitor_dex_pc << "; was " | 
 | 1264 |       << reinterpret_cast<const void*>(monitor_enter_instruction); | 
| Elliott Hughes | 08fc03a | 2012-06-26 17:34:00 -0700 | [diff] [blame] | 1265 |  | 
| Sebastien Hertz | 0f7c933 | 2015-11-05 15:57:30 +0100 | [diff] [blame] | 1266 |     uint16_t monitor_register = monitor_enter_instruction->VRegA(); | 
| Nicolas Geoffray | 15b9d52 | 2015-03-12 15:05:13 +0000 | [diff] [blame] | 1267 |     uint32_t value; | 
 | 1268 |     bool success = stack_visitor->GetVReg(m, monitor_register, kReferenceVReg, &value); | 
 | 1269 |     CHECK(success) << "Failed to read v" << monitor_register << " of kind " | 
| David Sehr | 709b070 | 2016-10-13 09:12:37 -0700 | [diff] [blame] | 1270 |                    << kReferenceVReg << " in method " << m->PrettyMethod(); | 
| Nicolas Geoffray | 15b9d52 | 2015-03-12 15:05:13 +0000 | [diff] [blame] | 1271 |     mirror::Object* o = reinterpret_cast<mirror::Object*>(value); | 
| Elliott Hughes | 4993bbc | 2013-01-10 15:41:25 -0800 | [diff] [blame] | 1272 |     callback(o, callback_context); | 
| Elliott Hughes | 08fc03a | 2012-06-26 17:34:00 -0700 | [diff] [blame] | 1273 |   } | 
 | 1274 | } | 
 | 1275 |  | 
| Ian Rogers | d9c4fc9 | 2013-10-01 19:45:43 -0700 | [diff] [blame] | 1276 | bool Monitor::IsValidLockWord(LockWord lock_word) { | 
 | 1277 |   switch (lock_word.GetState()) { | 
 | 1278 |     case LockWord::kUnlocked: | 
 | 1279 |       // Nothing to check. | 
 | 1280 |       return true; | 
 | 1281 |     case LockWord::kThinLocked: | 
 | 1282 |       // Basic sanity check of owner. | 
 | 1283 |       return lock_word.ThinLockOwner() != ThreadList::kInvalidThreadId; | 
 | 1284 |     case LockWord::kFatLocked: { | 
 | 1285 |       // Check the  monitor appears in the monitor list. | 
 | 1286 |       Monitor* mon = lock_word.FatLockMonitor(); | 
 | 1287 |       MonitorList* list = Runtime::Current()->GetMonitorList(); | 
 | 1288 |       MutexLock mu(Thread::Current(), list->monitor_list_lock_); | 
 | 1289 |       for (Monitor* list_mon : list->list_) { | 
 | 1290 |         if (mon == list_mon) { | 
 | 1291 |           return true;  // Found our monitor. | 
 | 1292 |         } | 
| Ian Rogers | 7dfb28c | 2013-08-22 08:18:36 -0700 | [diff] [blame] | 1293 |       } | 
| Ian Rogers | d9c4fc9 | 2013-10-01 19:45:43 -0700 | [diff] [blame] | 1294 |       return false;  // Fail - unowned monitor in an object. | 
| Ian Rogers | 7dfb28c | 2013-08-22 08:18:36 -0700 | [diff] [blame] | 1295 |     } | 
| Mathieu Chartier | ad2541a | 2013-10-25 10:05:23 -0700 | [diff] [blame] | 1296 |     case LockWord::kHashCode: | 
 | 1297 |       return true; | 
| Ian Rogers | d9c4fc9 | 2013-10-01 19:45:43 -0700 | [diff] [blame] | 1298 |     default: | 
 | 1299 |       LOG(FATAL) << "Unreachable"; | 
| Ian Rogers | 2c4257b | 2014-10-24 14:20:06 -0700 | [diff] [blame] | 1300 |       UNREACHABLE(); | 
| Ian Rogers | 7dfb28c | 2013-08-22 08:18:36 -0700 | [diff] [blame] | 1301 |   } | 
 | 1302 | } | 
 | 1303 |  | 
| Andreas Gampe | bdf7f1c | 2016-08-30 16:38:47 -0700 | [diff] [blame] | 1304 | bool Monitor::IsLocked() REQUIRES_SHARED(Locks::mutator_lock_) { | 
| Mathieu Chartier | ad2541a | 2013-10-25 10:05:23 -0700 | [diff] [blame] | 1305 |   MutexLock mu(Thread::Current(), monitor_lock_); | 
 | 1306 |   return owner_ != nullptr; | 
 | 1307 | } | 
 | 1308 |  | 
| Mathieu Chartier | 74b3c8f | 2016-04-15 19:11:45 -0700 | [diff] [blame] | 1309 | void Monitor::TranslateLocation(ArtMethod* method, | 
 | 1310 |                                 uint32_t dex_pc, | 
 | 1311 |                                 const char** source_file, | 
 | 1312 |                                 int32_t* line_number) { | 
| jeffhao | 33dc771 | 2011-11-09 17:54:24 -0800 | [diff] [blame] | 1313 |   // If method is null, location is unknown | 
| Mathieu Chartier | 2cebb24 | 2015-04-21 16:50:40 -0700 | [diff] [blame] | 1314 |   if (method == nullptr) { | 
| Ian Rogers | d9c4fc9 | 2013-10-01 19:45:43 -0700 | [diff] [blame] | 1315 |     *source_file = ""; | 
 | 1316 |     *line_number = 0; | 
| jeffhao | 33dc771 | 2011-11-09 17:54:24 -0800 | [diff] [blame] | 1317 |     return; | 
 | 1318 |   } | 
| Mathieu Chartier | bfd9a43 | 2014-05-21 17:43:44 -0700 | [diff] [blame] | 1319 |   *source_file = method->GetDeclaringClassSourceFile(); | 
| Mathieu Chartier | 2cebb24 | 2015-04-21 16:50:40 -0700 | [diff] [blame] | 1320 |   if (*source_file == nullptr) { | 
| Ian Rogers | d9c4fc9 | 2013-10-01 19:45:43 -0700 | [diff] [blame] | 1321 |     *source_file = ""; | 
| Elliott Hughes | 12c51e3 | 2012-01-17 20:25:05 -0800 | [diff] [blame] | 1322 |   } | 
| Mathieu Chartier | bfd9a43 | 2014-05-21 17:43:44 -0700 | [diff] [blame] | 1323 |   *line_number = method->GetLineNumFromDexPC(dex_pc); | 
| Ian Rogers | d9c4fc9 | 2013-10-01 19:45:43 -0700 | [diff] [blame] | 1324 | } | 
 | 1325 |  | 
 | 1326 | uint32_t Monitor::GetOwnerThreadId() { | 
 | 1327 |   MutexLock mu(Thread::Current(), monitor_lock_); | 
 | 1328 |   Thread* owner = owner_; | 
| Mathieu Chartier | 2cebb24 | 2015-04-21 16:50:40 -0700 | [diff] [blame] | 1329 |   if (owner != nullptr) { | 
| Ian Rogers | d9c4fc9 | 2013-10-01 19:45:43 -0700 | [diff] [blame] | 1330 |     return owner->GetThreadId(); | 
 | 1331 |   } else { | 
 | 1332 |     return ThreadList::kInvalidThreadId; | 
 | 1333 |   } | 
| jeffhao | 33dc771 | 2011-11-09 17:54:24 -0800 | [diff] [blame] | 1334 | } | 
 | 1335 |  | 
| Mathieu Chartier | c11d9b8 | 2013-09-19 10:01:59 -0700 | [diff] [blame] | 1336 | MonitorList::MonitorList() | 
| Mathieu Chartier | 440e4ce | 2014-03-31 16:36:35 -0700 | [diff] [blame] | 1337 |     : allow_new_monitors_(true), monitor_list_lock_("MonitorList lock", kMonitorListLock), | 
| Mathieu Chartier | c11d9b8 | 2013-09-19 10:01:59 -0700 | [diff] [blame] | 1338 |       monitor_add_condition_("MonitorList disallow condition", monitor_list_lock_) { | 
| Elliott Hughes | c33a32b | 2011-10-11 18:18:07 -0700 | [diff] [blame] | 1339 | } | 
 | 1340 |  | 
 | 1341 | MonitorList::~MonitorList() { | 
| Andreas Gampe | 7424081 | 2014-04-17 10:35:09 -0700 | [diff] [blame] | 1342 |   Thread* self = Thread::Current(); | 
 | 1343 |   MutexLock mu(self, monitor_list_lock_); | 
 | 1344 |   // Release all monitors to the pool. | 
 | 1345 |   // TODO: Is it an invariant that *all* open monitors are in the list? Then we could | 
 | 1346 |   // clear faster in the pool. | 
 | 1347 |   MonitorPool::ReleaseMonitors(self, &list_); | 
| Elliott Hughes | c33a32b | 2011-10-11 18:18:07 -0700 | [diff] [blame] | 1348 | } | 
 | 1349 |  | 
| Mathieu Chartier | c11d9b8 | 2013-09-19 10:01:59 -0700 | [diff] [blame] | 1350 | void MonitorList::DisallowNewMonitors() { | 
| Hiroshi Yamauchi | fdbd13c | 2015-09-02 16:16:58 -0700 | [diff] [blame] | 1351 |   CHECK(!kUseReadBarrier); | 
| Ian Rogers | 50b35e2 | 2012-10-04 10:09:15 -0700 | [diff] [blame] | 1352 |   MutexLock mu(Thread::Current(), monitor_list_lock_); | 
| Mathieu Chartier | c11d9b8 | 2013-09-19 10:01:59 -0700 | [diff] [blame] | 1353 |   allow_new_monitors_ = false; | 
 | 1354 | } | 
 | 1355 |  | 
 | 1356 | void MonitorList::AllowNewMonitors() { | 
| Hiroshi Yamauchi | fdbd13c | 2015-09-02 16:16:58 -0700 | [diff] [blame] | 1357 |   CHECK(!kUseReadBarrier); | 
| Mathieu Chartier | c11d9b8 | 2013-09-19 10:01:59 -0700 | [diff] [blame] | 1358 |   Thread* self = Thread::Current(); | 
 | 1359 |   MutexLock mu(self, monitor_list_lock_); | 
 | 1360 |   allow_new_monitors_ = true; | 
 | 1361 |   monitor_add_condition_.Broadcast(self); | 
 | 1362 | } | 
 | 1363 |  | 
| Hiroshi Yamauchi | 0b71357 | 2015-06-16 18:29:23 -0700 | [diff] [blame] | 1364 | void MonitorList::BroadcastForNewMonitors() { | 
| Hiroshi Yamauchi | 0b71357 | 2015-06-16 18:29:23 -0700 | [diff] [blame] | 1365 |   Thread* self = Thread::Current(); | 
 | 1366 |   MutexLock mu(self, monitor_list_lock_); | 
 | 1367 |   monitor_add_condition_.Broadcast(self); | 
 | 1368 | } | 
 | 1369 |  | 
| Mathieu Chartier | c11d9b8 | 2013-09-19 10:01:59 -0700 | [diff] [blame] | 1370 | void MonitorList::Add(Monitor* m) { | 
 | 1371 |   Thread* self = Thread::Current(); | 
 | 1372 |   MutexLock mu(self, monitor_list_lock_); | 
| Hiroshi Yamauchi | f1c6f87 | 2017-01-06 12:23:47 -0800 | [diff] [blame] | 1373 |   // CMS needs this to block for concurrent reference processing because an object allocated during | 
 | 1374 |   // the GC won't be marked and concurrent reference processing would incorrectly clear the JNI weak | 
 | 1375 |   // ref. But CC (kUseReadBarrier == true) doesn't because of the to-space invariant. | 
 | 1376 |   while (!kUseReadBarrier && UNLIKELY(!allow_new_monitors_)) { | 
| Hiroshi Yamauchi | 3049324 | 2016-11-03 13:06:52 -0700 | [diff] [blame] | 1377 |     // Check and run the empty checkpoint before blocking so the empty checkpoint will work in the | 
 | 1378 |     // presence of threads blocking for weak ref access. | 
| Hiroshi Yamauchi | a222404 | 2017-02-08 16:35:45 -0800 | [diff] [blame] | 1379 |     self->CheckEmptyCheckpointFromWeakRefAccess(&monitor_list_lock_); | 
| Mathieu Chartier | c11d9b8 | 2013-09-19 10:01:59 -0700 | [diff] [blame] | 1380 |     monitor_add_condition_.WaitHoldingLocks(self); | 
 | 1381 |   } | 
| Elliott Hughes | c33a32b | 2011-10-11 18:18:07 -0700 | [diff] [blame] | 1382 |   list_.push_front(m); | 
 | 1383 | } | 
 | 1384 |  | 
| Mathieu Chartier | 9750995 | 2015-07-13 14:35:43 -0700 | [diff] [blame] | 1385 | void MonitorList::SweepMonitorList(IsMarkedVisitor* visitor) { | 
| Andreas Gampe | 7424081 | 2014-04-17 10:35:09 -0700 | [diff] [blame] | 1386 |   Thread* self = Thread::Current(); | 
 | 1387 |   MutexLock mu(self, monitor_list_lock_); | 
| Mathieu Chartier | 02e2511 | 2013-08-14 16:14:24 -0700 | [diff] [blame] | 1388 |   for (auto it = list_.begin(); it != list_.end(); ) { | 
| Elliott Hughes | c33a32b | 2011-10-11 18:18:07 -0700 | [diff] [blame] | 1389 |     Monitor* m = *it; | 
| Hiroshi Yamauchi | 4cba0d9 | 2014-05-21 21:10:23 -0700 | [diff] [blame] | 1390 |     // Disable the read barrier in GetObject() as this is called by GC. | 
 | 1391 |     mirror::Object* obj = m->GetObject<kWithoutReadBarrier>(); | 
| Mathieu Chartier | 590fee9 | 2013-09-13 13:46:47 -0700 | [diff] [blame] | 1392 |     // The object of a monitor can be null if we have deflated it. | 
| Mathieu Chartier | 9750995 | 2015-07-13 14:35:43 -0700 | [diff] [blame] | 1393 |     mirror::Object* new_obj = obj != nullptr ? visitor->IsMarked(obj) : nullptr; | 
| Mathieu Chartier | 6aa3df9 | 2013-09-17 15:17:28 -0700 | [diff] [blame] | 1394 |     if (new_obj == nullptr) { | 
 | 1395 |       VLOG(monitor) << "freeing monitor " << m << " belonging to unmarked object " | 
| Hiroshi Yamauchi | 4cba0d9 | 2014-05-21 21:10:23 -0700 | [diff] [blame] | 1396 |                     << obj; | 
| Andreas Gampe | 7424081 | 2014-04-17 10:35:09 -0700 | [diff] [blame] | 1397 |       MonitorPool::ReleaseMonitor(self, m); | 
| Elliott Hughes | c33a32b | 2011-10-11 18:18:07 -0700 | [diff] [blame] | 1398 |       it = list_.erase(it); | 
 | 1399 |     } else { | 
| Mathieu Chartier | 6aa3df9 | 2013-09-17 15:17:28 -0700 | [diff] [blame] | 1400 |       m->SetObject(new_obj); | 
| Elliott Hughes | c33a32b | 2011-10-11 18:18:07 -0700 | [diff] [blame] | 1401 |       ++it; | 
 | 1402 |     } | 
 | 1403 |   } | 
 | 1404 | } | 
 | 1405 |  | 
| Hans Boehm | 6fe97e0 | 2016-05-04 18:35:57 -0700 | [diff] [blame] | 1406 | size_t MonitorList::Size() { | 
 | 1407 |   Thread* self = Thread::Current(); | 
 | 1408 |   MutexLock mu(self, monitor_list_lock_); | 
 | 1409 |   return list_.size(); | 
 | 1410 | } | 
 | 1411 |  | 
| Mathieu Chartier | 9750995 | 2015-07-13 14:35:43 -0700 | [diff] [blame] | 1412 | class MonitorDeflateVisitor : public IsMarkedVisitor { | 
 | 1413 |  public: | 
 | 1414 |   MonitorDeflateVisitor() : self_(Thread::Current()), deflate_count_(0) {} | 
 | 1415 |  | 
 | 1416 |   virtual mirror::Object* IsMarked(mirror::Object* object) OVERRIDE | 
| Andreas Gampe | bdf7f1c | 2016-08-30 16:38:47 -0700 | [diff] [blame] | 1417 |       REQUIRES_SHARED(Locks::mutator_lock_) { | 
| Mathieu Chartier | 9750995 | 2015-07-13 14:35:43 -0700 | [diff] [blame] | 1418 |     if (Monitor::Deflate(self_, object)) { | 
 | 1419 |       DCHECK_NE(object->GetLockWord(true).GetState(), LockWord::kFatLocked); | 
 | 1420 |       ++deflate_count_; | 
 | 1421 |       // If we deflated, return null so that the monitor gets removed from the array. | 
 | 1422 |       return nullptr; | 
 | 1423 |     } | 
 | 1424 |     return object;  // Monitor was not deflated. | 
 | 1425 |   } | 
 | 1426 |  | 
 | 1427 |   Thread* const self_; | 
 | 1428 |   size_t deflate_count_; | 
| Mathieu Chartier | 48ab687 | 2014-06-24 11:21:59 -0700 | [diff] [blame] | 1429 | }; | 
 | 1430 |  | 
| Mathieu Chartier | 48ab687 | 2014-06-24 11:21:59 -0700 | [diff] [blame] | 1431 | size_t MonitorList::DeflateMonitors() { | 
| Mathieu Chartier | 9750995 | 2015-07-13 14:35:43 -0700 | [diff] [blame] | 1432 |   MonitorDeflateVisitor visitor; | 
 | 1433 |   Locks::mutator_lock_->AssertExclusiveHeld(visitor.self_); | 
 | 1434 |   SweepMonitorList(&visitor); | 
 | 1435 |   return visitor.deflate_count_; | 
| Mathieu Chartier | 440e4ce | 2014-03-31 16:36:35 -0700 | [diff] [blame] | 1436 | } | 
 | 1437 |  | 
| Mathieu Chartier | 2cebb24 | 2015-04-21 16:50:40 -0700 | [diff] [blame] | 1438 | MonitorInfo::MonitorInfo(mirror::Object* obj) : owner_(nullptr), entry_count_(0) { | 
| Mathieu Chartier | 4d7f61d | 2014-04-17 14:43:39 -0700 | [diff] [blame] | 1439 |   DCHECK(obj != nullptr); | 
 | 1440 |   LockWord lock_word = obj->GetLockWord(true); | 
| Ian Rogers | d9c4fc9 | 2013-10-01 19:45:43 -0700 | [diff] [blame] | 1441 |   switch (lock_word.GetState()) { | 
 | 1442 |     case LockWord::kUnlocked: | 
| Mathieu Chartier | ad2541a | 2013-10-25 10:05:23 -0700 | [diff] [blame] | 1443 |       // Fall-through. | 
| Mathieu Chartier | 590fee9 | 2013-09-13 13:46:47 -0700 | [diff] [blame] | 1444 |     case LockWord::kForwardingAddress: | 
 | 1445 |       // Fall-through. | 
| Mathieu Chartier | ad2541a | 2013-10-25 10:05:23 -0700 | [diff] [blame] | 1446 |     case LockWord::kHashCode: | 
| Ian Rogers | d9c4fc9 | 2013-10-01 19:45:43 -0700 | [diff] [blame] | 1447 |       break; | 
 | 1448 |     case LockWord::kThinLocked: | 
 | 1449 |       owner_ = Runtime::Current()->GetThreadList()->FindThreadByThreadId(lock_word.ThinLockOwner()); | 
 | 1450 |       entry_count_ = 1 + lock_word.ThinLockCount(); | 
 | 1451 |       // Thin locks have no waiters. | 
 | 1452 |       break; | 
 | 1453 |     case LockWord::kFatLocked: { | 
 | 1454 |       Monitor* mon = lock_word.FatLockMonitor(); | 
 | 1455 |       owner_ = mon->owner_; | 
 | 1456 |       entry_count_ = 1 + mon->lock_count_; | 
| Mathieu Chartier | 2cebb24 | 2015-04-21 16:50:40 -0700 | [diff] [blame] | 1457 |       for (Thread* waiter = mon->wait_set_; waiter != nullptr; waiter = waiter->GetWaitNext()) { | 
| Ian Rogers | d9c4fc9 | 2013-10-01 19:45:43 -0700 | [diff] [blame] | 1458 |         waiters_.push_back(waiter); | 
 | 1459 |       } | 
 | 1460 |       break; | 
| Elliott Hughes | f327e07 | 2013-01-09 16:01:26 -0800 | [diff] [blame] | 1461 |     } | 
 | 1462 |   } | 
 | 1463 | } | 
 | 1464 |  | 
| Elliott Hughes | 5f79133 | 2011-09-15 17:45:30 -0700 | [diff] [blame] | 1465 | }  // namespace art |