blob: 0e33f3cc48d2feda06181d882fa2428a8d64448c [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
Ian Rogers81d425b2012-09-27 16:03:43 -070022#include "cutils/atomic.h"
23#include "cutils/atomic-inline.h"
Elliott Hughes8daa0922011-09-11 13:46:25 -070024#include "logging.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"
Elliott Hughesffb465f2012-03-01 18:46:05 -080027#include "thread.h"
28#include "utils.h"
Elliott Hughes8daa0922011-09-11 13:46:25 -070029
Elliott Hughesb08e8a32012-04-02 10:51:41 -070030#if defined(__APPLE__)
31#include "AvailabilityMacros.h" // For MAC_OS_X_VERSION_MAX_ALLOWED
Ian Rogers27913a22012-10-19 17:33:10 -070032// No clocks to specify on OS/X, fake value to pass to routines that require a clock.
Elliott Hughes63af6362012-10-19 18:16:36 -070033#define CLOCK_REALTIME 0xebadf00d
Elliott Hughesb08e8a32012-04-02 10:51:41 -070034#endif
35
Elliott Hughes8d768a92011-09-14 16:35:25 -070036#define CHECK_MUTEX_CALL(call, args) CHECK_PTHREAD_CALL(call, args, name_)
37
Elliott Hughesf8349362012-06-18 15:00:06 -070038extern int pthread_mutex_lock(pthread_mutex_t* mutex) EXCLUSIVE_LOCK_FUNCTION(mutex);
39extern int pthread_mutex_unlock(pthread_mutex_t* mutex) UNLOCK_FUNCTION(1);
40extern int pthread_mutex_trylock(pthread_mutex_t* mutex) EXCLUSIVE_TRYLOCK_FUNCTION(0, mutex);
41
Ian Rogers81d425b2012-09-27 16:03:43 -070042#if ART_USE_FUTEXES
Ian Rogersacc46d62012-09-27 21:39:40 -070043#include "linux/futex.h"
Ian Rogers81d425b2012-09-27 16:03:43 -070044#include "sys/syscall.h"
45#ifndef SYS_futex
46#define SYS_futex __NR_futex
47#endif
Ian Rogersc604d732012-10-14 16:09:54 -070048int futex(volatile int *uaddr, int op, int val, const struct timespec *timeout, volatile int *uaddr2, int val3) {
49 return syscall(SYS_futex, uaddr, op, val, timeout, uaddr2, val3);
Ian Rogers81d425b2012-09-27 16:03:43 -070050}
51#endif // ART_USE_FUTEXES
52
Elliott Hughes8daa0922011-09-11 13:46:25 -070053namespace art {
54
Brian Carlstromf3a26412012-08-24 11:06:02 -070055// This works on Mac OS 10.6 but hasn't been tested on older releases.
Elliott Hughesf1498432012-03-28 19:34:27 -070056struct __attribute__((__may_alias__)) darwin_pthread_mutex_t {
Brian Carlstromf3a26412012-08-24 11:06:02 -070057 long padding0;
58 int padding1;
59 uint32_t padding2;
60 int16_t padding3;
61 int16_t padding4;
62 uint32_t padding5;
63 pthread_t darwin_pthread_mutex_owner;
Ian Rogers00f7d0e2012-07-19 15:28:27 -070064 // ...other stuff we don't care about.
65};
66
67struct __attribute__((__may_alias__)) darwin_pthread_rwlock_t {
Brian Carlstromf3a26412012-08-24 11:06:02 -070068 long padding0;
69 pthread_mutex_t padding1;
70 int padding2;
71 pthread_cond_t padding3;
72 pthread_cond_t padding4;
73 int padding5;
74 int padding6;
75 pthread_t darwin_pthread_rwlock_owner;
Elliott Hughesf1498432012-03-28 19:34:27 -070076 // ...other stuff we don't care about.
77};
78
79struct __attribute__((__may_alias__)) glibc_pthread_mutex_t {
Ian Rogers00f7d0e2012-07-19 15:28:27 -070080 int32_t padding0[2];
Elliott Hughesf1498432012-03-28 19:34:27 -070081 int owner;
82 // ...other stuff we don't care about.
83};
84
Ian Rogers00f7d0e2012-07-19 15:28:27 -070085struct __attribute__((__may_alias__)) glibc_pthread_rwlock_t {
86#ifdef __LP64__
87 int32_t padding0[6];
88#else
89 int32_t padding0[7];
90#endif
91 int writer;
92 // ...other stuff we don't care about.
93};
94
Ian Rogers01ae5802012-09-28 16:14:01 -070095static uint64_t SafeGetTid(const Thread* self) {
96 if (self != NULL) {
97 return static_cast<uint64_t>(self->GetTid());
98 } else {
99 return static_cast<uint64_t>(GetTid());
100 }
101}
102
Ian Rogersc604d732012-10-14 16:09:54 -0700103// Initialize a timespec to either an absolute or relative time.
104static void InitTimeSpec(Thread* self, bool absolute, int clock, int64_t ms, int32_t ns,
105 timespec* ts) {
106 int64_t endSec;
107
108 if (absolute) {
Ian Rogers4c54e722012-10-15 16:12:54 -0700109#if !defined(__APPLE__)
Ian Rogersc604d732012-10-14 16:09:54 -0700110 clock_gettime(clock, ts);
Ian Rogers4c54e722012-10-15 16:12:54 -0700111#else
112 UNUSED(clock);
113 timeval tv;
114 gettimeofday(&tv, NULL);
115 ts->tv_sec = tv.tv_sec;
116 ts->tv_nsec = tv.tv_usec * 1000;
117#endif
Ian Rogersc604d732012-10-14 16:09:54 -0700118 } else {
119 ts->tv_sec = 0;
120 ts->tv_nsec = 0;
121 }
122 endSec = ts->tv_sec + ms / 1000;
123 if (UNLIKELY(endSec >= 0x7fffffff)) {
124 std::ostringstream ss;
125 ScopedObjectAccess soa(self);
126 self->Dump(ss);
127 LOG(INFO) << "Note: end time exceeds epoch: " << ss.str();
128 endSec = 0x7ffffffe;
129 }
130 ts->tv_sec = endSec;
131 ts->tv_nsec = (ts->tv_nsec + (ms % 1000) * 1000000) + ns;
132
133 // Catch rollover.
134 if (ts->tv_nsec >= 1000000000L) {
135 ts->tv_sec++;
136 ts->tv_nsec -= 1000000000L;
137 }
138}
139
140#if ART_USE_FUTEXES
141static bool ComputeRelativeTimeSpec(timespec* result_ts, const timespec& lhs, const timespec& rhs) {
142 const long int one_sec = 1000 * 1000 * 1000; // one second in nanoseconds.
143 result_ts->tv_sec = lhs.tv_sec - rhs.tv_sec;
144 result_ts->tv_nsec = lhs.tv_nsec - rhs.tv_nsec;
145 if (result_ts->tv_nsec < 0) {
146 result_ts->tv_sec--;
147 result_ts->tv_nsec += one_sec;
148 } else if (result_ts->tv_nsec > one_sec) {
149 result_ts->tv_sec++;
150 result_ts->tv_nsec -= one_sec;
151 }
152 return result_ts->tv_sec < 0;
153}
154#endif
155
Ian Rogers81d425b2012-09-27 16:03:43 -0700156BaseMutex::BaseMutex(const char* name, LockLevel level) : level_(level), name_(name) {}
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700157
Ian Rogers120f1c72012-09-28 17:17:10 -0700158static void CheckUnattachedThread(LockLevel level) NO_THREAD_SAFETY_ANALYSIS {
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700159 // The check below enumerates the cases where we expect not to be able to sanity check locks
Ian Rogers120f1c72012-09-28 17:17:10 -0700160 // on a thread. Lock checking is disabled to avoid deadlock when checking shutdown lock.
161 // TODO: tighten this check.
Ian Rogers25fd14b2012-09-05 10:56:38 -0700162 if (kDebugLocking) {
163 Runtime* runtime = Runtime::Current();
164 CHECK(runtime == NULL || !runtime->IsStarted() || runtime->IsShuttingDown() ||
Ian Rogers120f1c72012-09-28 17:17:10 -0700165 level == kDefaultMutexLevel || level == kRuntimeShutdownLock ||
166 level == kThreadListLock || level == kLoggingLock || level == kAbortLock);
Ian Rogers25fd14b2012-09-05 10:56:38 -0700167 }
Elliott Hughesffb465f2012-03-01 18:46:05 -0800168}
169
Ian Rogers81d425b2012-09-27 16:03:43 -0700170void BaseMutex::RegisterAsLocked(Thread* self) {
171 if (UNLIKELY(self == NULL)) {
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700172 CheckUnattachedThread(level_);
173 return;
174 }
Ian Rogers25fd14b2012-09-05 10:56:38 -0700175 if (kDebugLocking) {
176 // Check if a bad Mutex of this level or lower is held.
177 bool bad_mutexes_held = false;
178 for (int i = level_; i >= 0; --i) {
Ian Rogers81d425b2012-09-27 16:03:43 -0700179 BaseMutex* held_mutex = self->GetHeldMutex(static_cast<LockLevel>(i));
Ian Rogers25fd14b2012-09-05 10:56:38 -0700180 if (UNLIKELY(held_mutex != NULL)) {
181 LOG(ERROR) << "Lock level violation: holding \"" << held_mutex->name_ << "\" (level " << i
182 << ") while locking \"" << name_ << "\" (level " << static_cast<int>(level_) << ")";
183 if (i > kAbortLock) {
184 // Only abort in the check below if this is more than abort level lock.
185 bad_mutexes_held = true;
186 }
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700187 }
188 }
Ian Rogers25fd14b2012-09-05 10:56:38 -0700189 CHECK(!bad_mutexes_held);
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700190 }
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700191 // Don't record monitors as they are outside the scope of analysis. They may be inspected off of
192 // the monitor list.
193 if (level_ != kMonitorLock) {
194 self->SetHeldMutex(level_, this);
195 }
196}
197
Ian Rogers81d425b2012-09-27 16:03:43 -0700198void BaseMutex::RegisterAsUnlocked(Thread* self) {
199 if (UNLIKELY(self == NULL)) {
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700200 CheckUnattachedThread(level_);
201 return;
202 }
203 if (level_ != kMonitorLock) {
Ian Rogers25fd14b2012-09-05 10:56:38 -0700204 if (kDebugLocking) {
205 CHECK(self->GetHeldMutex(level_) == this) << "Unlocking on unacquired mutex: " << name_;
206 }
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700207 self->SetHeldMutex(level_, NULL);
208 }
209}
210
Ian Rogers81d425b2012-09-27 16:03:43 -0700211void BaseMutex::CheckSafeToWait(Thread* self) {
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700212 if (self == NULL) {
213 CheckUnattachedThread(level_);
214 return;
215 }
Ian Rogers25fd14b2012-09-05 10:56:38 -0700216 if (kDebugLocking) {
217 CHECK(self->GetHeldMutex(level_) == this) << "Waiting on unacquired mutex: " << name_;
218 bool bad_mutexes_held = false;
219 for (int i = kMaxMutexLevel; i >= 0; --i) {
220 if (i != level_) {
Ian Rogers81d425b2012-09-27 16:03:43 -0700221 BaseMutex* held_mutex = self->GetHeldMutex(static_cast<LockLevel>(i));
Ian Rogers25fd14b2012-09-05 10:56:38 -0700222 if (held_mutex != NULL) {
223 LOG(ERROR) << "Holding " << held_mutex->name_ << " (level " << i
224 << ") while performing wait on: "
225 << name_ << " (level " << static_cast<int>(level_) << ")";
226 bad_mutexes_held = true;
227 }
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700228 }
229 }
Ian Rogers25fd14b2012-09-05 10:56:38 -0700230 CHECK(!bad_mutexes_held);
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700231 }
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700232}
233
Ian Rogers81d425b2012-09-27 16:03:43 -0700234Mutex::Mutex(const char* name, LockLevel level, bool recursive)
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700235 : BaseMutex(name, level), recursive_(recursive), recursion_count_(0) {
Ian Rogersc604d732012-10-14 16:09:54 -0700236#if ART_USE_FUTEXES
237 state_ = 0;
238 exclusive_owner_ = 0;
239 num_contenders_ = 0;
240#elif defined(__BIONIC__) || defined(__APPLE__)
Brian Carlstromf3a26412012-08-24 11:06:02 -0700241 // Use recursive mutexes for bionic and Apple otherwise the
242 // non-recursive mutexes don't have TIDs to check lock ownership of.
Elliott Hughesbbd9d832011-11-07 14:40:00 -0800243 pthread_mutexattr_t attributes;
244 CHECK_MUTEX_CALL(pthread_mutexattr_init, (&attributes));
245 CHECK_MUTEX_CALL(pthread_mutexattr_settype, (&attributes, PTHREAD_MUTEX_RECURSIVE));
246 CHECK_MUTEX_CALL(pthread_mutex_init, (&mutex_, &attributes));
247 CHECK_MUTEX_CALL(pthread_mutexattr_destroy, (&attributes));
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700248#else
249 CHECK_MUTEX_CALL(pthread_mutex_init, (&mutex_, NULL));
250#endif
Elliott Hughes8daa0922011-09-11 13:46:25 -0700251}
252
253Mutex::~Mutex() {
Ian Rogersc604d732012-10-14 16:09:54 -0700254#if ART_USE_FUTEXES
255 if (state_ != 0) {
256 MutexLock mu(Thread::Current(), *Locks::runtime_shutdown_lock_);
257 Runtime* runtime = Runtime::Current();
258 bool shutting_down = (runtime == NULL) || runtime->IsShuttingDown();
259 LOG(shutting_down ? WARNING : FATAL) << "destroying mutex with owner: " << exclusive_owner_;
260 } else {
261 CHECK_EQ(exclusive_owner_, 0U) << "unexpectedly found an owner on unlocked mutex " << name_;
262 CHECK_EQ(num_contenders_, 0) << "unexpectedly found a contender on mutex " << name_;
263 }
264#else
Elliott Hughese62934d2012-04-09 11:24:29 -0700265 // We can't use CHECK_MUTEX_CALL here because on shutdown a suspended daemon thread
266 // may still be using locks.
Elliott Hughes6b355752012-01-13 16:49:08 -0800267 int rc = pthread_mutex_destroy(&mutex_);
268 if (rc != 0) {
269 errno = rc;
Elliott Hughesb3bd5f02012-03-08 21:05:27 -0800270 // TODO: should we just not log at all if shutting down? this could be the logging mutex!
Ian Rogers50b35e22012-10-04 10:09:15 -0700271 MutexLock mu(Thread::Current(), *Locks::runtime_shutdown_lock_);
Ian Rogers120f1c72012-09-28 17:17:10 -0700272 Runtime* runtime = Runtime::Current();
273 bool shutting_down = (runtime == NULL) || runtime->IsShuttingDown();
Elliott Hughes6b355752012-01-13 16:49:08 -0800274 PLOG(shutting_down ? WARNING : FATAL) << "pthread_mutex_destroy failed for " << name_;
275 }
Ian Rogersc604d732012-10-14 16:09:54 -0700276#endif
Elliott Hughes8daa0922011-09-11 13:46:25 -0700277}
278
Ian Rogers81d425b2012-09-27 16:03:43 -0700279void Mutex::ExclusiveLock(Thread* self) {
Ian Rogers01ae5802012-09-28 16:14:01 -0700280 DCHECK(self == NULL || self == Thread::Current());
Ian Rogers25fd14b2012-09-05 10:56:38 -0700281 if (kDebugLocking && !recursive_) {
Ian Rogers81d425b2012-09-27 16:03:43 -0700282 AssertNotHeld(self);
Ian Rogers25fd14b2012-09-05 10:56:38 -0700283 }
Ian Rogers81d425b2012-09-27 16:03:43 -0700284 if (!recursive_ || !IsExclusiveHeld(self)) {
Ian Rogersc604d732012-10-14 16:09:54 -0700285#if ART_USE_FUTEXES
286 bool done = false;
287 do {
288 int32_t cur_state = state_;
289 if (cur_state == 0) {
290 // Change state from 0 to 1.
291 done = android_atomic_cmpxchg(0, 1, &state_) == 0;
292 } else {
293 // Failed to acquire, hang up.
294 android_atomic_inc(&num_contenders_);
295 if (futex(&state_, FUTEX_WAIT, 1, NULL, NULL, 0) != 0) {
296 if (errno != EAGAIN) {
297 PLOG(FATAL) << "futex wait failed for " << name_;
298 }
299 }
300 android_atomic_dec(&num_contenders_);
301 }
302 } while(!done);
303 DCHECK_EQ(state_, 1);
304 exclusive_owner_ = SafeGetTid(self);
305#else
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700306 CHECK_MUTEX_CALL(pthread_mutex_lock, (&mutex_));
Ian Rogersc604d732012-10-14 16:09:54 -0700307#endif
Ian Rogers81d425b2012-09-27 16:03:43 -0700308 RegisterAsLocked(self);
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700309 }
310 recursion_count_++;
Ian Rogers25fd14b2012-09-05 10:56:38 -0700311 if (kDebugLocking) {
312 CHECK(recursion_count_ == 1 || recursive_) << "Unexpected recursion count on mutex: "
313 << name_ << " " << recursion_count_;
Ian Rogers81d425b2012-09-27 16:03:43 -0700314 AssertHeld(self);
Ian Rogers25fd14b2012-09-05 10:56:38 -0700315 }
Elliott Hughes8daa0922011-09-11 13:46:25 -0700316}
317
Ian Rogers81d425b2012-09-27 16:03:43 -0700318bool Mutex::ExclusiveTryLock(Thread* self) {
Ian Rogers01ae5802012-09-28 16:14:01 -0700319 DCHECK(self == NULL || self == Thread::Current());
Ian Rogers25fd14b2012-09-05 10:56:38 -0700320 if (kDebugLocking && !recursive_) {
Ian Rogers81d425b2012-09-27 16:03:43 -0700321 AssertNotHeld(self);
Ian Rogers25fd14b2012-09-05 10:56:38 -0700322 }
Ian Rogers81d425b2012-09-27 16:03:43 -0700323 if (!recursive_ || !IsExclusiveHeld(self)) {
Ian Rogersc604d732012-10-14 16:09:54 -0700324#if ART_USE_FUTEXES
325 bool done = false;
326 do {
327 int32_t cur_state = state_;
328 if (cur_state == 0) {
329 // Change state from 0 to 1.
330 done = android_atomic_cmpxchg(0, 1, &state_) == 0;
331 } else {
332 return false;
333 }
334 } while(!done);
335 DCHECK_EQ(state_, 1);
336 exclusive_owner_ = SafeGetTid(self);
337#else
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700338 int result = pthread_mutex_trylock(&mutex_);
339 if (result == EBUSY) {
340 return false;
341 }
342 if (result != 0) {
343 errno = result;
344 PLOG(FATAL) << "pthread_mutex_trylock failed for " << name_;
345 }
Ian Rogersc604d732012-10-14 16:09:54 -0700346#endif
Ian Rogers81d425b2012-09-27 16:03:43 -0700347 RegisterAsLocked(self);
Elliott Hughes8daa0922011-09-11 13:46:25 -0700348 }
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700349 recursion_count_++;
Ian Rogers25fd14b2012-09-05 10:56:38 -0700350 if (kDebugLocking) {
351 CHECK(recursion_count_ == 1 || recursive_) << "Unexpected recursion count on mutex: "
352 << name_ << " " << recursion_count_;
Ian Rogers81d425b2012-09-27 16:03:43 -0700353 AssertHeld(self);
Ian Rogers25fd14b2012-09-05 10:56:38 -0700354 }
Elliott Hughes8daa0922011-09-11 13:46:25 -0700355 return true;
356}
357
Ian Rogers81d425b2012-09-27 16:03:43 -0700358void Mutex::ExclusiveUnlock(Thread* self) {
Ian Rogers01ae5802012-09-28 16:14:01 -0700359 DCHECK(self == NULL || self == Thread::Current());
Ian Rogers81d425b2012-09-27 16:03:43 -0700360 AssertHeld(self);
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700361 recursion_count_--;
362 if (!recursive_ || recursion_count_ == 0) {
Ian Rogers25fd14b2012-09-05 10:56:38 -0700363 if (kDebugLocking) {
364 CHECK(recursion_count_ == 0 || recursive_) << "Unexpected recursion count on mutex: "
365 << name_ << " " << recursion_count_;
366 }
Ian Rogers81d425b2012-09-27 16:03:43 -0700367 RegisterAsUnlocked(self);
Ian Rogersc604d732012-10-14 16:09:54 -0700368#if ART_USE_FUTEXES
369 bool done = false;
370 do {
371 int32_t cur_state = state_;
372 if (cur_state == 1) {
373 // We're no longer the owner.
374 exclusive_owner_ = 0;
375 // Change state to 0.
376 done = android_atomic_cmpxchg(cur_state, 0, &state_) == 0;
377 if (done) { // Spurious fail?
378 // Wake a contender
379 if (num_contenders_ > 0) {
380 futex(&state_, FUTEX_WAKE, 1, NULL, NULL, 0);
381 }
382 }
383 } else {
384 LOG(FATAL) << "Unexpected state_:" << cur_state << " for " << name_;
385 }
386 } while(!done);
387#else
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700388 CHECK_MUTEX_CALL(pthread_mutex_unlock, (&mutex_));
Ian Rogersc604d732012-10-14 16:09:54 -0700389#endif
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700390 }
Elliott Hughes8daa0922011-09-11 13:46:25 -0700391}
392
Ian Rogers81d425b2012-09-27 16:03:43 -0700393bool Mutex::IsExclusiveHeld(const Thread* self) const {
Ian Rogers01ae5802012-09-28 16:14:01 -0700394 DCHECK(self == NULL || self == Thread::Current());
395 bool result = (GetExclusiveOwnerTid() == SafeGetTid(self));
396 if (kDebugLocking) {
397 // Sanity debug check that if we think it is locked we have it in our held mutexes.
398 if (result && self != NULL && level_ != kMonitorLock) {
399 CHECK_EQ(self->GetHeldMutex(level_), this);
Ian Rogers25fd14b2012-09-05 10:56:38 -0700400 }
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700401 }
402 return result;
Elliott Hughesf1498432012-03-28 19:34:27 -0700403}
404
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700405uint64_t Mutex::GetExclusiveOwnerTid() const {
Ian Rogersc604d732012-10-14 16:09:54 -0700406#if ART_USE_FUTEXES
407 return exclusive_owner_;
408#elif defined(__BIONIC__)
Elliott Hughesf1498432012-03-28 19:34:27 -0700409 return static_cast<uint64_t>((mutex_.value >> 16) & 0xffff);
Elliott Hughes3147a232011-10-12 15:55:07 -0700410#elif defined(__GLIBC__)
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700411 return reinterpret_cast<const glibc_pthread_mutex_t*>(&mutex_)->owner;
Elliott Hughescf044312012-01-23 18:48:51 -0800412#elif defined(__APPLE__)
Brian Carlstromf3a26412012-08-24 11:06:02 -0700413 const darwin_pthread_mutex_t* dpmutex = reinterpret_cast<const darwin_pthread_mutex_t*>(&mutex_);
414 pthread_t owner = dpmutex->darwin_pthread_mutex_owner;
Brian Carlstrombd93c302012-08-27 16:58:28 -0700415 // 0 for unowned, -1 for PTHREAD_MTX_TID_SWITCHING
416 // TODO: should we make darwin_pthread_mutex_owner volatile and recheck until not -1?
Brian Carlstromf3a26412012-08-24 11:06:02 -0700417 if ((owner == (pthread_t)0) || (owner == (pthread_t)-1)) {
418 return 0;
419 }
420 uint64_t tid;
421 CHECK_PTHREAD_CALL(pthread_threadid_np, (owner, &tid), __FUNCTION__); // Requires Mac OS 10.6
422 return tid;
Elliott Hughes8daa0922011-09-11 13:46:25 -0700423#else
Elliott Hughesf1498432012-03-28 19:34:27 -0700424#error unsupported C library
Elliott Hughes8daa0922011-09-11 13:46:25 -0700425#endif
426}
427
Ian Rogers01ae5802012-09-28 16:14:01 -0700428std::string Mutex::Dump() const {
429 return StringPrintf("%s %s level=%d count=%d owner=%llx",
430 recursive_ ? "recursive" : "non-recursive",
431 name_.c_str(),
432 static_cast<int>(level_),
433 recursion_count_,
434 GetExclusiveOwnerTid());
435}
436
437std::ostream& operator<<(std::ostream& os, const Mutex& mu) {
438 return os << mu.Dump();
439}
440
Ian Rogers81d425b2012-09-27 16:03:43 -0700441ReaderWriterMutex::ReaderWriterMutex(const char* name, LockLevel level) :
442 BaseMutex(name, level)
443#if ART_USE_FUTEXES
444 , state_(0), exclusive_owner_(0), num_pending_readers_(0), num_pending_writers_(0)
445#endif
446{
447#if !ART_USE_FUTEXES
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700448 CHECK_MUTEX_CALL(pthread_rwlock_init, (&rwlock_, NULL));
Ian Rogers81d425b2012-09-27 16:03:43 -0700449#endif
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700450}
451
452ReaderWriterMutex::~ReaderWriterMutex() {
Ian Rogers81d425b2012-09-27 16:03:43 -0700453#if ART_USE_FUTEXES
454 CHECK_EQ(state_, 0);
455 CHECK_EQ(exclusive_owner_, 0U);
456 CHECK_EQ(num_pending_readers_, 0);
457 CHECK_EQ(num_pending_writers_, 0);
458#else
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700459 // We can't use CHECK_MUTEX_CALL here because on shutdown a suspended daemon thread
460 // may still be using locks.
461 int rc = pthread_rwlock_destroy(&rwlock_);
462 if (rc != 0) {
463 errno = rc;
464 // TODO: should we just not log at all if shutting down? this could be the logging mutex!
Ian Rogers50b35e22012-10-04 10:09:15 -0700465 MutexLock mu(Thread::Current(), *Locks::runtime_shutdown_lock_);
Ian Rogers120f1c72012-09-28 17:17:10 -0700466 Runtime* runtime = Runtime::Current();
467 bool shutting_down = runtime == NULL || runtime->IsShuttingDown();
468 PLOG(shutting_down ? WARNING : FATAL) << "pthread_rwlock_destroy failed for " << name_;
Brian Carlstromcd74c4b2012-01-23 13:21:00 -0800469 }
Ian Rogers81d425b2012-09-27 16:03:43 -0700470#endif
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700471}
472
Ian Rogers81d425b2012-09-27 16:03:43 -0700473void ReaderWriterMutex::ExclusiveLock(Thread* self) {
Ian Rogers01ae5802012-09-28 16:14:01 -0700474 DCHECK(self == NULL || self == Thread::Current());
Ian Rogers81d425b2012-09-27 16:03:43 -0700475 AssertNotExclusiveHeld(self);
476#if ART_USE_FUTEXES
477 bool done = false;
478 do {
479 int32_t cur_state = state_;
480 if (cur_state == 0) {
481 // Change state from 0 to -1.
482 done = android_atomic_cmpxchg(0, -1, &state_) == 0;
483 } else {
484 // Failed to acquire, hang up.
485 android_atomic_inc(&num_pending_writers_);
486 if (futex(&state_, FUTEX_WAIT, cur_state, NULL, NULL, 0) != 0) {
487 if (errno != EAGAIN) {
488 PLOG(FATAL) << "futex wait failed for " << name_;
489 }
490 }
491 android_atomic_dec(&num_pending_writers_);
492 }
493 } while(!done);
Ian Rogersab470162012-09-29 23:06:53 -0700494 DCHECK_EQ(state_, -1);
495 exclusive_owner_ = SafeGetTid(self);
Ian Rogers81d425b2012-09-27 16:03:43 -0700496#else
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700497 CHECK_MUTEX_CALL(pthread_rwlock_wrlock, (&rwlock_));
Ian Rogers81d425b2012-09-27 16:03:43 -0700498#endif
499 RegisterAsLocked(self);
500 AssertExclusiveHeld(self);
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700501}
502
Ian Rogers81d425b2012-09-27 16:03:43 -0700503void ReaderWriterMutex::ExclusiveUnlock(Thread* self) {
Ian Rogers01ae5802012-09-28 16:14:01 -0700504 DCHECK(self == NULL || self == Thread::Current());
Ian Rogers81d425b2012-09-27 16:03:43 -0700505 AssertExclusiveHeld(self);
506 RegisterAsUnlocked(self);
507#if ART_USE_FUTEXES
508 bool done = false;
509 do {
510 int32_t cur_state = state_;
511 if (cur_state == -1) {
512 // We're no longer the owner.
513 exclusive_owner_ = 0;
514 // Change state from -1 to 0.
515 done = android_atomic_cmpxchg(-1, 0, &state_) == 0;
516 if (done) { // cmpxchg may fail due to noise?
517 // Wake any waiters.
518 if (num_pending_readers_ > 0 || num_pending_writers_ > 0) {
519 futex(&state_, FUTEX_WAKE, -1, NULL, NULL, 0);
520 }
521 }
522 } else {
523 LOG(FATAL) << "Unexpected state_:" << cur_state << " for " << name_;
524 }
525 } while(!done);
526#else
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700527 CHECK_MUTEX_CALL(pthread_rwlock_unlock, (&rwlock_));
Ian Rogers81d425b2012-09-27 16:03:43 -0700528#endif
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700529}
530
Ian Rogers66aee5c2012-08-15 17:17:47 -0700531#if HAVE_TIMED_RWLOCK
Ian Rogersc604d732012-10-14 16:09:54 -0700532bool ReaderWriterMutex::ExclusiveLockWithTimeout(Thread* self, int64_t ms, int32_t ns) {
Ian Rogers01ae5802012-09-28 16:14:01 -0700533 DCHECK(self == NULL || self == Thread::Current());
Ian Rogers81d425b2012-09-27 16:03:43 -0700534#if ART_USE_FUTEXES
535 bool done = false;
Ian Rogersc604d732012-10-14 16:09:54 -0700536 timespec end_abs_ts;
537 InitTimeSpec(self, true, CLOCK_REALTIME, ms, ns, &end_abs_ts);
Ian Rogers81d425b2012-09-27 16:03:43 -0700538 do {
539 int32_t cur_state = state_;
540 if (cur_state == 0) {
541 // Change state from 0 to -1.
542 done = android_atomic_cmpxchg(0, -1, &state_) == 0;
543 } else {
544 // Failed to acquire, hang up.
Ian Rogersc604d732012-10-14 16:09:54 -0700545 timespec now_abs_ts;
546 InitTimeSpec(self, true, CLOCK_REALTIME, 0, 0, &now_abs_ts);
547 timespec rel_ts;
548 if (ComputeRelativeTimeSpec(&rel_ts, end_abs_ts, now_abs_ts)) {
549 return false; // Timed out.
550 }
Ian Rogers81d425b2012-09-27 16:03:43 -0700551 android_atomic_inc(&num_pending_writers_);
Ian Rogersc604d732012-10-14 16:09:54 -0700552 if (futex(&state_, FUTEX_WAIT, cur_state, &rel_ts, NULL, 0) != 0) {
Ian Rogers81d425b2012-09-27 16:03:43 -0700553 if (errno == ETIMEDOUT) {
554 android_atomic_dec(&num_pending_writers_);
Ian Rogersc604d732012-10-14 16:09:54 -0700555 return false; // Timed out.
556 } else if (errno != EAGAIN && errno != EINTR) {
Ian Rogers81d425b2012-09-27 16:03:43 -0700557 PLOG(FATAL) << "timed futex wait failed for " << name_;
558 }
559 }
560 android_atomic_dec(&num_pending_writers_);
561 }
562 } while(!done);
Ian Rogers01ae5802012-09-28 16:14:01 -0700563 exclusive_owner_ = SafeGetTid(self);
Ian Rogers81d425b2012-09-27 16:03:43 -0700564#else
Ian Rogersc604d732012-10-14 16:09:54 -0700565 timespec ts;
566 InitTimeSpec(self, true, CLOCK_REALTIME, ms, ns, &ts);
567 int result = pthread_rwlock_timedwrlock(&rwlock_, &ts);
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700568 if (result == ETIMEDOUT) {
569 return false;
570 }
571 if (result != 0) {
572 errno = result;
Ian Rogersa5acfd32012-08-15 11:50:10 -0700573 PLOG(FATAL) << "pthread_rwlock_timedwrlock failed for " << name_;
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700574 }
Ian Rogers81d425b2012-09-27 16:03:43 -0700575#endif
576 RegisterAsLocked(self);
577 AssertSharedHeld(self);
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700578 return true;
579}
Ian Rogers66aee5c2012-08-15 17:17:47 -0700580#endif
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700581
Ian Rogers81d425b2012-09-27 16:03:43 -0700582void ReaderWriterMutex::SharedLock(Thread* self) {
Ian Rogers01ae5802012-09-28 16:14:01 -0700583 DCHECK(self == NULL || self == Thread::Current());
Ian Rogers81d425b2012-09-27 16:03:43 -0700584#if ART_USE_FUTEXES
585 bool done = false;
586 do {
587 int32_t cur_state = state_;
588 if (cur_state >= 0) {
589 // Add as an extra reader.
590 done = android_atomic_cmpxchg(cur_state, cur_state + 1, &state_) == 0;
591 } else {
592 // Owner holds it exclusively, hang up.
593 android_atomic_inc(&num_pending_readers_);
594 if (futex(&state_, FUTEX_WAIT, cur_state, NULL, NULL, 0) != 0) {
595 if (errno != EAGAIN) {
596 PLOG(FATAL) << "futex wait failed for " << name_;
597 }
598 }
599 android_atomic_dec(&num_pending_readers_);
600 }
601 } while(!done);
602#else
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700603 CHECK_MUTEX_CALL(pthread_rwlock_rdlock, (&rwlock_));
Ian Rogers81d425b2012-09-27 16:03:43 -0700604#endif
605 RegisterAsLocked(self);
606 AssertSharedHeld(self);
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700607}
608
Ian Rogers81d425b2012-09-27 16:03:43 -0700609bool ReaderWriterMutex::SharedTryLock(Thread* self) {
Ian Rogers01ae5802012-09-28 16:14:01 -0700610 DCHECK(self == NULL || self == Thread::Current());
Ian Rogers81d425b2012-09-27 16:03:43 -0700611#if ART_USE_FUTEXES
612 bool done = false;
613 do {
614 int32_t cur_state = state_;
615 if (cur_state >= 0) {
616 // Add as an extra reader.
617 done = android_atomic_cmpxchg(cur_state, cur_state + 1, &state_) == 0;
618 } else {
619 // Owner holds it exclusively.
620 return false;
621 }
622 } while(!done);
623#else
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700624 int result = pthread_rwlock_tryrdlock(&rwlock_);
625 if (result == EBUSY) {
626 return false;
627 }
628 if (result != 0) {
629 errno = result;
630 PLOG(FATAL) << "pthread_mutex_trylock failed for " << name_;
631 }
Ian Rogers81d425b2012-09-27 16:03:43 -0700632#endif
633 RegisterAsLocked(self);
634 AssertSharedHeld(self);
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700635 return true;
636}
637
Ian Rogers81d425b2012-09-27 16:03:43 -0700638void ReaderWriterMutex::SharedUnlock(Thread* self) {
Ian Rogers01ae5802012-09-28 16:14:01 -0700639 DCHECK(self == NULL || self == Thread::Current());
Ian Rogers81d425b2012-09-27 16:03:43 -0700640 AssertSharedHeld(self);
641 RegisterAsUnlocked(self);
642#if ART_USE_FUTEXES
643 bool done = false;
644 do {
645 int32_t cur_state = state_;
646 if (LIKELY(cur_state > 0)) {
647 // Reduce state by 1.
648 done = android_atomic_cmpxchg(cur_state, cur_state - 1, &state_) == 0;
649 if (done && (cur_state - 1) == 0) { // cmpxchg may fail due to noise?
650 if (num_pending_writers_ > 0 || num_pending_readers_ > 0) {
651 // Wake any exclusive waiters as there are now no readers.
652 futex(&state_, FUTEX_WAKE, -1, NULL, NULL, 0);
653 }
654 }
655 } else {
656 LOG(FATAL) << "Unexpected state_:" << cur_state << " for " << name_;
657 }
658 } while(!done);
659#else
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700660 CHECK_MUTEX_CALL(pthread_rwlock_unlock, (&rwlock_));
Ian Rogers81d425b2012-09-27 16:03:43 -0700661#endif
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700662}
663
Ian Rogers81d425b2012-09-27 16:03:43 -0700664bool ReaderWriterMutex::IsExclusiveHeld(const Thread* self) const {
Ian Rogers01ae5802012-09-28 16:14:01 -0700665 DCHECK(self == NULL || self == Thread::Current());
666 bool result = (GetExclusiveOwnerTid() == SafeGetTid(self));
Ian Rogers25fd14b2012-09-05 10:56:38 -0700667 if (kDebugLocking) {
668 // Sanity that if the pthread thinks we own the lock the Thread agrees.
Ian Rogers01ae5802012-09-28 16:14:01 -0700669 if (self != NULL && result) {
670 CHECK_EQ(self->GetHeldMutex(level_), this);
671 }
Ian Rogers25fd14b2012-09-05 10:56:38 -0700672 }
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700673 return result;
674}
675
Ian Rogers81d425b2012-09-27 16:03:43 -0700676bool ReaderWriterMutex::IsSharedHeld(const Thread* self) const {
Ian Rogers01ae5802012-09-28 16:14:01 -0700677 DCHECK(self == NULL || self == Thread::Current());
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700678 bool result;
679 if (UNLIKELY(self == NULL)) { // Handle unattached threads.
Ian Rogers01ae5802012-09-28 16:14:01 -0700680 result = IsExclusiveHeld(self); // TODO: a better best effort here.
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700681 } else {
682 result = (self->GetHeldMutex(level_) == this);
683 }
684 return result;
685}
686
687uint64_t ReaderWriterMutex::GetExclusiveOwnerTid() const {
Ian Rogers81d425b2012-09-27 16:03:43 -0700688#if ART_USE_FUTEXES
689 return exclusive_owner_;
690#else
Brian Carlstromcd74c4b2012-01-23 13:21:00 -0800691#if defined(__BIONIC__)
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700692 return rwlock_.writerThreadId;
Brian Carlstromcd74c4b2012-01-23 13:21:00 -0800693#elif defined(__GLIBC__)
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700694 return reinterpret_cast<const glibc_pthread_rwlock_t*>(&rwlock_)->writer;
Brian Carlstromcd74c4b2012-01-23 13:21:00 -0800695#elif defined(__APPLE__)
Ian Rogers81d425b2012-09-27 16:03:43 -0700696 const darwin_pthread_rwlock_t*
697 dprwlock = reinterpret_cast<const darwin_pthread_rwlock_t*>(&rwlock_);
Brian Carlstromf3a26412012-08-24 11:06:02 -0700698 pthread_t owner = dprwlock->darwin_pthread_rwlock_owner;
699 if (owner == (pthread_t)0) {
700 return 0;
701 }
702 uint64_t tid;
703 CHECK_PTHREAD_CALL(pthread_threadid_np, (owner, &tid), __FUNCTION__); // Requires Mac OS 10.6
704 return tid;
Brian Carlstromcd74c4b2012-01-23 13:21:00 -0800705#else
Elliott Hughesf1498432012-03-28 19:34:27 -0700706#error unsupported C library
Brian Carlstromcd74c4b2012-01-23 13:21:00 -0800707#endif
Ian Rogers81d425b2012-09-27 16:03:43 -0700708#endif
Brian Carlstromcd74c4b2012-01-23 13:21:00 -0800709}
710
Ian Rogers01ae5802012-09-28 16:14:01 -0700711std::string ReaderWriterMutex::Dump() const {
712 return StringPrintf("%s level=%d owner=%llx",
713 name_.c_str(),
714 static_cast<int>(level_),
715 GetExclusiveOwnerTid());
716}
717
718std::ostream& operator<<(std::ostream& os, const ReaderWriterMutex& mu) {
719 return os << mu.Dump();
720}
721
Ian Rogersc604d732012-10-14 16:09:54 -0700722ConditionVariable::ConditionVariable(const std::string& name, Mutex& guard)
723 : name_(name), guard_(guard) {
724#if ART_USE_FUTEXES
725 state_ = 0;
726 num_waiters_ = 0;
727 num_awoken_ = 0;
728#else
Elliott Hughes5f791332011-09-15 17:45:30 -0700729 CHECK_MUTEX_CALL(pthread_cond_init, (&cond_, NULL));
Ian Rogersc604d732012-10-14 16:09:54 -0700730#endif
Elliott Hughes5f791332011-09-15 17:45:30 -0700731}
732
733ConditionVariable::~ConditionVariable() {
Ian Rogersc604d732012-10-14 16:09:54 -0700734#if !ART_USE_FUTEXES
Elliott Hughese62934d2012-04-09 11:24:29 -0700735 // We can't use CHECK_MUTEX_CALL here because on shutdown a suspended daemon thread
736 // may still be using condition variables.
737 int rc = pthread_cond_destroy(&cond_);
738 if (rc != 0) {
739 errno = rc;
Ian Rogers50b35e22012-10-04 10:09:15 -0700740 MutexLock mu(Thread::Current(), *Locks::runtime_shutdown_lock_);
Ian Rogers120f1c72012-09-28 17:17:10 -0700741 Runtime* runtime = Runtime::Current();
742 bool shutting_down = (runtime == NULL) || runtime->IsShuttingDown();
Elliott Hughese62934d2012-04-09 11:24:29 -0700743 PLOG(shutting_down ? WARNING : FATAL) << "pthread_cond_destroy failed for " << name_;
744 }
Ian Rogersc604d732012-10-14 16:09:54 -0700745#endif
Elliott Hughes5f791332011-09-15 17:45:30 -0700746}
747
Ian Rogersc604d732012-10-14 16:09:54 -0700748void ConditionVariable::Broadcast(Thread* self) {
749 DCHECK(self == NULL || self == Thread::Current());
750 // TODO: enable below, there's a race in thread creation that causes false failures currently.
751 // guard_.AssertExclusiveHeld(self);
Mathieu Chartiere46cd752012-10-31 16:56:18 -0700752 DCHECK_EQ(guard_.GetExclusiveOwnerTid(), SafeGetTid(self));
Ian Rogersc604d732012-10-14 16:09:54 -0700753#if ART_USE_FUTEXES
754 if (num_waiters_ > 0) {
755 android_atomic_inc(&state_); // Indicate a wake has occurred to waiters coming in.
756 bool done = false;
757 do {
758 int32_t cur_state = state_;
759 // Compute number of waiters requeued and add to mutex contenders.
760 int32_t num_requeued = num_waiters_ - num_awoken_;
761 android_atomic_add(num_requeued, &guard_.num_contenders_);
762 // Requeue waiters onto contenders.
763 done = futex(&state_, FUTEX_CMP_REQUEUE, 0,
764 reinterpret_cast<const timespec*>(std::numeric_limits<int32_t>::max()),
765 &guard_.state_, cur_state) != -1;
766 if (!done) {
767 if (errno != EAGAIN) {
768 PLOG(FATAL) << "futex cmp requeue failed for " << name_;
769 }
770 } else {
771 num_awoken_ = num_waiters_;
772 }
773 } while (!done);
774 }
775#else
Elliott Hughes5f791332011-09-15 17:45:30 -0700776 CHECK_MUTEX_CALL(pthread_cond_broadcast, (&cond_));
Ian Rogersc604d732012-10-14 16:09:54 -0700777#endif
Elliott Hughes5f791332011-09-15 17:45:30 -0700778}
779
Ian Rogersc604d732012-10-14 16:09:54 -0700780void ConditionVariable::Signal(Thread* self) {
781 DCHECK(self == NULL || self == Thread::Current());
782 guard_.AssertExclusiveHeld(self);
783#if ART_USE_FUTEXES
784 if (num_waiters_ > 0) {
785 android_atomic_inc(&state_); // Indicate a wake has occurred to waiters coming in.
786 // Futex wake 1 waiter who will then come and in contend on mutex. It'd be nice to requeue them
787 // to avoid this, however, requeueing can only move all waiters.
788 if (futex(&state_, FUTEX_WAKE, 1, NULL, NULL, 0) == 1) {
789 // Wake success.
790 // We weren't requeued, however, to make accounting simpler in the Wait code, increment the
791 // number of contenders on the mutex.
792 num_awoken_++;
793 android_atomic_inc(&guard_.num_contenders_);
794 }
795 }
796#else
Elliott Hughes5f791332011-09-15 17:45:30 -0700797 CHECK_MUTEX_CALL(pthread_cond_signal, (&cond_));
Ian Rogersc604d732012-10-14 16:09:54 -0700798#endif
Elliott Hughes5f791332011-09-15 17:45:30 -0700799}
800
Ian Rogersc604d732012-10-14 16:09:54 -0700801void ConditionVariable::Wait(Thread* self) {
802 DCHECK(self == NULL || self == Thread::Current());
803 guard_.AssertExclusiveHeld(self);
804 guard_.CheckSafeToWait(self);
805 unsigned int old_recursion_count = guard_.recursion_count_;
806#if ART_USE_FUTEXES
807 int32_t cur_state = state_;
808 num_waiters_++;
809 guard_.recursion_count_ = 1;
810 guard_.ExclusiveUnlock(self);
811 bool woken = true;
812 while (futex(&state_, FUTEX_WAIT, cur_state, NULL, NULL, 0) != 0) {
813 if (errno == EINTR || errno == EAGAIN) {
814 if (state_ != cur_state) {
815 // We failed and a signal has come in.
816 woken = false;
817 break;
818 }
819 } else {
820 PLOG(FATAL) << "futex wait failed for " << name_;
821 }
822 }
823 guard_.ExclusiveLock(self);
824 num_waiters_--;
825 if (woken) {
826 // If we were woken we were requeued on the mutex, decrement the mutex's contender count.
827 android_atomic_dec(&guard_.num_contenders_);
828 num_awoken_--;
829 }
830#else
831 guard_.recursion_count_ = 0;
832 CHECK_MUTEX_CALL(pthread_cond_wait, (&cond_, &guard_.mutex_));
833#endif
834 guard_.recursion_count_ = old_recursion_count;
Elliott Hughes5f791332011-09-15 17:45:30 -0700835}
836
Ian Rogersc604d732012-10-14 16:09:54 -0700837void ConditionVariable::TimedWait(Thread* self, int64_t ms, int32_t ns) {
838 DCHECK(self == NULL || self == Thread::Current());
839 guard_.AssertExclusiveHeld(self);
840 guard_.CheckSafeToWait(self);
841 unsigned int old_recursion_count = guard_.recursion_count_;
842#if ART_USE_FUTEXES
843 // Record the original end time so that if the futex call fails we can recompute the appropriate
844 // relative time.
845 timespec end_abs_ts;
846 InitTimeSpec(self, true, CLOCK_REALTIME, ms, ns, &end_abs_ts);
847 timespec rel_ts;
848 InitTimeSpec(self, false, CLOCK_REALTIME, ms, ns, &rel_ts);
849 // Read state so that we can know if a signal comes in during before we sleep.
850 int32_t cur_state = state_;
851 num_waiters_++;
852 guard_.recursion_count_ = 1;
853 guard_.ExclusiveUnlock(self);
854 bool woken = true; // Did the futex wait end because we were awoken?
855 while (futex(&state_, FUTEX_WAIT, cur_state, &rel_ts, NULL, 0) != 0) {
856 if (errno == ETIMEDOUT) {
857 woken = false;
858 break;
859 }
860 if ((errno == EINTR) || (errno == EAGAIN)) {
861 if (state_ != cur_state) {
862 // We failed and a signal has come in.
863 woken = false;
864 break;
865 }
866 timespec now_abs_ts;
867 InitTimeSpec(self, true, CLOCK_REALTIME, 0, 0, &now_abs_ts);
868 if (ComputeRelativeTimeSpec(&rel_ts, end_abs_ts, now_abs_ts)) {
869 // futex failed and we timed out in the meantime.
870 woken = false;
871 break;
872 }
873 } else {
874 PLOG(FATAL) << "timed futex wait failed for " << name_;
875 }
876 }
877 guard_.ExclusiveLock(self);
878 num_waiters_--;
879 if (woken) {
880 // If we were woken we were requeued on the mutex, decrement the mutex's contender count.
881 android_atomic_dec(&guard_.num_contenders_);
882 num_awoken_--;
883 }
884#else
Elliott Hughes5f791332011-09-15 17:45:30 -0700885#ifdef HAVE_TIMEDWAIT_MONOTONIC
886#define TIMEDWAIT pthread_cond_timedwait_monotonic
Ian Rogersc604d732012-10-14 16:09:54 -0700887 int clock = CLOCK_MONOTONIC;
Elliott Hughes5f791332011-09-15 17:45:30 -0700888#else
889#define TIMEDWAIT pthread_cond_timedwait
Ian Rogersc604d732012-10-14 16:09:54 -0700890 int clock = CLOCK_REALTIME;
Elliott Hughes5f791332011-09-15 17:45:30 -0700891#endif
Ian Rogersc604d732012-10-14 16:09:54 -0700892 guard_.recursion_count_ = 0;
893 timespec ts;
894 InitTimeSpec(self, true, clock, ms, ns, &ts);
895 int rc = TIMEDWAIT(&cond_, &guard_.mutex_, &ts);
Elliott Hughes5f791332011-09-15 17:45:30 -0700896 if (rc != 0 && rc != ETIMEDOUT) {
897 errno = rc;
898 PLOG(FATAL) << "TimedWait failed for " << name_;
899 }
Ian Rogersc604d732012-10-14 16:09:54 -0700900#endif
901 guard_.recursion_count_ = old_recursion_count;
Elliott Hughes5f791332011-09-15 17:45:30 -0700902}
903
Elliott Hughese62934d2012-04-09 11:24:29 -0700904} // namespace art