blob: 532e6c45fdd2091bfa8e587b2d4027d51d5466a3 [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;
34Mutex* Locks::deoptimization_lock_ = nullptr;
35ReaderWriterMutex* Locks::classlinker_classes_lock_ = nullptr;
36ReaderWriterMutex* Locks::heap_bitmap_lock_ = nullptr;
37Mutex* Locks::logging_lock_ = nullptr;
38ReaderWriterMutex* Locks::mutator_lock_ = nullptr;
39Mutex* Locks::runtime_shutdown_lock_ = nullptr;
40Mutex* Locks::thread_list_lock_ = nullptr;
41Mutex* Locks::thread_suspend_count_lock_ = nullptr;
42Mutex* Locks::trace_lock_ = nullptr;
43Mutex* Locks::profiler_lock_ = nullptr;
44Mutex* Locks::unexpected_signal_lock_ = nullptr;
45Mutex* Locks::intern_table_lock_ = nullptr;
46
47struct AllMutexData {
48 // A guard for all_mutexes_ that's not a mutex (Mutexes must CAS to acquire and busy wait).
49 Atomic<const BaseMutex*> all_mutexes_guard;
50 // All created mutexes guarded by all_mutexes_guard_.
51 std::set<BaseMutex*>* all_mutexes;
52 AllMutexData() : all_mutexes(NULL) {}
53};
54static struct AllMutexData gAllMutexData[kAllMutexDataSize];
55
Ian Rogersc604d732012-10-14 16:09:54 -070056#if ART_USE_FUTEXES
57static bool ComputeRelativeTimeSpec(timespec* result_ts, const timespec& lhs, const timespec& rhs) {
Brian Carlstromfb6996f2013-07-18 18:21:14 -070058 const int32_t one_sec = 1000 * 1000 * 1000; // one second in nanoseconds.
Ian Rogersc604d732012-10-14 16:09:54 -070059 result_ts->tv_sec = lhs.tv_sec - rhs.tv_sec;
60 result_ts->tv_nsec = lhs.tv_nsec - rhs.tv_nsec;
61 if (result_ts->tv_nsec < 0) {
62 result_ts->tv_sec--;
63 result_ts->tv_nsec += one_sec;
64 } else if (result_ts->tv_nsec > one_sec) {
65 result_ts->tv_sec++;
66 result_ts->tv_nsec -= one_sec;
67 }
68 return result_ts->tv_sec < 0;
69}
70#endif
71
Ian Rogers56edc432013-01-18 16:51:51 -080072class ScopedAllMutexesLock {
73 public:
Brian Carlstrom93ba8932013-07-17 21:31:49 -070074 explicit ScopedAllMutexesLock(const BaseMutex* mutex) : mutex_(mutex) {
Ian Rogersef7d42f2014-01-06 12:55:46 -080075 while (!gAllMutexData->all_mutexes_guard.CompareAndSwap(0, mutex)) {
Ian Rogers56edc432013-01-18 16:51:51 -080076 NanoSleep(100);
77 }
78 }
79 ~ScopedAllMutexesLock() {
Ian Rogersef7d42f2014-01-06 12:55:46 -080080 while (!gAllMutexData->all_mutexes_guard.CompareAndSwap(mutex_, 0)) {
Ian Rogers56edc432013-01-18 16:51:51 -080081 NanoSleep(100);
82 }
83 }
84 private:
85 const BaseMutex* const mutex_;
86};
Ian Rogers56edc432013-01-18 16:51:51 -080087
88BaseMutex::BaseMutex(const char* name, LockLevel level) : level_(level), name_(name) {
Hiroshi Yamauchi1afde132013-08-06 17:09:30 -070089 if (kLogLockContentions) {
90 ScopedAllMutexesLock mu(this);
Ian Rogersd9c4fc92013-10-01 19:45:43 -070091 std::set<BaseMutex*>** all_mutexes_ptr = &gAllMutexData->all_mutexes;
Hiroshi Yamauchi1afde132013-08-06 17:09:30 -070092 if (*all_mutexes_ptr == NULL) {
93 // We leak the global set of all mutexes to avoid ordering issues in global variable
94 // construction/destruction.
95 *all_mutexes_ptr = new std::set<BaseMutex*>();
96 }
97 (*all_mutexes_ptr)->insert(this);
Ian Rogers56edc432013-01-18 16:51:51 -080098 }
Ian Rogers56edc432013-01-18 16:51:51 -080099}
100
101BaseMutex::~BaseMutex() {
Hiroshi Yamauchi1afde132013-08-06 17:09:30 -0700102 if (kLogLockContentions) {
103 ScopedAllMutexesLock mu(this);
Ian Rogersd9c4fc92013-10-01 19:45:43 -0700104 gAllMutexData->all_mutexes->erase(this);
Hiroshi Yamauchi1afde132013-08-06 17:09:30 -0700105 }
Ian Rogers56edc432013-01-18 16:51:51 -0800106}
107
108void BaseMutex::DumpAll(std::ostream& os) {
Hiroshi Yamauchi1afde132013-08-06 17:09:30 -0700109 if (kLogLockContentions) {
110 os << "Mutex logging:\n";
111 ScopedAllMutexesLock mu(reinterpret_cast<const BaseMutex*>(-1));
Ian Rogersd9c4fc92013-10-01 19:45:43 -0700112 std::set<BaseMutex*>* all_mutexes = gAllMutexData->all_mutexes;
Hiroshi Yamauchi1afde132013-08-06 17:09:30 -0700113 if (all_mutexes == NULL) {
114 // No mutexes have been created yet during at startup.
115 return;
116 }
117 typedef std::set<BaseMutex*>::const_iterator It;
Ian Rogersd9c4fc92013-10-01 19:45:43 -0700118 os << "(Contended)\n";
Hiroshi Yamauchi1afde132013-08-06 17:09:30 -0700119 for (It it = all_mutexes->begin(); it != all_mutexes->end(); ++it) {
120 BaseMutex* mutex = *it;
121 if (mutex->HasEverContended()) {
122 mutex->Dump(os);
123 os << "\n";
124 }
125 }
126 os << "(Never contented)\n";
127 for (It it = all_mutexes->begin(); it != all_mutexes->end(); ++it) {
128 BaseMutex* mutex = *it;
129 if (!mutex->HasEverContended()) {
130 mutex->Dump(os);
131 os << "\n";
132 }
133 }
Ian Rogers56edc432013-01-18 16:51:51 -0800134 }
Ian Rogers56edc432013-01-18 16:51:51 -0800135}
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700136
Ian Rogers81d425b2012-09-27 16:03:43 -0700137void BaseMutex::CheckSafeToWait(Thread* self) {
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700138 if (self == NULL) {
139 CheckUnattachedThread(level_);
140 return;
141 }
Ian Rogers25fd14b2012-09-05 10:56:38 -0700142 if (kDebugLocking) {
Ian Rogersd9c4fc92013-10-01 19:45:43 -0700143 CHECK(self->GetHeldMutex(level_) == this || level_ == kMonitorLock)
144 << "Waiting on unacquired mutex: " << name_;
Ian Rogers25fd14b2012-09-05 10:56:38 -0700145 bool bad_mutexes_held = false;
Elliott Hughes0f827162013-02-26 12:12:58 -0800146 for (int i = kLockLevelCount - 1; i >= 0; --i) {
Ian Rogers25fd14b2012-09-05 10:56:38 -0700147 if (i != level_) {
Ian Rogers81d425b2012-09-27 16:03:43 -0700148 BaseMutex* held_mutex = self->GetHeldMutex(static_cast<LockLevel>(i));
Ian Rogers25fd14b2012-09-05 10:56:38 -0700149 if (held_mutex != NULL) {
Elliott Hughes0f827162013-02-26 12:12:58 -0800150 LOG(ERROR) << "Holding \"" << held_mutex->name_ << "\" "
151 << "(level " << LockLevel(i) << ") while performing wait on "
152 << "\"" << name_ << "\" (level " << level_ << ")";
Ian Rogers25fd14b2012-09-05 10:56:38 -0700153 bad_mutexes_held = true;
154 }
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700155 }
156 }
Ian Rogers25fd14b2012-09-05 10:56:38 -0700157 CHECK(!bad_mutexes_held);
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700158 }
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700159}
160
Hiroshi Yamauchi1afde132013-08-06 17:09:30 -0700161inline void BaseMutex::ContentionLogData::AddToWaitTime(uint64_t value) {
162 if (kLogLockContentions) {
163 // Atomically add value to wait_time.
164 uint64_t new_val, old_val;
165 volatile int64_t* addr = reinterpret_cast<volatile int64_t*>(&wait_time);
166 volatile const int64_t* caddr = const_cast<volatile const int64_t*>(addr);
167 do {
168 old_val = static_cast<uint64_t>(QuasiAtomic::Read64(caddr));
169 new_val = old_val + value;
170 } while (!QuasiAtomic::Cas64(static_cast<int64_t>(old_val), static_cast<int64_t>(new_val), addr));
171 }
172}
173
Brian Carlstrom0de79852013-07-25 22:29:58 -0700174void BaseMutex::RecordContention(uint64_t blocked_tid,
175 uint64_t owner_tid,
Hiroshi Yamauchi1afde132013-08-06 17:09:30 -0700176 uint64_t nano_time_blocked) {
177 if (kLogLockContentions) {
178 ContentionLogData* data = contetion_log_data_;
179 ++(data->contention_count);
180 data->AddToWaitTime(nano_time_blocked);
181 ContentionLogEntry* log = data->contention_log;
182 // This code is intentionally racy as it is only used for diagnostics.
183 uint32_t slot = data->cur_content_log_entry;
184 if (log[slot].blocked_tid == blocked_tid &&
185 log[slot].owner_tid == blocked_tid) {
186 ++log[slot].count;
187 } else {
188 uint32_t new_slot;
189 do {
190 slot = data->cur_content_log_entry;
191 new_slot = (slot + 1) % kContentionLogSize;
Ian Rogersb122a4b2013-11-19 18:00:50 -0800192 } while (!data->cur_content_log_entry.CompareAndSwap(slot, new_slot));
Hiroshi Yamauchi1afde132013-08-06 17:09:30 -0700193 log[new_slot].blocked_tid = blocked_tid;
194 log[new_slot].owner_tid = owner_tid;
195 log[new_slot].count = 1;
196 }
Ian Rogers56edc432013-01-18 16:51:51 -0800197 }
Ian Rogers56edc432013-01-18 16:51:51 -0800198}
199
Ian Rogers56edc432013-01-18 16:51:51 -0800200void BaseMutex::DumpContention(std::ostream& os) const {
Hiroshi Yamauchi1afde132013-08-06 17:09:30 -0700201 if (kLogLockContentions) {
202 const ContentionLogData* data = contetion_log_data_;
203 const ContentionLogEntry* log = data->contention_log;
204 uint64_t wait_time = data->wait_time;
205 uint32_t contention_count = data->contention_count;
206 if (contention_count == 0) {
207 os << "never contended";
208 } else {
209 os << "contended " << contention_count
210 << " times, average wait of contender " << PrettyDuration(wait_time / contention_count);
211 SafeMap<uint64_t, size_t> most_common_blocker;
212 SafeMap<uint64_t, size_t> most_common_blocked;
213 typedef SafeMap<uint64_t, size_t>::const_iterator It;
214 for (size_t i = 0; i < kContentionLogSize; ++i) {
215 uint64_t blocked_tid = log[i].blocked_tid;
216 uint64_t owner_tid = log[i].owner_tid;
217 uint32_t count = log[i].count;
218 if (count > 0) {
219 It it = most_common_blocked.find(blocked_tid);
220 if (it != most_common_blocked.end()) {
221 most_common_blocked.Overwrite(blocked_tid, it->second + count);
222 } else {
223 most_common_blocked.Put(blocked_tid, count);
224 }
225 it = most_common_blocker.find(owner_tid);
226 if (it != most_common_blocker.end()) {
227 most_common_blocker.Overwrite(owner_tid, it->second + count);
228 } else {
229 most_common_blocker.Put(owner_tid, count);
230 }
Ian Rogers56edc432013-01-18 16:51:51 -0800231 }
232 }
Hiroshi Yamauchi1afde132013-08-06 17:09:30 -0700233 uint64_t max_tid = 0;
234 size_t max_tid_count = 0;
235 for (It it = most_common_blocked.begin(); it != most_common_blocked.end(); ++it) {
236 if (it->second > max_tid_count) {
237 max_tid = it->first;
238 max_tid_count = it->second;
239 }
Ian Rogers56edc432013-01-18 16:51:51 -0800240 }
Hiroshi Yamauchi1afde132013-08-06 17:09:30 -0700241 if (max_tid != 0) {
242 os << " sample shows most blocked tid=" << max_tid;
Ian Rogers56edc432013-01-18 16:51:51 -0800243 }
Hiroshi Yamauchi1afde132013-08-06 17:09:30 -0700244 max_tid = 0;
245 max_tid_count = 0;
246 for (It it = most_common_blocker.begin(); it != most_common_blocker.end(); ++it) {
247 if (it->second > max_tid_count) {
248 max_tid = it->first;
249 max_tid_count = it->second;
250 }
251 }
252 if (max_tid != 0) {
253 os << " sample shows tid=" << max_tid << " owning during this time";
254 }
Ian Rogers56edc432013-01-18 16:51:51 -0800255 }
256 }
Ian Rogers56edc432013-01-18 16:51:51 -0800257}
258
259
Ian Rogers81d425b2012-09-27 16:03:43 -0700260Mutex::Mutex(const char* name, LockLevel level, bool recursive)
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700261 : BaseMutex(name, level), recursive_(recursive), recursion_count_(0) {
Ian Rogersc604d732012-10-14 16:09:54 -0700262#if ART_USE_FUTEXES
263 state_ = 0;
264 exclusive_owner_ = 0;
265 num_contenders_ = 0;
266#elif defined(__BIONIC__) || defined(__APPLE__)
Brian Carlstromf3a26412012-08-24 11:06:02 -0700267 // Use recursive mutexes for bionic and Apple otherwise the
268 // non-recursive mutexes don't have TIDs to check lock ownership of.
Elliott Hughesbbd9d832011-11-07 14:40:00 -0800269 pthread_mutexattr_t attributes;
270 CHECK_MUTEX_CALL(pthread_mutexattr_init, (&attributes));
271 CHECK_MUTEX_CALL(pthread_mutexattr_settype, (&attributes, PTHREAD_MUTEX_RECURSIVE));
272 CHECK_MUTEX_CALL(pthread_mutex_init, (&mutex_, &attributes));
273 CHECK_MUTEX_CALL(pthread_mutexattr_destroy, (&attributes));
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700274#else
275 CHECK_MUTEX_CALL(pthread_mutex_init, (&mutex_, NULL));
276#endif
Elliott Hughes8daa0922011-09-11 13:46:25 -0700277}
278
279Mutex::~Mutex() {
Ian Rogersc604d732012-10-14 16:09:54 -0700280#if ART_USE_FUTEXES
281 if (state_ != 0) {
Ian Rogersc604d732012-10-14 16:09:54 -0700282 Runtime* runtime = Runtime::Current();
Mathieu Chartier590fee92013-09-13 13:46:47 -0700283 bool shutting_down = runtime == nullptr || runtime->IsShuttingDown(Thread::Current());
Ian Rogersc604d732012-10-14 16:09:54 -0700284 LOG(shutting_down ? WARNING : FATAL) << "destroying mutex with owner: " << exclusive_owner_;
285 } else {
286 CHECK_EQ(exclusive_owner_, 0U) << "unexpectedly found an owner on unlocked mutex " << name_;
287 CHECK_EQ(num_contenders_, 0) << "unexpectedly found a contender on mutex " << name_;
288 }
289#else
Elliott Hughese62934d2012-04-09 11:24:29 -0700290 // We can't use CHECK_MUTEX_CALL here because on shutdown a suspended daemon thread
291 // may still be using locks.
Elliott Hughes6b355752012-01-13 16:49:08 -0800292 int rc = pthread_mutex_destroy(&mutex_);
293 if (rc != 0) {
294 errno = rc;
Elliott Hughesb3bd5f02012-03-08 21:05:27 -0800295 // TODO: should we just not log at all if shutting down? this could be the logging mutex!
Ian Rogers50b35e22012-10-04 10:09:15 -0700296 MutexLock mu(Thread::Current(), *Locks::runtime_shutdown_lock_);
Ian Rogers120f1c72012-09-28 17:17:10 -0700297 Runtime* runtime = Runtime::Current();
Mathieu Chartier34e82932013-11-12 18:22:47 -0800298 bool shutting_down = (runtime == NULL) || runtime->IsShuttingDownLocked();
Elliott Hughes6b355752012-01-13 16:49:08 -0800299 PLOG(shutting_down ? WARNING : FATAL) << "pthread_mutex_destroy failed for " << name_;
300 }
Ian Rogersc604d732012-10-14 16:09:54 -0700301#endif
Elliott Hughes8daa0922011-09-11 13:46:25 -0700302}
303
Ian Rogers81d425b2012-09-27 16:03:43 -0700304void Mutex::ExclusiveLock(Thread* self) {
Ian Rogers01ae5802012-09-28 16:14:01 -0700305 DCHECK(self == NULL || self == Thread::Current());
Ian Rogers25fd14b2012-09-05 10:56:38 -0700306 if (kDebugLocking && !recursive_) {
Ian Rogers81d425b2012-09-27 16:03:43 -0700307 AssertNotHeld(self);
Ian Rogers25fd14b2012-09-05 10:56:38 -0700308 }
Ian Rogers81d425b2012-09-27 16:03:43 -0700309 if (!recursive_ || !IsExclusiveHeld(self)) {
Ian Rogersc604d732012-10-14 16:09:54 -0700310#if ART_USE_FUTEXES
311 bool done = false;
312 do {
313 int32_t cur_state = state_;
Hiroshi Yamauchi967a0ad2013-09-10 16:24:21 -0700314 if (LIKELY(cur_state == 0)) {
Ian Rogersc604d732012-10-14 16:09:54 -0700315 // Change state from 0 to 1.
Ian Rogersb122a4b2013-11-19 18:00:50 -0800316 done = __sync_bool_compare_and_swap(&state_, 0 /* cur_state */, 1 /* new state */);
Ian Rogersc604d732012-10-14 16:09:54 -0700317 } else {
318 // Failed to acquire, hang up.
Hiroshi Yamauchib3733082013-08-12 17:28:49 -0700319 ScopedContentionRecorder scr(this, SafeGetTid(self), GetExclusiveOwnerTid());
Ian Rogersb122a4b2013-11-19 18:00:50 -0800320 num_contenders_++;
Ian Rogersc604d732012-10-14 16:09:54 -0700321 if (futex(&state_, FUTEX_WAIT, 1, NULL, NULL, 0) != 0) {
Brian Carlstrom0de79852013-07-25 22:29:58 -0700322 // EAGAIN and EINTR both indicate a spurious failure, try again from the beginning.
323 // We don't use TEMP_FAILURE_RETRY so we can intentionally retry to acquire the lock.
324 if ((errno != EAGAIN) && (errno != EINTR)) {
Ian Rogersc604d732012-10-14 16:09:54 -0700325 PLOG(FATAL) << "futex wait failed for " << name_;
326 }
327 }
Ian Rogersb122a4b2013-11-19 18:00:50 -0800328 num_contenders_--;
Ian Rogersc604d732012-10-14 16:09:54 -0700329 }
Brian Carlstromdf629502013-07-17 22:39:56 -0700330 } while (!done);
Ian Rogersb122a4b2013-11-19 18:00:50 -0800331 QuasiAtomic::MembarStoreLoad();
Ian Rogersc604d732012-10-14 16:09:54 -0700332 DCHECK_EQ(state_, 1);
333 exclusive_owner_ = SafeGetTid(self);
334#else
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700335 CHECK_MUTEX_CALL(pthread_mutex_lock, (&mutex_));
Ian Rogersc604d732012-10-14 16:09:54 -0700336#endif
Ian Rogers81d425b2012-09-27 16:03:43 -0700337 RegisterAsLocked(self);
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700338 }
339 recursion_count_++;
Ian Rogers25fd14b2012-09-05 10:56:38 -0700340 if (kDebugLocking) {
341 CHECK(recursion_count_ == 1 || recursive_) << "Unexpected recursion count on mutex: "
342 << name_ << " " << recursion_count_;
Ian Rogers81d425b2012-09-27 16:03:43 -0700343 AssertHeld(self);
Ian Rogers25fd14b2012-09-05 10:56:38 -0700344 }
Elliott Hughes8daa0922011-09-11 13:46:25 -0700345}
346
Ian Rogers81d425b2012-09-27 16:03:43 -0700347bool Mutex::ExclusiveTryLock(Thread* self) {
Ian Rogers01ae5802012-09-28 16:14:01 -0700348 DCHECK(self == NULL || self == Thread::Current());
Ian Rogers25fd14b2012-09-05 10:56:38 -0700349 if (kDebugLocking && !recursive_) {
Ian Rogers81d425b2012-09-27 16:03:43 -0700350 AssertNotHeld(self);
Ian Rogers25fd14b2012-09-05 10:56:38 -0700351 }
Ian Rogers81d425b2012-09-27 16:03:43 -0700352 if (!recursive_ || !IsExclusiveHeld(self)) {
Ian Rogersc604d732012-10-14 16:09:54 -0700353#if ART_USE_FUTEXES
354 bool done = false;
355 do {
356 int32_t cur_state = state_;
357 if (cur_state == 0) {
358 // Change state from 0 to 1.
Ian Rogersb122a4b2013-11-19 18:00:50 -0800359 done = __sync_bool_compare_and_swap(&state_, 0 /* cur_state */, 1 /* new state */);
Ian Rogersc604d732012-10-14 16:09:54 -0700360 } else {
361 return false;
362 }
Brian Carlstromdf629502013-07-17 22:39:56 -0700363 } while (!done);
Ian Rogersb122a4b2013-11-19 18:00:50 -0800364 QuasiAtomic::MembarStoreLoad();
Ian Rogersc604d732012-10-14 16:09:54 -0700365 DCHECK_EQ(state_, 1);
366 exclusive_owner_ = SafeGetTid(self);
367#else
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700368 int result = pthread_mutex_trylock(&mutex_);
369 if (result == EBUSY) {
370 return false;
371 }
372 if (result != 0) {
373 errno = result;
374 PLOG(FATAL) << "pthread_mutex_trylock failed for " << name_;
375 }
Ian Rogersc604d732012-10-14 16:09:54 -0700376#endif
Ian Rogers81d425b2012-09-27 16:03:43 -0700377 RegisterAsLocked(self);
Elliott Hughes8daa0922011-09-11 13:46:25 -0700378 }
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700379 recursion_count_++;
Ian Rogers25fd14b2012-09-05 10:56:38 -0700380 if (kDebugLocking) {
381 CHECK(recursion_count_ == 1 || recursive_) << "Unexpected recursion count on mutex: "
382 << name_ << " " << recursion_count_;
Ian Rogers81d425b2012-09-27 16:03:43 -0700383 AssertHeld(self);
Ian Rogers25fd14b2012-09-05 10:56:38 -0700384 }
Elliott Hughes8daa0922011-09-11 13:46:25 -0700385 return true;
386}
387
Ian Rogers81d425b2012-09-27 16:03:43 -0700388void Mutex::ExclusiveUnlock(Thread* self) {
Ian Rogers01ae5802012-09-28 16:14:01 -0700389 DCHECK(self == NULL || self == Thread::Current());
Ian Rogers81d425b2012-09-27 16:03:43 -0700390 AssertHeld(self);
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700391 recursion_count_--;
392 if (!recursive_ || recursion_count_ == 0) {
Ian Rogers25fd14b2012-09-05 10:56:38 -0700393 if (kDebugLocking) {
394 CHECK(recursion_count_ == 0 || recursive_) << "Unexpected recursion count on mutex: "
395 << name_ << " " << recursion_count_;
396 }
Ian Rogers81d425b2012-09-27 16:03:43 -0700397 RegisterAsUnlocked(self);
Ian Rogersc604d732012-10-14 16:09:54 -0700398#if ART_USE_FUTEXES
399 bool done = false;
400 do {
401 int32_t cur_state = state_;
Hiroshi Yamauchi967a0ad2013-09-10 16:24:21 -0700402 if (LIKELY(cur_state == 1)) {
Ian Rogersb122a4b2013-11-19 18:00:50 -0800403 QuasiAtomic::MembarStoreStore();
Ian Rogersc604d732012-10-14 16:09:54 -0700404 // We're no longer the owner.
405 exclusive_owner_ = 0;
406 // Change state to 0.
Ian Rogersb122a4b2013-11-19 18:00:50 -0800407 done = __sync_bool_compare_and_swap(&state_, cur_state, 0 /* new state */);
Hiroshi Yamauchi967a0ad2013-09-10 16:24:21 -0700408 if (LIKELY(done)) { // Spurious fail?
Ian Rogersc604d732012-10-14 16:09:54 -0700409 // Wake a contender
Hiroshi Yamauchi967a0ad2013-09-10 16:24:21 -0700410 if (UNLIKELY(num_contenders_ > 0)) {
Ian Rogersc604d732012-10-14 16:09:54 -0700411 futex(&state_, FUTEX_WAKE, 1, NULL, NULL, 0);
412 }
413 }
414 } else {
Ian Rogersc4ee12e2013-05-16 11:19:53 -0700415 // Logging acquires the logging lock, avoid infinite recursion in that case.
416 if (this != Locks::logging_lock_) {
417 LOG(FATAL) << "Unexpected state_ in unlock " << cur_state << " for " << name_;
418 } else {
419 LogMessageData data(__FILE__, __LINE__, INTERNAL_FATAL, -1);
420 LogMessage::LogLine(data, StringPrintf("Unexpected state_ %d in unlock for %s",
421 cur_state, name_).c_str());
422 _exit(1);
423 }
Ian Rogersc604d732012-10-14 16:09:54 -0700424 }
Brian Carlstromdf629502013-07-17 22:39:56 -0700425 } while (!done);
Ian Rogersb122a4b2013-11-19 18:00:50 -0800426 QuasiAtomic::MembarStoreLoad();
Ian Rogersc604d732012-10-14 16:09:54 -0700427#else
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700428 CHECK_MUTEX_CALL(pthread_mutex_unlock, (&mutex_));
Ian Rogersc604d732012-10-14 16:09:54 -0700429#endif
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700430 }
Elliott Hughes8daa0922011-09-11 13:46:25 -0700431}
432
Ian Rogers56edc432013-01-18 16:51:51 -0800433void Mutex::Dump(std::ostream& os) const {
434 os << (recursive_ ? "recursive " : "non-recursive ")
435 << name_
436 << " level=" << static_cast<int>(level_)
437 << " rec=" << recursion_count_
438 << " owner=" << GetExclusiveOwnerTid() << " ";
439 DumpContention(os);
Ian Rogers01ae5802012-09-28 16:14:01 -0700440}
441
442std::ostream& operator<<(std::ostream& os, const Mutex& mu) {
Ian Rogers56edc432013-01-18 16:51:51 -0800443 mu.Dump(os);
444 return os;
Ian Rogers01ae5802012-09-28 16:14:01 -0700445}
446
Brian Carlstrom02c8cc62013-07-18 15:54:44 -0700447ReaderWriterMutex::ReaderWriterMutex(const char* name, LockLevel level)
448 : BaseMutex(name, level)
Ian Rogers81d425b2012-09-27 16:03:43 -0700449#if ART_USE_FUTEXES
450 , state_(0), exclusive_owner_(0), num_pending_readers_(0), num_pending_writers_(0)
451#endif
Brian Carlstrom7934ac22013-07-26 10:54:15 -0700452{ // NOLINT(whitespace/braces)
Ian Rogers81d425b2012-09-27 16:03:43 -0700453#if !ART_USE_FUTEXES
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700454 CHECK_MUTEX_CALL(pthread_rwlock_init, (&rwlock_, NULL));
Ian Rogers81d425b2012-09-27 16:03:43 -0700455#endif
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700456}
457
458ReaderWriterMutex::~ReaderWriterMutex() {
Ian Rogers81d425b2012-09-27 16:03:43 -0700459#if ART_USE_FUTEXES
460 CHECK_EQ(state_, 0);
461 CHECK_EQ(exclusive_owner_, 0U);
462 CHECK_EQ(num_pending_readers_, 0);
463 CHECK_EQ(num_pending_writers_, 0);
464#else
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700465 // We can't use CHECK_MUTEX_CALL here because on shutdown a suspended daemon thread
466 // may still be using locks.
467 int rc = pthread_rwlock_destroy(&rwlock_);
468 if (rc != 0) {
469 errno = rc;
470 // TODO: should we just not log at all if shutting down? this could be the logging mutex!
Ian Rogers50b35e22012-10-04 10:09:15 -0700471 MutexLock mu(Thread::Current(), *Locks::runtime_shutdown_lock_);
Ian Rogers120f1c72012-09-28 17:17:10 -0700472 Runtime* runtime = Runtime::Current();
Mathieu Chartier34e82932013-11-12 18:22:47 -0800473 bool shutting_down = runtime == NULL || runtime->IsShuttingDownLocked();
Ian Rogers120f1c72012-09-28 17:17:10 -0700474 PLOG(shutting_down ? WARNING : FATAL) << "pthread_rwlock_destroy failed for " << name_;
Brian Carlstromcd74c4b2012-01-23 13:21:00 -0800475 }
Ian Rogers81d425b2012-09-27 16:03:43 -0700476#endif
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700477}
478
Ian Rogers81d425b2012-09-27 16:03:43 -0700479void ReaderWriterMutex::ExclusiveLock(Thread* self) {
Ian Rogers01ae5802012-09-28 16:14:01 -0700480 DCHECK(self == NULL || self == Thread::Current());
Ian Rogers81d425b2012-09-27 16:03:43 -0700481 AssertNotExclusiveHeld(self);
482#if ART_USE_FUTEXES
483 bool done = false;
484 do {
485 int32_t cur_state = state_;
Hiroshi Yamauchi967a0ad2013-09-10 16:24:21 -0700486 if (LIKELY(cur_state == 0)) {
Ian Rogers81d425b2012-09-27 16:03:43 -0700487 // Change state from 0 to -1.
Ian Rogersb122a4b2013-11-19 18:00:50 -0800488 done = __sync_bool_compare_and_swap(&state_, 0 /* cur_state*/, -1 /* new state */);
Ian Rogers81d425b2012-09-27 16:03:43 -0700489 } else {
490 // Failed to acquire, hang up.
Hiroshi Yamauchib3733082013-08-12 17:28:49 -0700491 ScopedContentionRecorder scr(this, SafeGetTid(self), GetExclusiveOwnerTid());
Ian Rogersb122a4b2013-11-19 18:00:50 -0800492 num_pending_writers_++;
Ian Rogers81d425b2012-09-27 16:03:43 -0700493 if (futex(&state_, FUTEX_WAIT, cur_state, NULL, NULL, 0) != 0) {
Brian Carlstrom0de79852013-07-25 22:29:58 -0700494 // EAGAIN and EINTR both indicate a spurious failure, try again from the beginning.
495 // We don't use TEMP_FAILURE_RETRY so we can intentionally retry to acquire the lock.
496 if ((errno != EAGAIN) && (errno != EINTR)) {
Ian Rogers81d425b2012-09-27 16:03:43 -0700497 PLOG(FATAL) << "futex wait failed for " << name_;
498 }
499 }
Ian Rogersb122a4b2013-11-19 18:00:50 -0800500 num_pending_writers_--;
Ian Rogers81d425b2012-09-27 16:03:43 -0700501 }
Brian Carlstromdf629502013-07-17 22:39:56 -0700502 } while (!done);
Ian Rogersab470162012-09-29 23:06:53 -0700503 DCHECK_EQ(state_, -1);
504 exclusive_owner_ = SafeGetTid(self);
Ian Rogers81d425b2012-09-27 16:03:43 -0700505#else
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700506 CHECK_MUTEX_CALL(pthread_rwlock_wrlock, (&rwlock_));
Ian Rogers81d425b2012-09-27 16:03:43 -0700507#endif
508 RegisterAsLocked(self);
509 AssertExclusiveHeld(self);
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700510}
511
Ian Rogers81d425b2012-09-27 16:03:43 -0700512void ReaderWriterMutex::ExclusiveUnlock(Thread* self) {
Ian Rogers01ae5802012-09-28 16:14:01 -0700513 DCHECK(self == NULL || self == Thread::Current());
Ian Rogers81d425b2012-09-27 16:03:43 -0700514 AssertExclusiveHeld(self);
515 RegisterAsUnlocked(self);
516#if ART_USE_FUTEXES
517 bool done = false;
518 do {
519 int32_t cur_state = state_;
Hiroshi Yamauchi967a0ad2013-09-10 16:24:21 -0700520 if (LIKELY(cur_state == -1)) {
Ian Rogers81d425b2012-09-27 16:03:43 -0700521 // We're no longer the owner.
522 exclusive_owner_ = 0;
523 // Change state from -1 to 0.
Ian Rogersb122a4b2013-11-19 18:00:50 -0800524 done = __sync_bool_compare_and_swap(&state_, -1 /* cur_state*/, 0 /* new state */);
Hiroshi Yamauchi967a0ad2013-09-10 16:24:21 -0700525 if (LIKELY(done)) { // cmpxchg may fail due to noise?
Ian Rogers81d425b2012-09-27 16:03:43 -0700526 // Wake any waiters.
Hiroshi Yamauchi967a0ad2013-09-10 16:24:21 -0700527 if (UNLIKELY(num_pending_readers_ > 0 || num_pending_writers_ > 0)) {
Ian Rogers81d425b2012-09-27 16:03:43 -0700528 futex(&state_, FUTEX_WAKE, -1, NULL, NULL, 0);
529 }
530 }
531 } else {
532 LOG(FATAL) << "Unexpected state_:" << cur_state << " for " << name_;
533 }
Brian Carlstromdf629502013-07-17 22:39:56 -0700534 } while (!done);
Ian Rogers81d425b2012-09-27 16:03:43 -0700535#else
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700536 CHECK_MUTEX_CALL(pthread_rwlock_unlock, (&rwlock_));
Ian Rogers81d425b2012-09-27 16:03:43 -0700537#endif
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700538}
539
Ian Rogers66aee5c2012-08-15 17:17:47 -0700540#if HAVE_TIMED_RWLOCK
Ian Rogersc604d732012-10-14 16:09:54 -0700541bool ReaderWriterMutex::ExclusiveLockWithTimeout(Thread* self, int64_t ms, int32_t ns) {
Ian Rogers01ae5802012-09-28 16:14:01 -0700542 DCHECK(self == NULL || self == Thread::Current());
Ian Rogers81d425b2012-09-27 16:03:43 -0700543#if ART_USE_FUTEXES
544 bool done = false;
Ian Rogersc604d732012-10-14 16:09:54 -0700545 timespec end_abs_ts;
Ian Rogers5bd97c42012-11-27 02:38:26 -0800546 InitTimeSpec(true, CLOCK_REALTIME, ms, ns, &end_abs_ts);
Ian Rogers81d425b2012-09-27 16:03:43 -0700547 do {
548 int32_t cur_state = state_;
549 if (cur_state == 0) {
550 // Change state from 0 to -1.
Ian Rogersb122a4b2013-11-19 18:00:50 -0800551 done = __sync_bool_compare_and_swap(&state_, 0 /* cur_state */, -1 /* new state */);
Ian Rogers81d425b2012-09-27 16:03:43 -0700552 } else {
553 // Failed to acquire, hang up.
Ian Rogersc604d732012-10-14 16:09:54 -0700554 timespec now_abs_ts;
Ian Rogers5bd97c42012-11-27 02:38:26 -0800555 InitTimeSpec(true, CLOCK_REALTIME, 0, 0, &now_abs_ts);
Ian Rogersc604d732012-10-14 16:09:54 -0700556 timespec rel_ts;
557 if (ComputeRelativeTimeSpec(&rel_ts, end_abs_ts, now_abs_ts)) {
558 return false; // Timed out.
559 }
Hiroshi Yamauchib3733082013-08-12 17:28:49 -0700560 ScopedContentionRecorder scr(this, SafeGetTid(self), GetExclusiveOwnerTid());
Ian Rogersb122a4b2013-11-19 18:00:50 -0800561 num_pending_writers_++;
Ian Rogersc604d732012-10-14 16:09:54 -0700562 if (futex(&state_, FUTEX_WAIT, cur_state, &rel_ts, NULL, 0) != 0) {
Ian Rogers81d425b2012-09-27 16:03:43 -0700563 if (errno == ETIMEDOUT) {
Ian Rogersb122a4b2013-11-19 18:00:50 -0800564 num_pending_writers_--;
Ian Rogersc604d732012-10-14 16:09:54 -0700565 return false; // Timed out.
Brian Carlstrom0de79852013-07-25 22:29:58 -0700566 } else if ((errno != EAGAIN) && (errno != EINTR)) {
567 // EAGAIN and EINTR both indicate a spurious failure,
568 // recompute the relative time out from now and try again.
569 // We don't use TEMP_FAILURE_RETRY so we can recompute rel_ts;
Ian Rogers81d425b2012-09-27 16:03:43 -0700570 PLOG(FATAL) << "timed futex wait failed for " << name_;
571 }
572 }
Ian Rogersb122a4b2013-11-19 18:00:50 -0800573 num_pending_writers_--;
Ian Rogers81d425b2012-09-27 16:03:43 -0700574 }
Brian Carlstromdf629502013-07-17 22:39:56 -0700575 } while (!done);
Ian Rogers01ae5802012-09-28 16:14:01 -0700576 exclusive_owner_ = SafeGetTid(self);
Ian Rogers81d425b2012-09-27 16:03:43 -0700577#else
Ian Rogersc604d732012-10-14 16:09:54 -0700578 timespec ts;
Brian Carlstrombcc29262012-11-02 11:36:03 -0700579 InitTimeSpec(true, CLOCK_REALTIME, ms, ns, &ts);
Ian Rogersc604d732012-10-14 16:09:54 -0700580 int result = pthread_rwlock_timedwrlock(&rwlock_, &ts);
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700581 if (result == ETIMEDOUT) {
582 return false;
583 }
584 if (result != 0) {
585 errno = result;
Ian Rogersa5acfd32012-08-15 11:50:10 -0700586 PLOG(FATAL) << "pthread_rwlock_timedwrlock failed for " << name_;
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700587 }
Ian Rogers81d425b2012-09-27 16:03:43 -0700588#endif
589 RegisterAsLocked(self);
590 AssertSharedHeld(self);
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700591 return true;
592}
Ian Rogers66aee5c2012-08-15 17:17:47 -0700593#endif
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700594
Ian Rogers81d425b2012-09-27 16:03:43 -0700595bool ReaderWriterMutex::SharedTryLock(Thread* self) {
Ian Rogers01ae5802012-09-28 16:14:01 -0700596 DCHECK(self == NULL || self == Thread::Current());
Ian Rogers81d425b2012-09-27 16:03:43 -0700597#if ART_USE_FUTEXES
598 bool done = false;
599 do {
600 int32_t cur_state = state_;
601 if (cur_state >= 0) {
602 // Add as an extra reader.
Ian Rogersb122a4b2013-11-19 18:00:50 -0800603 done = __sync_bool_compare_and_swap(&state_, cur_state, cur_state + 1);
Ian Rogers81d425b2012-09-27 16:03:43 -0700604 } else {
605 // Owner holds it exclusively.
606 return false;
607 }
Brian Carlstromdf629502013-07-17 22:39:56 -0700608 } while (!done);
Ian Rogers81d425b2012-09-27 16:03:43 -0700609#else
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700610 int result = pthread_rwlock_tryrdlock(&rwlock_);
611 if (result == EBUSY) {
612 return false;
613 }
614 if (result != 0) {
615 errno = result;
616 PLOG(FATAL) << "pthread_mutex_trylock failed for " << name_;
617 }
Ian Rogers81d425b2012-09-27 16:03:43 -0700618#endif
619 RegisterAsLocked(self);
620 AssertSharedHeld(self);
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700621 return true;
622}
623
Ian Rogers81d425b2012-09-27 16:03:43 -0700624bool ReaderWriterMutex::IsSharedHeld(const Thread* self) const {
Ian Rogers01ae5802012-09-28 16:14:01 -0700625 DCHECK(self == NULL || self == Thread::Current());
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700626 bool result;
627 if (UNLIKELY(self == NULL)) { // Handle unattached threads.
Ian Rogers01ae5802012-09-28 16:14:01 -0700628 result = IsExclusiveHeld(self); // TODO: a better best effort here.
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700629 } else {
630 result = (self->GetHeldMutex(level_) == this);
631 }
632 return result;
633}
634
Ian Rogers56edc432013-01-18 16:51:51 -0800635void ReaderWriterMutex::Dump(std::ostream& os) const {
636 os << name_
637 << " level=" << static_cast<int>(level_)
638 << " owner=" << GetExclusiveOwnerTid() << " ";
639 DumpContention(os);
Ian Rogers01ae5802012-09-28 16:14:01 -0700640}
641
642std::ostream& operator<<(std::ostream& os, const ReaderWriterMutex& mu) {
Ian Rogers56edc432013-01-18 16:51:51 -0800643 mu.Dump(os);
644 return os;
Ian Rogers01ae5802012-09-28 16:14:01 -0700645}
646
Ian Rogers23055dc2013-04-18 16:29:16 -0700647ConditionVariable::ConditionVariable(const char* name, Mutex& guard)
Ian Rogersc604d732012-10-14 16:09:54 -0700648 : name_(name), guard_(guard) {
649#if ART_USE_FUTEXES
Ian Rogersd45f2012012-11-28 11:46:23 -0800650 sequence_ = 0;
Ian Rogersc604d732012-10-14 16:09:54 -0700651 num_waiters_ = 0;
Ian Rogersc604d732012-10-14 16:09:54 -0700652#else
Narayan Kamath51b71022014-03-04 11:57:09 +0000653 pthread_condattr_t cond_attrs;
654 CHECK_MUTEX_CALL(pthread_condattr_init(&cond_attrs));
655#if !defined(__APPLE__)
656 // Apple doesn't have CLOCK_MONOTONIC or pthread_condattr_setclock.
657 CHECK_MUTEX_CALL(pthread_condattr_setclock(&cond_attrs, CLOCK_MONOTONIC));
658#endif
659 CHECK_MUTEX_CALL(pthread_cond_init, (&cond_, &cond_attrs));
Ian Rogersc604d732012-10-14 16:09:54 -0700660#endif
Elliott Hughes5f791332011-09-15 17:45:30 -0700661}
662
663ConditionVariable::~ConditionVariable() {
Ian Rogers5bd97c42012-11-27 02:38:26 -0800664#if ART_USE_FUTEXES
665 if (num_waiters_!= 0) {
Ian Rogers5bd97c42012-11-27 02:38:26 -0800666 Runtime* runtime = Runtime::Current();
Mathieu Chartier590fee92013-09-13 13:46:47 -0700667 bool shutting_down = runtime == nullptr || runtime->IsShuttingDown(Thread::Current());
Ian Rogersd45f2012012-11-28 11:46:23 -0800668 LOG(shutting_down ? WARNING : FATAL) << "ConditionVariable::~ConditionVariable for " << name_
669 << " called with " << num_waiters_ << " waiters.";
Ian Rogers5bd97c42012-11-27 02:38:26 -0800670 }
671#else
Elliott Hughese62934d2012-04-09 11:24:29 -0700672 // We can't use CHECK_MUTEX_CALL here because on shutdown a suspended daemon thread
673 // may still be using condition variables.
674 int rc = pthread_cond_destroy(&cond_);
675 if (rc != 0) {
676 errno = rc;
Ian Rogers50b35e22012-10-04 10:09:15 -0700677 MutexLock mu(Thread::Current(), *Locks::runtime_shutdown_lock_);
Ian Rogers120f1c72012-09-28 17:17:10 -0700678 Runtime* runtime = Runtime::Current();
Mathieu Chartier34e82932013-11-12 18:22:47 -0800679 bool shutting_down = (runtime == NULL) || runtime->IsShuttingDownLocked();
Elliott Hughese62934d2012-04-09 11:24:29 -0700680 PLOG(shutting_down ? WARNING : FATAL) << "pthread_cond_destroy failed for " << name_;
681 }
Ian Rogersc604d732012-10-14 16:09:54 -0700682#endif
Elliott Hughes5f791332011-09-15 17:45:30 -0700683}
684
Ian Rogersc604d732012-10-14 16:09:54 -0700685void ConditionVariable::Broadcast(Thread* self) {
686 DCHECK(self == NULL || self == Thread::Current());
687 // TODO: enable below, there's a race in thread creation that causes false failures currently.
688 // guard_.AssertExclusiveHeld(self);
Mathieu Chartiere46cd752012-10-31 16:56:18 -0700689 DCHECK_EQ(guard_.GetExclusiveOwnerTid(), SafeGetTid(self));
Ian Rogersc604d732012-10-14 16:09:54 -0700690#if ART_USE_FUTEXES
Ian Rogersd45f2012012-11-28 11:46:23 -0800691 if (num_waiters_ > 0) {
Ian Rogersb122a4b2013-11-19 18:00:50 -0800692 sequence_++; // Indicate the broadcast occurred.
Ian Rogersc604d732012-10-14 16:09:54 -0700693 bool done = false;
694 do {
Ian Rogersd45f2012012-11-28 11:46:23 -0800695 int32_t cur_sequence = sequence_;
696 // Requeue waiters onto mutex. The waiter holds the contender count on the mutex high ensuring
697 // mutex unlocks will awaken the requeued waiter thread.
Ian Rogersb122a4b2013-11-19 18:00:50 -0800698 done = futex(sequence_.Address(), FUTEX_CMP_REQUEUE, 0,
Ian Rogers5bd97c42012-11-27 02:38:26 -0800699 reinterpret_cast<const timespec*>(std::numeric_limits<int32_t>::max()),
Ian Rogersd45f2012012-11-28 11:46:23 -0800700 &guard_.state_, cur_sequence) != -1;
Ian Rogers5bd97c42012-11-27 02:38:26 -0800701 if (!done) {
702 if (errno != EAGAIN) {
703 PLOG(FATAL) << "futex cmp requeue failed for " << name_;
704 }
Ian Rogers5bd97c42012-11-27 02:38:26 -0800705 }
Ian Rogersc604d732012-10-14 16:09:54 -0700706 } while (!done);
707 }
708#else
Elliott Hughes5f791332011-09-15 17:45:30 -0700709 CHECK_MUTEX_CALL(pthread_cond_broadcast, (&cond_));
Ian Rogersc604d732012-10-14 16:09:54 -0700710#endif
Elliott Hughes5f791332011-09-15 17:45:30 -0700711}
712
Ian Rogersc604d732012-10-14 16:09:54 -0700713void ConditionVariable::Signal(Thread* self) {
714 DCHECK(self == NULL || self == Thread::Current());
715 guard_.AssertExclusiveHeld(self);
716#if ART_USE_FUTEXES
Ian Rogersd45f2012012-11-28 11:46:23 -0800717 if (num_waiters_ > 0) {
Ian Rogersb122a4b2013-11-19 18:00:50 -0800718 sequence_++; // Indicate a signal occurred.
Ian Rogersc604d732012-10-14 16:09:54 -0700719 // Futex wake 1 waiter who will then come and in contend on mutex. It'd be nice to requeue them
720 // to avoid this, however, requeueing can only move all waiters.
Ian Rogersb122a4b2013-11-19 18:00:50 -0800721 int num_woken = futex(sequence_.Address(), FUTEX_WAKE, 1, NULL, NULL, 0);
Ian Rogersd45f2012012-11-28 11:46:23 -0800722 // Check something was woken or else we changed sequence_ before they had chance to wait.
Ian Rogers5bd97c42012-11-27 02:38:26 -0800723 CHECK((num_woken == 0) || (num_woken == 1));
Ian Rogersc604d732012-10-14 16:09:54 -0700724 }
725#else
Elliott Hughes5f791332011-09-15 17:45:30 -0700726 CHECK_MUTEX_CALL(pthread_cond_signal, (&cond_));
Ian Rogersc604d732012-10-14 16:09:54 -0700727#endif
Elliott Hughes5f791332011-09-15 17:45:30 -0700728}
729
Ian Rogersc604d732012-10-14 16:09:54 -0700730void ConditionVariable::Wait(Thread* self) {
Ian Rogers1d54e732013-05-02 21:10:01 -0700731 guard_.CheckSafeToWait(self);
732 WaitHoldingLocks(self);
733}
734
735void ConditionVariable::WaitHoldingLocks(Thread* self) {
Ian Rogersc604d732012-10-14 16:09:54 -0700736 DCHECK(self == NULL || self == Thread::Current());
737 guard_.AssertExclusiveHeld(self);
Ian Rogersc604d732012-10-14 16:09:54 -0700738 unsigned int old_recursion_count = guard_.recursion_count_;
739#if ART_USE_FUTEXES
Ian Rogersc604d732012-10-14 16:09:54 -0700740 num_waiters_++;
Ian Rogersd45f2012012-11-28 11:46:23 -0800741 // Ensure the Mutex is contended so that requeued threads are awoken.
Ian Rogersb122a4b2013-11-19 18:00:50 -0800742 guard_.num_contenders_++;
Ian Rogersc604d732012-10-14 16:09:54 -0700743 guard_.recursion_count_ = 1;
Ian Rogersd45f2012012-11-28 11:46:23 -0800744 int32_t cur_sequence = sequence_;
Ian Rogersc604d732012-10-14 16:09:54 -0700745 guard_.ExclusiveUnlock(self);
Ian Rogersb122a4b2013-11-19 18:00:50 -0800746 if (futex(sequence_.Address(), FUTEX_WAIT, cur_sequence, NULL, NULL, 0) != 0) {
Ian Rogersd45f2012012-11-28 11:46:23 -0800747 // Futex failed, check it is an expected error.
748 // EAGAIN == EWOULDBLK, so we let the caller try again.
749 // EINTR implies a signal was sent to this thread.
750 if ((errno != EINTR) && (errno != EAGAIN)) {
Ian Rogersc604d732012-10-14 16:09:54 -0700751 PLOG(FATAL) << "futex wait failed for " << name_;
752 }
753 }
754 guard_.ExclusiveLock(self);
Ian Rogersd45f2012012-11-28 11:46:23 -0800755 CHECK_GE(num_waiters_, 0);
Ian Rogersc604d732012-10-14 16:09:54 -0700756 num_waiters_--;
Ian Rogersd45f2012012-11-28 11:46:23 -0800757 // We awoke and so no longer require awakes from the guard_'s unlock.
758 CHECK_GE(guard_.num_contenders_, 0);
Ian Rogersb122a4b2013-11-19 18:00:50 -0800759 guard_.num_contenders_--;
Ian Rogersc604d732012-10-14 16:09:54 -0700760#else
761 guard_.recursion_count_ = 0;
762 CHECK_MUTEX_CALL(pthread_cond_wait, (&cond_, &guard_.mutex_));
763#endif
764 guard_.recursion_count_ = old_recursion_count;
Elliott Hughes5f791332011-09-15 17:45:30 -0700765}
766
Ian Rogersc604d732012-10-14 16:09:54 -0700767void ConditionVariable::TimedWait(Thread* self, int64_t ms, int32_t ns) {
768 DCHECK(self == NULL || self == Thread::Current());
769 guard_.AssertExclusiveHeld(self);
Ian Rogers1d54e732013-05-02 21:10:01 -0700770 guard_.CheckSafeToWait(self);
Ian Rogersc604d732012-10-14 16:09:54 -0700771 unsigned int old_recursion_count = guard_.recursion_count_;
772#if ART_USE_FUTEXES
Ian Rogersc604d732012-10-14 16:09:54 -0700773 timespec rel_ts;
Ian Rogers5bd97c42012-11-27 02:38:26 -0800774 InitTimeSpec(false, CLOCK_REALTIME, ms, ns, &rel_ts);
Ian Rogersc604d732012-10-14 16:09:54 -0700775 num_waiters_++;
Ian Rogersd45f2012012-11-28 11:46:23 -0800776 // Ensure the Mutex is contended so that requeued threads are awoken.
Ian Rogersb122a4b2013-11-19 18:00:50 -0800777 guard_.num_contenders_++;
Ian Rogersc604d732012-10-14 16:09:54 -0700778 guard_.recursion_count_ = 1;
Ian Rogersd45f2012012-11-28 11:46:23 -0800779 int32_t cur_sequence = sequence_;
Ian Rogersc604d732012-10-14 16:09:54 -0700780 guard_.ExclusiveUnlock(self);
Ian Rogersb122a4b2013-11-19 18:00:50 -0800781 if (futex(sequence_.Address(), FUTEX_WAIT, cur_sequence, &rel_ts, NULL, 0) != 0) {
Ian Rogersc604d732012-10-14 16:09:54 -0700782 if (errno == ETIMEDOUT) {
Ian Rogersd45f2012012-11-28 11:46:23 -0800783 // Timed out we're done.
Brian Carlstrom0de79852013-07-25 22:29:58 -0700784 } else if ((errno == EAGAIN) || (errno == EINTR)) {
Ian Rogersd45f2012012-11-28 11:46:23 -0800785 // A signal or ConditionVariable::Signal/Broadcast has come in.
Ian Rogersc604d732012-10-14 16:09:54 -0700786 } else {
787 PLOG(FATAL) << "timed futex wait failed for " << name_;
788 }
789 }
790 guard_.ExclusiveLock(self);
Ian Rogersd45f2012012-11-28 11:46:23 -0800791 CHECK_GE(num_waiters_, 0);
Ian Rogersc604d732012-10-14 16:09:54 -0700792 num_waiters_--;
Ian Rogersd45f2012012-11-28 11:46:23 -0800793 // We awoke and so no longer require awakes from the guard_'s unlock.
794 CHECK_GE(guard_.num_contenders_, 0);
Ian Rogersb122a4b2013-11-19 18:00:50 -0800795 guard_.num_contenders_--;
Ian Rogersc604d732012-10-14 16:09:54 -0700796#else
Narayan Kamath51b71022014-03-04 11:57:09 +0000797#if !defined(__APPLE__)
Ian Rogersc604d732012-10-14 16:09:54 -0700798 int clock = CLOCK_MONOTONIC;
Elliott Hughes5f791332011-09-15 17:45:30 -0700799#else
Ian Rogersc604d732012-10-14 16:09:54 -0700800 int clock = CLOCK_REALTIME;
Elliott Hughes5f791332011-09-15 17:45:30 -0700801#endif
Ian Rogersc604d732012-10-14 16:09:54 -0700802 guard_.recursion_count_ = 0;
803 timespec ts;
Brian Carlstrombcc29262012-11-02 11:36:03 -0700804 InitTimeSpec(true, clock, ms, ns, &ts);
Narayan Kamath51b71022014-03-04 11:57:09 +0000805 int rc = TEMP_FAILURE_RETRY(pthread_cond_timedwait(&cond_, &guard_.mutex_, &ts));
Elliott Hughes5f791332011-09-15 17:45:30 -0700806 if (rc != 0 && rc != ETIMEDOUT) {
807 errno = rc;
808 PLOG(FATAL) << "TimedWait failed for " << name_;
809 }
Ian Rogersc604d732012-10-14 16:09:54 -0700810#endif
811 guard_.recursion_count_ = old_recursion_count;
Elliott Hughes5f791332011-09-15 17:45:30 -0700812}
813
Ian Rogers719d1a32014-03-06 12:13:39 -0800814void Locks::Init() {
815 if (logging_lock_ != nullptr) {
816 // Already initialized.
817 DCHECK(abort_lock_ != nullptr);
818 DCHECK(breakpoint_lock_ != nullptr);
819 DCHECK(deoptimization_lock_ != nullptr);
820 DCHECK(classlinker_classes_lock_ != nullptr);
821 DCHECK(heap_bitmap_lock_ != nullptr);
822 DCHECK(logging_lock_ != nullptr);
823 DCHECK(mutator_lock_ != nullptr);
824 DCHECK(thread_list_lock_ != nullptr);
825 DCHECK(thread_suspend_count_lock_ != nullptr);
826 DCHECK(trace_lock_ != nullptr);
827 DCHECK(profiler_lock_ != nullptr);
828 DCHECK(unexpected_signal_lock_ != nullptr);
829 DCHECK(intern_table_lock_ != nullptr);
830 } else {
831 logging_lock_ = new Mutex("logging lock", kLoggingLock, true);
832 abort_lock_ = new Mutex("abort lock", kAbortLock, true);
833
834 DCHECK(breakpoint_lock_ == nullptr);
835 breakpoint_lock_ = new Mutex("breakpoint lock", kBreakpointLock);
836 DCHECK(deoptimization_lock_ == nullptr);
837 deoptimization_lock_ = new Mutex("deoptimization lock", kDeoptimizationLock);
838 DCHECK(classlinker_classes_lock_ == nullptr);
839 classlinker_classes_lock_ = new ReaderWriterMutex("ClassLinker classes lock",
840 kClassLinkerClassesLock);
841 DCHECK(heap_bitmap_lock_ == nullptr);
842 heap_bitmap_lock_ = new ReaderWriterMutex("heap bitmap lock", kHeapBitmapLock);
843 DCHECK(mutator_lock_ == nullptr);
844 mutator_lock_ = new ReaderWriterMutex("mutator lock", kMutatorLock);
845 DCHECK(runtime_shutdown_lock_ == nullptr);
846 runtime_shutdown_lock_ = new Mutex("runtime shutdown lock", kRuntimeShutdownLock);
847 DCHECK(thread_list_lock_ == nullptr);
848 thread_list_lock_ = new Mutex("thread list lock", kThreadListLock);
849 DCHECK(thread_suspend_count_lock_ == nullptr);
850 thread_suspend_count_lock_ = new Mutex("thread suspend count lock", kThreadSuspendCountLock);
851 DCHECK(trace_lock_ == nullptr);
852 trace_lock_ = new Mutex("trace lock", kTraceLock);
853 DCHECK(profiler_lock_ == nullptr);
854 profiler_lock_ = new Mutex("profiler lock", kProfilerLock);
855 DCHECK(unexpected_signal_lock_ == nullptr);
856 unexpected_signal_lock_ = new Mutex("unexpected signal lock", kUnexpectedSignalLock, true);
857 DCHECK(intern_table_lock_ == nullptr);
858 intern_table_lock_ = new Mutex("InternTable lock", kInternTableLock);
859 }
860}
861
862
Elliott Hughese62934d2012-04-09 11:24:29 -0700863} // namespace art