blob: a3aec41ca679cdde3dcda05ef77af4d98eaa6ac6 [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>
20
Ian Rogers81d425b2012-09-27 16:03:43 -070021#include "cutils/atomic.h"
22#include "cutils/atomic-inline.h"
Elliott Hughes8daa0922011-09-11 13:46:25 -070023#include "logging.h"
Elliott Hughes6b355752012-01-13 16:49:08 -080024#include "runtime.h"
Elliott Hughesffb465f2012-03-01 18:46:05 -080025#include "thread.h"
26#include "utils.h"
Elliott Hughes8daa0922011-09-11 13:46:25 -070027
Elliott Hughesb08e8a32012-04-02 10:51:41 -070028#if defined(__APPLE__)
29#include "AvailabilityMacros.h" // For MAC_OS_X_VERSION_MAX_ALLOWED
30#endif
31
Elliott Hughes8d768a92011-09-14 16:35:25 -070032#define CHECK_MUTEX_CALL(call, args) CHECK_PTHREAD_CALL(call, args, name_)
33
Elliott Hughesf8349362012-06-18 15:00:06 -070034extern int pthread_mutex_lock(pthread_mutex_t* mutex) EXCLUSIVE_LOCK_FUNCTION(mutex);
35extern int pthread_mutex_unlock(pthread_mutex_t* mutex) UNLOCK_FUNCTION(1);
36extern int pthread_mutex_trylock(pthread_mutex_t* mutex) EXCLUSIVE_TRYLOCK_FUNCTION(0, mutex);
37
Ian Rogers81d425b2012-09-27 16:03:43 -070038#if ART_USE_FUTEXES
Ian Rogersacc46d62012-09-27 21:39:40 -070039#include "linux/futex.h"
Ian Rogers81d425b2012-09-27 16:03:43 -070040#include "sys/syscall.h"
41#ifndef SYS_futex
42#define SYS_futex __NR_futex
43#endif
44int futex(volatile int *uaddr, int op, int val, const struct timespec *timeout, int *, int ) {
45 return syscall(SYS_futex, uaddr, op, val, timeout, NULL, NULL);
46}
47#endif // ART_USE_FUTEXES
48
Elliott Hughes8daa0922011-09-11 13:46:25 -070049namespace art {
50
Brian Carlstromf3a26412012-08-24 11:06:02 -070051// This works on Mac OS 10.6 but hasn't been tested on older releases.
Elliott Hughesf1498432012-03-28 19:34:27 -070052struct __attribute__((__may_alias__)) darwin_pthread_mutex_t {
Brian Carlstromf3a26412012-08-24 11:06:02 -070053 long padding0;
54 int padding1;
55 uint32_t padding2;
56 int16_t padding3;
57 int16_t padding4;
58 uint32_t padding5;
59 pthread_t darwin_pthread_mutex_owner;
Ian Rogers00f7d0e2012-07-19 15:28:27 -070060 // ...other stuff we don't care about.
61};
62
63struct __attribute__((__may_alias__)) darwin_pthread_rwlock_t {
Brian Carlstromf3a26412012-08-24 11:06:02 -070064 long padding0;
65 pthread_mutex_t padding1;
66 int padding2;
67 pthread_cond_t padding3;
68 pthread_cond_t padding4;
69 int padding5;
70 int padding6;
71 pthread_t darwin_pthread_rwlock_owner;
Elliott Hughesf1498432012-03-28 19:34:27 -070072 // ...other stuff we don't care about.
73};
74
75struct __attribute__((__may_alias__)) glibc_pthread_mutex_t {
Ian Rogers00f7d0e2012-07-19 15:28:27 -070076 int32_t padding0[2];
Elliott Hughesf1498432012-03-28 19:34:27 -070077 int owner;
78 // ...other stuff we don't care about.
79};
80
Ian Rogers00f7d0e2012-07-19 15:28:27 -070081struct __attribute__((__may_alias__)) glibc_pthread_rwlock_t {
82#ifdef __LP64__
83 int32_t padding0[6];
84#else
85 int32_t padding0[7];
86#endif
87 int writer;
88 // ...other stuff we don't care about.
89};
90
Ian Rogers01ae5802012-09-28 16:14:01 -070091static uint64_t SafeGetTid(const Thread* self) {
92 if (self != NULL) {
93 return static_cast<uint64_t>(self->GetTid());
94 } else {
95 return static_cast<uint64_t>(GetTid());
96 }
97}
98
Ian Rogers81d425b2012-09-27 16:03:43 -070099BaseMutex::BaseMutex(const char* name, LockLevel level) : level_(level), name_(name) {}
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700100
Ian Rogers81d425b2012-09-27 16:03:43 -0700101static void CheckUnattachedThread(LockLevel level) {
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700102 // The check below enumerates the cases where we expect not to be able to sanity check locks
103 // on a thread. TODO: tighten this check.
Ian Rogers25fd14b2012-09-05 10:56:38 -0700104 if (kDebugLocking) {
105 Runtime* runtime = Runtime::Current();
106 CHECK(runtime == NULL || !runtime->IsStarted() || runtime->IsShuttingDown() ||
107 level == kDefaultMutexLevel || level == kThreadListLock ||
108 level == kLoggingLock || level == kAbortLock);
109 }
Elliott Hughesffb465f2012-03-01 18:46:05 -0800110}
111
Ian Rogers81d425b2012-09-27 16:03:43 -0700112void BaseMutex::RegisterAsLocked(Thread* self) {
113 if (UNLIKELY(self == NULL)) {
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700114 CheckUnattachedThread(level_);
115 return;
116 }
Ian Rogers25fd14b2012-09-05 10:56:38 -0700117 if (kDebugLocking) {
118 // Check if a bad Mutex of this level or lower is held.
119 bool bad_mutexes_held = false;
120 for (int i = level_; i >= 0; --i) {
Ian Rogers81d425b2012-09-27 16:03:43 -0700121 BaseMutex* held_mutex = self->GetHeldMutex(static_cast<LockLevel>(i));
Ian Rogers25fd14b2012-09-05 10:56:38 -0700122 if (UNLIKELY(held_mutex != NULL)) {
123 LOG(ERROR) << "Lock level violation: holding \"" << held_mutex->name_ << "\" (level " << i
124 << ") while locking \"" << name_ << "\" (level " << static_cast<int>(level_) << ")";
125 if (i > kAbortLock) {
126 // Only abort in the check below if this is more than abort level lock.
127 bad_mutexes_held = true;
128 }
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700129 }
130 }
Ian Rogers25fd14b2012-09-05 10:56:38 -0700131 CHECK(!bad_mutexes_held);
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700132 }
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700133 // Don't record monitors as they are outside the scope of analysis. They may be inspected off of
134 // the monitor list.
135 if (level_ != kMonitorLock) {
136 self->SetHeldMutex(level_, this);
137 }
138}
139
Ian Rogers81d425b2012-09-27 16:03:43 -0700140void BaseMutex::RegisterAsUnlocked(Thread* self) {
141 if (UNLIKELY(self == NULL)) {
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700142 CheckUnattachedThread(level_);
143 return;
144 }
145 if (level_ != kMonitorLock) {
Ian Rogers25fd14b2012-09-05 10:56:38 -0700146 if (kDebugLocking) {
147 CHECK(self->GetHeldMutex(level_) == this) << "Unlocking on unacquired mutex: " << name_;
148 }
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700149 self->SetHeldMutex(level_, NULL);
150 }
151}
152
Ian Rogers81d425b2012-09-27 16:03:43 -0700153void BaseMutex::CheckSafeToWait(Thread* self) {
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700154 if (self == NULL) {
155 CheckUnattachedThread(level_);
156 return;
157 }
Ian Rogers25fd14b2012-09-05 10:56:38 -0700158 if (kDebugLocking) {
159 CHECK(self->GetHeldMutex(level_) == this) << "Waiting on unacquired mutex: " << name_;
160 bool bad_mutexes_held = false;
161 for (int i = kMaxMutexLevel; i >= 0; --i) {
162 if (i != level_) {
Ian Rogers81d425b2012-09-27 16:03:43 -0700163 BaseMutex* held_mutex = self->GetHeldMutex(static_cast<LockLevel>(i));
Ian Rogers25fd14b2012-09-05 10:56:38 -0700164 if (held_mutex != NULL) {
165 LOG(ERROR) << "Holding " << held_mutex->name_ << " (level " << i
166 << ") while performing wait on: "
167 << name_ << " (level " << static_cast<int>(level_) << ")";
168 bad_mutexes_held = true;
169 }
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700170 }
171 }
Ian Rogers25fd14b2012-09-05 10:56:38 -0700172 CHECK(!bad_mutexes_held);
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700173 }
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700174}
175
Ian Rogers81d425b2012-09-27 16:03:43 -0700176Mutex::Mutex(const char* name, LockLevel level, bool recursive)
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700177 : BaseMutex(name, level), recursive_(recursive), recursion_count_(0) {
Brian Carlstromf3a26412012-08-24 11:06:02 -0700178#if defined(__BIONIC__) || defined(__APPLE__)
179 // Use recursive mutexes for bionic and Apple otherwise the
180 // non-recursive mutexes don't have TIDs to check lock ownership of.
Elliott Hughesbbd9d832011-11-07 14:40:00 -0800181 pthread_mutexattr_t attributes;
182 CHECK_MUTEX_CALL(pthread_mutexattr_init, (&attributes));
183 CHECK_MUTEX_CALL(pthread_mutexattr_settype, (&attributes, PTHREAD_MUTEX_RECURSIVE));
184 CHECK_MUTEX_CALL(pthread_mutex_init, (&mutex_, &attributes));
185 CHECK_MUTEX_CALL(pthread_mutexattr_destroy, (&attributes));
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700186#else
187 CHECK_MUTEX_CALL(pthread_mutex_init, (&mutex_, NULL));
188#endif
Elliott Hughes8daa0922011-09-11 13:46:25 -0700189}
190
191Mutex::~Mutex() {
Elliott Hughese62934d2012-04-09 11:24:29 -0700192 // We can't use CHECK_MUTEX_CALL here because on shutdown a suspended daemon thread
193 // may still be using locks.
Elliott Hughes6b355752012-01-13 16:49:08 -0800194 int rc = pthread_mutex_destroy(&mutex_);
195 if (rc != 0) {
196 errno = rc;
Elliott Hughesb3bd5f02012-03-08 21:05:27 -0800197 // TODO: should we just not log at all if shutting down? this could be the logging mutex!
Elliott Hughes6b355752012-01-13 16:49:08 -0800198 bool shutting_down = Runtime::Current()->IsShuttingDown();
199 PLOG(shutting_down ? WARNING : FATAL) << "pthread_mutex_destroy failed for " << name_;
200 }
Elliott Hughes8daa0922011-09-11 13:46:25 -0700201}
202
Ian Rogers81d425b2012-09-27 16:03:43 -0700203void Mutex::ExclusiveLock(Thread* self) {
Ian Rogers01ae5802012-09-28 16:14:01 -0700204 DCHECK(self == NULL || self == Thread::Current());
Ian Rogers25fd14b2012-09-05 10:56:38 -0700205 if (kDebugLocking && !recursive_) {
Ian Rogers81d425b2012-09-27 16:03:43 -0700206 AssertNotHeld(self);
Ian Rogers25fd14b2012-09-05 10:56:38 -0700207 }
Ian Rogers81d425b2012-09-27 16:03:43 -0700208 if (!recursive_ || !IsExclusiveHeld(self)) {
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700209 CHECK_MUTEX_CALL(pthread_mutex_lock, (&mutex_));
Ian Rogers81d425b2012-09-27 16:03:43 -0700210 RegisterAsLocked(self);
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700211 }
212 recursion_count_++;
Ian Rogers25fd14b2012-09-05 10:56:38 -0700213 if (kDebugLocking) {
214 CHECK(recursion_count_ == 1 || recursive_) << "Unexpected recursion count on mutex: "
215 << name_ << " " << recursion_count_;
Ian Rogers81d425b2012-09-27 16:03:43 -0700216 AssertHeld(self);
Ian Rogers25fd14b2012-09-05 10:56:38 -0700217 }
Elliott Hughes8daa0922011-09-11 13:46:25 -0700218}
219
Ian Rogers81d425b2012-09-27 16:03:43 -0700220bool Mutex::ExclusiveTryLock(Thread* self) {
Ian Rogers01ae5802012-09-28 16:14:01 -0700221 DCHECK(self == NULL || self == Thread::Current());
Ian Rogers25fd14b2012-09-05 10:56:38 -0700222 if (kDebugLocking && !recursive_) {
Ian Rogers81d425b2012-09-27 16:03:43 -0700223 AssertNotHeld(self);
Ian Rogers25fd14b2012-09-05 10:56:38 -0700224 }
Ian Rogers81d425b2012-09-27 16:03:43 -0700225 if (!recursive_ || !IsExclusiveHeld(self)) {
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700226 int result = pthread_mutex_trylock(&mutex_);
227 if (result == EBUSY) {
228 return false;
229 }
230 if (result != 0) {
231 errno = result;
232 PLOG(FATAL) << "pthread_mutex_trylock failed for " << name_;
233 }
Ian Rogers81d425b2012-09-27 16:03:43 -0700234 RegisterAsLocked(self);
Elliott Hughes8daa0922011-09-11 13:46:25 -0700235 }
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700236 recursion_count_++;
Ian Rogers25fd14b2012-09-05 10:56:38 -0700237 if (kDebugLocking) {
238 CHECK(recursion_count_ == 1 || recursive_) << "Unexpected recursion count on mutex: "
239 << name_ << " " << recursion_count_;
Ian Rogers81d425b2012-09-27 16:03:43 -0700240 AssertHeld(self);
Ian Rogers25fd14b2012-09-05 10:56:38 -0700241 }
Elliott Hughes8daa0922011-09-11 13:46:25 -0700242 return true;
243}
244
Ian Rogers81d425b2012-09-27 16:03:43 -0700245void Mutex::ExclusiveUnlock(Thread* self) {
Ian Rogers01ae5802012-09-28 16:14:01 -0700246 DCHECK(self == NULL || self == Thread::Current());
Ian Rogers81d425b2012-09-27 16:03:43 -0700247 AssertHeld(self);
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700248 recursion_count_--;
249 if (!recursive_ || recursion_count_ == 0) {
Ian Rogers25fd14b2012-09-05 10:56:38 -0700250 if (kDebugLocking) {
251 CHECK(recursion_count_ == 0 || recursive_) << "Unexpected recursion count on mutex: "
252 << name_ << " " << recursion_count_;
253 }
Ian Rogers81d425b2012-09-27 16:03:43 -0700254 RegisterAsUnlocked(self);
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700255 CHECK_MUTEX_CALL(pthread_mutex_unlock, (&mutex_));
256 }
Elliott Hughes8daa0922011-09-11 13:46:25 -0700257}
258
Ian Rogers81d425b2012-09-27 16:03:43 -0700259bool Mutex::IsExclusiveHeld(const Thread* self) const {
Ian Rogers01ae5802012-09-28 16:14:01 -0700260 DCHECK(self == NULL || self == Thread::Current());
261 bool result = (GetExclusiveOwnerTid() == SafeGetTid(self));
262 if (kDebugLocking) {
263 // Sanity debug check that if we think it is locked we have it in our held mutexes.
264 if (result && self != NULL && level_ != kMonitorLock) {
265 CHECK_EQ(self->GetHeldMutex(level_), this);
Ian Rogers25fd14b2012-09-05 10:56:38 -0700266 }
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700267 }
268 return result;
Elliott Hughesf1498432012-03-28 19:34:27 -0700269}
270
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700271uint64_t Mutex::GetExclusiveOwnerTid() const {
Elliott Hughes3147a232011-10-12 15:55:07 -0700272#if defined(__BIONIC__)
Elliott Hughesf1498432012-03-28 19:34:27 -0700273 return static_cast<uint64_t>((mutex_.value >> 16) & 0xffff);
Elliott Hughes3147a232011-10-12 15:55:07 -0700274#elif defined(__GLIBC__)
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700275 return reinterpret_cast<const glibc_pthread_mutex_t*>(&mutex_)->owner;
Elliott Hughescf044312012-01-23 18:48:51 -0800276#elif defined(__APPLE__)
Brian Carlstromf3a26412012-08-24 11:06:02 -0700277 const darwin_pthread_mutex_t* dpmutex = reinterpret_cast<const darwin_pthread_mutex_t*>(&mutex_);
278 pthread_t owner = dpmutex->darwin_pthread_mutex_owner;
Brian Carlstrombd93c302012-08-27 16:58:28 -0700279 // 0 for unowned, -1 for PTHREAD_MTX_TID_SWITCHING
280 // TODO: should we make darwin_pthread_mutex_owner volatile and recheck until not -1?
Brian Carlstromf3a26412012-08-24 11:06:02 -0700281 if ((owner == (pthread_t)0) || (owner == (pthread_t)-1)) {
282 return 0;
283 }
284 uint64_t tid;
285 CHECK_PTHREAD_CALL(pthread_threadid_np, (owner, &tid), __FUNCTION__); // Requires Mac OS 10.6
286 return tid;
Elliott Hughes8daa0922011-09-11 13:46:25 -0700287#else
Elliott Hughesf1498432012-03-28 19:34:27 -0700288#error unsupported C library
Elliott Hughes8daa0922011-09-11 13:46:25 -0700289#endif
290}
291
Ian Rogers01ae5802012-09-28 16:14:01 -0700292std::string Mutex::Dump() const {
293 return StringPrintf("%s %s level=%d count=%d owner=%llx",
294 recursive_ ? "recursive" : "non-recursive",
295 name_.c_str(),
296 static_cast<int>(level_),
297 recursion_count_,
298 GetExclusiveOwnerTid());
299}
300
301std::ostream& operator<<(std::ostream& os, const Mutex& mu) {
302 return os << mu.Dump();
303}
304
Ian Rogers81d425b2012-09-27 16:03:43 -0700305ReaderWriterMutex::ReaderWriterMutex(const char* name, LockLevel level) :
306 BaseMutex(name, level)
307#if ART_USE_FUTEXES
308 , state_(0), exclusive_owner_(0), num_pending_readers_(0), num_pending_writers_(0)
309#endif
310{
311#if !ART_USE_FUTEXES
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700312 CHECK_MUTEX_CALL(pthread_rwlock_init, (&rwlock_, NULL));
Ian Rogers81d425b2012-09-27 16:03:43 -0700313#endif
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700314}
315
316ReaderWriterMutex::~ReaderWriterMutex() {
Ian Rogers81d425b2012-09-27 16:03:43 -0700317#if ART_USE_FUTEXES
318 CHECK_EQ(state_, 0);
319 CHECK_EQ(exclusive_owner_, 0U);
320 CHECK_EQ(num_pending_readers_, 0);
321 CHECK_EQ(num_pending_writers_, 0);
322#else
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700323 // We can't use CHECK_MUTEX_CALL here because on shutdown a suspended daemon thread
324 // may still be using locks.
325 int rc = pthread_rwlock_destroy(&rwlock_);
326 if (rc != 0) {
327 errno = rc;
328 // TODO: should we just not log at all if shutting down? this could be the logging mutex!
329 bool shutting_down = Runtime::Current()->IsShuttingDown();
330 PLOG(shutting_down ? WARNING : FATAL) << "pthread_mutex_destroy failed for " << name_;
Brian Carlstromcd74c4b2012-01-23 13:21:00 -0800331 }
Ian Rogers81d425b2012-09-27 16:03:43 -0700332#endif
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700333}
334
Ian Rogers81d425b2012-09-27 16:03:43 -0700335void ReaderWriterMutex::ExclusiveLock(Thread* self) {
Ian Rogers01ae5802012-09-28 16:14:01 -0700336 DCHECK(self == NULL || self == Thread::Current());
Ian Rogers81d425b2012-09-27 16:03:43 -0700337 AssertNotExclusiveHeld(self);
338#if ART_USE_FUTEXES
339 bool done = false;
340 do {
341 int32_t cur_state = state_;
342 if (cur_state == 0) {
343 // Change state from 0 to -1.
344 done = android_atomic_cmpxchg(0, -1, &state_) == 0;
345 } else {
346 // Failed to acquire, hang up.
347 android_atomic_inc(&num_pending_writers_);
348 if (futex(&state_, FUTEX_WAIT, cur_state, NULL, NULL, 0) != 0) {
349 if (errno != EAGAIN) {
350 PLOG(FATAL) << "futex wait failed for " << name_;
351 }
352 }
353 android_atomic_dec(&num_pending_writers_);
354 }
355 } while(!done);
Ian Rogers01ae5802012-09-28 16:14:01 -0700356 exclusive_owner_ = static_cast<uint64_t>(self->GetTid());
Ian Rogers81d425b2012-09-27 16:03:43 -0700357#else
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700358 CHECK_MUTEX_CALL(pthread_rwlock_wrlock, (&rwlock_));
Ian Rogers81d425b2012-09-27 16:03:43 -0700359#endif
360 RegisterAsLocked(self);
361 AssertExclusiveHeld(self);
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700362}
363
Ian Rogers81d425b2012-09-27 16:03:43 -0700364void ReaderWriterMutex::ExclusiveUnlock(Thread* self) {
Ian Rogers01ae5802012-09-28 16:14:01 -0700365 DCHECK(self == NULL || self == Thread::Current());
Ian Rogers81d425b2012-09-27 16:03:43 -0700366 AssertExclusiveHeld(self);
367 RegisterAsUnlocked(self);
368#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 from -1 to 0.
376 done = android_atomic_cmpxchg(-1, 0, &state_) == 0;
377 if (done) { // cmpxchg may fail due to noise?
378 // Wake any waiters.
379 if (num_pending_readers_ > 0 || num_pending_writers_ > 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_rwlock_unlock, (&rwlock_));
Ian Rogers81d425b2012-09-27 16:03:43 -0700389#endif
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700390}
391
Ian Rogers66aee5c2012-08-15 17:17:47 -0700392#if HAVE_TIMED_RWLOCK
Ian Rogers81d425b2012-09-27 16:03:43 -0700393bool ReaderWriterMutex::ExclusiveLockWithTimeout(Thread* self, const timespec& abs_timeout) {
Ian Rogers01ae5802012-09-28 16:14:01 -0700394 DCHECK(self == NULL || self == Thread::Current());
Ian Rogers81d425b2012-09-27 16:03:43 -0700395#if ART_USE_FUTEXES
396 bool done = false;
397 do {
398 int32_t cur_state = state_;
399 if (cur_state == 0) {
400 // Change state from 0 to -1.
401 done = android_atomic_cmpxchg(0, -1, &state_) == 0;
402 } else {
403 // Failed to acquire, hang up.
404 android_atomic_inc(&num_pending_writers_);
405 if (futex(&state_, FUTEX_WAIT, cur_state, &abs_timeout, NULL, 0) != 0) {
406 if (errno == ETIMEDOUT) {
407 android_atomic_dec(&num_pending_writers_);
408 return false;
409 } else if (errno != EAGAIN) {
410 PLOG(FATAL) << "timed futex wait failed for " << name_;
411 }
412 }
413 android_atomic_dec(&num_pending_writers_);
414 }
415 } while(!done);
Ian Rogers01ae5802012-09-28 16:14:01 -0700416 exclusive_owner_ = SafeGetTid(self);
Ian Rogers81d425b2012-09-27 16:03:43 -0700417#else
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700418 int result = pthread_rwlock_timedwrlock(&rwlock_, &abs_timeout);
419 if (result == ETIMEDOUT) {
420 return false;
421 }
422 if (result != 0) {
423 errno = result;
Ian Rogersa5acfd32012-08-15 11:50:10 -0700424 PLOG(FATAL) << "pthread_rwlock_timedwrlock failed for " << name_;
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700425 }
Ian Rogers81d425b2012-09-27 16:03:43 -0700426#endif
427 RegisterAsLocked(self);
428 AssertSharedHeld(self);
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700429 return true;
430}
Ian Rogers66aee5c2012-08-15 17:17:47 -0700431#endif
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700432
Ian Rogers81d425b2012-09-27 16:03:43 -0700433void ReaderWriterMutex::SharedLock(Thread* self) {
Ian Rogers01ae5802012-09-28 16:14:01 -0700434 DCHECK(self == NULL || self == Thread::Current());
Ian Rogers81d425b2012-09-27 16:03:43 -0700435#if ART_USE_FUTEXES
436 bool done = false;
437 do {
438 int32_t cur_state = state_;
439 if (cur_state >= 0) {
440 // Add as an extra reader.
441 done = android_atomic_cmpxchg(cur_state, cur_state + 1, &state_) == 0;
442 } else {
443 // Owner holds it exclusively, hang up.
444 android_atomic_inc(&num_pending_readers_);
445 if (futex(&state_, FUTEX_WAIT, cur_state, NULL, NULL, 0) != 0) {
446 if (errno != EAGAIN) {
447 PLOG(FATAL) << "futex wait failed for " << name_;
448 }
449 }
450 android_atomic_dec(&num_pending_readers_);
451 }
452 } while(!done);
453#else
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700454 CHECK_MUTEX_CALL(pthread_rwlock_rdlock, (&rwlock_));
Ian Rogers81d425b2012-09-27 16:03:43 -0700455#endif
456 RegisterAsLocked(self);
457 AssertSharedHeld(self);
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700458}
459
Ian Rogers81d425b2012-09-27 16:03:43 -0700460bool ReaderWriterMutex::SharedTryLock(Thread* self) {
Ian Rogers01ae5802012-09-28 16:14:01 -0700461 DCHECK(self == NULL || self == Thread::Current());
Ian Rogers81d425b2012-09-27 16:03:43 -0700462#if ART_USE_FUTEXES
463 bool done = false;
464 do {
465 int32_t cur_state = state_;
466 if (cur_state >= 0) {
467 // Add as an extra reader.
468 done = android_atomic_cmpxchg(cur_state, cur_state + 1, &state_) == 0;
469 } else {
470 // Owner holds it exclusively.
471 return false;
472 }
473 } while(!done);
474#else
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700475 int result = pthread_rwlock_tryrdlock(&rwlock_);
476 if (result == EBUSY) {
477 return false;
478 }
479 if (result != 0) {
480 errno = result;
481 PLOG(FATAL) << "pthread_mutex_trylock failed for " << name_;
482 }
Ian Rogers81d425b2012-09-27 16:03:43 -0700483#endif
484 RegisterAsLocked(self);
485 AssertSharedHeld(self);
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700486 return true;
487}
488
Ian Rogers81d425b2012-09-27 16:03:43 -0700489void ReaderWriterMutex::SharedUnlock(Thread* self) {
Ian Rogers01ae5802012-09-28 16:14:01 -0700490 DCHECK(self == NULL || self == Thread::Current());
Ian Rogers81d425b2012-09-27 16:03:43 -0700491 AssertSharedHeld(self);
492 RegisterAsUnlocked(self);
493#if ART_USE_FUTEXES
494 bool done = false;
495 do {
496 int32_t cur_state = state_;
497 if (LIKELY(cur_state > 0)) {
498 // Reduce state by 1.
499 done = android_atomic_cmpxchg(cur_state, cur_state - 1, &state_) == 0;
500 if (done && (cur_state - 1) == 0) { // cmpxchg may fail due to noise?
501 if (num_pending_writers_ > 0 || num_pending_readers_ > 0) {
502 // Wake any exclusive waiters as there are now no readers.
503 futex(&state_, FUTEX_WAKE, -1, NULL, NULL, 0);
504 }
505 }
506 } else {
507 LOG(FATAL) << "Unexpected state_:" << cur_state << " for " << name_;
508 }
509 } while(!done);
510#else
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700511 CHECK_MUTEX_CALL(pthread_rwlock_unlock, (&rwlock_));
Ian Rogers81d425b2012-09-27 16:03:43 -0700512#endif
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700513}
514
Ian Rogers81d425b2012-09-27 16:03:43 -0700515bool ReaderWriterMutex::IsExclusiveHeld(const Thread* self) const {
Ian Rogers01ae5802012-09-28 16:14:01 -0700516 DCHECK(self == NULL || self == Thread::Current());
517 bool result = (GetExclusiveOwnerTid() == SafeGetTid(self));
Ian Rogers25fd14b2012-09-05 10:56:38 -0700518 if (kDebugLocking) {
519 // Sanity that if the pthread thinks we own the lock the Thread agrees.
Ian Rogers01ae5802012-09-28 16:14:01 -0700520 if (self != NULL && result) {
521 CHECK_EQ(self->GetHeldMutex(level_), this);
522 }
Ian Rogers25fd14b2012-09-05 10:56:38 -0700523 }
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700524 return result;
525}
526
Ian Rogers81d425b2012-09-27 16:03:43 -0700527bool ReaderWriterMutex::IsSharedHeld(const Thread* self) const {
Ian Rogers01ae5802012-09-28 16:14:01 -0700528 DCHECK(self == NULL || self == Thread::Current());
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700529 bool result;
530 if (UNLIKELY(self == NULL)) { // Handle unattached threads.
Ian Rogers01ae5802012-09-28 16:14:01 -0700531 result = IsExclusiveHeld(self); // TODO: a better best effort here.
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700532 } else {
533 result = (self->GetHeldMutex(level_) == this);
534 }
535 return result;
536}
537
538uint64_t ReaderWriterMutex::GetExclusiveOwnerTid() const {
Ian Rogers81d425b2012-09-27 16:03:43 -0700539#if ART_USE_FUTEXES
540 return exclusive_owner_;
541#else
Brian Carlstromcd74c4b2012-01-23 13:21:00 -0800542#if defined(__BIONIC__)
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700543 return rwlock_.writerThreadId;
Brian Carlstromcd74c4b2012-01-23 13:21:00 -0800544#elif defined(__GLIBC__)
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700545 return reinterpret_cast<const glibc_pthread_rwlock_t*>(&rwlock_)->writer;
Brian Carlstromcd74c4b2012-01-23 13:21:00 -0800546#elif defined(__APPLE__)
Ian Rogers81d425b2012-09-27 16:03:43 -0700547 const darwin_pthread_rwlock_t*
548 dprwlock = reinterpret_cast<const darwin_pthread_rwlock_t*>(&rwlock_);
Brian Carlstromf3a26412012-08-24 11:06:02 -0700549 pthread_t owner = dprwlock->darwin_pthread_rwlock_owner;
550 if (owner == (pthread_t)0) {
551 return 0;
552 }
553 uint64_t tid;
554 CHECK_PTHREAD_CALL(pthread_threadid_np, (owner, &tid), __FUNCTION__); // Requires Mac OS 10.6
555 return tid;
Brian Carlstromcd74c4b2012-01-23 13:21:00 -0800556#else
Elliott Hughesf1498432012-03-28 19:34:27 -0700557#error unsupported C library
Brian Carlstromcd74c4b2012-01-23 13:21:00 -0800558#endif
Ian Rogers81d425b2012-09-27 16:03:43 -0700559#endif
Brian Carlstromcd74c4b2012-01-23 13:21:00 -0800560}
561
Ian Rogers01ae5802012-09-28 16:14:01 -0700562std::string ReaderWriterMutex::Dump() const {
563 return StringPrintf("%s level=%d owner=%llx",
564 name_.c_str(),
565 static_cast<int>(level_),
566 GetExclusiveOwnerTid());
567}
568
569std::ostream& operator<<(std::ostream& os, const ReaderWriterMutex& mu) {
570 return os << mu.Dump();
571}
572
Elliott Hughes5f791332011-09-15 17:45:30 -0700573ConditionVariable::ConditionVariable(const std::string& name) : name_(name) {
574 CHECK_MUTEX_CALL(pthread_cond_init, (&cond_, NULL));
575}
576
577ConditionVariable::~ConditionVariable() {
Elliott Hughese62934d2012-04-09 11:24:29 -0700578 // We can't use CHECK_MUTEX_CALL here because on shutdown a suspended daemon thread
579 // may still be using condition variables.
580 int rc = pthread_cond_destroy(&cond_);
581 if (rc != 0) {
582 errno = rc;
583 bool shutting_down = Runtime::Current()->IsShuttingDown();
584 PLOG(shutting_down ? WARNING : FATAL) << "pthread_cond_destroy failed for " << name_;
585 }
Elliott Hughes5f791332011-09-15 17:45:30 -0700586}
587
588void ConditionVariable::Broadcast() {
589 CHECK_MUTEX_CALL(pthread_cond_broadcast, (&cond_));
590}
591
592void ConditionVariable::Signal() {
593 CHECK_MUTEX_CALL(pthread_cond_signal, (&cond_));
594}
595
Ian Rogers81d425b2012-09-27 16:03:43 -0700596void ConditionVariable::Wait(Thread* self, Mutex& mutex) {
597 mutex.CheckSafeToWait(self);
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700598 unsigned int old_recursion_count = mutex.recursion_count_;
599 mutex.recursion_count_ = 0;
Elliott Hughesf1498432012-03-28 19:34:27 -0700600 CHECK_MUTEX_CALL(pthread_cond_wait, (&cond_, &mutex.mutex_));
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700601 mutex.recursion_count_ = old_recursion_count;
Elliott Hughes5f791332011-09-15 17:45:30 -0700602}
603
Ian Rogers81d425b2012-09-27 16:03:43 -0700604void ConditionVariable::TimedWait(Thread* self, Mutex& mutex, const timespec& ts) {
Elliott Hughes5f791332011-09-15 17:45:30 -0700605#ifdef HAVE_TIMEDWAIT_MONOTONIC
606#define TIMEDWAIT pthread_cond_timedwait_monotonic
607#else
608#define TIMEDWAIT pthread_cond_timedwait
609#endif
Ian Rogers81d425b2012-09-27 16:03:43 -0700610 mutex.CheckSafeToWait(self);
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700611 unsigned int old_recursion_count = mutex.recursion_count_;
612 mutex.recursion_count_ = 0;
Elliott Hughesf1498432012-03-28 19:34:27 -0700613 int rc = TIMEDWAIT(&cond_, &mutex.mutex_, &ts);
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700614 mutex.recursion_count_ = old_recursion_count;
Elliott Hughes5f791332011-09-15 17:45:30 -0700615 if (rc != 0 && rc != ETIMEDOUT) {
616 errno = rc;
617 PLOG(FATAL) << "TimedWait failed for " << name_;
618 }
619}
620
Elliott Hughese62934d2012-04-09 11:24:29 -0700621} // namespace art