blob: cbf115e925bb62b291126d14f29b46ac9d888849 [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) {
Ian Rogers4c54e722012-10-15 16:12:54 -0700107#if !defined(__APPLE__)
Ian Rogersc604d732012-10-14 16:09:54 -0700108 clock_gettime(clock, ts);
Ian Rogers4c54e722012-10-15 16:12:54 -0700109#else
110 UNUSED(clock);
111 timeval tv;
112 gettimeofday(&tv, NULL);
113 ts->tv_sec = tv.tv_sec;
114 ts->tv_nsec = tv.tv_usec * 1000;
115#endif
Ian Rogersc604d732012-10-14 16:09:54 -0700116 } else {
117 ts->tv_sec = 0;
118 ts->tv_nsec = 0;
119 }
120 endSec = ts->tv_sec + ms / 1000;
121 if (UNLIKELY(endSec >= 0x7fffffff)) {
122 std::ostringstream ss;
123 ScopedObjectAccess soa(self);
124 self->Dump(ss);
125 LOG(INFO) << "Note: end time exceeds epoch: " << ss.str();
126 endSec = 0x7ffffffe;
127 }
128 ts->tv_sec = endSec;
129 ts->tv_nsec = (ts->tv_nsec + (ms % 1000) * 1000000) + ns;
130
131 // Catch rollover.
132 if (ts->tv_nsec >= 1000000000L) {
133 ts->tv_sec++;
134 ts->tv_nsec -= 1000000000L;
135 }
136}
137
138#if ART_USE_FUTEXES
139static bool ComputeRelativeTimeSpec(timespec* result_ts, const timespec& lhs, const timespec& rhs) {
140 const long int one_sec = 1000 * 1000 * 1000; // one second in nanoseconds.
141 result_ts->tv_sec = lhs.tv_sec - rhs.tv_sec;
142 result_ts->tv_nsec = lhs.tv_nsec - rhs.tv_nsec;
143 if (result_ts->tv_nsec < 0) {
144 result_ts->tv_sec--;
145 result_ts->tv_nsec += one_sec;
146 } else if (result_ts->tv_nsec > one_sec) {
147 result_ts->tv_sec++;
148 result_ts->tv_nsec -= one_sec;
149 }
150 return result_ts->tv_sec < 0;
151}
152#endif
153
Ian Rogers81d425b2012-09-27 16:03:43 -0700154BaseMutex::BaseMutex(const char* name, LockLevel level) : level_(level), name_(name) {}
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700155
Ian Rogers120f1c72012-09-28 17:17:10 -0700156static void CheckUnattachedThread(LockLevel level) NO_THREAD_SAFETY_ANALYSIS {
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700157 // The check below enumerates the cases where we expect not to be able to sanity check locks
Ian Rogers120f1c72012-09-28 17:17:10 -0700158 // on a thread. Lock checking is disabled to avoid deadlock when checking shutdown lock.
159 // TODO: tighten this check.
Ian Rogers25fd14b2012-09-05 10:56:38 -0700160 if (kDebugLocking) {
161 Runtime* runtime = Runtime::Current();
162 CHECK(runtime == NULL || !runtime->IsStarted() || runtime->IsShuttingDown() ||
Ian Rogers120f1c72012-09-28 17:17:10 -0700163 level == kDefaultMutexLevel || level == kRuntimeShutdownLock ||
164 level == kThreadListLock || level == kLoggingLock || level == kAbortLock);
Ian Rogers25fd14b2012-09-05 10:56:38 -0700165 }
Elliott Hughesffb465f2012-03-01 18:46:05 -0800166}
167
Ian Rogers81d425b2012-09-27 16:03:43 -0700168void BaseMutex::RegisterAsLocked(Thread* self) {
169 if (UNLIKELY(self == NULL)) {
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700170 CheckUnattachedThread(level_);
171 return;
172 }
Ian Rogers25fd14b2012-09-05 10:56:38 -0700173 if (kDebugLocking) {
174 // Check if a bad Mutex of this level or lower is held.
175 bool bad_mutexes_held = false;
176 for (int i = level_; i >= 0; --i) {
Ian Rogers81d425b2012-09-27 16:03:43 -0700177 BaseMutex* held_mutex = self->GetHeldMutex(static_cast<LockLevel>(i));
Ian Rogers25fd14b2012-09-05 10:56:38 -0700178 if (UNLIKELY(held_mutex != NULL)) {
179 LOG(ERROR) << "Lock level violation: holding \"" << held_mutex->name_ << "\" (level " << i
180 << ") while locking \"" << name_ << "\" (level " << static_cast<int>(level_) << ")";
181 if (i > kAbortLock) {
182 // Only abort in the check below if this is more than abort level lock.
183 bad_mutexes_held = true;
184 }
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700185 }
186 }
Ian Rogers25fd14b2012-09-05 10:56:38 -0700187 CHECK(!bad_mutexes_held);
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700188 }
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700189 // Don't record monitors as they are outside the scope of analysis. They may be inspected off of
190 // the monitor list.
191 if (level_ != kMonitorLock) {
192 self->SetHeldMutex(level_, this);
193 }
194}
195
Ian Rogers81d425b2012-09-27 16:03:43 -0700196void BaseMutex::RegisterAsUnlocked(Thread* self) {
197 if (UNLIKELY(self == NULL)) {
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700198 CheckUnattachedThread(level_);
199 return;
200 }
201 if (level_ != kMonitorLock) {
Ian Rogers25fd14b2012-09-05 10:56:38 -0700202 if (kDebugLocking) {
203 CHECK(self->GetHeldMutex(level_) == this) << "Unlocking on unacquired mutex: " << name_;
204 }
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700205 self->SetHeldMutex(level_, NULL);
206 }
207}
208
Ian Rogers81d425b2012-09-27 16:03:43 -0700209void BaseMutex::CheckSafeToWait(Thread* self) {
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700210 if (self == NULL) {
211 CheckUnattachedThread(level_);
212 return;
213 }
Ian Rogers25fd14b2012-09-05 10:56:38 -0700214 if (kDebugLocking) {
215 CHECK(self->GetHeldMutex(level_) == this) << "Waiting on unacquired mutex: " << name_;
216 bool bad_mutexes_held = false;
217 for (int i = kMaxMutexLevel; i >= 0; --i) {
218 if (i != level_) {
Ian Rogers81d425b2012-09-27 16:03:43 -0700219 BaseMutex* held_mutex = self->GetHeldMutex(static_cast<LockLevel>(i));
Ian Rogers25fd14b2012-09-05 10:56:38 -0700220 if (held_mutex != NULL) {
221 LOG(ERROR) << "Holding " << held_mutex->name_ << " (level " << i
222 << ") while performing wait on: "
223 << name_ << " (level " << static_cast<int>(level_) << ")";
224 bad_mutexes_held = true;
225 }
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700226 }
227 }
Ian Rogers25fd14b2012-09-05 10:56:38 -0700228 CHECK(!bad_mutexes_held);
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700229 }
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700230}
231
Ian Rogers81d425b2012-09-27 16:03:43 -0700232Mutex::Mutex(const char* name, LockLevel level, bool recursive)
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700233 : BaseMutex(name, level), recursive_(recursive), recursion_count_(0) {
Ian Rogersc604d732012-10-14 16:09:54 -0700234#if ART_USE_FUTEXES
235 state_ = 0;
236 exclusive_owner_ = 0;
237 num_contenders_ = 0;
238#elif defined(__BIONIC__) || defined(__APPLE__)
Brian Carlstromf3a26412012-08-24 11:06:02 -0700239 // Use recursive mutexes for bionic and Apple otherwise the
240 // non-recursive mutexes don't have TIDs to check lock ownership of.
Elliott Hughesbbd9d832011-11-07 14:40:00 -0800241 pthread_mutexattr_t attributes;
242 CHECK_MUTEX_CALL(pthread_mutexattr_init, (&attributes));
243 CHECK_MUTEX_CALL(pthread_mutexattr_settype, (&attributes, PTHREAD_MUTEX_RECURSIVE));
244 CHECK_MUTEX_CALL(pthread_mutex_init, (&mutex_, &attributes));
245 CHECK_MUTEX_CALL(pthread_mutexattr_destroy, (&attributes));
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700246#else
247 CHECK_MUTEX_CALL(pthread_mutex_init, (&mutex_, NULL));
248#endif
Elliott Hughes8daa0922011-09-11 13:46:25 -0700249}
250
251Mutex::~Mutex() {
Ian Rogersc604d732012-10-14 16:09:54 -0700252#if ART_USE_FUTEXES
253 if (state_ != 0) {
254 MutexLock mu(Thread::Current(), *Locks::runtime_shutdown_lock_);
255 Runtime* runtime = Runtime::Current();
256 bool shutting_down = (runtime == NULL) || runtime->IsShuttingDown();
257 LOG(shutting_down ? WARNING : FATAL) << "destroying mutex with owner: " << exclusive_owner_;
258 } else {
259 CHECK_EQ(exclusive_owner_, 0U) << "unexpectedly found an owner on unlocked mutex " << name_;
260 CHECK_EQ(num_contenders_, 0) << "unexpectedly found a contender on mutex " << name_;
261 }
262#else
Elliott Hughese62934d2012-04-09 11:24:29 -0700263 // We can't use CHECK_MUTEX_CALL here because on shutdown a suspended daemon thread
264 // may still be using locks.
Elliott Hughes6b355752012-01-13 16:49:08 -0800265 int rc = pthread_mutex_destroy(&mutex_);
266 if (rc != 0) {
267 errno = rc;
Elliott Hughesb3bd5f02012-03-08 21:05:27 -0800268 // TODO: should we just not log at all if shutting down? this could be the logging mutex!
Ian Rogers50b35e22012-10-04 10:09:15 -0700269 MutexLock mu(Thread::Current(), *Locks::runtime_shutdown_lock_);
Ian Rogers120f1c72012-09-28 17:17:10 -0700270 Runtime* runtime = Runtime::Current();
271 bool shutting_down = (runtime == NULL) || runtime->IsShuttingDown();
Elliott Hughes6b355752012-01-13 16:49:08 -0800272 PLOG(shutting_down ? WARNING : FATAL) << "pthread_mutex_destroy failed for " << name_;
273 }
Ian Rogersc604d732012-10-14 16:09:54 -0700274#endif
Elliott Hughes8daa0922011-09-11 13:46:25 -0700275}
276
Ian Rogers81d425b2012-09-27 16:03:43 -0700277void Mutex::ExclusiveLock(Thread* self) {
Ian Rogers01ae5802012-09-28 16:14:01 -0700278 DCHECK(self == NULL || self == Thread::Current());
Ian Rogers25fd14b2012-09-05 10:56:38 -0700279 if (kDebugLocking && !recursive_) {
Ian Rogers81d425b2012-09-27 16:03:43 -0700280 AssertNotHeld(self);
Ian Rogers25fd14b2012-09-05 10:56:38 -0700281 }
Ian Rogers81d425b2012-09-27 16:03:43 -0700282 if (!recursive_ || !IsExclusiveHeld(self)) {
Ian Rogersc604d732012-10-14 16:09:54 -0700283#if ART_USE_FUTEXES
284 bool done = false;
285 do {
286 int32_t cur_state = state_;
287 if (cur_state == 0) {
288 // Change state from 0 to 1.
289 done = android_atomic_cmpxchg(0, 1, &state_) == 0;
290 } else {
291 // Failed to acquire, hang up.
292 android_atomic_inc(&num_contenders_);
293 if (futex(&state_, FUTEX_WAIT, 1, NULL, NULL, 0) != 0) {
294 if (errno != EAGAIN) {
295 PLOG(FATAL) << "futex wait failed for " << name_;
296 }
297 }
298 android_atomic_dec(&num_contenders_);
299 }
300 } while(!done);
301 DCHECK_EQ(state_, 1);
302 exclusive_owner_ = SafeGetTid(self);
303#else
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700304 CHECK_MUTEX_CALL(pthread_mutex_lock, (&mutex_));
Ian Rogersc604d732012-10-14 16:09:54 -0700305#endif
Ian Rogers81d425b2012-09-27 16:03:43 -0700306 RegisterAsLocked(self);
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700307 }
308 recursion_count_++;
Ian Rogers25fd14b2012-09-05 10:56:38 -0700309 if (kDebugLocking) {
310 CHECK(recursion_count_ == 1 || recursive_) << "Unexpected recursion count on mutex: "
311 << name_ << " " << recursion_count_;
Ian Rogers81d425b2012-09-27 16:03:43 -0700312 AssertHeld(self);
Ian Rogers25fd14b2012-09-05 10:56:38 -0700313 }
Elliott Hughes8daa0922011-09-11 13:46:25 -0700314}
315
Ian Rogers81d425b2012-09-27 16:03:43 -0700316bool Mutex::ExclusiveTryLock(Thread* self) {
Ian Rogers01ae5802012-09-28 16:14:01 -0700317 DCHECK(self == NULL || self == Thread::Current());
Ian Rogers25fd14b2012-09-05 10:56:38 -0700318 if (kDebugLocking && !recursive_) {
Ian Rogers81d425b2012-09-27 16:03:43 -0700319 AssertNotHeld(self);
Ian Rogers25fd14b2012-09-05 10:56:38 -0700320 }
Ian Rogers81d425b2012-09-27 16:03:43 -0700321 if (!recursive_ || !IsExclusiveHeld(self)) {
Ian Rogersc604d732012-10-14 16:09:54 -0700322#if ART_USE_FUTEXES
323 bool done = false;
324 do {
325 int32_t cur_state = state_;
326 if (cur_state == 0) {
327 // Change state from 0 to 1.
328 done = android_atomic_cmpxchg(0, 1, &state_) == 0;
329 } else {
330 return false;
331 }
332 } while(!done);
333 DCHECK_EQ(state_, 1);
334 exclusive_owner_ = SafeGetTid(self);
335#else
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700336 int result = pthread_mutex_trylock(&mutex_);
337 if (result == EBUSY) {
338 return false;
339 }
340 if (result != 0) {
341 errno = result;
342 PLOG(FATAL) << "pthread_mutex_trylock failed for " << name_;
343 }
Ian Rogersc604d732012-10-14 16:09:54 -0700344#endif
Ian Rogers81d425b2012-09-27 16:03:43 -0700345 RegisterAsLocked(self);
Elliott Hughes8daa0922011-09-11 13:46:25 -0700346 }
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700347 recursion_count_++;
Ian Rogers25fd14b2012-09-05 10:56:38 -0700348 if (kDebugLocking) {
349 CHECK(recursion_count_ == 1 || recursive_) << "Unexpected recursion count on mutex: "
350 << name_ << " " << recursion_count_;
Ian Rogers81d425b2012-09-27 16:03:43 -0700351 AssertHeld(self);
Ian Rogers25fd14b2012-09-05 10:56:38 -0700352 }
Elliott Hughes8daa0922011-09-11 13:46:25 -0700353 return true;
354}
355
Ian Rogers81d425b2012-09-27 16:03:43 -0700356void Mutex::ExclusiveUnlock(Thread* self) {
Ian Rogers01ae5802012-09-28 16:14:01 -0700357 DCHECK(self == NULL || self == Thread::Current());
Ian Rogers81d425b2012-09-27 16:03:43 -0700358 AssertHeld(self);
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700359 recursion_count_--;
360 if (!recursive_ || recursion_count_ == 0) {
Ian Rogers25fd14b2012-09-05 10:56:38 -0700361 if (kDebugLocking) {
362 CHECK(recursion_count_ == 0 || recursive_) << "Unexpected recursion count on mutex: "
363 << name_ << " " << recursion_count_;
364 }
Ian Rogers81d425b2012-09-27 16:03:43 -0700365 RegisterAsUnlocked(self);
Ian Rogersc604d732012-10-14 16:09:54 -0700366#if ART_USE_FUTEXES
367 bool done = false;
368 do {
369 int32_t cur_state = state_;
370 if (cur_state == 1) {
371 // We're no longer the owner.
372 exclusive_owner_ = 0;
373 // Change state to 0.
374 done = android_atomic_cmpxchg(cur_state, 0, &state_) == 0;
375 if (done) { // Spurious fail?
376 // Wake a contender
377 if (num_contenders_ > 0) {
378 futex(&state_, FUTEX_WAKE, 1, NULL, NULL, 0);
379 }
380 }
381 } else {
382 LOG(FATAL) << "Unexpected state_:" << cur_state << " for " << name_;
383 }
384 } while(!done);
385#else
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700386 CHECK_MUTEX_CALL(pthread_mutex_unlock, (&mutex_));
Ian Rogersc604d732012-10-14 16:09:54 -0700387#endif
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700388 }
Elliott Hughes8daa0922011-09-11 13:46:25 -0700389}
390
Ian Rogers81d425b2012-09-27 16:03:43 -0700391bool Mutex::IsExclusiveHeld(const Thread* self) const {
Ian Rogers01ae5802012-09-28 16:14:01 -0700392 DCHECK(self == NULL || self == Thread::Current());
393 bool result = (GetExclusiveOwnerTid() == SafeGetTid(self));
394 if (kDebugLocking) {
395 // Sanity debug check that if we think it is locked we have it in our held mutexes.
396 if (result && self != NULL && level_ != kMonitorLock) {
397 CHECK_EQ(self->GetHeldMutex(level_), this);
Ian Rogers25fd14b2012-09-05 10:56:38 -0700398 }
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700399 }
400 return result;
Elliott Hughesf1498432012-03-28 19:34:27 -0700401}
402
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700403uint64_t Mutex::GetExclusiveOwnerTid() const {
Ian Rogersc604d732012-10-14 16:09:54 -0700404#if ART_USE_FUTEXES
405 return exclusive_owner_;
406#elif defined(__BIONIC__)
Elliott Hughesf1498432012-03-28 19:34:27 -0700407 return static_cast<uint64_t>((mutex_.value >> 16) & 0xffff);
Elliott Hughes3147a232011-10-12 15:55:07 -0700408#elif defined(__GLIBC__)
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700409 return reinterpret_cast<const glibc_pthread_mutex_t*>(&mutex_)->owner;
Elliott Hughescf044312012-01-23 18:48:51 -0800410#elif defined(__APPLE__)
Brian Carlstromf3a26412012-08-24 11:06:02 -0700411 const darwin_pthread_mutex_t* dpmutex = reinterpret_cast<const darwin_pthread_mutex_t*>(&mutex_);
412 pthread_t owner = dpmutex->darwin_pthread_mutex_owner;
Brian Carlstrombd93c302012-08-27 16:58:28 -0700413 // 0 for unowned, -1 for PTHREAD_MTX_TID_SWITCHING
414 // TODO: should we make darwin_pthread_mutex_owner volatile and recheck until not -1?
Brian Carlstromf3a26412012-08-24 11:06:02 -0700415 if ((owner == (pthread_t)0) || (owner == (pthread_t)-1)) {
416 return 0;
417 }
418 uint64_t tid;
419 CHECK_PTHREAD_CALL(pthread_threadid_np, (owner, &tid), __FUNCTION__); // Requires Mac OS 10.6
420 return tid;
Elliott Hughes8daa0922011-09-11 13:46:25 -0700421#else
Elliott Hughesf1498432012-03-28 19:34:27 -0700422#error unsupported C library
Elliott Hughes8daa0922011-09-11 13:46:25 -0700423#endif
424}
425
Ian Rogers01ae5802012-09-28 16:14:01 -0700426std::string Mutex::Dump() const {
427 return StringPrintf("%s %s level=%d count=%d owner=%llx",
428 recursive_ ? "recursive" : "non-recursive",
429 name_.c_str(),
430 static_cast<int>(level_),
431 recursion_count_,
432 GetExclusiveOwnerTid());
433}
434
435std::ostream& operator<<(std::ostream& os, const Mutex& mu) {
436 return os << mu.Dump();
437}
438
Ian Rogers81d425b2012-09-27 16:03:43 -0700439ReaderWriterMutex::ReaderWriterMutex(const char* name, LockLevel level) :
440 BaseMutex(name, level)
441#if ART_USE_FUTEXES
442 , state_(0), exclusive_owner_(0), num_pending_readers_(0), num_pending_writers_(0)
443#endif
444{
445#if !ART_USE_FUTEXES
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700446 CHECK_MUTEX_CALL(pthread_rwlock_init, (&rwlock_, NULL));
Ian Rogers81d425b2012-09-27 16:03:43 -0700447#endif
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700448}
449
450ReaderWriterMutex::~ReaderWriterMutex() {
Ian Rogers81d425b2012-09-27 16:03:43 -0700451#if ART_USE_FUTEXES
452 CHECK_EQ(state_, 0);
453 CHECK_EQ(exclusive_owner_, 0U);
454 CHECK_EQ(num_pending_readers_, 0);
455 CHECK_EQ(num_pending_writers_, 0);
456#else
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700457 // We can't use CHECK_MUTEX_CALL here because on shutdown a suspended daemon thread
458 // may still be using locks.
459 int rc = pthread_rwlock_destroy(&rwlock_);
460 if (rc != 0) {
461 errno = rc;
462 // TODO: should we just not log at all if shutting down? this could be the logging mutex!
Ian Rogers50b35e22012-10-04 10:09:15 -0700463 MutexLock mu(Thread::Current(), *Locks::runtime_shutdown_lock_);
Ian Rogers120f1c72012-09-28 17:17:10 -0700464 Runtime* runtime = Runtime::Current();
465 bool shutting_down = runtime == NULL || runtime->IsShuttingDown();
466 PLOG(shutting_down ? WARNING : FATAL) << "pthread_rwlock_destroy failed for " << name_;
Brian Carlstromcd74c4b2012-01-23 13:21:00 -0800467 }
Ian Rogers81d425b2012-09-27 16:03:43 -0700468#endif
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700469}
470
Ian Rogers81d425b2012-09-27 16:03:43 -0700471void ReaderWriterMutex::ExclusiveLock(Thread* self) {
Ian Rogers01ae5802012-09-28 16:14:01 -0700472 DCHECK(self == NULL || self == Thread::Current());
Ian Rogers81d425b2012-09-27 16:03:43 -0700473 AssertNotExclusiveHeld(self);
474#if ART_USE_FUTEXES
475 bool done = false;
476 do {
477 int32_t cur_state = state_;
478 if (cur_state == 0) {
479 // Change state from 0 to -1.
480 done = android_atomic_cmpxchg(0, -1, &state_) == 0;
481 } else {
482 // Failed to acquire, hang up.
483 android_atomic_inc(&num_pending_writers_);
484 if (futex(&state_, FUTEX_WAIT, cur_state, NULL, NULL, 0) != 0) {
485 if (errno != EAGAIN) {
486 PLOG(FATAL) << "futex wait failed for " << name_;
487 }
488 }
489 android_atomic_dec(&num_pending_writers_);
490 }
491 } while(!done);
Ian Rogersab470162012-09-29 23:06:53 -0700492 DCHECK_EQ(state_, -1);
493 exclusive_owner_ = SafeGetTid(self);
Ian Rogers81d425b2012-09-27 16:03:43 -0700494#else
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700495 CHECK_MUTEX_CALL(pthread_rwlock_wrlock, (&rwlock_));
Ian Rogers81d425b2012-09-27 16:03:43 -0700496#endif
497 RegisterAsLocked(self);
498 AssertExclusiveHeld(self);
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700499}
500
Ian Rogers81d425b2012-09-27 16:03:43 -0700501void ReaderWriterMutex::ExclusiveUnlock(Thread* self) {
Ian Rogers01ae5802012-09-28 16:14:01 -0700502 DCHECK(self == NULL || self == Thread::Current());
Ian Rogers81d425b2012-09-27 16:03:43 -0700503 AssertExclusiveHeld(self);
504 RegisterAsUnlocked(self);
505#if ART_USE_FUTEXES
506 bool done = false;
507 do {
508 int32_t cur_state = state_;
509 if (cur_state == -1) {
510 // We're no longer the owner.
511 exclusive_owner_ = 0;
512 // Change state from -1 to 0.
513 done = android_atomic_cmpxchg(-1, 0, &state_) == 0;
514 if (done) { // cmpxchg may fail due to noise?
515 // Wake any waiters.
516 if (num_pending_readers_ > 0 || num_pending_writers_ > 0) {
517 futex(&state_, FUTEX_WAKE, -1, NULL, NULL, 0);
518 }
519 }
520 } else {
521 LOG(FATAL) << "Unexpected state_:" << cur_state << " for " << name_;
522 }
523 } while(!done);
524#else
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700525 CHECK_MUTEX_CALL(pthread_rwlock_unlock, (&rwlock_));
Ian Rogers81d425b2012-09-27 16:03:43 -0700526#endif
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700527}
528
Ian Rogers66aee5c2012-08-15 17:17:47 -0700529#if HAVE_TIMED_RWLOCK
Ian Rogersc604d732012-10-14 16:09:54 -0700530bool ReaderWriterMutex::ExclusiveLockWithTimeout(Thread* self, int64_t ms, int32_t ns) {
Ian Rogers01ae5802012-09-28 16:14:01 -0700531 DCHECK(self == NULL || self == Thread::Current());
Ian Rogers81d425b2012-09-27 16:03:43 -0700532#if ART_USE_FUTEXES
533 bool done = false;
Ian Rogersc604d732012-10-14 16:09:54 -0700534 timespec end_abs_ts;
535 InitTimeSpec(self, true, CLOCK_REALTIME, ms, ns, &end_abs_ts);
Ian Rogers81d425b2012-09-27 16:03:43 -0700536 do {
537 int32_t cur_state = state_;
538 if (cur_state == 0) {
539 // Change state from 0 to -1.
540 done = android_atomic_cmpxchg(0, -1, &state_) == 0;
541 } else {
542 // Failed to acquire, hang up.
Ian Rogersc604d732012-10-14 16:09:54 -0700543 timespec now_abs_ts;
544 InitTimeSpec(self, true, CLOCK_REALTIME, 0, 0, &now_abs_ts);
545 timespec rel_ts;
546 if (ComputeRelativeTimeSpec(&rel_ts, end_abs_ts, now_abs_ts)) {
547 return false; // Timed out.
548 }
Ian Rogers81d425b2012-09-27 16:03:43 -0700549 android_atomic_inc(&num_pending_writers_);
Ian Rogersc604d732012-10-14 16:09:54 -0700550 if (futex(&state_, FUTEX_WAIT, cur_state, &rel_ts, NULL, 0) != 0) {
Ian Rogers81d425b2012-09-27 16:03:43 -0700551 if (errno == ETIMEDOUT) {
552 android_atomic_dec(&num_pending_writers_);
Ian Rogersc604d732012-10-14 16:09:54 -0700553 return false; // Timed out.
554 } else if (errno != EAGAIN && errno != EINTR) {
Ian Rogers81d425b2012-09-27 16:03:43 -0700555 PLOG(FATAL) << "timed futex wait failed for " << name_;
556 }
557 }
558 android_atomic_dec(&num_pending_writers_);
559 }
560 } while(!done);
Ian Rogers01ae5802012-09-28 16:14:01 -0700561 exclusive_owner_ = SafeGetTid(self);
Ian Rogers81d425b2012-09-27 16:03:43 -0700562#else
Ian Rogersc604d732012-10-14 16:09:54 -0700563 timespec ts;
564 InitTimeSpec(self, true, CLOCK_REALTIME, ms, ns, &ts);
565 int result = pthread_rwlock_timedwrlock(&rwlock_, &ts);
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700566 if (result == ETIMEDOUT) {
567 return false;
568 }
569 if (result != 0) {
570 errno = result;
Ian Rogersa5acfd32012-08-15 11:50:10 -0700571 PLOG(FATAL) << "pthread_rwlock_timedwrlock failed for " << name_;
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700572 }
Ian Rogers81d425b2012-09-27 16:03:43 -0700573#endif
574 RegisterAsLocked(self);
575 AssertSharedHeld(self);
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700576 return true;
577}
Ian Rogers66aee5c2012-08-15 17:17:47 -0700578#endif
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700579
Ian Rogers81d425b2012-09-27 16:03:43 -0700580void ReaderWriterMutex::SharedLock(Thread* self) {
Ian Rogers01ae5802012-09-28 16:14:01 -0700581 DCHECK(self == NULL || self == Thread::Current());
Ian Rogers81d425b2012-09-27 16:03:43 -0700582#if ART_USE_FUTEXES
583 bool done = false;
584 do {
585 int32_t cur_state = state_;
586 if (cur_state >= 0) {
587 // Add as an extra reader.
588 done = android_atomic_cmpxchg(cur_state, cur_state + 1, &state_) == 0;
589 } else {
590 // Owner holds it exclusively, hang up.
591 android_atomic_inc(&num_pending_readers_);
592 if (futex(&state_, FUTEX_WAIT, cur_state, NULL, NULL, 0) != 0) {
593 if (errno != EAGAIN) {
594 PLOG(FATAL) << "futex wait failed for " << name_;
595 }
596 }
597 android_atomic_dec(&num_pending_readers_);
598 }
599 } while(!done);
600#else
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700601 CHECK_MUTEX_CALL(pthread_rwlock_rdlock, (&rwlock_));
Ian Rogers81d425b2012-09-27 16:03:43 -0700602#endif
603 RegisterAsLocked(self);
604 AssertSharedHeld(self);
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700605}
606
Ian Rogers81d425b2012-09-27 16:03:43 -0700607bool ReaderWriterMutex::SharedTryLock(Thread* self) {
Ian Rogers01ae5802012-09-28 16:14:01 -0700608 DCHECK(self == NULL || self == Thread::Current());
Ian Rogers81d425b2012-09-27 16:03:43 -0700609#if ART_USE_FUTEXES
610 bool done = false;
611 do {
612 int32_t cur_state = state_;
613 if (cur_state >= 0) {
614 // Add as an extra reader.
615 done = android_atomic_cmpxchg(cur_state, cur_state + 1, &state_) == 0;
616 } else {
617 // Owner holds it exclusively.
618 return false;
619 }
620 } while(!done);
621#else
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700622 int result = pthread_rwlock_tryrdlock(&rwlock_);
623 if (result == EBUSY) {
624 return false;
625 }
626 if (result != 0) {
627 errno = result;
628 PLOG(FATAL) << "pthread_mutex_trylock failed for " << name_;
629 }
Ian Rogers81d425b2012-09-27 16:03:43 -0700630#endif
631 RegisterAsLocked(self);
632 AssertSharedHeld(self);
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700633 return true;
634}
635
Ian Rogers81d425b2012-09-27 16:03:43 -0700636void ReaderWriterMutex::SharedUnlock(Thread* self) {
Ian Rogers01ae5802012-09-28 16:14:01 -0700637 DCHECK(self == NULL || self == Thread::Current());
Ian Rogers81d425b2012-09-27 16:03:43 -0700638 AssertSharedHeld(self);
639 RegisterAsUnlocked(self);
640#if ART_USE_FUTEXES
641 bool done = false;
642 do {
643 int32_t cur_state = state_;
644 if (LIKELY(cur_state > 0)) {
645 // Reduce state by 1.
646 done = android_atomic_cmpxchg(cur_state, cur_state - 1, &state_) == 0;
647 if (done && (cur_state - 1) == 0) { // cmpxchg may fail due to noise?
648 if (num_pending_writers_ > 0 || num_pending_readers_ > 0) {
649 // Wake any exclusive waiters as there are now no readers.
650 futex(&state_, FUTEX_WAKE, -1, NULL, NULL, 0);
651 }
652 }
653 } else {
654 LOG(FATAL) << "Unexpected state_:" << cur_state << " for " << name_;
655 }
656 } while(!done);
657#else
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700658 CHECK_MUTEX_CALL(pthread_rwlock_unlock, (&rwlock_));
Ian Rogers81d425b2012-09-27 16:03:43 -0700659#endif
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700660}
661
Ian Rogers81d425b2012-09-27 16:03:43 -0700662bool ReaderWriterMutex::IsExclusiveHeld(const Thread* self) const {
Ian Rogers01ae5802012-09-28 16:14:01 -0700663 DCHECK(self == NULL || self == Thread::Current());
664 bool result = (GetExclusiveOwnerTid() == SafeGetTid(self));
Ian Rogers25fd14b2012-09-05 10:56:38 -0700665 if (kDebugLocking) {
666 // Sanity that if the pthread thinks we own the lock the Thread agrees.
Ian Rogers01ae5802012-09-28 16:14:01 -0700667 if (self != NULL && result) {
668 CHECK_EQ(self->GetHeldMutex(level_), this);
669 }
Ian Rogers25fd14b2012-09-05 10:56:38 -0700670 }
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700671 return result;
672}
673
Ian Rogers81d425b2012-09-27 16:03:43 -0700674bool ReaderWriterMutex::IsSharedHeld(const Thread* self) const {
Ian Rogers01ae5802012-09-28 16:14:01 -0700675 DCHECK(self == NULL || self == Thread::Current());
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700676 bool result;
677 if (UNLIKELY(self == NULL)) { // Handle unattached threads.
Ian Rogers01ae5802012-09-28 16:14:01 -0700678 result = IsExclusiveHeld(self); // TODO: a better best effort here.
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700679 } else {
680 result = (self->GetHeldMutex(level_) == this);
681 }
682 return result;
683}
684
685uint64_t ReaderWriterMutex::GetExclusiveOwnerTid() const {
Ian Rogers81d425b2012-09-27 16:03:43 -0700686#if ART_USE_FUTEXES
687 return exclusive_owner_;
688#else
Brian Carlstromcd74c4b2012-01-23 13:21:00 -0800689#if defined(__BIONIC__)
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700690 return rwlock_.writerThreadId;
Brian Carlstromcd74c4b2012-01-23 13:21:00 -0800691#elif defined(__GLIBC__)
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700692 return reinterpret_cast<const glibc_pthread_rwlock_t*>(&rwlock_)->writer;
Brian Carlstromcd74c4b2012-01-23 13:21:00 -0800693#elif defined(__APPLE__)
Ian Rogers81d425b2012-09-27 16:03:43 -0700694 const darwin_pthread_rwlock_t*
695 dprwlock = reinterpret_cast<const darwin_pthread_rwlock_t*>(&rwlock_);
Brian Carlstromf3a26412012-08-24 11:06:02 -0700696 pthread_t owner = dprwlock->darwin_pthread_rwlock_owner;
697 if (owner == (pthread_t)0) {
698 return 0;
699 }
700 uint64_t tid;
701 CHECK_PTHREAD_CALL(pthread_threadid_np, (owner, &tid), __FUNCTION__); // Requires Mac OS 10.6
702 return tid;
Brian Carlstromcd74c4b2012-01-23 13:21:00 -0800703#else
Elliott Hughesf1498432012-03-28 19:34:27 -0700704#error unsupported C library
Brian Carlstromcd74c4b2012-01-23 13:21:00 -0800705#endif
Ian Rogers81d425b2012-09-27 16:03:43 -0700706#endif
Brian Carlstromcd74c4b2012-01-23 13:21:00 -0800707}
708
Ian Rogers01ae5802012-09-28 16:14:01 -0700709std::string ReaderWriterMutex::Dump() const {
710 return StringPrintf("%s level=%d owner=%llx",
711 name_.c_str(),
712 static_cast<int>(level_),
713 GetExclusiveOwnerTid());
714}
715
716std::ostream& operator<<(std::ostream& os, const ReaderWriterMutex& mu) {
717 return os << mu.Dump();
718}
719
Ian Rogersc604d732012-10-14 16:09:54 -0700720ConditionVariable::ConditionVariable(const std::string& name, Mutex& guard)
721 : name_(name), guard_(guard) {
722#if ART_USE_FUTEXES
723 state_ = 0;
724 num_waiters_ = 0;
725 num_awoken_ = 0;
726#else
Elliott Hughes5f791332011-09-15 17:45:30 -0700727 CHECK_MUTEX_CALL(pthread_cond_init, (&cond_, NULL));
Ian Rogersc604d732012-10-14 16:09:54 -0700728#endif
Elliott Hughes5f791332011-09-15 17:45:30 -0700729}
730
731ConditionVariable::~ConditionVariable() {
Ian Rogersc604d732012-10-14 16:09:54 -0700732#if !ART_USE_FUTEXES
Elliott Hughese62934d2012-04-09 11:24:29 -0700733 // We can't use CHECK_MUTEX_CALL here because on shutdown a suspended daemon thread
734 // may still be using condition variables.
735 int rc = pthread_cond_destroy(&cond_);
736 if (rc != 0) {
737 errno = rc;
Ian Rogers50b35e22012-10-04 10:09:15 -0700738 MutexLock mu(Thread::Current(), *Locks::runtime_shutdown_lock_);
Ian Rogers120f1c72012-09-28 17:17:10 -0700739 Runtime* runtime = Runtime::Current();
740 bool shutting_down = (runtime == NULL) || runtime->IsShuttingDown();
Elliott Hughese62934d2012-04-09 11:24:29 -0700741 PLOG(shutting_down ? WARNING : FATAL) << "pthread_cond_destroy failed for " << name_;
742 }
Ian Rogersc604d732012-10-14 16:09:54 -0700743#endif
Elliott Hughes5f791332011-09-15 17:45:30 -0700744}
745
Ian Rogersc604d732012-10-14 16:09:54 -0700746void ConditionVariable::Broadcast(Thread* self) {
747 DCHECK(self == NULL || self == Thread::Current());
748 // TODO: enable below, there's a race in thread creation that causes false failures currently.
749 // guard_.AssertExclusiveHeld(self);
750#if ART_USE_FUTEXES
751 if (num_waiters_ > 0) {
752 android_atomic_inc(&state_); // Indicate a wake has occurred to waiters coming in.
753 bool done = false;
754 do {
755 int32_t cur_state = state_;
756 // Compute number of waiters requeued and add to mutex contenders.
757 int32_t num_requeued = num_waiters_ - num_awoken_;
758 android_atomic_add(num_requeued, &guard_.num_contenders_);
759 // Requeue waiters onto contenders.
760 done = futex(&state_, FUTEX_CMP_REQUEUE, 0,
761 reinterpret_cast<const timespec*>(std::numeric_limits<int32_t>::max()),
762 &guard_.state_, cur_state) != -1;
763 if (!done) {
764 if (errno != EAGAIN) {
765 PLOG(FATAL) << "futex cmp requeue failed for " << name_;
766 }
767 } else {
768 num_awoken_ = num_waiters_;
769 }
770 } while (!done);
771 }
772#else
Elliott Hughes5f791332011-09-15 17:45:30 -0700773 CHECK_MUTEX_CALL(pthread_cond_broadcast, (&cond_));
Ian Rogersc604d732012-10-14 16:09:54 -0700774#endif
Elliott Hughes5f791332011-09-15 17:45:30 -0700775}
776
Ian Rogersc604d732012-10-14 16:09:54 -0700777void ConditionVariable::Signal(Thread* self) {
778 DCHECK(self == NULL || self == Thread::Current());
779 guard_.AssertExclusiveHeld(self);
780#if ART_USE_FUTEXES
781 if (num_waiters_ > 0) {
782 android_atomic_inc(&state_); // Indicate a wake has occurred to waiters coming in.
783 // Futex wake 1 waiter who will then come and in contend on mutex. It'd be nice to requeue them
784 // to avoid this, however, requeueing can only move all waiters.
785 if (futex(&state_, FUTEX_WAKE, 1, NULL, NULL, 0) == 1) {
786 // Wake success.
787 // We weren't requeued, however, to make accounting simpler in the Wait code, increment the
788 // number of contenders on the mutex.
789 num_awoken_++;
790 android_atomic_inc(&guard_.num_contenders_);
791 }
792 }
793#else
Elliott Hughes5f791332011-09-15 17:45:30 -0700794 CHECK_MUTEX_CALL(pthread_cond_signal, (&cond_));
Ian Rogersc604d732012-10-14 16:09:54 -0700795#endif
Elliott Hughes5f791332011-09-15 17:45:30 -0700796}
797
Ian Rogersc604d732012-10-14 16:09:54 -0700798void ConditionVariable::Wait(Thread* self) {
799 DCHECK(self == NULL || self == Thread::Current());
800 guard_.AssertExclusiveHeld(self);
801 guard_.CheckSafeToWait(self);
802 unsigned int old_recursion_count = guard_.recursion_count_;
803#if ART_USE_FUTEXES
804 int32_t cur_state = state_;
805 num_waiters_++;
806 guard_.recursion_count_ = 1;
807 guard_.ExclusiveUnlock(self);
808 bool woken = true;
809 while (futex(&state_, FUTEX_WAIT, cur_state, NULL, NULL, 0) != 0) {
810 if (errno == EINTR || errno == EAGAIN) {
811 if (state_ != cur_state) {
812 // We failed and a signal has come in.
813 woken = false;
814 break;
815 }
816 } else {
817 PLOG(FATAL) << "futex wait failed for " << name_;
818 }
819 }
820 guard_.ExclusiveLock(self);
821 num_waiters_--;
822 if (woken) {
823 // If we were woken we were requeued on the mutex, decrement the mutex's contender count.
824 android_atomic_dec(&guard_.num_contenders_);
825 num_awoken_--;
826 }
827#else
828 guard_.recursion_count_ = 0;
829 CHECK_MUTEX_CALL(pthread_cond_wait, (&cond_, &guard_.mutex_));
830#endif
831 guard_.recursion_count_ = old_recursion_count;
Elliott Hughes5f791332011-09-15 17:45:30 -0700832}
833
Ian Rogersc604d732012-10-14 16:09:54 -0700834void ConditionVariable::TimedWait(Thread* self, int64_t ms, int32_t ns) {
835 DCHECK(self == NULL || self == Thread::Current());
836 guard_.AssertExclusiveHeld(self);
837 guard_.CheckSafeToWait(self);
838 unsigned int old_recursion_count = guard_.recursion_count_;
839#if ART_USE_FUTEXES
840 // Record the original end time so that if the futex call fails we can recompute the appropriate
841 // relative time.
842 timespec end_abs_ts;
843 InitTimeSpec(self, true, CLOCK_REALTIME, ms, ns, &end_abs_ts);
844 timespec rel_ts;
845 InitTimeSpec(self, false, CLOCK_REALTIME, ms, ns, &rel_ts);
846 // Read state so that we can know if a signal comes in during before we sleep.
847 int32_t cur_state = state_;
848 num_waiters_++;
849 guard_.recursion_count_ = 1;
850 guard_.ExclusiveUnlock(self);
851 bool woken = true; // Did the futex wait end because we were awoken?
852 while (futex(&state_, FUTEX_WAIT, cur_state, &rel_ts, NULL, 0) != 0) {
853 if (errno == ETIMEDOUT) {
854 woken = false;
855 break;
856 }
857 if ((errno == EINTR) || (errno == EAGAIN)) {
858 if (state_ != cur_state) {
859 // We failed and a signal has come in.
860 woken = false;
861 break;
862 }
863 timespec now_abs_ts;
864 InitTimeSpec(self, true, CLOCK_REALTIME, 0, 0, &now_abs_ts);
865 if (ComputeRelativeTimeSpec(&rel_ts, end_abs_ts, now_abs_ts)) {
866 // futex failed and we timed out in the meantime.
867 woken = false;
868 break;
869 }
870 } else {
871 PLOG(FATAL) << "timed futex wait failed for " << name_;
872 }
873 }
874 guard_.ExclusiveLock(self);
875 num_waiters_--;
876 if (woken) {
877 // If we were woken we were requeued on the mutex, decrement the mutex's contender count.
878 android_atomic_dec(&guard_.num_contenders_);
879 num_awoken_--;
880 }
881#else
Elliott Hughes5f791332011-09-15 17:45:30 -0700882#ifdef HAVE_TIMEDWAIT_MONOTONIC
883#define TIMEDWAIT pthread_cond_timedwait_monotonic
Ian Rogersc604d732012-10-14 16:09:54 -0700884 int clock = CLOCK_MONOTONIC;
Elliott Hughes5f791332011-09-15 17:45:30 -0700885#else
886#define TIMEDWAIT pthread_cond_timedwait
Ian Rogersc604d732012-10-14 16:09:54 -0700887 int clock = CLOCK_REALTIME;
Elliott Hughes5f791332011-09-15 17:45:30 -0700888#endif
Ian Rogersc604d732012-10-14 16:09:54 -0700889 guard_.recursion_count_ = 0;
890 timespec ts;
891 InitTimeSpec(self, true, clock, ms, ns, &ts);
892 int rc = TIMEDWAIT(&cond_, &guard_.mutex_, &ts);
Elliott Hughes5f791332011-09-15 17:45:30 -0700893 if (rc != 0 && rc != ETIMEDOUT) {
894 errno = rc;
895 PLOG(FATAL) << "TimedWait failed for " << name_;
896 }
Ian Rogersc604d732012-10-14 16:09:54 -0700897#endif
898 guard_.recursion_count_ = old_recursion_count;
Elliott Hughes5f791332011-09-15 17:45:30 -0700899}
900
Elliott Hughese62934d2012-04-09 11:24:29 -0700901} // namespace art