blob: 18dc863914a7e115d022dfe46f1b8150e0363db4 [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
32#endif
33
Elliott Hughes8d768a92011-09-14 16:35:25 -070034#define CHECK_MUTEX_CALL(call, args) CHECK_PTHREAD_CALL(call, args, name_)
35
Elliott Hughesf8349362012-06-18 15:00:06 -070036extern int pthread_mutex_lock(pthread_mutex_t* mutex) EXCLUSIVE_LOCK_FUNCTION(mutex);
37extern int pthread_mutex_unlock(pthread_mutex_t* mutex) UNLOCK_FUNCTION(1);
38extern int pthread_mutex_trylock(pthread_mutex_t* mutex) EXCLUSIVE_TRYLOCK_FUNCTION(0, mutex);
39
Ian Rogers81d425b2012-09-27 16:03:43 -070040#if ART_USE_FUTEXES
Ian Rogersacc46d62012-09-27 21:39:40 -070041#include "linux/futex.h"
Ian Rogers81d425b2012-09-27 16:03:43 -070042#include "sys/syscall.h"
43#ifndef SYS_futex
44#define SYS_futex __NR_futex
45#endif
Ian Rogersc604d732012-10-14 16:09:54 -070046int futex(volatile int *uaddr, int op, int val, const struct timespec *timeout, volatile int *uaddr2, int val3) {
47 return syscall(SYS_futex, uaddr, op, val, timeout, uaddr2, val3);
Ian Rogers81d425b2012-09-27 16:03:43 -070048}
49#endif // ART_USE_FUTEXES
50
Elliott Hughes8daa0922011-09-11 13:46:25 -070051namespace art {
52
Brian Carlstromf3a26412012-08-24 11:06:02 -070053// This works on Mac OS 10.6 but hasn't been tested on older releases.
Elliott Hughesf1498432012-03-28 19:34:27 -070054struct __attribute__((__may_alias__)) darwin_pthread_mutex_t {
Brian Carlstromf3a26412012-08-24 11:06:02 -070055 long padding0;
56 int padding1;
57 uint32_t padding2;
58 int16_t padding3;
59 int16_t padding4;
60 uint32_t padding5;
61 pthread_t darwin_pthread_mutex_owner;
Ian Rogers00f7d0e2012-07-19 15:28:27 -070062 // ...other stuff we don't care about.
63};
64
65struct __attribute__((__may_alias__)) darwin_pthread_rwlock_t {
Brian Carlstromf3a26412012-08-24 11:06:02 -070066 long padding0;
67 pthread_mutex_t padding1;
68 int padding2;
69 pthread_cond_t padding3;
70 pthread_cond_t padding4;
71 int padding5;
72 int padding6;
73 pthread_t darwin_pthread_rwlock_owner;
Elliott Hughesf1498432012-03-28 19:34:27 -070074 // ...other stuff we don't care about.
75};
76
77struct __attribute__((__may_alias__)) glibc_pthread_mutex_t {
Ian Rogers00f7d0e2012-07-19 15:28:27 -070078 int32_t padding0[2];
Elliott Hughesf1498432012-03-28 19:34:27 -070079 int owner;
80 // ...other stuff we don't care about.
81};
82
Ian Rogers00f7d0e2012-07-19 15:28:27 -070083struct __attribute__((__may_alias__)) glibc_pthread_rwlock_t {
84#ifdef __LP64__
85 int32_t padding0[6];
86#else
87 int32_t padding0[7];
88#endif
89 int writer;
90 // ...other stuff we don't care about.
91};
92
Ian Rogers01ae5802012-09-28 16:14:01 -070093static uint64_t SafeGetTid(const Thread* self) {
94 if (self != NULL) {
95 return static_cast<uint64_t>(self->GetTid());
96 } else {
97 return static_cast<uint64_t>(GetTid());
98 }
99}
100
Ian Rogersc604d732012-10-14 16:09:54 -0700101// Initialize a timespec to either an absolute or relative time.
102static void InitTimeSpec(Thread* self, bool absolute, int clock, int64_t ms, int32_t ns,
103 timespec* ts) {
104 int64_t endSec;
105
106 if (absolute) {
107 clock_gettime(clock, ts);
108 } else {
109 ts->tv_sec = 0;
110 ts->tv_nsec = 0;
111 }
112 endSec = ts->tv_sec + ms / 1000;
113 if (UNLIKELY(endSec >= 0x7fffffff)) {
114 std::ostringstream ss;
115 ScopedObjectAccess soa(self);
116 self->Dump(ss);
117 LOG(INFO) << "Note: end time exceeds epoch: " << ss.str();
118 endSec = 0x7ffffffe;
119 }
120 ts->tv_sec = endSec;
121 ts->tv_nsec = (ts->tv_nsec + (ms % 1000) * 1000000) + ns;
122
123 // Catch rollover.
124 if (ts->tv_nsec >= 1000000000L) {
125 ts->tv_sec++;
126 ts->tv_nsec -= 1000000000L;
127 }
128}
129
130#if ART_USE_FUTEXES
131static bool ComputeRelativeTimeSpec(timespec* result_ts, const timespec& lhs, const timespec& rhs) {
132 const long int one_sec = 1000 * 1000 * 1000; // one second in nanoseconds.
133 result_ts->tv_sec = lhs.tv_sec - rhs.tv_sec;
134 result_ts->tv_nsec = lhs.tv_nsec - rhs.tv_nsec;
135 if (result_ts->tv_nsec < 0) {
136 result_ts->tv_sec--;
137 result_ts->tv_nsec += one_sec;
138 } else if (result_ts->tv_nsec > one_sec) {
139 result_ts->tv_sec++;
140 result_ts->tv_nsec -= one_sec;
141 }
142 return result_ts->tv_sec < 0;
143}
144#endif
145
Ian Rogers81d425b2012-09-27 16:03:43 -0700146BaseMutex::BaseMutex(const char* name, LockLevel level) : level_(level), name_(name) {}
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700147
Ian Rogers120f1c72012-09-28 17:17:10 -0700148static void CheckUnattachedThread(LockLevel level) NO_THREAD_SAFETY_ANALYSIS {
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700149 // The check below enumerates the cases where we expect not to be able to sanity check locks
Ian Rogers120f1c72012-09-28 17:17:10 -0700150 // on a thread. Lock checking is disabled to avoid deadlock when checking shutdown lock.
151 // TODO: tighten this check.
Ian Rogers25fd14b2012-09-05 10:56:38 -0700152 if (kDebugLocking) {
153 Runtime* runtime = Runtime::Current();
154 CHECK(runtime == NULL || !runtime->IsStarted() || runtime->IsShuttingDown() ||
Ian Rogers120f1c72012-09-28 17:17:10 -0700155 level == kDefaultMutexLevel || level == kRuntimeShutdownLock ||
156 level == kThreadListLock || level == kLoggingLock || level == kAbortLock);
Ian Rogers25fd14b2012-09-05 10:56:38 -0700157 }
Elliott Hughesffb465f2012-03-01 18:46:05 -0800158}
159
Ian Rogers81d425b2012-09-27 16:03:43 -0700160void BaseMutex::RegisterAsLocked(Thread* self) {
161 if (UNLIKELY(self == NULL)) {
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700162 CheckUnattachedThread(level_);
163 return;
164 }
Ian Rogers25fd14b2012-09-05 10:56:38 -0700165 if (kDebugLocking) {
166 // Check if a bad Mutex of this level or lower is held.
167 bool bad_mutexes_held = false;
168 for (int i = level_; i >= 0; --i) {
Ian Rogers81d425b2012-09-27 16:03:43 -0700169 BaseMutex* held_mutex = self->GetHeldMutex(static_cast<LockLevel>(i));
Ian Rogers25fd14b2012-09-05 10:56:38 -0700170 if (UNLIKELY(held_mutex != NULL)) {
171 LOG(ERROR) << "Lock level violation: holding \"" << held_mutex->name_ << "\" (level " << i
172 << ") while locking \"" << name_ << "\" (level " << static_cast<int>(level_) << ")";
173 if (i > kAbortLock) {
174 // Only abort in the check below if this is more than abort level lock.
175 bad_mutexes_held = true;
176 }
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700177 }
178 }
Ian Rogers25fd14b2012-09-05 10:56:38 -0700179 CHECK(!bad_mutexes_held);
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700180 }
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700181 // Don't record monitors as they are outside the scope of analysis. They may be inspected off of
182 // the monitor list.
183 if (level_ != kMonitorLock) {
184 self->SetHeldMutex(level_, this);
185 }
186}
187
Ian Rogers81d425b2012-09-27 16:03:43 -0700188void BaseMutex::RegisterAsUnlocked(Thread* self) {
189 if (UNLIKELY(self == NULL)) {
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700190 CheckUnattachedThread(level_);
191 return;
192 }
193 if (level_ != kMonitorLock) {
Ian Rogers25fd14b2012-09-05 10:56:38 -0700194 if (kDebugLocking) {
195 CHECK(self->GetHeldMutex(level_) == this) << "Unlocking on unacquired mutex: " << name_;
196 }
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700197 self->SetHeldMutex(level_, NULL);
198 }
199}
200
Ian Rogers81d425b2012-09-27 16:03:43 -0700201void BaseMutex::CheckSafeToWait(Thread* self) {
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700202 if (self == NULL) {
203 CheckUnattachedThread(level_);
204 return;
205 }
Ian Rogers25fd14b2012-09-05 10:56:38 -0700206 if (kDebugLocking) {
207 CHECK(self->GetHeldMutex(level_) == this) << "Waiting on unacquired mutex: " << name_;
208 bool bad_mutexes_held = false;
209 for (int i = kMaxMutexLevel; i >= 0; --i) {
210 if (i != level_) {
Ian Rogers81d425b2012-09-27 16:03:43 -0700211 BaseMutex* held_mutex = self->GetHeldMutex(static_cast<LockLevel>(i));
Ian Rogers25fd14b2012-09-05 10:56:38 -0700212 if (held_mutex != NULL) {
213 LOG(ERROR) << "Holding " << held_mutex->name_ << " (level " << i
214 << ") while performing wait on: "
215 << name_ << " (level " << static_cast<int>(level_) << ")";
216 bad_mutexes_held = true;
217 }
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700218 }
219 }
Ian Rogers25fd14b2012-09-05 10:56:38 -0700220 CHECK(!bad_mutexes_held);
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700221 }
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700222}
223
Ian Rogers81d425b2012-09-27 16:03:43 -0700224Mutex::Mutex(const char* name, LockLevel level, bool recursive)
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700225 : BaseMutex(name, level), recursive_(recursive), recursion_count_(0) {
Ian Rogersc604d732012-10-14 16:09:54 -0700226#if ART_USE_FUTEXES
227 state_ = 0;
228 exclusive_owner_ = 0;
229 num_contenders_ = 0;
230#elif defined(__BIONIC__) || defined(__APPLE__)
Brian Carlstromf3a26412012-08-24 11:06:02 -0700231 // Use recursive mutexes for bionic and Apple otherwise the
232 // non-recursive mutexes don't have TIDs to check lock ownership of.
Elliott Hughesbbd9d832011-11-07 14:40:00 -0800233 pthread_mutexattr_t attributes;
234 CHECK_MUTEX_CALL(pthread_mutexattr_init, (&attributes));
235 CHECK_MUTEX_CALL(pthread_mutexattr_settype, (&attributes, PTHREAD_MUTEX_RECURSIVE));
236 CHECK_MUTEX_CALL(pthread_mutex_init, (&mutex_, &attributes));
237 CHECK_MUTEX_CALL(pthread_mutexattr_destroy, (&attributes));
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700238#else
239 CHECK_MUTEX_CALL(pthread_mutex_init, (&mutex_, NULL));
240#endif
Elliott Hughes8daa0922011-09-11 13:46:25 -0700241}
242
243Mutex::~Mutex() {
Ian Rogersc604d732012-10-14 16:09:54 -0700244#if ART_USE_FUTEXES
245 if (state_ != 0) {
246 MutexLock mu(Thread::Current(), *Locks::runtime_shutdown_lock_);
247 Runtime* runtime = Runtime::Current();
248 bool shutting_down = (runtime == NULL) || runtime->IsShuttingDown();
249 LOG(shutting_down ? WARNING : FATAL) << "destroying mutex with owner: " << exclusive_owner_;
250 } else {
251 CHECK_EQ(exclusive_owner_, 0U) << "unexpectedly found an owner on unlocked mutex " << name_;
252 CHECK_EQ(num_contenders_, 0) << "unexpectedly found a contender on mutex " << name_;
253 }
254#else
Elliott Hughese62934d2012-04-09 11:24:29 -0700255 // We can't use CHECK_MUTEX_CALL here because on shutdown a suspended daemon thread
256 // may still be using locks.
Elliott Hughes6b355752012-01-13 16:49:08 -0800257 int rc = pthread_mutex_destroy(&mutex_);
258 if (rc != 0) {
259 errno = rc;
Elliott Hughesb3bd5f02012-03-08 21:05:27 -0800260 // TODO: should we just not log at all if shutting down? this could be the logging mutex!
Ian Rogers50b35e22012-10-04 10:09:15 -0700261 MutexLock mu(Thread::Current(), *Locks::runtime_shutdown_lock_);
Ian Rogers120f1c72012-09-28 17:17:10 -0700262 Runtime* runtime = Runtime::Current();
263 bool shutting_down = (runtime == NULL) || runtime->IsShuttingDown();
Elliott Hughes6b355752012-01-13 16:49:08 -0800264 PLOG(shutting_down ? WARNING : FATAL) << "pthread_mutex_destroy failed for " << name_;
265 }
Ian Rogersc604d732012-10-14 16:09:54 -0700266#endif
Elliott Hughes8daa0922011-09-11 13:46:25 -0700267}
268
Ian Rogers81d425b2012-09-27 16:03:43 -0700269void Mutex::ExclusiveLock(Thread* self) {
Ian Rogers01ae5802012-09-28 16:14:01 -0700270 DCHECK(self == NULL || self == Thread::Current());
Ian Rogers25fd14b2012-09-05 10:56:38 -0700271 if (kDebugLocking && !recursive_) {
Ian Rogers81d425b2012-09-27 16:03:43 -0700272 AssertNotHeld(self);
Ian Rogers25fd14b2012-09-05 10:56:38 -0700273 }
Ian Rogers81d425b2012-09-27 16:03:43 -0700274 if (!recursive_ || !IsExclusiveHeld(self)) {
Ian Rogersc604d732012-10-14 16:09:54 -0700275#if ART_USE_FUTEXES
276 bool done = false;
277 do {
278 int32_t cur_state = state_;
279 if (cur_state == 0) {
280 // Change state from 0 to 1.
281 done = android_atomic_cmpxchg(0, 1, &state_) == 0;
282 } else {
283 // Failed to acquire, hang up.
284 android_atomic_inc(&num_contenders_);
285 if (futex(&state_, FUTEX_WAIT, 1, NULL, NULL, 0) != 0) {
286 if (errno != EAGAIN) {
287 PLOG(FATAL) << "futex wait failed for " << name_;
288 }
289 }
290 android_atomic_dec(&num_contenders_);
291 }
292 } while(!done);
293 DCHECK_EQ(state_, 1);
294 exclusive_owner_ = SafeGetTid(self);
295#else
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700296 CHECK_MUTEX_CALL(pthread_mutex_lock, (&mutex_));
Ian Rogersc604d732012-10-14 16:09:54 -0700297#endif
Ian Rogers81d425b2012-09-27 16:03:43 -0700298 RegisterAsLocked(self);
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700299 }
300 recursion_count_++;
Ian Rogers25fd14b2012-09-05 10:56:38 -0700301 if (kDebugLocking) {
302 CHECK(recursion_count_ == 1 || recursive_) << "Unexpected recursion count on mutex: "
303 << name_ << " " << recursion_count_;
Ian Rogers81d425b2012-09-27 16:03:43 -0700304 AssertHeld(self);
Ian Rogers25fd14b2012-09-05 10:56:38 -0700305 }
Elliott Hughes8daa0922011-09-11 13:46:25 -0700306}
307
Ian Rogers81d425b2012-09-27 16:03:43 -0700308bool Mutex::ExclusiveTryLock(Thread* self) {
Ian Rogers01ae5802012-09-28 16:14:01 -0700309 DCHECK(self == NULL || self == Thread::Current());
Ian Rogers25fd14b2012-09-05 10:56:38 -0700310 if (kDebugLocking && !recursive_) {
Ian Rogers81d425b2012-09-27 16:03:43 -0700311 AssertNotHeld(self);
Ian Rogers25fd14b2012-09-05 10:56:38 -0700312 }
Ian Rogers81d425b2012-09-27 16:03:43 -0700313 if (!recursive_ || !IsExclusiveHeld(self)) {
Ian Rogersc604d732012-10-14 16:09:54 -0700314#if ART_USE_FUTEXES
315 bool done = false;
316 do {
317 int32_t cur_state = state_;
318 if (cur_state == 0) {
319 // Change state from 0 to 1.
320 done = android_atomic_cmpxchg(0, 1, &state_) == 0;
321 } else {
322 return false;
323 }
324 } while(!done);
325 DCHECK_EQ(state_, 1);
326 exclusive_owner_ = SafeGetTid(self);
327#else
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700328 int result = pthread_mutex_trylock(&mutex_);
329 if (result == EBUSY) {
330 return false;
331 }
332 if (result != 0) {
333 errno = result;
334 PLOG(FATAL) << "pthread_mutex_trylock failed for " << name_;
335 }
Ian Rogersc604d732012-10-14 16:09:54 -0700336#endif
Ian Rogers81d425b2012-09-27 16:03:43 -0700337 RegisterAsLocked(self);
Elliott Hughes8daa0922011-09-11 13:46:25 -0700338 }
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700339 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 return true;
346}
347
Ian Rogers81d425b2012-09-27 16:03:43 -0700348void Mutex::ExclusiveUnlock(Thread* self) {
Ian Rogers01ae5802012-09-28 16:14:01 -0700349 DCHECK(self == NULL || self == Thread::Current());
Ian Rogers81d425b2012-09-27 16:03:43 -0700350 AssertHeld(self);
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700351 recursion_count_--;
352 if (!recursive_ || recursion_count_ == 0) {
Ian Rogers25fd14b2012-09-05 10:56:38 -0700353 if (kDebugLocking) {
354 CHECK(recursion_count_ == 0 || recursive_) << "Unexpected recursion count on mutex: "
355 << name_ << " " << recursion_count_;
356 }
Ian Rogers81d425b2012-09-27 16:03:43 -0700357 RegisterAsUnlocked(self);
Ian Rogersc604d732012-10-14 16:09:54 -0700358#if ART_USE_FUTEXES
359 bool done = false;
360 do {
361 int32_t cur_state = state_;
362 if (cur_state == 1) {
363 // We're no longer the owner.
364 exclusive_owner_ = 0;
365 // Change state to 0.
366 done = android_atomic_cmpxchg(cur_state, 0, &state_) == 0;
367 if (done) { // Spurious fail?
368 // Wake a contender
369 if (num_contenders_ > 0) {
370 futex(&state_, FUTEX_WAKE, 1, NULL, NULL, 0);
371 }
372 }
373 } else {
374 LOG(FATAL) << "Unexpected state_:" << cur_state << " for " << name_;
375 }
376 } while(!done);
377#else
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700378 CHECK_MUTEX_CALL(pthread_mutex_unlock, (&mutex_));
Ian Rogersc604d732012-10-14 16:09:54 -0700379#endif
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700380 }
Elliott Hughes8daa0922011-09-11 13:46:25 -0700381}
382
Ian Rogers81d425b2012-09-27 16:03:43 -0700383bool Mutex::IsExclusiveHeld(const Thread* self) const {
Ian Rogers01ae5802012-09-28 16:14:01 -0700384 DCHECK(self == NULL || self == Thread::Current());
385 bool result = (GetExclusiveOwnerTid() == SafeGetTid(self));
386 if (kDebugLocking) {
387 // Sanity debug check that if we think it is locked we have it in our held mutexes.
388 if (result && self != NULL && level_ != kMonitorLock) {
389 CHECK_EQ(self->GetHeldMutex(level_), this);
Ian Rogers25fd14b2012-09-05 10:56:38 -0700390 }
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700391 }
392 return result;
Elliott Hughesf1498432012-03-28 19:34:27 -0700393}
394
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700395uint64_t Mutex::GetExclusiveOwnerTid() const {
Ian Rogersc604d732012-10-14 16:09:54 -0700396#if ART_USE_FUTEXES
397 return exclusive_owner_;
398#elif defined(__BIONIC__)
Elliott Hughesf1498432012-03-28 19:34:27 -0700399 return static_cast<uint64_t>((mutex_.value >> 16) & 0xffff);
Elliott Hughes3147a232011-10-12 15:55:07 -0700400#elif defined(__GLIBC__)
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700401 return reinterpret_cast<const glibc_pthread_mutex_t*>(&mutex_)->owner;
Elliott Hughescf044312012-01-23 18:48:51 -0800402#elif defined(__APPLE__)
Brian Carlstromf3a26412012-08-24 11:06:02 -0700403 const darwin_pthread_mutex_t* dpmutex = reinterpret_cast<const darwin_pthread_mutex_t*>(&mutex_);
404 pthread_t owner = dpmutex->darwin_pthread_mutex_owner;
Brian Carlstrombd93c302012-08-27 16:58:28 -0700405 // 0 for unowned, -1 for PTHREAD_MTX_TID_SWITCHING
406 // TODO: should we make darwin_pthread_mutex_owner volatile and recheck until not -1?
Brian Carlstromf3a26412012-08-24 11:06:02 -0700407 if ((owner == (pthread_t)0) || (owner == (pthread_t)-1)) {
408 return 0;
409 }
410 uint64_t tid;
411 CHECK_PTHREAD_CALL(pthread_threadid_np, (owner, &tid), __FUNCTION__); // Requires Mac OS 10.6
412 return tid;
Elliott Hughes8daa0922011-09-11 13:46:25 -0700413#else
Elliott Hughesf1498432012-03-28 19:34:27 -0700414#error unsupported C library
Elliott Hughes8daa0922011-09-11 13:46:25 -0700415#endif
416}
417
Ian Rogers01ae5802012-09-28 16:14:01 -0700418std::string Mutex::Dump() const {
419 return StringPrintf("%s %s level=%d count=%d owner=%llx",
420 recursive_ ? "recursive" : "non-recursive",
421 name_.c_str(),
422 static_cast<int>(level_),
423 recursion_count_,
424 GetExclusiveOwnerTid());
425}
426
427std::ostream& operator<<(std::ostream& os, const Mutex& mu) {
428 return os << mu.Dump();
429}
430
Ian Rogers81d425b2012-09-27 16:03:43 -0700431ReaderWriterMutex::ReaderWriterMutex(const char* name, LockLevel level) :
432 BaseMutex(name, level)
433#if ART_USE_FUTEXES
434 , state_(0), exclusive_owner_(0), num_pending_readers_(0), num_pending_writers_(0)
435#endif
436{
437#if !ART_USE_FUTEXES
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700438 CHECK_MUTEX_CALL(pthread_rwlock_init, (&rwlock_, NULL));
Ian Rogers81d425b2012-09-27 16:03:43 -0700439#endif
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700440}
441
442ReaderWriterMutex::~ReaderWriterMutex() {
Ian Rogers81d425b2012-09-27 16:03:43 -0700443#if ART_USE_FUTEXES
444 CHECK_EQ(state_, 0);
445 CHECK_EQ(exclusive_owner_, 0U);
446 CHECK_EQ(num_pending_readers_, 0);
447 CHECK_EQ(num_pending_writers_, 0);
448#else
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700449 // We can't use CHECK_MUTEX_CALL here because on shutdown a suspended daemon thread
450 // may still be using locks.
451 int rc = pthread_rwlock_destroy(&rwlock_);
452 if (rc != 0) {
453 errno = rc;
454 // TODO: should we just not log at all if shutting down? this could be the logging mutex!
Ian Rogers50b35e22012-10-04 10:09:15 -0700455 MutexLock mu(Thread::Current(), *Locks::runtime_shutdown_lock_);
Ian Rogers120f1c72012-09-28 17:17:10 -0700456 Runtime* runtime = Runtime::Current();
457 bool shutting_down = runtime == NULL || runtime->IsShuttingDown();
458 PLOG(shutting_down ? WARNING : FATAL) << "pthread_rwlock_destroy failed for " << name_;
Brian Carlstromcd74c4b2012-01-23 13:21:00 -0800459 }
Ian Rogers81d425b2012-09-27 16:03:43 -0700460#endif
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700461}
462
Ian Rogers81d425b2012-09-27 16:03:43 -0700463void ReaderWriterMutex::ExclusiveLock(Thread* self) {
Ian Rogers01ae5802012-09-28 16:14:01 -0700464 DCHECK(self == NULL || self == Thread::Current());
Ian Rogers81d425b2012-09-27 16:03:43 -0700465 AssertNotExclusiveHeld(self);
466#if ART_USE_FUTEXES
467 bool done = false;
468 do {
469 int32_t cur_state = state_;
470 if (cur_state == 0) {
471 // Change state from 0 to -1.
472 done = android_atomic_cmpxchg(0, -1, &state_) == 0;
473 } else {
474 // Failed to acquire, hang up.
475 android_atomic_inc(&num_pending_writers_);
476 if (futex(&state_, FUTEX_WAIT, cur_state, NULL, NULL, 0) != 0) {
477 if (errno != EAGAIN) {
478 PLOG(FATAL) << "futex wait failed for " << name_;
479 }
480 }
481 android_atomic_dec(&num_pending_writers_);
482 }
483 } while(!done);
Ian Rogersab470162012-09-29 23:06:53 -0700484 DCHECK_EQ(state_, -1);
485 exclusive_owner_ = SafeGetTid(self);
Ian Rogers81d425b2012-09-27 16:03:43 -0700486#else
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700487 CHECK_MUTEX_CALL(pthread_rwlock_wrlock, (&rwlock_));
Ian Rogers81d425b2012-09-27 16:03:43 -0700488#endif
489 RegisterAsLocked(self);
490 AssertExclusiveHeld(self);
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700491}
492
Ian Rogers81d425b2012-09-27 16:03:43 -0700493void ReaderWriterMutex::ExclusiveUnlock(Thread* self) {
Ian Rogers01ae5802012-09-28 16:14:01 -0700494 DCHECK(self == NULL || self == Thread::Current());
Ian Rogers81d425b2012-09-27 16:03:43 -0700495 AssertExclusiveHeld(self);
496 RegisterAsUnlocked(self);
497#if ART_USE_FUTEXES
498 bool done = false;
499 do {
500 int32_t cur_state = state_;
501 if (cur_state == -1) {
502 // We're no longer the owner.
503 exclusive_owner_ = 0;
504 // Change state from -1 to 0.
505 done = android_atomic_cmpxchg(-1, 0, &state_) == 0;
506 if (done) { // cmpxchg may fail due to noise?
507 // Wake any waiters.
508 if (num_pending_readers_ > 0 || num_pending_writers_ > 0) {
509 futex(&state_, FUTEX_WAKE, -1, NULL, NULL, 0);
510 }
511 }
512 } else {
513 LOG(FATAL) << "Unexpected state_:" << cur_state << " for " << name_;
514 }
515 } while(!done);
516#else
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700517 CHECK_MUTEX_CALL(pthread_rwlock_unlock, (&rwlock_));
Ian Rogers81d425b2012-09-27 16:03:43 -0700518#endif
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700519}
520
Ian Rogers66aee5c2012-08-15 17:17:47 -0700521#if HAVE_TIMED_RWLOCK
Ian Rogersc604d732012-10-14 16:09:54 -0700522bool ReaderWriterMutex::ExclusiveLockWithTimeout(Thread* self, int64_t ms, int32_t ns) {
Ian Rogers01ae5802012-09-28 16:14:01 -0700523 DCHECK(self == NULL || self == Thread::Current());
Ian Rogers81d425b2012-09-27 16:03:43 -0700524#if ART_USE_FUTEXES
525 bool done = false;
Ian Rogersc604d732012-10-14 16:09:54 -0700526 timespec end_abs_ts;
527 InitTimeSpec(self, true, CLOCK_REALTIME, ms, ns, &end_abs_ts);
Ian Rogers81d425b2012-09-27 16:03:43 -0700528 do {
529 int32_t cur_state = state_;
530 if (cur_state == 0) {
531 // Change state from 0 to -1.
532 done = android_atomic_cmpxchg(0, -1, &state_) == 0;
533 } else {
534 // Failed to acquire, hang up.
Ian Rogersc604d732012-10-14 16:09:54 -0700535 timespec now_abs_ts;
536 InitTimeSpec(self, true, CLOCK_REALTIME, 0, 0, &now_abs_ts);
537 timespec rel_ts;
538 if (ComputeRelativeTimeSpec(&rel_ts, end_abs_ts, now_abs_ts)) {
539 return false; // Timed out.
540 }
Ian Rogers81d425b2012-09-27 16:03:43 -0700541 android_atomic_inc(&num_pending_writers_);
Ian Rogersc604d732012-10-14 16:09:54 -0700542 if (futex(&state_, FUTEX_WAIT, cur_state, &rel_ts, NULL, 0) != 0) {
Ian Rogers81d425b2012-09-27 16:03:43 -0700543 if (errno == ETIMEDOUT) {
544 android_atomic_dec(&num_pending_writers_);
Ian Rogersc604d732012-10-14 16:09:54 -0700545 return false; // Timed out.
546 } else if (errno != EAGAIN && errno != EINTR) {
Ian Rogers81d425b2012-09-27 16:03:43 -0700547 PLOG(FATAL) << "timed futex wait failed for " << name_;
548 }
549 }
550 android_atomic_dec(&num_pending_writers_);
551 }
552 } while(!done);
Ian Rogers01ae5802012-09-28 16:14:01 -0700553 exclusive_owner_ = SafeGetTid(self);
Ian Rogers81d425b2012-09-27 16:03:43 -0700554#else
Ian Rogersc604d732012-10-14 16:09:54 -0700555 timespec ts;
556 InitTimeSpec(self, true, CLOCK_REALTIME, ms, ns, &ts);
557 int result = pthread_rwlock_timedwrlock(&rwlock_, &ts);
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700558 if (result == ETIMEDOUT) {
559 return false;
560 }
561 if (result != 0) {
562 errno = result;
Ian Rogersa5acfd32012-08-15 11:50:10 -0700563 PLOG(FATAL) << "pthread_rwlock_timedwrlock failed for " << name_;
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700564 }
Ian Rogers81d425b2012-09-27 16:03:43 -0700565#endif
566 RegisterAsLocked(self);
567 AssertSharedHeld(self);
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700568 return true;
569}
Ian Rogers66aee5c2012-08-15 17:17:47 -0700570#endif
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700571
Ian Rogers81d425b2012-09-27 16:03:43 -0700572void ReaderWriterMutex::SharedLock(Thread* self) {
Ian Rogers01ae5802012-09-28 16:14:01 -0700573 DCHECK(self == NULL || self == Thread::Current());
Ian Rogers81d425b2012-09-27 16:03:43 -0700574#if ART_USE_FUTEXES
575 bool done = false;
576 do {
577 int32_t cur_state = state_;
578 if (cur_state >= 0) {
579 // Add as an extra reader.
580 done = android_atomic_cmpxchg(cur_state, cur_state + 1, &state_) == 0;
581 } else {
582 // Owner holds it exclusively, hang up.
583 android_atomic_inc(&num_pending_readers_);
584 if (futex(&state_, FUTEX_WAIT, cur_state, NULL, NULL, 0) != 0) {
585 if (errno != EAGAIN) {
586 PLOG(FATAL) << "futex wait failed for " << name_;
587 }
588 }
589 android_atomic_dec(&num_pending_readers_);
590 }
591 } while(!done);
592#else
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700593 CHECK_MUTEX_CALL(pthread_rwlock_rdlock, (&rwlock_));
Ian Rogers81d425b2012-09-27 16:03:43 -0700594#endif
595 RegisterAsLocked(self);
596 AssertSharedHeld(self);
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700597}
598
Ian Rogers81d425b2012-09-27 16:03:43 -0700599bool ReaderWriterMutex::SharedTryLock(Thread* self) {
Ian Rogers01ae5802012-09-28 16:14:01 -0700600 DCHECK(self == NULL || self == Thread::Current());
Ian Rogers81d425b2012-09-27 16:03:43 -0700601#if ART_USE_FUTEXES
602 bool done = false;
603 do {
604 int32_t cur_state = state_;
605 if (cur_state >= 0) {
606 // Add as an extra reader.
607 done = android_atomic_cmpxchg(cur_state, cur_state + 1, &state_) == 0;
608 } else {
609 // Owner holds it exclusively.
610 return false;
611 }
612 } while(!done);
613#else
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700614 int result = pthread_rwlock_tryrdlock(&rwlock_);
615 if (result == EBUSY) {
616 return false;
617 }
618 if (result != 0) {
619 errno = result;
620 PLOG(FATAL) << "pthread_mutex_trylock failed for " << name_;
621 }
Ian Rogers81d425b2012-09-27 16:03:43 -0700622#endif
623 RegisterAsLocked(self);
624 AssertSharedHeld(self);
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700625 return true;
626}
627
Ian Rogers81d425b2012-09-27 16:03:43 -0700628void ReaderWriterMutex::SharedUnlock(Thread* self) {
Ian Rogers01ae5802012-09-28 16:14:01 -0700629 DCHECK(self == NULL || self == Thread::Current());
Ian Rogers81d425b2012-09-27 16:03:43 -0700630 AssertSharedHeld(self);
631 RegisterAsUnlocked(self);
632#if ART_USE_FUTEXES
633 bool done = false;
634 do {
635 int32_t cur_state = state_;
636 if (LIKELY(cur_state > 0)) {
637 // Reduce state by 1.
638 done = android_atomic_cmpxchg(cur_state, cur_state - 1, &state_) == 0;
639 if (done && (cur_state - 1) == 0) { // cmpxchg may fail due to noise?
640 if (num_pending_writers_ > 0 || num_pending_readers_ > 0) {
641 // Wake any exclusive waiters as there are now no readers.
642 futex(&state_, FUTEX_WAKE, -1, NULL, NULL, 0);
643 }
644 }
645 } else {
646 LOG(FATAL) << "Unexpected state_:" << cur_state << " for " << name_;
647 }
648 } while(!done);
649#else
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700650 CHECK_MUTEX_CALL(pthread_rwlock_unlock, (&rwlock_));
Ian Rogers81d425b2012-09-27 16:03:43 -0700651#endif
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700652}
653
Ian Rogers81d425b2012-09-27 16:03:43 -0700654bool ReaderWriterMutex::IsExclusiveHeld(const Thread* self) const {
Ian Rogers01ae5802012-09-28 16:14:01 -0700655 DCHECK(self == NULL || self == Thread::Current());
656 bool result = (GetExclusiveOwnerTid() == SafeGetTid(self));
Ian Rogers25fd14b2012-09-05 10:56:38 -0700657 if (kDebugLocking) {
658 // Sanity that if the pthread thinks we own the lock the Thread agrees.
Ian Rogers01ae5802012-09-28 16:14:01 -0700659 if (self != NULL && result) {
660 CHECK_EQ(self->GetHeldMutex(level_), this);
661 }
Ian Rogers25fd14b2012-09-05 10:56:38 -0700662 }
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700663 return result;
664}
665
Ian Rogers81d425b2012-09-27 16:03:43 -0700666bool ReaderWriterMutex::IsSharedHeld(const Thread* self) const {
Ian Rogers01ae5802012-09-28 16:14:01 -0700667 DCHECK(self == NULL || self == Thread::Current());
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700668 bool result;
669 if (UNLIKELY(self == NULL)) { // Handle unattached threads.
Ian Rogers01ae5802012-09-28 16:14:01 -0700670 result = IsExclusiveHeld(self); // TODO: a better best effort here.
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700671 } else {
672 result = (self->GetHeldMutex(level_) == this);
673 }
674 return result;
675}
676
677uint64_t ReaderWriterMutex::GetExclusiveOwnerTid() const {
Ian Rogers81d425b2012-09-27 16:03:43 -0700678#if ART_USE_FUTEXES
679 return exclusive_owner_;
680#else
Brian Carlstromcd74c4b2012-01-23 13:21:00 -0800681#if defined(__BIONIC__)
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700682 return rwlock_.writerThreadId;
Brian Carlstromcd74c4b2012-01-23 13:21:00 -0800683#elif defined(__GLIBC__)
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700684 return reinterpret_cast<const glibc_pthread_rwlock_t*>(&rwlock_)->writer;
Brian Carlstromcd74c4b2012-01-23 13:21:00 -0800685#elif defined(__APPLE__)
Ian Rogers81d425b2012-09-27 16:03:43 -0700686 const darwin_pthread_rwlock_t*
687 dprwlock = reinterpret_cast<const darwin_pthread_rwlock_t*>(&rwlock_);
Brian Carlstromf3a26412012-08-24 11:06:02 -0700688 pthread_t owner = dprwlock->darwin_pthread_rwlock_owner;
689 if (owner == (pthread_t)0) {
690 return 0;
691 }
692 uint64_t tid;
693 CHECK_PTHREAD_CALL(pthread_threadid_np, (owner, &tid), __FUNCTION__); // Requires Mac OS 10.6
694 return tid;
Brian Carlstromcd74c4b2012-01-23 13:21:00 -0800695#else
Elliott Hughesf1498432012-03-28 19:34:27 -0700696#error unsupported C library
Brian Carlstromcd74c4b2012-01-23 13:21:00 -0800697#endif
Ian Rogers81d425b2012-09-27 16:03:43 -0700698#endif
Brian Carlstromcd74c4b2012-01-23 13:21:00 -0800699}
700
Ian Rogers01ae5802012-09-28 16:14:01 -0700701std::string ReaderWriterMutex::Dump() const {
702 return StringPrintf("%s level=%d owner=%llx",
703 name_.c_str(),
704 static_cast<int>(level_),
705 GetExclusiveOwnerTid());
706}
707
708std::ostream& operator<<(std::ostream& os, const ReaderWriterMutex& mu) {
709 return os << mu.Dump();
710}
711
Ian Rogersc604d732012-10-14 16:09:54 -0700712ConditionVariable::ConditionVariable(const std::string& name, Mutex& guard)
713 : name_(name), guard_(guard) {
714#if ART_USE_FUTEXES
715 state_ = 0;
716 num_waiters_ = 0;
717 num_awoken_ = 0;
718#else
Elliott Hughes5f791332011-09-15 17:45:30 -0700719 CHECK_MUTEX_CALL(pthread_cond_init, (&cond_, NULL));
Ian Rogersc604d732012-10-14 16:09:54 -0700720#endif
Elliott Hughes5f791332011-09-15 17:45:30 -0700721}
722
723ConditionVariable::~ConditionVariable() {
Ian Rogersc604d732012-10-14 16:09:54 -0700724#if !ART_USE_FUTEXES
Elliott Hughese62934d2012-04-09 11:24:29 -0700725 // We can't use CHECK_MUTEX_CALL here because on shutdown a suspended daemon thread
726 // may still be using condition variables.
727 int rc = pthread_cond_destroy(&cond_);
728 if (rc != 0) {
729 errno = rc;
Ian Rogers50b35e22012-10-04 10:09:15 -0700730 MutexLock mu(Thread::Current(), *Locks::runtime_shutdown_lock_);
Ian Rogers120f1c72012-09-28 17:17:10 -0700731 Runtime* runtime = Runtime::Current();
732 bool shutting_down = (runtime == NULL) || runtime->IsShuttingDown();
Elliott Hughese62934d2012-04-09 11:24:29 -0700733 PLOG(shutting_down ? WARNING : FATAL) << "pthread_cond_destroy failed for " << name_;
734 }
Ian Rogersc604d732012-10-14 16:09:54 -0700735#endif
Elliott Hughes5f791332011-09-15 17:45:30 -0700736}
737
Ian Rogersc604d732012-10-14 16:09:54 -0700738void ConditionVariable::Broadcast(Thread* self) {
739 DCHECK(self == NULL || self == Thread::Current());
740 // TODO: enable below, there's a race in thread creation that causes false failures currently.
741 // guard_.AssertExclusiveHeld(self);
742#if ART_USE_FUTEXES
743 if (num_waiters_ > 0) {
744 android_atomic_inc(&state_); // Indicate a wake has occurred to waiters coming in.
745 bool done = false;
746 do {
747 int32_t cur_state = state_;
748 // Compute number of waiters requeued and add to mutex contenders.
749 int32_t num_requeued = num_waiters_ - num_awoken_;
750 android_atomic_add(num_requeued, &guard_.num_contenders_);
751 // Requeue waiters onto contenders.
752 done = futex(&state_, FUTEX_CMP_REQUEUE, 0,
753 reinterpret_cast<const timespec*>(std::numeric_limits<int32_t>::max()),
754 &guard_.state_, cur_state) != -1;
755 if (!done) {
756 if (errno != EAGAIN) {
757 PLOG(FATAL) << "futex cmp requeue failed for " << name_;
758 }
759 } else {
760 num_awoken_ = num_waiters_;
761 }
762 } while (!done);
763 }
764#else
Elliott Hughes5f791332011-09-15 17:45:30 -0700765 CHECK_MUTEX_CALL(pthread_cond_broadcast, (&cond_));
Ian Rogersc604d732012-10-14 16:09:54 -0700766#endif
Elliott Hughes5f791332011-09-15 17:45:30 -0700767}
768
Ian Rogersc604d732012-10-14 16:09:54 -0700769void ConditionVariable::Signal(Thread* self) {
770 DCHECK(self == NULL || self == Thread::Current());
771 guard_.AssertExclusiveHeld(self);
772#if ART_USE_FUTEXES
773 if (num_waiters_ > 0) {
774 android_atomic_inc(&state_); // Indicate a wake has occurred to waiters coming in.
775 // Futex wake 1 waiter who will then come and in contend on mutex. It'd be nice to requeue them
776 // to avoid this, however, requeueing can only move all waiters.
777 if (futex(&state_, FUTEX_WAKE, 1, NULL, NULL, 0) == 1) {
778 // Wake success.
779 // We weren't requeued, however, to make accounting simpler in the Wait code, increment the
780 // number of contenders on the mutex.
781 num_awoken_++;
782 android_atomic_inc(&guard_.num_contenders_);
783 }
784 }
785#else
Elliott Hughes5f791332011-09-15 17:45:30 -0700786 CHECK_MUTEX_CALL(pthread_cond_signal, (&cond_));
Ian Rogersc604d732012-10-14 16:09:54 -0700787#endif
Elliott Hughes5f791332011-09-15 17:45:30 -0700788}
789
Ian Rogersc604d732012-10-14 16:09:54 -0700790void ConditionVariable::Wait(Thread* self) {
791 DCHECK(self == NULL || self == Thread::Current());
792 guard_.AssertExclusiveHeld(self);
793 guard_.CheckSafeToWait(self);
794 unsigned int old_recursion_count = guard_.recursion_count_;
795#if ART_USE_FUTEXES
796 int32_t cur_state = state_;
797 num_waiters_++;
798 guard_.recursion_count_ = 1;
799 guard_.ExclusiveUnlock(self);
800 bool woken = true;
801 while (futex(&state_, FUTEX_WAIT, cur_state, NULL, NULL, 0) != 0) {
802 if (errno == EINTR || errno == EAGAIN) {
803 if (state_ != cur_state) {
804 // We failed and a signal has come in.
805 woken = false;
806 break;
807 }
808 } else {
809 PLOG(FATAL) << "futex wait failed for " << name_;
810 }
811 }
812 guard_.ExclusiveLock(self);
813 num_waiters_--;
814 if (woken) {
815 // If we were woken we were requeued on the mutex, decrement the mutex's contender count.
816 android_atomic_dec(&guard_.num_contenders_);
817 num_awoken_--;
818 }
819#else
820 guard_.recursion_count_ = 0;
821 CHECK_MUTEX_CALL(pthread_cond_wait, (&cond_, &guard_.mutex_));
822#endif
823 guard_.recursion_count_ = old_recursion_count;
Elliott Hughes5f791332011-09-15 17:45:30 -0700824}
825
Ian Rogersc604d732012-10-14 16:09:54 -0700826void ConditionVariable::TimedWait(Thread* self, int64_t ms, int32_t ns) {
827 DCHECK(self == NULL || self == Thread::Current());
828 guard_.AssertExclusiveHeld(self);
829 guard_.CheckSafeToWait(self);
830 unsigned int old_recursion_count = guard_.recursion_count_;
831#if ART_USE_FUTEXES
832 // Record the original end time so that if the futex call fails we can recompute the appropriate
833 // relative time.
834 timespec end_abs_ts;
835 InitTimeSpec(self, true, CLOCK_REALTIME, ms, ns, &end_abs_ts);
836 timespec rel_ts;
837 InitTimeSpec(self, false, CLOCK_REALTIME, ms, ns, &rel_ts);
838 // Read state so that we can know if a signal comes in during before we sleep.
839 int32_t cur_state = state_;
840 num_waiters_++;
841 guard_.recursion_count_ = 1;
842 guard_.ExclusiveUnlock(self);
843 bool woken = true; // Did the futex wait end because we were awoken?
844 while (futex(&state_, FUTEX_WAIT, cur_state, &rel_ts, NULL, 0) != 0) {
845 if (errno == ETIMEDOUT) {
846 woken = false;
847 break;
848 }
849 if ((errno == EINTR) || (errno == EAGAIN)) {
850 if (state_ != cur_state) {
851 // We failed and a signal has come in.
852 woken = false;
853 break;
854 }
855 timespec now_abs_ts;
856 InitTimeSpec(self, true, CLOCK_REALTIME, 0, 0, &now_abs_ts);
857 if (ComputeRelativeTimeSpec(&rel_ts, end_abs_ts, now_abs_ts)) {
858 // futex failed and we timed out in the meantime.
859 woken = false;
860 break;
861 }
862 } else {
863 PLOG(FATAL) << "timed futex wait failed for " << name_;
864 }
865 }
866 guard_.ExclusiveLock(self);
867 num_waiters_--;
868 if (woken) {
869 // If we were woken we were requeued on the mutex, decrement the mutex's contender count.
870 android_atomic_dec(&guard_.num_contenders_);
871 num_awoken_--;
872 }
873#else
Elliott Hughes5f791332011-09-15 17:45:30 -0700874#ifdef HAVE_TIMEDWAIT_MONOTONIC
875#define TIMEDWAIT pthread_cond_timedwait_monotonic
Ian Rogersc604d732012-10-14 16:09:54 -0700876 int clock = CLOCK_MONOTONIC;
Elliott Hughes5f791332011-09-15 17:45:30 -0700877#else
878#define TIMEDWAIT pthread_cond_timedwait
Ian Rogersc604d732012-10-14 16:09:54 -0700879 int clock = CLOCK_REALTIME;
Elliott Hughes5f791332011-09-15 17:45:30 -0700880#endif
Ian Rogersc604d732012-10-14 16:09:54 -0700881 guard_.recursion_count_ = 0;
882 timespec ts;
883 InitTimeSpec(self, true, clock, ms, ns, &ts);
884 int rc = TIMEDWAIT(&cond_, &guard_.mutex_, &ts);
Elliott Hughes5f791332011-09-15 17:45:30 -0700885 if (rc != 0 && rc != ETIMEDOUT) {
886 errno = rc;
887 PLOG(FATAL) << "TimedWait failed for " << name_;
888 }
Ian Rogersc604d732012-10-14 16:09:54 -0700889#endif
890 guard_.recursion_count_ = old_recursion_count;
Elliott Hughes5f791332011-09-15 17:45:30 -0700891}
892
Elliott Hughese62934d2012-04-09 11:24:29 -0700893} // namespace art