blob: 2bc17bf4038d317c0547e76d6084e3e1c83dff96 [file] [log] [blame]
Elliott Hughes8daa0922011-09-11 13:46:25 -07001/*
2 * Copyright (C) 2011 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include "mutex.h"
18
19#include <errno.h>
Ian Rogersc604d732012-10-14 16:09:54 -070020#include <sys/time.h>
Elliott Hughes8daa0922011-09-11 13:46:25 -070021
Hiroshi Yamauchi1afde132013-08-06 17:09:30 -070022#include "atomic.h"
Elliott Hughes07ed66b2012-12-12 18:34:25 -080023#include "base/logging.h"
Ian Rogers693ff612013-02-01 10:56:12 -080024#include "mutex-inl.h"
Elliott Hughes6b355752012-01-13 16:49:08 -080025#include "runtime.h"
Ian Rogersc604d732012-10-14 16:09:54 -070026#include "scoped_thread_state_change.h"
Ian Rogers04d7aa92013-03-16 14:29:17 -070027#include "thread-inl.h"
Elliott Hughesffb465f2012-03-01 18:46:05 -080028#include "utils.h"
Elliott Hughes8daa0922011-09-11 13:46:25 -070029
30namespace art {
31
Ian Rogers719d1a32014-03-06 12:13:39 -080032Mutex* Locks::abort_lock_ = nullptr;
33Mutex* Locks::breakpoint_lock_ = nullptr;
Ian Rogers719d1a32014-03-06 12:13:39 -080034ReaderWriterMutex* Locks::classlinker_classes_lock_ = nullptr;
35ReaderWriterMutex* Locks::heap_bitmap_lock_ = nullptr;
36Mutex* Locks::logging_lock_ = nullptr;
37ReaderWriterMutex* Locks::mutator_lock_ = nullptr;
38Mutex* Locks::runtime_shutdown_lock_ = nullptr;
39Mutex* Locks::thread_list_lock_ = nullptr;
40Mutex* Locks::thread_suspend_count_lock_ = nullptr;
41Mutex* Locks::trace_lock_ = nullptr;
42Mutex* Locks::profiler_lock_ = nullptr;
43Mutex* Locks::unexpected_signal_lock_ = nullptr;
44Mutex* Locks::intern_table_lock_ = nullptr;
45
46struct AllMutexData {
47 // A guard for all_mutexes_ that's not a mutex (Mutexes must CAS to acquire and busy wait).
48 Atomic<const BaseMutex*> all_mutexes_guard;
49 // All created mutexes guarded by all_mutexes_guard_.
50 std::set<BaseMutex*>* all_mutexes;
51 AllMutexData() : all_mutexes(NULL) {}
52};
53static struct AllMutexData gAllMutexData[kAllMutexDataSize];
54
Ian Rogersc604d732012-10-14 16:09:54 -070055#if ART_USE_FUTEXES
56static bool ComputeRelativeTimeSpec(timespec* result_ts, const timespec& lhs, const timespec& rhs) {
Brian Carlstromfb6996f2013-07-18 18:21:14 -070057 const int32_t one_sec = 1000 * 1000 * 1000; // one second in nanoseconds.
Ian Rogersc604d732012-10-14 16:09:54 -070058 result_ts->tv_sec = lhs.tv_sec - rhs.tv_sec;
59 result_ts->tv_nsec = lhs.tv_nsec - rhs.tv_nsec;
60 if (result_ts->tv_nsec < 0) {
61 result_ts->tv_sec--;
62 result_ts->tv_nsec += one_sec;
63 } else if (result_ts->tv_nsec > one_sec) {
64 result_ts->tv_sec++;
65 result_ts->tv_nsec -= one_sec;
66 }
67 return result_ts->tv_sec < 0;
68}
69#endif
70
Ian Rogers56edc432013-01-18 16:51:51 -080071class ScopedAllMutexesLock {
72 public:
Brian Carlstrom93ba8932013-07-17 21:31:49 -070073 explicit ScopedAllMutexesLock(const BaseMutex* mutex) : mutex_(mutex) {
Ian Rogersef7d42f2014-01-06 12:55:46 -080074 while (!gAllMutexData->all_mutexes_guard.CompareAndSwap(0, mutex)) {
Ian Rogers56edc432013-01-18 16:51:51 -080075 NanoSleep(100);
76 }
77 }
78 ~ScopedAllMutexesLock() {
Ian Rogersef7d42f2014-01-06 12:55:46 -080079 while (!gAllMutexData->all_mutexes_guard.CompareAndSwap(mutex_, 0)) {
Ian Rogers56edc432013-01-18 16:51:51 -080080 NanoSleep(100);
81 }
82 }
83 private:
84 const BaseMutex* const mutex_;
85};
Ian Rogers56edc432013-01-18 16:51:51 -080086
87BaseMutex::BaseMutex(const char* name, LockLevel level) : level_(level), name_(name) {
Hiroshi Yamauchi1afde132013-08-06 17:09:30 -070088 if (kLogLockContentions) {
89 ScopedAllMutexesLock mu(this);
Ian Rogersd9c4fc92013-10-01 19:45:43 -070090 std::set<BaseMutex*>** all_mutexes_ptr = &gAllMutexData->all_mutexes;
Hiroshi Yamauchi1afde132013-08-06 17:09:30 -070091 if (*all_mutexes_ptr == NULL) {
92 // We leak the global set of all mutexes to avoid ordering issues in global variable
93 // construction/destruction.
94 *all_mutexes_ptr = new std::set<BaseMutex*>();
95 }
96 (*all_mutexes_ptr)->insert(this);
Ian Rogers56edc432013-01-18 16:51:51 -080097 }
Ian Rogers56edc432013-01-18 16:51:51 -080098}
99
100BaseMutex::~BaseMutex() {
Hiroshi Yamauchi1afde132013-08-06 17:09:30 -0700101 if (kLogLockContentions) {
102 ScopedAllMutexesLock mu(this);
Ian Rogersd9c4fc92013-10-01 19:45:43 -0700103 gAllMutexData->all_mutexes->erase(this);
Hiroshi Yamauchi1afde132013-08-06 17:09:30 -0700104 }
Ian Rogers56edc432013-01-18 16:51:51 -0800105}
106
107void BaseMutex::DumpAll(std::ostream& os) {
Hiroshi Yamauchi1afde132013-08-06 17:09:30 -0700108 if (kLogLockContentions) {
109 os << "Mutex logging:\n";
110 ScopedAllMutexesLock mu(reinterpret_cast<const BaseMutex*>(-1));
Ian Rogersd9c4fc92013-10-01 19:45:43 -0700111 std::set<BaseMutex*>* all_mutexes = gAllMutexData->all_mutexes;
Hiroshi Yamauchi1afde132013-08-06 17:09:30 -0700112 if (all_mutexes == NULL) {
113 // No mutexes have been created yet during at startup.
114 return;
115 }
116 typedef std::set<BaseMutex*>::const_iterator It;
Ian Rogersd9c4fc92013-10-01 19:45:43 -0700117 os << "(Contended)\n";
Hiroshi Yamauchi1afde132013-08-06 17:09:30 -0700118 for (It it = all_mutexes->begin(); it != all_mutexes->end(); ++it) {
119 BaseMutex* mutex = *it;
120 if (mutex->HasEverContended()) {
121 mutex->Dump(os);
122 os << "\n";
123 }
124 }
125 os << "(Never contented)\n";
126 for (It it = all_mutexes->begin(); it != all_mutexes->end(); ++it) {
127 BaseMutex* mutex = *it;
128 if (!mutex->HasEverContended()) {
129 mutex->Dump(os);
130 os << "\n";
131 }
132 }
Ian Rogers56edc432013-01-18 16:51:51 -0800133 }
Ian Rogers56edc432013-01-18 16:51:51 -0800134}
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700135
Ian Rogers81d425b2012-09-27 16:03:43 -0700136void BaseMutex::CheckSafeToWait(Thread* self) {
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700137 if (self == NULL) {
138 CheckUnattachedThread(level_);
139 return;
140 }
Ian Rogers25fd14b2012-09-05 10:56:38 -0700141 if (kDebugLocking) {
Ian Rogersd9c4fc92013-10-01 19:45:43 -0700142 CHECK(self->GetHeldMutex(level_) == this || level_ == kMonitorLock)
143 << "Waiting on unacquired mutex: " << name_;
Ian Rogers25fd14b2012-09-05 10:56:38 -0700144 bool bad_mutexes_held = false;
Elliott Hughes0f827162013-02-26 12:12:58 -0800145 for (int i = kLockLevelCount - 1; i >= 0; --i) {
Ian Rogers25fd14b2012-09-05 10:56:38 -0700146 if (i != level_) {
Ian Rogers81d425b2012-09-27 16:03:43 -0700147 BaseMutex* held_mutex = self->GetHeldMutex(static_cast<LockLevel>(i));
Ian Rogers25fd14b2012-09-05 10:56:38 -0700148 if (held_mutex != NULL) {
Elliott Hughes0f827162013-02-26 12:12:58 -0800149 LOG(ERROR) << "Holding \"" << held_mutex->name_ << "\" "
150 << "(level " << LockLevel(i) << ") while performing wait on "
151 << "\"" << name_ << "\" (level " << level_ << ")";
Ian Rogers25fd14b2012-09-05 10:56:38 -0700152 bad_mutexes_held = true;
153 }
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700154 }
155 }
Ian Rogers25fd14b2012-09-05 10:56:38 -0700156 CHECK(!bad_mutexes_held);
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700157 }
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700158}
159
Hiroshi Yamauchi1afde132013-08-06 17:09:30 -0700160inline void BaseMutex::ContentionLogData::AddToWaitTime(uint64_t value) {
161 if (kLogLockContentions) {
162 // Atomically add value to wait_time.
163 uint64_t new_val, old_val;
164 volatile int64_t* addr = reinterpret_cast<volatile int64_t*>(&wait_time);
165 volatile const int64_t* caddr = const_cast<volatile const int64_t*>(addr);
166 do {
167 old_val = static_cast<uint64_t>(QuasiAtomic::Read64(caddr));
168 new_val = old_val + value;
169 } while (!QuasiAtomic::Cas64(static_cast<int64_t>(old_val), static_cast<int64_t>(new_val), addr));
170 }
171}
172
Brian Carlstrom0de79852013-07-25 22:29:58 -0700173void BaseMutex::RecordContention(uint64_t blocked_tid,
174 uint64_t owner_tid,
Hiroshi Yamauchi1afde132013-08-06 17:09:30 -0700175 uint64_t nano_time_blocked) {
176 if (kLogLockContentions) {
177 ContentionLogData* data = contetion_log_data_;
178 ++(data->contention_count);
179 data->AddToWaitTime(nano_time_blocked);
180 ContentionLogEntry* log = data->contention_log;
181 // This code is intentionally racy as it is only used for diagnostics.
182 uint32_t slot = data->cur_content_log_entry;
183 if (log[slot].blocked_tid == blocked_tid &&
184 log[slot].owner_tid == blocked_tid) {
185 ++log[slot].count;
186 } else {
187 uint32_t new_slot;
188 do {
189 slot = data->cur_content_log_entry;
190 new_slot = (slot + 1) % kContentionLogSize;
Ian Rogersb122a4b2013-11-19 18:00:50 -0800191 } while (!data->cur_content_log_entry.CompareAndSwap(slot, new_slot));
Hiroshi Yamauchi1afde132013-08-06 17:09:30 -0700192 log[new_slot].blocked_tid = blocked_tid;
193 log[new_slot].owner_tid = owner_tid;
194 log[new_slot].count = 1;
195 }
Ian Rogers56edc432013-01-18 16:51:51 -0800196 }
Ian Rogers56edc432013-01-18 16:51:51 -0800197}
198
Ian Rogers56edc432013-01-18 16:51:51 -0800199void BaseMutex::DumpContention(std::ostream& os) const {
Hiroshi Yamauchi1afde132013-08-06 17:09:30 -0700200 if (kLogLockContentions) {
201 const ContentionLogData* data = contetion_log_data_;
202 const ContentionLogEntry* log = data->contention_log;
203 uint64_t wait_time = data->wait_time;
204 uint32_t contention_count = data->contention_count;
205 if (contention_count == 0) {
206 os << "never contended";
207 } else {
208 os << "contended " << contention_count
Mathieu Chartier73d1e172014-04-11 17:53:48 -0700209 << " total wait of contender " << PrettyDuration(wait_time)
210 << " average " << PrettyDuration(wait_time / contention_count);
Hiroshi Yamauchi1afde132013-08-06 17:09:30 -0700211 SafeMap<uint64_t, size_t> most_common_blocker;
212 SafeMap<uint64_t, size_t> most_common_blocked;
Hiroshi Yamauchi1afde132013-08-06 17:09:30 -0700213 for (size_t i = 0; i < kContentionLogSize; ++i) {
214 uint64_t blocked_tid = log[i].blocked_tid;
215 uint64_t owner_tid = log[i].owner_tid;
216 uint32_t count = log[i].count;
217 if (count > 0) {
Mathieu Chartier73d1e172014-04-11 17:53:48 -0700218 auto it = most_common_blocked.find(blocked_tid);
Hiroshi Yamauchi1afde132013-08-06 17:09:30 -0700219 if (it != most_common_blocked.end()) {
220 most_common_blocked.Overwrite(blocked_tid, it->second + count);
221 } else {
222 most_common_blocked.Put(blocked_tid, count);
223 }
224 it = most_common_blocker.find(owner_tid);
225 if (it != most_common_blocker.end()) {
226 most_common_blocker.Overwrite(owner_tid, it->second + count);
227 } else {
228 most_common_blocker.Put(owner_tid, count);
229 }
Ian Rogers56edc432013-01-18 16:51:51 -0800230 }
231 }
Hiroshi Yamauchi1afde132013-08-06 17:09:30 -0700232 uint64_t max_tid = 0;
233 size_t max_tid_count = 0;
Mathieu Chartier73d1e172014-04-11 17:53:48 -0700234 for (const auto& pair : most_common_blocked) {
235 if (pair.second > max_tid_count) {
236 max_tid = pair.first;
237 max_tid_count = pair.second;
Hiroshi Yamauchi1afde132013-08-06 17:09:30 -0700238 }
Ian Rogers56edc432013-01-18 16:51:51 -0800239 }
Hiroshi Yamauchi1afde132013-08-06 17:09:30 -0700240 if (max_tid != 0) {
241 os << " sample shows most blocked tid=" << max_tid;
Ian Rogers56edc432013-01-18 16:51:51 -0800242 }
Hiroshi Yamauchi1afde132013-08-06 17:09:30 -0700243 max_tid = 0;
244 max_tid_count = 0;
Mathieu Chartier73d1e172014-04-11 17:53:48 -0700245 for (const auto& pair : most_common_blocker) {
246 if (pair.second > max_tid_count) {
247 max_tid = pair.first;
248 max_tid_count = pair.second;
Hiroshi Yamauchi1afde132013-08-06 17:09:30 -0700249 }
250 }
251 if (max_tid != 0) {
252 os << " sample shows tid=" << max_tid << " owning during this time";
253 }
Ian Rogers56edc432013-01-18 16:51:51 -0800254 }
255 }
Ian Rogers56edc432013-01-18 16:51:51 -0800256}
257
258
Ian Rogers81d425b2012-09-27 16:03:43 -0700259Mutex::Mutex(const char* name, LockLevel level, bool recursive)
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700260 : BaseMutex(name, level), recursive_(recursive), recursion_count_(0) {
Ian Rogersc604d732012-10-14 16:09:54 -0700261#if ART_USE_FUTEXES
262 state_ = 0;
263 exclusive_owner_ = 0;
264 num_contenders_ = 0;
265#elif defined(__BIONIC__) || defined(__APPLE__)
Brian Carlstromf3a26412012-08-24 11:06:02 -0700266 // Use recursive mutexes for bionic and Apple otherwise the
267 // non-recursive mutexes don't have TIDs to check lock ownership of.
Elliott Hughesbbd9d832011-11-07 14:40:00 -0800268 pthread_mutexattr_t attributes;
269 CHECK_MUTEX_CALL(pthread_mutexattr_init, (&attributes));
270 CHECK_MUTEX_CALL(pthread_mutexattr_settype, (&attributes, PTHREAD_MUTEX_RECURSIVE));
271 CHECK_MUTEX_CALL(pthread_mutex_init, (&mutex_, &attributes));
272 CHECK_MUTEX_CALL(pthread_mutexattr_destroy, (&attributes));
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700273#else
274 CHECK_MUTEX_CALL(pthread_mutex_init, (&mutex_, NULL));
275#endif
Elliott Hughes8daa0922011-09-11 13:46:25 -0700276}
277
278Mutex::~Mutex() {
Ian Rogersc604d732012-10-14 16:09:54 -0700279#if ART_USE_FUTEXES
280 if (state_ != 0) {
Ian Rogersc604d732012-10-14 16:09:54 -0700281 Runtime* runtime = Runtime::Current();
Mathieu Chartier590fee92013-09-13 13:46:47 -0700282 bool shutting_down = runtime == nullptr || runtime->IsShuttingDown(Thread::Current());
Ian Rogersc604d732012-10-14 16:09:54 -0700283 LOG(shutting_down ? WARNING : FATAL) << "destroying mutex with owner: " << exclusive_owner_;
284 } else {
285 CHECK_EQ(exclusive_owner_, 0U) << "unexpectedly found an owner on unlocked mutex " << name_;
286 CHECK_EQ(num_contenders_, 0) << "unexpectedly found a contender on mutex " << name_;
287 }
288#else
Elliott Hughese62934d2012-04-09 11:24:29 -0700289 // We can't use CHECK_MUTEX_CALL here because on shutdown a suspended daemon thread
290 // may still be using locks.
Elliott Hughes6b355752012-01-13 16:49:08 -0800291 int rc = pthread_mutex_destroy(&mutex_);
292 if (rc != 0) {
293 errno = rc;
Elliott Hughesb3bd5f02012-03-08 21:05:27 -0800294 // TODO: should we just not log at all if shutting down? this could be the logging mutex!
Ian Rogers50b35e22012-10-04 10:09:15 -0700295 MutexLock mu(Thread::Current(), *Locks::runtime_shutdown_lock_);
Ian Rogers120f1c72012-09-28 17:17:10 -0700296 Runtime* runtime = Runtime::Current();
Mathieu Chartier34e82932013-11-12 18:22:47 -0800297 bool shutting_down = (runtime == NULL) || runtime->IsShuttingDownLocked();
Elliott Hughes6b355752012-01-13 16:49:08 -0800298 PLOG(shutting_down ? WARNING : FATAL) << "pthread_mutex_destroy failed for " << name_;
299 }
Ian Rogersc604d732012-10-14 16:09:54 -0700300#endif
Elliott Hughes8daa0922011-09-11 13:46:25 -0700301}
302
Ian Rogers81d425b2012-09-27 16:03:43 -0700303void Mutex::ExclusiveLock(Thread* self) {
Ian Rogers01ae5802012-09-28 16:14:01 -0700304 DCHECK(self == NULL || self == Thread::Current());
Ian Rogers25fd14b2012-09-05 10:56:38 -0700305 if (kDebugLocking && !recursive_) {
Ian Rogers81d425b2012-09-27 16:03:43 -0700306 AssertNotHeld(self);
Ian Rogers25fd14b2012-09-05 10:56:38 -0700307 }
Ian Rogers81d425b2012-09-27 16:03:43 -0700308 if (!recursive_ || !IsExclusiveHeld(self)) {
Ian Rogersc604d732012-10-14 16:09:54 -0700309#if ART_USE_FUTEXES
310 bool done = false;
311 do {
312 int32_t cur_state = state_;
Hiroshi Yamauchi967a0ad2013-09-10 16:24:21 -0700313 if (LIKELY(cur_state == 0)) {
Ian Rogersc604d732012-10-14 16:09:54 -0700314 // Change state from 0 to 1.
Ian Rogersb122a4b2013-11-19 18:00:50 -0800315 done = __sync_bool_compare_and_swap(&state_, 0 /* cur_state */, 1 /* new state */);
Ian Rogersc604d732012-10-14 16:09:54 -0700316 } else {
317 // Failed to acquire, hang up.
Hiroshi Yamauchib3733082013-08-12 17:28:49 -0700318 ScopedContentionRecorder scr(this, SafeGetTid(self), GetExclusiveOwnerTid());
Ian Rogersb122a4b2013-11-19 18:00:50 -0800319 num_contenders_++;
Ian Rogersc604d732012-10-14 16:09:54 -0700320 if (futex(&state_, FUTEX_WAIT, 1, NULL, NULL, 0) != 0) {
Brian Carlstrom0de79852013-07-25 22:29:58 -0700321 // EAGAIN and EINTR both indicate a spurious failure, try again from the beginning.
322 // We don't use TEMP_FAILURE_RETRY so we can intentionally retry to acquire the lock.
323 if ((errno != EAGAIN) && (errno != EINTR)) {
Ian Rogersc604d732012-10-14 16:09:54 -0700324 PLOG(FATAL) << "futex wait failed for " << name_;
325 }
326 }
Ian Rogersb122a4b2013-11-19 18:00:50 -0800327 num_contenders_--;
Ian Rogersc604d732012-10-14 16:09:54 -0700328 }
Brian Carlstromdf629502013-07-17 22:39:56 -0700329 } while (!done);
Ian Rogersb122a4b2013-11-19 18:00:50 -0800330 QuasiAtomic::MembarStoreLoad();
Ian Rogersc604d732012-10-14 16:09:54 -0700331 DCHECK_EQ(state_, 1);
332 exclusive_owner_ = SafeGetTid(self);
333#else
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700334 CHECK_MUTEX_CALL(pthread_mutex_lock, (&mutex_));
Ian Rogersc604d732012-10-14 16:09:54 -0700335#endif
Ian Rogers81d425b2012-09-27 16:03:43 -0700336 RegisterAsLocked(self);
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700337 }
338 recursion_count_++;
Ian Rogers25fd14b2012-09-05 10:56:38 -0700339 if (kDebugLocking) {
340 CHECK(recursion_count_ == 1 || recursive_) << "Unexpected recursion count on mutex: "
341 << name_ << " " << recursion_count_;
Ian Rogers81d425b2012-09-27 16:03:43 -0700342 AssertHeld(self);
Ian Rogers25fd14b2012-09-05 10:56:38 -0700343 }
Elliott Hughes8daa0922011-09-11 13:46:25 -0700344}
345
Ian Rogers81d425b2012-09-27 16:03:43 -0700346bool Mutex::ExclusiveTryLock(Thread* self) {
Ian Rogers01ae5802012-09-28 16:14:01 -0700347 DCHECK(self == NULL || self == Thread::Current());
Ian Rogers25fd14b2012-09-05 10:56:38 -0700348 if (kDebugLocking && !recursive_) {
Ian Rogers81d425b2012-09-27 16:03:43 -0700349 AssertNotHeld(self);
Ian Rogers25fd14b2012-09-05 10:56:38 -0700350 }
Ian Rogers81d425b2012-09-27 16:03:43 -0700351 if (!recursive_ || !IsExclusiveHeld(self)) {
Ian Rogersc604d732012-10-14 16:09:54 -0700352#if ART_USE_FUTEXES
353 bool done = false;
354 do {
355 int32_t cur_state = state_;
356 if (cur_state == 0) {
357 // Change state from 0 to 1.
Ian Rogersb122a4b2013-11-19 18:00:50 -0800358 done = __sync_bool_compare_and_swap(&state_, 0 /* cur_state */, 1 /* new state */);
Ian Rogersc604d732012-10-14 16:09:54 -0700359 } else {
360 return false;
361 }
Brian Carlstromdf629502013-07-17 22:39:56 -0700362 } while (!done);
Ian Rogersb122a4b2013-11-19 18:00:50 -0800363 QuasiAtomic::MembarStoreLoad();
Ian Rogersc604d732012-10-14 16:09:54 -0700364 DCHECK_EQ(state_, 1);
365 exclusive_owner_ = SafeGetTid(self);
366#else
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700367 int result = pthread_mutex_trylock(&mutex_);
368 if (result == EBUSY) {
369 return false;
370 }
371 if (result != 0) {
372 errno = result;
373 PLOG(FATAL) << "pthread_mutex_trylock failed for " << name_;
374 }
Ian Rogersc604d732012-10-14 16:09:54 -0700375#endif
Ian Rogers81d425b2012-09-27 16:03:43 -0700376 RegisterAsLocked(self);
Elliott Hughes8daa0922011-09-11 13:46:25 -0700377 }
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700378 recursion_count_++;
Ian Rogers25fd14b2012-09-05 10:56:38 -0700379 if (kDebugLocking) {
380 CHECK(recursion_count_ == 1 || recursive_) << "Unexpected recursion count on mutex: "
381 << name_ << " " << recursion_count_;
Ian Rogers81d425b2012-09-27 16:03:43 -0700382 AssertHeld(self);
Ian Rogers25fd14b2012-09-05 10:56:38 -0700383 }
Elliott Hughes8daa0922011-09-11 13:46:25 -0700384 return true;
385}
386
Ian Rogers81d425b2012-09-27 16:03:43 -0700387void Mutex::ExclusiveUnlock(Thread* self) {
Ian Rogers01ae5802012-09-28 16:14:01 -0700388 DCHECK(self == NULL || self == Thread::Current());
Ian Rogers81d425b2012-09-27 16:03:43 -0700389 AssertHeld(self);
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700390 recursion_count_--;
391 if (!recursive_ || recursion_count_ == 0) {
Ian Rogers25fd14b2012-09-05 10:56:38 -0700392 if (kDebugLocking) {
393 CHECK(recursion_count_ == 0 || recursive_) << "Unexpected recursion count on mutex: "
394 << name_ << " " << recursion_count_;
395 }
Ian Rogers81d425b2012-09-27 16:03:43 -0700396 RegisterAsUnlocked(self);
Ian Rogersc604d732012-10-14 16:09:54 -0700397#if ART_USE_FUTEXES
398 bool done = false;
399 do {
400 int32_t cur_state = state_;
Hiroshi Yamauchi967a0ad2013-09-10 16:24:21 -0700401 if (LIKELY(cur_state == 1)) {
Ian Rogersb122a4b2013-11-19 18:00:50 -0800402 QuasiAtomic::MembarStoreStore();
Ian Rogersc604d732012-10-14 16:09:54 -0700403 // We're no longer the owner.
404 exclusive_owner_ = 0;
405 // Change state to 0.
Ian Rogersb122a4b2013-11-19 18:00:50 -0800406 done = __sync_bool_compare_and_swap(&state_, cur_state, 0 /* new state */);
Hiroshi Yamauchi967a0ad2013-09-10 16:24:21 -0700407 if (LIKELY(done)) { // Spurious fail?
Ian Rogersc604d732012-10-14 16:09:54 -0700408 // Wake a contender
Hiroshi Yamauchi967a0ad2013-09-10 16:24:21 -0700409 if (UNLIKELY(num_contenders_ > 0)) {
Ian Rogersc604d732012-10-14 16:09:54 -0700410 futex(&state_, FUTEX_WAKE, 1, NULL, NULL, 0);
411 }
412 }
413 } else {
Ian Rogersc4ee12e2013-05-16 11:19:53 -0700414 // Logging acquires the logging lock, avoid infinite recursion in that case.
415 if (this != Locks::logging_lock_) {
416 LOG(FATAL) << "Unexpected state_ in unlock " << cur_state << " for " << name_;
417 } else {
418 LogMessageData data(__FILE__, __LINE__, INTERNAL_FATAL, -1);
419 LogMessage::LogLine(data, StringPrintf("Unexpected state_ %d in unlock for %s",
420 cur_state, name_).c_str());
421 _exit(1);
422 }
Ian Rogersc604d732012-10-14 16:09:54 -0700423 }
Brian Carlstromdf629502013-07-17 22:39:56 -0700424 } while (!done);
Ian Rogersb122a4b2013-11-19 18:00:50 -0800425 QuasiAtomic::MembarStoreLoad();
Ian Rogersc604d732012-10-14 16:09:54 -0700426#else
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700427 CHECK_MUTEX_CALL(pthread_mutex_unlock, (&mutex_));
Ian Rogersc604d732012-10-14 16:09:54 -0700428#endif
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700429 }
Elliott Hughes8daa0922011-09-11 13:46:25 -0700430}
431
Ian Rogers56edc432013-01-18 16:51:51 -0800432void Mutex::Dump(std::ostream& os) const {
433 os << (recursive_ ? "recursive " : "non-recursive ")
434 << name_
435 << " level=" << static_cast<int>(level_)
436 << " rec=" << recursion_count_
437 << " owner=" << GetExclusiveOwnerTid() << " ";
438 DumpContention(os);
Ian Rogers01ae5802012-09-28 16:14:01 -0700439}
440
441std::ostream& operator<<(std::ostream& os, const Mutex& mu) {
Ian Rogers56edc432013-01-18 16:51:51 -0800442 mu.Dump(os);
443 return os;
Ian Rogers01ae5802012-09-28 16:14:01 -0700444}
445
Brian Carlstrom02c8cc62013-07-18 15:54:44 -0700446ReaderWriterMutex::ReaderWriterMutex(const char* name, LockLevel level)
447 : BaseMutex(name, level)
Ian Rogers81d425b2012-09-27 16:03:43 -0700448#if ART_USE_FUTEXES
449 , state_(0), exclusive_owner_(0), num_pending_readers_(0), num_pending_writers_(0)
450#endif
Brian Carlstrom7934ac22013-07-26 10:54:15 -0700451{ // NOLINT(whitespace/braces)
Ian Rogers81d425b2012-09-27 16:03:43 -0700452#if !ART_USE_FUTEXES
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700453 CHECK_MUTEX_CALL(pthread_rwlock_init, (&rwlock_, NULL));
Ian Rogers81d425b2012-09-27 16:03:43 -0700454#endif
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700455}
456
457ReaderWriterMutex::~ReaderWriterMutex() {
Ian Rogers81d425b2012-09-27 16:03:43 -0700458#if ART_USE_FUTEXES
459 CHECK_EQ(state_, 0);
460 CHECK_EQ(exclusive_owner_, 0U);
461 CHECK_EQ(num_pending_readers_, 0);
462 CHECK_EQ(num_pending_writers_, 0);
463#else
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700464 // We can't use CHECK_MUTEX_CALL here because on shutdown a suspended daemon thread
465 // may still be using locks.
466 int rc = pthread_rwlock_destroy(&rwlock_);
467 if (rc != 0) {
468 errno = rc;
469 // TODO: should we just not log at all if shutting down? this could be the logging mutex!
Ian Rogers50b35e22012-10-04 10:09:15 -0700470 MutexLock mu(Thread::Current(), *Locks::runtime_shutdown_lock_);
Ian Rogers120f1c72012-09-28 17:17:10 -0700471 Runtime* runtime = Runtime::Current();
Mathieu Chartier34e82932013-11-12 18:22:47 -0800472 bool shutting_down = runtime == NULL || runtime->IsShuttingDownLocked();
Ian Rogers120f1c72012-09-28 17:17:10 -0700473 PLOG(shutting_down ? WARNING : FATAL) << "pthread_rwlock_destroy failed for " << name_;
Brian Carlstromcd74c4b2012-01-23 13:21:00 -0800474 }
Ian Rogers81d425b2012-09-27 16:03:43 -0700475#endif
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700476}
477
Ian Rogers81d425b2012-09-27 16:03:43 -0700478void ReaderWriterMutex::ExclusiveLock(Thread* self) {
Ian Rogers01ae5802012-09-28 16:14:01 -0700479 DCHECK(self == NULL || self == Thread::Current());
Ian Rogers81d425b2012-09-27 16:03:43 -0700480 AssertNotExclusiveHeld(self);
481#if ART_USE_FUTEXES
482 bool done = false;
483 do {
484 int32_t cur_state = state_;
Hiroshi Yamauchi967a0ad2013-09-10 16:24:21 -0700485 if (LIKELY(cur_state == 0)) {
Ian Rogers81d425b2012-09-27 16:03:43 -0700486 // Change state from 0 to -1.
Ian Rogersb122a4b2013-11-19 18:00:50 -0800487 done = __sync_bool_compare_and_swap(&state_, 0 /* cur_state*/, -1 /* new state */);
Ian Rogers81d425b2012-09-27 16:03:43 -0700488 } else {
489 // Failed to acquire, hang up.
Hiroshi Yamauchib3733082013-08-12 17:28:49 -0700490 ScopedContentionRecorder scr(this, SafeGetTid(self), GetExclusiveOwnerTid());
Ian Rogersb122a4b2013-11-19 18:00:50 -0800491 num_pending_writers_++;
Ian Rogers81d425b2012-09-27 16:03:43 -0700492 if (futex(&state_, FUTEX_WAIT, cur_state, NULL, NULL, 0) != 0) {
Brian Carlstrom0de79852013-07-25 22:29:58 -0700493 // EAGAIN and EINTR both indicate a spurious failure, try again from the beginning.
494 // We don't use TEMP_FAILURE_RETRY so we can intentionally retry to acquire the lock.
495 if ((errno != EAGAIN) && (errno != EINTR)) {
Ian Rogers81d425b2012-09-27 16:03:43 -0700496 PLOG(FATAL) << "futex wait failed for " << name_;
497 }
498 }
Ian Rogersb122a4b2013-11-19 18:00:50 -0800499 num_pending_writers_--;
Ian Rogers81d425b2012-09-27 16:03:43 -0700500 }
Brian Carlstromdf629502013-07-17 22:39:56 -0700501 } while (!done);
Ian Rogersab470162012-09-29 23:06:53 -0700502 DCHECK_EQ(state_, -1);
503 exclusive_owner_ = SafeGetTid(self);
Ian Rogers81d425b2012-09-27 16:03:43 -0700504#else
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700505 CHECK_MUTEX_CALL(pthread_rwlock_wrlock, (&rwlock_));
Ian Rogers81d425b2012-09-27 16:03:43 -0700506#endif
507 RegisterAsLocked(self);
508 AssertExclusiveHeld(self);
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700509}
510
Ian Rogers81d425b2012-09-27 16:03:43 -0700511void ReaderWriterMutex::ExclusiveUnlock(Thread* self) {
Ian Rogers01ae5802012-09-28 16:14:01 -0700512 DCHECK(self == NULL || self == Thread::Current());
Ian Rogers81d425b2012-09-27 16:03:43 -0700513 AssertExclusiveHeld(self);
514 RegisterAsUnlocked(self);
515#if ART_USE_FUTEXES
516 bool done = false;
517 do {
518 int32_t cur_state = state_;
Hiroshi Yamauchi967a0ad2013-09-10 16:24:21 -0700519 if (LIKELY(cur_state == -1)) {
Ian Rogers81d425b2012-09-27 16:03:43 -0700520 // We're no longer the owner.
521 exclusive_owner_ = 0;
522 // Change state from -1 to 0.
Ian Rogersb122a4b2013-11-19 18:00:50 -0800523 done = __sync_bool_compare_and_swap(&state_, -1 /* cur_state*/, 0 /* new state */);
Hiroshi Yamauchi967a0ad2013-09-10 16:24:21 -0700524 if (LIKELY(done)) { // cmpxchg may fail due to noise?
Ian Rogers81d425b2012-09-27 16:03:43 -0700525 // Wake any waiters.
Hiroshi Yamauchi967a0ad2013-09-10 16:24:21 -0700526 if (UNLIKELY(num_pending_readers_ > 0 || num_pending_writers_ > 0)) {
Ian Rogers81d425b2012-09-27 16:03:43 -0700527 futex(&state_, FUTEX_WAKE, -1, NULL, NULL, 0);
528 }
529 }
530 } else {
531 LOG(FATAL) << "Unexpected state_:" << cur_state << " for " << name_;
532 }
Brian Carlstromdf629502013-07-17 22:39:56 -0700533 } while (!done);
Ian Rogers81d425b2012-09-27 16:03:43 -0700534#else
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700535 CHECK_MUTEX_CALL(pthread_rwlock_unlock, (&rwlock_));
Ian Rogers81d425b2012-09-27 16:03:43 -0700536#endif
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700537}
538
Ian Rogers66aee5c2012-08-15 17:17:47 -0700539#if HAVE_TIMED_RWLOCK
Ian Rogersc604d732012-10-14 16:09:54 -0700540bool ReaderWriterMutex::ExclusiveLockWithTimeout(Thread* self, int64_t ms, int32_t ns) {
Ian Rogers01ae5802012-09-28 16:14:01 -0700541 DCHECK(self == NULL || self == Thread::Current());
Ian Rogers81d425b2012-09-27 16:03:43 -0700542#if ART_USE_FUTEXES
543 bool done = false;
Ian Rogersc604d732012-10-14 16:09:54 -0700544 timespec end_abs_ts;
Ian Rogers5bd97c42012-11-27 02:38:26 -0800545 InitTimeSpec(true, CLOCK_REALTIME, ms, ns, &end_abs_ts);
Ian Rogers81d425b2012-09-27 16:03:43 -0700546 do {
547 int32_t cur_state = state_;
548 if (cur_state == 0) {
549 // Change state from 0 to -1.
Ian Rogersb122a4b2013-11-19 18:00:50 -0800550 done = __sync_bool_compare_and_swap(&state_, 0 /* cur_state */, -1 /* new state */);
Ian Rogers81d425b2012-09-27 16:03:43 -0700551 } else {
552 // Failed to acquire, hang up.
Ian Rogersc604d732012-10-14 16:09:54 -0700553 timespec now_abs_ts;
Ian Rogers5bd97c42012-11-27 02:38:26 -0800554 InitTimeSpec(true, CLOCK_REALTIME, 0, 0, &now_abs_ts);
Ian Rogersc604d732012-10-14 16:09:54 -0700555 timespec rel_ts;
556 if (ComputeRelativeTimeSpec(&rel_ts, end_abs_ts, now_abs_ts)) {
557 return false; // Timed out.
558 }
Hiroshi Yamauchib3733082013-08-12 17:28:49 -0700559 ScopedContentionRecorder scr(this, SafeGetTid(self), GetExclusiveOwnerTid());
Ian Rogersb122a4b2013-11-19 18:00:50 -0800560 num_pending_writers_++;
Ian Rogersc604d732012-10-14 16:09:54 -0700561 if (futex(&state_, FUTEX_WAIT, cur_state, &rel_ts, NULL, 0) != 0) {
Ian Rogers81d425b2012-09-27 16:03:43 -0700562 if (errno == ETIMEDOUT) {
Ian Rogersb122a4b2013-11-19 18:00:50 -0800563 num_pending_writers_--;
Ian Rogersc604d732012-10-14 16:09:54 -0700564 return false; // Timed out.
Brian Carlstrom0de79852013-07-25 22:29:58 -0700565 } else if ((errno != EAGAIN) && (errno != EINTR)) {
566 // EAGAIN and EINTR both indicate a spurious failure,
567 // recompute the relative time out from now and try again.
568 // We don't use TEMP_FAILURE_RETRY so we can recompute rel_ts;
Ian Rogers81d425b2012-09-27 16:03:43 -0700569 PLOG(FATAL) << "timed futex wait failed for " << name_;
570 }
571 }
Ian Rogersb122a4b2013-11-19 18:00:50 -0800572 num_pending_writers_--;
Ian Rogers81d425b2012-09-27 16:03:43 -0700573 }
Brian Carlstromdf629502013-07-17 22:39:56 -0700574 } while (!done);
Ian Rogers01ae5802012-09-28 16:14:01 -0700575 exclusive_owner_ = SafeGetTid(self);
Ian Rogers81d425b2012-09-27 16:03:43 -0700576#else
Ian Rogersc604d732012-10-14 16:09:54 -0700577 timespec ts;
Brian Carlstrombcc29262012-11-02 11:36:03 -0700578 InitTimeSpec(true, CLOCK_REALTIME, ms, ns, &ts);
Ian Rogersc604d732012-10-14 16:09:54 -0700579 int result = pthread_rwlock_timedwrlock(&rwlock_, &ts);
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700580 if (result == ETIMEDOUT) {
581 return false;
582 }
583 if (result != 0) {
584 errno = result;
Ian Rogersa5acfd32012-08-15 11:50:10 -0700585 PLOG(FATAL) << "pthread_rwlock_timedwrlock failed for " << name_;
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700586 }
Ian Rogers81d425b2012-09-27 16:03:43 -0700587#endif
588 RegisterAsLocked(self);
589 AssertSharedHeld(self);
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700590 return true;
591}
Ian Rogers66aee5c2012-08-15 17:17:47 -0700592#endif
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700593
Ian Rogers81d425b2012-09-27 16:03:43 -0700594bool ReaderWriterMutex::SharedTryLock(Thread* self) {
Ian Rogers01ae5802012-09-28 16:14:01 -0700595 DCHECK(self == NULL || self == Thread::Current());
Ian Rogers81d425b2012-09-27 16:03:43 -0700596#if ART_USE_FUTEXES
597 bool done = false;
598 do {
599 int32_t cur_state = state_;
600 if (cur_state >= 0) {
601 // Add as an extra reader.
Ian Rogersb122a4b2013-11-19 18:00:50 -0800602 done = __sync_bool_compare_and_swap(&state_, cur_state, cur_state + 1);
Ian Rogers81d425b2012-09-27 16:03:43 -0700603 } else {
604 // Owner holds it exclusively.
605 return false;
606 }
Brian Carlstromdf629502013-07-17 22:39:56 -0700607 } while (!done);
Ian Rogers81d425b2012-09-27 16:03:43 -0700608#else
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700609 int result = pthread_rwlock_tryrdlock(&rwlock_);
610 if (result == EBUSY) {
611 return false;
612 }
613 if (result != 0) {
614 errno = result;
615 PLOG(FATAL) << "pthread_mutex_trylock failed for " << name_;
616 }
Ian Rogers81d425b2012-09-27 16:03:43 -0700617#endif
618 RegisterAsLocked(self);
619 AssertSharedHeld(self);
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700620 return true;
621}
622
Ian Rogers81d425b2012-09-27 16:03:43 -0700623bool ReaderWriterMutex::IsSharedHeld(const Thread* self) const {
Ian Rogers01ae5802012-09-28 16:14:01 -0700624 DCHECK(self == NULL || self == Thread::Current());
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700625 bool result;
626 if (UNLIKELY(self == NULL)) { // Handle unattached threads.
Ian Rogers01ae5802012-09-28 16:14:01 -0700627 result = IsExclusiveHeld(self); // TODO: a better best effort here.
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700628 } else {
629 result = (self->GetHeldMutex(level_) == this);
630 }
631 return result;
632}
633
Ian Rogers56edc432013-01-18 16:51:51 -0800634void ReaderWriterMutex::Dump(std::ostream& os) const {
635 os << name_
636 << " level=" << static_cast<int>(level_)
637 << " owner=" << GetExclusiveOwnerTid() << " ";
638 DumpContention(os);
Ian Rogers01ae5802012-09-28 16:14:01 -0700639}
640
641std::ostream& operator<<(std::ostream& os, const ReaderWriterMutex& mu) {
Ian Rogers56edc432013-01-18 16:51:51 -0800642 mu.Dump(os);
643 return os;
Ian Rogers01ae5802012-09-28 16:14:01 -0700644}
645
Ian Rogers23055dc2013-04-18 16:29:16 -0700646ConditionVariable::ConditionVariable(const char* name, Mutex& guard)
Ian Rogersc604d732012-10-14 16:09:54 -0700647 : name_(name), guard_(guard) {
648#if ART_USE_FUTEXES
Ian Rogersd45f2012012-11-28 11:46:23 -0800649 sequence_ = 0;
Ian Rogersc604d732012-10-14 16:09:54 -0700650 num_waiters_ = 0;
Ian Rogersc604d732012-10-14 16:09:54 -0700651#else
Narayan Kamath51b71022014-03-04 11:57:09 +0000652 pthread_condattr_t cond_attrs;
653 CHECK_MUTEX_CALL(pthread_condattr_init(&cond_attrs));
654#if !defined(__APPLE__)
655 // Apple doesn't have CLOCK_MONOTONIC or pthread_condattr_setclock.
656 CHECK_MUTEX_CALL(pthread_condattr_setclock(&cond_attrs, CLOCK_MONOTONIC));
657#endif
658 CHECK_MUTEX_CALL(pthread_cond_init, (&cond_, &cond_attrs));
Ian Rogersc604d732012-10-14 16:09:54 -0700659#endif
Elliott Hughes5f791332011-09-15 17:45:30 -0700660}
661
662ConditionVariable::~ConditionVariable() {
Ian Rogers5bd97c42012-11-27 02:38:26 -0800663#if ART_USE_FUTEXES
664 if (num_waiters_!= 0) {
Ian Rogers5bd97c42012-11-27 02:38:26 -0800665 Runtime* runtime = Runtime::Current();
Mathieu Chartier590fee92013-09-13 13:46:47 -0700666 bool shutting_down = runtime == nullptr || runtime->IsShuttingDown(Thread::Current());
Ian Rogersd45f2012012-11-28 11:46:23 -0800667 LOG(shutting_down ? WARNING : FATAL) << "ConditionVariable::~ConditionVariable for " << name_
668 << " called with " << num_waiters_ << " waiters.";
Ian Rogers5bd97c42012-11-27 02:38:26 -0800669 }
670#else
Elliott Hughese62934d2012-04-09 11:24:29 -0700671 // We can't use CHECK_MUTEX_CALL here because on shutdown a suspended daemon thread
672 // may still be using condition variables.
673 int rc = pthread_cond_destroy(&cond_);
674 if (rc != 0) {
675 errno = rc;
Ian Rogers50b35e22012-10-04 10:09:15 -0700676 MutexLock mu(Thread::Current(), *Locks::runtime_shutdown_lock_);
Ian Rogers120f1c72012-09-28 17:17:10 -0700677 Runtime* runtime = Runtime::Current();
Mathieu Chartier34e82932013-11-12 18:22:47 -0800678 bool shutting_down = (runtime == NULL) || runtime->IsShuttingDownLocked();
Elliott Hughese62934d2012-04-09 11:24:29 -0700679 PLOG(shutting_down ? WARNING : FATAL) << "pthread_cond_destroy failed for " << name_;
680 }
Ian Rogersc604d732012-10-14 16:09:54 -0700681#endif
Elliott Hughes5f791332011-09-15 17:45:30 -0700682}
683
Ian Rogersc604d732012-10-14 16:09:54 -0700684void ConditionVariable::Broadcast(Thread* self) {
685 DCHECK(self == NULL || self == Thread::Current());
686 // TODO: enable below, there's a race in thread creation that causes false failures currently.
687 // guard_.AssertExclusiveHeld(self);
Mathieu Chartiere46cd752012-10-31 16:56:18 -0700688 DCHECK_EQ(guard_.GetExclusiveOwnerTid(), SafeGetTid(self));
Ian Rogersc604d732012-10-14 16:09:54 -0700689#if ART_USE_FUTEXES
Ian Rogersd45f2012012-11-28 11:46:23 -0800690 if (num_waiters_ > 0) {
Ian Rogersb122a4b2013-11-19 18:00:50 -0800691 sequence_++; // Indicate the broadcast occurred.
Ian Rogersc604d732012-10-14 16:09:54 -0700692 bool done = false;
693 do {
Ian Rogersd45f2012012-11-28 11:46:23 -0800694 int32_t cur_sequence = sequence_;
695 // Requeue waiters onto mutex. The waiter holds the contender count on the mutex high ensuring
696 // mutex unlocks will awaken the requeued waiter thread.
Ian Rogersb122a4b2013-11-19 18:00:50 -0800697 done = futex(sequence_.Address(), FUTEX_CMP_REQUEUE, 0,
Ian Rogers5bd97c42012-11-27 02:38:26 -0800698 reinterpret_cast<const timespec*>(std::numeric_limits<int32_t>::max()),
Ian Rogersd45f2012012-11-28 11:46:23 -0800699 &guard_.state_, cur_sequence) != -1;
Ian Rogers5bd97c42012-11-27 02:38:26 -0800700 if (!done) {
701 if (errno != EAGAIN) {
702 PLOG(FATAL) << "futex cmp requeue failed for " << name_;
703 }
Ian Rogers5bd97c42012-11-27 02:38:26 -0800704 }
Ian Rogersc604d732012-10-14 16:09:54 -0700705 } while (!done);
706 }
707#else
Elliott Hughes5f791332011-09-15 17:45:30 -0700708 CHECK_MUTEX_CALL(pthread_cond_broadcast, (&cond_));
Ian Rogersc604d732012-10-14 16:09:54 -0700709#endif
Elliott Hughes5f791332011-09-15 17:45:30 -0700710}
711
Ian Rogersc604d732012-10-14 16:09:54 -0700712void ConditionVariable::Signal(Thread* self) {
713 DCHECK(self == NULL || self == Thread::Current());
714 guard_.AssertExclusiveHeld(self);
715#if ART_USE_FUTEXES
Ian Rogersd45f2012012-11-28 11:46:23 -0800716 if (num_waiters_ > 0) {
Ian Rogersb122a4b2013-11-19 18:00:50 -0800717 sequence_++; // Indicate a signal occurred.
Ian Rogersc604d732012-10-14 16:09:54 -0700718 // Futex wake 1 waiter who will then come and in contend on mutex. It'd be nice to requeue them
719 // to avoid this, however, requeueing can only move all waiters.
Ian Rogersb122a4b2013-11-19 18:00:50 -0800720 int num_woken = futex(sequence_.Address(), FUTEX_WAKE, 1, NULL, NULL, 0);
Ian Rogersd45f2012012-11-28 11:46:23 -0800721 // Check something was woken or else we changed sequence_ before they had chance to wait.
Ian Rogers5bd97c42012-11-27 02:38:26 -0800722 CHECK((num_woken == 0) || (num_woken == 1));
Ian Rogersc604d732012-10-14 16:09:54 -0700723 }
724#else
Elliott Hughes5f791332011-09-15 17:45:30 -0700725 CHECK_MUTEX_CALL(pthread_cond_signal, (&cond_));
Ian Rogersc604d732012-10-14 16:09:54 -0700726#endif
Elliott Hughes5f791332011-09-15 17:45:30 -0700727}
728
Ian Rogersc604d732012-10-14 16:09:54 -0700729void ConditionVariable::Wait(Thread* self) {
Ian Rogers1d54e732013-05-02 21:10:01 -0700730 guard_.CheckSafeToWait(self);
731 WaitHoldingLocks(self);
732}
733
734void ConditionVariable::WaitHoldingLocks(Thread* self) {
Ian Rogersc604d732012-10-14 16:09:54 -0700735 DCHECK(self == NULL || self == Thread::Current());
736 guard_.AssertExclusiveHeld(self);
Ian Rogersc604d732012-10-14 16:09:54 -0700737 unsigned int old_recursion_count = guard_.recursion_count_;
738#if ART_USE_FUTEXES
Ian Rogersc604d732012-10-14 16:09:54 -0700739 num_waiters_++;
Ian Rogersd45f2012012-11-28 11:46:23 -0800740 // Ensure the Mutex is contended so that requeued threads are awoken.
Ian Rogersb122a4b2013-11-19 18:00:50 -0800741 guard_.num_contenders_++;
Ian Rogersc604d732012-10-14 16:09:54 -0700742 guard_.recursion_count_ = 1;
Ian Rogersd45f2012012-11-28 11:46:23 -0800743 int32_t cur_sequence = sequence_;
Ian Rogersc604d732012-10-14 16:09:54 -0700744 guard_.ExclusiveUnlock(self);
Ian Rogersb122a4b2013-11-19 18:00:50 -0800745 if (futex(sequence_.Address(), FUTEX_WAIT, cur_sequence, NULL, NULL, 0) != 0) {
Ian Rogersd45f2012012-11-28 11:46:23 -0800746 // Futex failed, check it is an expected error.
747 // EAGAIN == EWOULDBLK, so we let the caller try again.
748 // EINTR implies a signal was sent to this thread.
749 if ((errno != EINTR) && (errno != EAGAIN)) {
Ian Rogersc604d732012-10-14 16:09:54 -0700750 PLOG(FATAL) << "futex wait failed for " << name_;
751 }
752 }
753 guard_.ExclusiveLock(self);
Ian Rogersd45f2012012-11-28 11:46:23 -0800754 CHECK_GE(num_waiters_, 0);
Ian Rogersc604d732012-10-14 16:09:54 -0700755 num_waiters_--;
Ian Rogersd45f2012012-11-28 11:46:23 -0800756 // We awoke and so no longer require awakes from the guard_'s unlock.
757 CHECK_GE(guard_.num_contenders_, 0);
Ian Rogersb122a4b2013-11-19 18:00:50 -0800758 guard_.num_contenders_--;
Ian Rogersc604d732012-10-14 16:09:54 -0700759#else
760 guard_.recursion_count_ = 0;
761 CHECK_MUTEX_CALL(pthread_cond_wait, (&cond_, &guard_.mutex_));
762#endif
763 guard_.recursion_count_ = old_recursion_count;
Elliott Hughes5f791332011-09-15 17:45:30 -0700764}
765
Ian Rogersc604d732012-10-14 16:09:54 -0700766void ConditionVariable::TimedWait(Thread* self, int64_t ms, int32_t ns) {
767 DCHECK(self == NULL || self == Thread::Current());
768 guard_.AssertExclusiveHeld(self);
Ian Rogers1d54e732013-05-02 21:10:01 -0700769 guard_.CheckSafeToWait(self);
Ian Rogersc604d732012-10-14 16:09:54 -0700770 unsigned int old_recursion_count = guard_.recursion_count_;
771#if ART_USE_FUTEXES
Ian Rogersc604d732012-10-14 16:09:54 -0700772 timespec rel_ts;
Ian Rogers5bd97c42012-11-27 02:38:26 -0800773 InitTimeSpec(false, CLOCK_REALTIME, ms, ns, &rel_ts);
Ian Rogersc604d732012-10-14 16:09:54 -0700774 num_waiters_++;
Ian Rogersd45f2012012-11-28 11:46:23 -0800775 // Ensure the Mutex is contended so that requeued threads are awoken.
Ian Rogersb122a4b2013-11-19 18:00:50 -0800776 guard_.num_contenders_++;
Ian Rogersc604d732012-10-14 16:09:54 -0700777 guard_.recursion_count_ = 1;
Ian Rogersd45f2012012-11-28 11:46:23 -0800778 int32_t cur_sequence = sequence_;
Ian Rogersc604d732012-10-14 16:09:54 -0700779 guard_.ExclusiveUnlock(self);
Ian Rogersb122a4b2013-11-19 18:00:50 -0800780 if (futex(sequence_.Address(), FUTEX_WAIT, cur_sequence, &rel_ts, NULL, 0) != 0) {
Ian Rogersc604d732012-10-14 16:09:54 -0700781 if (errno == ETIMEDOUT) {
Ian Rogersd45f2012012-11-28 11:46:23 -0800782 // Timed out we're done.
Brian Carlstrom0de79852013-07-25 22:29:58 -0700783 } else if ((errno == EAGAIN) || (errno == EINTR)) {
Ian Rogersd45f2012012-11-28 11:46:23 -0800784 // A signal or ConditionVariable::Signal/Broadcast has come in.
Ian Rogersc604d732012-10-14 16:09:54 -0700785 } else {
786 PLOG(FATAL) << "timed futex wait failed for " << name_;
787 }
788 }
789 guard_.ExclusiveLock(self);
Ian Rogersd45f2012012-11-28 11:46:23 -0800790 CHECK_GE(num_waiters_, 0);
Ian Rogersc604d732012-10-14 16:09:54 -0700791 num_waiters_--;
Ian Rogersd45f2012012-11-28 11:46:23 -0800792 // We awoke and so no longer require awakes from the guard_'s unlock.
793 CHECK_GE(guard_.num_contenders_, 0);
Ian Rogersb122a4b2013-11-19 18:00:50 -0800794 guard_.num_contenders_--;
Ian Rogersc604d732012-10-14 16:09:54 -0700795#else
Narayan Kamath51b71022014-03-04 11:57:09 +0000796#if !defined(__APPLE__)
Ian Rogersc604d732012-10-14 16:09:54 -0700797 int clock = CLOCK_MONOTONIC;
Elliott Hughes5f791332011-09-15 17:45:30 -0700798#else
Ian Rogersc604d732012-10-14 16:09:54 -0700799 int clock = CLOCK_REALTIME;
Elliott Hughes5f791332011-09-15 17:45:30 -0700800#endif
Ian Rogersc604d732012-10-14 16:09:54 -0700801 guard_.recursion_count_ = 0;
802 timespec ts;
Brian Carlstrombcc29262012-11-02 11:36:03 -0700803 InitTimeSpec(true, clock, ms, ns, &ts);
Narayan Kamath51b71022014-03-04 11:57:09 +0000804 int rc = TEMP_FAILURE_RETRY(pthread_cond_timedwait(&cond_, &guard_.mutex_, &ts));
Elliott Hughes5f791332011-09-15 17:45:30 -0700805 if (rc != 0 && rc != ETIMEDOUT) {
806 errno = rc;
807 PLOG(FATAL) << "TimedWait failed for " << name_;
808 }
Ian Rogersc604d732012-10-14 16:09:54 -0700809#endif
810 guard_.recursion_count_ = old_recursion_count;
Elliott Hughes5f791332011-09-15 17:45:30 -0700811}
812
Ian Rogers719d1a32014-03-06 12:13:39 -0800813void Locks::Init() {
814 if (logging_lock_ != nullptr) {
815 // Already initialized.
816 DCHECK(abort_lock_ != nullptr);
817 DCHECK(breakpoint_lock_ != nullptr);
Ian Rogers719d1a32014-03-06 12:13:39 -0800818 DCHECK(classlinker_classes_lock_ != nullptr);
819 DCHECK(heap_bitmap_lock_ != nullptr);
820 DCHECK(logging_lock_ != nullptr);
821 DCHECK(mutator_lock_ != nullptr);
822 DCHECK(thread_list_lock_ != nullptr);
823 DCHECK(thread_suspend_count_lock_ != nullptr);
824 DCHECK(trace_lock_ != nullptr);
825 DCHECK(profiler_lock_ != nullptr);
826 DCHECK(unexpected_signal_lock_ != nullptr);
827 DCHECK(intern_table_lock_ != nullptr);
828 } else {
829 logging_lock_ = new Mutex("logging lock", kLoggingLock, true);
830 abort_lock_ = new Mutex("abort lock", kAbortLock, true);
831
832 DCHECK(breakpoint_lock_ == nullptr);
833 breakpoint_lock_ = new Mutex("breakpoint lock", kBreakpointLock);
Ian Rogers719d1a32014-03-06 12:13:39 -0800834 DCHECK(classlinker_classes_lock_ == nullptr);
835 classlinker_classes_lock_ = new ReaderWriterMutex("ClassLinker classes lock",
836 kClassLinkerClassesLock);
837 DCHECK(heap_bitmap_lock_ == nullptr);
838 heap_bitmap_lock_ = new ReaderWriterMutex("heap bitmap lock", kHeapBitmapLock);
839 DCHECK(mutator_lock_ == nullptr);
840 mutator_lock_ = new ReaderWriterMutex("mutator lock", kMutatorLock);
841 DCHECK(runtime_shutdown_lock_ == nullptr);
842 runtime_shutdown_lock_ = new Mutex("runtime shutdown lock", kRuntimeShutdownLock);
843 DCHECK(thread_list_lock_ == nullptr);
844 thread_list_lock_ = new Mutex("thread list lock", kThreadListLock);
845 DCHECK(thread_suspend_count_lock_ == nullptr);
846 thread_suspend_count_lock_ = new Mutex("thread suspend count lock", kThreadSuspendCountLock);
847 DCHECK(trace_lock_ == nullptr);
848 trace_lock_ = new Mutex("trace lock", kTraceLock);
849 DCHECK(profiler_lock_ == nullptr);
850 profiler_lock_ = new Mutex("profiler lock", kProfilerLock);
851 DCHECK(unexpected_signal_lock_ == nullptr);
852 unexpected_signal_lock_ = new Mutex("unexpected signal lock", kUnexpectedSignalLock, true);
853 DCHECK(intern_table_lock_ == nullptr);
854 intern_table_lock_ = new Mutex("InternTable lock", kInternTableLock);
855 }
856}
857
858
Elliott Hughese62934d2012-04-09 11:24:29 -0700859} // namespace art