blob: 47ad5828706ecfe93440ceee0b1df804f14be0a9 [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 Rogersab470162012-09-29 23:06:53 -0700356 DCHECK_EQ(state_, -1);
357 exclusive_owner_ = SafeGetTid(self);
Ian Rogers81d425b2012-09-27 16:03:43 -0700358#else
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700359 CHECK_MUTEX_CALL(pthread_rwlock_wrlock, (&rwlock_));
Ian Rogers81d425b2012-09-27 16:03:43 -0700360#endif
361 RegisterAsLocked(self);
362 AssertExclusiveHeld(self);
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700363}
364
Ian Rogers81d425b2012-09-27 16:03:43 -0700365void ReaderWriterMutex::ExclusiveUnlock(Thread* self) {
Ian Rogers01ae5802012-09-28 16:14:01 -0700366 DCHECK(self == NULL || self == Thread::Current());
Ian Rogers81d425b2012-09-27 16:03:43 -0700367 AssertExclusiveHeld(self);
368 RegisterAsUnlocked(self);
369#if ART_USE_FUTEXES
370 bool done = false;
371 do {
372 int32_t cur_state = state_;
373 if (cur_state == -1) {
374 // We're no longer the owner.
375 exclusive_owner_ = 0;
376 // Change state from -1 to 0.
377 done = android_atomic_cmpxchg(-1, 0, &state_) == 0;
378 if (done) { // cmpxchg may fail due to noise?
379 // Wake any waiters.
380 if (num_pending_readers_ > 0 || num_pending_writers_ > 0) {
381 futex(&state_, FUTEX_WAKE, -1, NULL, NULL, 0);
382 }
383 }
384 } else {
385 LOG(FATAL) << "Unexpected state_:" << cur_state << " for " << name_;
386 }
387 } while(!done);
388#else
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700389 CHECK_MUTEX_CALL(pthread_rwlock_unlock, (&rwlock_));
Ian Rogers81d425b2012-09-27 16:03:43 -0700390#endif
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700391}
392
Ian Rogers66aee5c2012-08-15 17:17:47 -0700393#if HAVE_TIMED_RWLOCK
Ian Rogers81d425b2012-09-27 16:03:43 -0700394bool ReaderWriterMutex::ExclusiveLockWithTimeout(Thread* self, const timespec& abs_timeout) {
Ian Rogers01ae5802012-09-28 16:14:01 -0700395 DCHECK(self == NULL || self == Thread::Current());
Ian Rogers81d425b2012-09-27 16:03:43 -0700396#if ART_USE_FUTEXES
397 bool done = false;
398 do {
399 int32_t cur_state = state_;
400 if (cur_state == 0) {
401 // Change state from 0 to -1.
402 done = android_atomic_cmpxchg(0, -1, &state_) == 0;
403 } else {
404 // Failed to acquire, hang up.
405 android_atomic_inc(&num_pending_writers_);
406 if (futex(&state_, FUTEX_WAIT, cur_state, &abs_timeout, NULL, 0) != 0) {
407 if (errno == ETIMEDOUT) {
408 android_atomic_dec(&num_pending_writers_);
409 return false;
410 } else if (errno != EAGAIN) {
411 PLOG(FATAL) << "timed futex wait failed for " << name_;
412 }
413 }
414 android_atomic_dec(&num_pending_writers_);
415 }
416 } while(!done);
Ian Rogers01ae5802012-09-28 16:14:01 -0700417 exclusive_owner_ = SafeGetTid(self);
Ian Rogers81d425b2012-09-27 16:03:43 -0700418#else
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700419 int result = pthread_rwlock_timedwrlock(&rwlock_, &abs_timeout);
420 if (result == ETIMEDOUT) {
421 return false;
422 }
423 if (result != 0) {
424 errno = result;
Ian Rogersa5acfd32012-08-15 11:50:10 -0700425 PLOG(FATAL) << "pthread_rwlock_timedwrlock failed for " << name_;
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700426 }
Ian Rogers81d425b2012-09-27 16:03:43 -0700427#endif
428 RegisterAsLocked(self);
429 AssertSharedHeld(self);
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700430 return true;
431}
Ian Rogers66aee5c2012-08-15 17:17:47 -0700432#endif
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700433
Ian Rogers81d425b2012-09-27 16:03:43 -0700434void ReaderWriterMutex::SharedLock(Thread* self) {
Ian Rogers01ae5802012-09-28 16:14:01 -0700435 DCHECK(self == NULL || self == Thread::Current());
Ian Rogers81d425b2012-09-27 16:03:43 -0700436#if ART_USE_FUTEXES
437 bool done = false;
438 do {
439 int32_t cur_state = state_;
440 if (cur_state >= 0) {
441 // Add as an extra reader.
442 done = android_atomic_cmpxchg(cur_state, cur_state + 1, &state_) == 0;
443 } else {
444 // Owner holds it exclusively, hang up.
445 android_atomic_inc(&num_pending_readers_);
446 if (futex(&state_, FUTEX_WAIT, cur_state, NULL, NULL, 0) != 0) {
447 if (errno != EAGAIN) {
448 PLOG(FATAL) << "futex wait failed for " << name_;
449 }
450 }
451 android_atomic_dec(&num_pending_readers_);
452 }
453 } while(!done);
454#else
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700455 CHECK_MUTEX_CALL(pthread_rwlock_rdlock, (&rwlock_));
Ian Rogers81d425b2012-09-27 16:03:43 -0700456#endif
457 RegisterAsLocked(self);
458 AssertSharedHeld(self);
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700459}
460
Ian Rogers81d425b2012-09-27 16:03:43 -0700461bool ReaderWriterMutex::SharedTryLock(Thread* self) {
Ian Rogers01ae5802012-09-28 16:14:01 -0700462 DCHECK(self == NULL || self == Thread::Current());
Ian Rogers81d425b2012-09-27 16:03:43 -0700463#if ART_USE_FUTEXES
464 bool done = false;
465 do {
466 int32_t cur_state = state_;
467 if (cur_state >= 0) {
468 // Add as an extra reader.
469 done = android_atomic_cmpxchg(cur_state, cur_state + 1, &state_) == 0;
470 } else {
471 // Owner holds it exclusively.
472 return false;
473 }
474 } while(!done);
475#else
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700476 int result = pthread_rwlock_tryrdlock(&rwlock_);
477 if (result == EBUSY) {
478 return false;
479 }
480 if (result != 0) {
481 errno = result;
482 PLOG(FATAL) << "pthread_mutex_trylock failed for " << name_;
483 }
Ian Rogers81d425b2012-09-27 16:03:43 -0700484#endif
485 RegisterAsLocked(self);
486 AssertSharedHeld(self);
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700487 return true;
488}
489
Ian Rogers81d425b2012-09-27 16:03:43 -0700490void ReaderWriterMutex::SharedUnlock(Thread* self) {
Ian Rogers01ae5802012-09-28 16:14:01 -0700491 DCHECK(self == NULL || self == Thread::Current());
Ian Rogers81d425b2012-09-27 16:03:43 -0700492 AssertSharedHeld(self);
493 RegisterAsUnlocked(self);
494#if ART_USE_FUTEXES
495 bool done = false;
496 do {
497 int32_t cur_state = state_;
498 if (LIKELY(cur_state > 0)) {
499 // Reduce state by 1.
500 done = android_atomic_cmpxchg(cur_state, cur_state - 1, &state_) == 0;
501 if (done && (cur_state - 1) == 0) { // cmpxchg may fail due to noise?
502 if (num_pending_writers_ > 0 || num_pending_readers_ > 0) {
503 // Wake any exclusive waiters as there are now no readers.
504 futex(&state_, FUTEX_WAKE, -1, NULL, NULL, 0);
505 }
506 }
507 } else {
508 LOG(FATAL) << "Unexpected state_:" << cur_state << " for " << name_;
509 }
510 } while(!done);
511#else
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700512 CHECK_MUTEX_CALL(pthread_rwlock_unlock, (&rwlock_));
Ian Rogers81d425b2012-09-27 16:03:43 -0700513#endif
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700514}
515
Ian Rogers81d425b2012-09-27 16:03:43 -0700516bool ReaderWriterMutex::IsExclusiveHeld(const Thread* self) const {
Ian Rogers01ae5802012-09-28 16:14:01 -0700517 DCHECK(self == NULL || self == Thread::Current());
518 bool result = (GetExclusiveOwnerTid() == SafeGetTid(self));
Ian Rogers25fd14b2012-09-05 10:56:38 -0700519 if (kDebugLocking) {
520 // Sanity that if the pthread thinks we own the lock the Thread agrees.
Ian Rogers01ae5802012-09-28 16:14:01 -0700521 if (self != NULL && result) {
522 CHECK_EQ(self->GetHeldMutex(level_), this);
523 }
Ian Rogers25fd14b2012-09-05 10:56:38 -0700524 }
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700525 return result;
526}
527
Ian Rogers81d425b2012-09-27 16:03:43 -0700528bool ReaderWriterMutex::IsSharedHeld(const Thread* self) const {
Ian Rogers01ae5802012-09-28 16:14:01 -0700529 DCHECK(self == NULL || self == Thread::Current());
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700530 bool result;
531 if (UNLIKELY(self == NULL)) { // Handle unattached threads.
Ian Rogers01ae5802012-09-28 16:14:01 -0700532 result = IsExclusiveHeld(self); // TODO: a better best effort here.
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700533 } else {
534 result = (self->GetHeldMutex(level_) == this);
535 }
536 return result;
537}
538
539uint64_t ReaderWriterMutex::GetExclusiveOwnerTid() const {
Ian Rogers81d425b2012-09-27 16:03:43 -0700540#if ART_USE_FUTEXES
541 return exclusive_owner_;
542#else
Brian Carlstromcd74c4b2012-01-23 13:21:00 -0800543#if defined(__BIONIC__)
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700544 return rwlock_.writerThreadId;
Brian Carlstromcd74c4b2012-01-23 13:21:00 -0800545#elif defined(__GLIBC__)
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700546 return reinterpret_cast<const glibc_pthread_rwlock_t*>(&rwlock_)->writer;
Brian Carlstromcd74c4b2012-01-23 13:21:00 -0800547#elif defined(__APPLE__)
Ian Rogers81d425b2012-09-27 16:03:43 -0700548 const darwin_pthread_rwlock_t*
549 dprwlock = reinterpret_cast<const darwin_pthread_rwlock_t*>(&rwlock_);
Brian Carlstromf3a26412012-08-24 11:06:02 -0700550 pthread_t owner = dprwlock->darwin_pthread_rwlock_owner;
551 if (owner == (pthread_t)0) {
552 return 0;
553 }
554 uint64_t tid;
555 CHECK_PTHREAD_CALL(pthread_threadid_np, (owner, &tid), __FUNCTION__); // Requires Mac OS 10.6
556 return tid;
Brian Carlstromcd74c4b2012-01-23 13:21:00 -0800557#else
Elliott Hughesf1498432012-03-28 19:34:27 -0700558#error unsupported C library
Brian Carlstromcd74c4b2012-01-23 13:21:00 -0800559#endif
Ian Rogers81d425b2012-09-27 16:03:43 -0700560#endif
Brian Carlstromcd74c4b2012-01-23 13:21:00 -0800561}
562
Ian Rogers01ae5802012-09-28 16:14:01 -0700563std::string ReaderWriterMutex::Dump() const {
564 return StringPrintf("%s level=%d owner=%llx",
565 name_.c_str(),
566 static_cast<int>(level_),
567 GetExclusiveOwnerTid());
568}
569
570std::ostream& operator<<(std::ostream& os, const ReaderWriterMutex& mu) {
571 return os << mu.Dump();
572}
573
Elliott Hughes5f791332011-09-15 17:45:30 -0700574ConditionVariable::ConditionVariable(const std::string& name) : name_(name) {
575 CHECK_MUTEX_CALL(pthread_cond_init, (&cond_, NULL));
576}
577
578ConditionVariable::~ConditionVariable() {
Elliott Hughese62934d2012-04-09 11:24:29 -0700579 // We can't use CHECK_MUTEX_CALL here because on shutdown a suspended daemon thread
580 // may still be using condition variables.
581 int rc = pthread_cond_destroy(&cond_);
582 if (rc != 0) {
583 errno = rc;
584 bool shutting_down = Runtime::Current()->IsShuttingDown();
585 PLOG(shutting_down ? WARNING : FATAL) << "pthread_cond_destroy failed for " << name_;
586 }
Elliott Hughes5f791332011-09-15 17:45:30 -0700587}
588
589void ConditionVariable::Broadcast() {
590 CHECK_MUTEX_CALL(pthread_cond_broadcast, (&cond_));
591}
592
593void ConditionVariable::Signal() {
594 CHECK_MUTEX_CALL(pthread_cond_signal, (&cond_));
595}
596
Ian Rogers81d425b2012-09-27 16:03:43 -0700597void ConditionVariable::Wait(Thread* self, Mutex& mutex) {
598 mutex.CheckSafeToWait(self);
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700599 unsigned int old_recursion_count = mutex.recursion_count_;
600 mutex.recursion_count_ = 0;
Elliott Hughesf1498432012-03-28 19:34:27 -0700601 CHECK_MUTEX_CALL(pthread_cond_wait, (&cond_, &mutex.mutex_));
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700602 mutex.recursion_count_ = old_recursion_count;
Elliott Hughes5f791332011-09-15 17:45:30 -0700603}
604
Ian Rogers81d425b2012-09-27 16:03:43 -0700605void ConditionVariable::TimedWait(Thread* self, Mutex& mutex, const timespec& ts) {
Elliott Hughes5f791332011-09-15 17:45:30 -0700606#ifdef HAVE_TIMEDWAIT_MONOTONIC
607#define TIMEDWAIT pthread_cond_timedwait_monotonic
608#else
609#define TIMEDWAIT pthread_cond_timedwait
610#endif
Ian Rogers81d425b2012-09-27 16:03:43 -0700611 mutex.CheckSafeToWait(self);
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700612 unsigned int old_recursion_count = mutex.recursion_count_;
613 mutex.recursion_count_ = 0;
Elliott Hughesf1498432012-03-28 19:34:27 -0700614 int rc = TIMEDWAIT(&cond_, &mutex.mutex_, &ts);
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700615 mutex.recursion_count_ = old_recursion_count;
Elliott Hughes5f791332011-09-15 17:45:30 -0700616 if (rc != 0 && rc != ETIMEDOUT) {
617 errno = rc;
618 PLOG(FATAL) << "TimedWait failed for " << name_;
619 }
620}
621
Elliott Hughese62934d2012-04-09 11:24:29 -0700622} // namespace art