blob: eef8bdc4d0d628d6376fcef82ce486b26e69e352 [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
Elliott Hughes8daa0922011-09-11 13:46:25 -070021#include "logging.h"
Elliott Hughes6b355752012-01-13 16:49:08 -080022#include "runtime.h"
Elliott Hughesffb465f2012-03-01 18:46:05 -080023#include "thread.h"
24#include "utils.h"
Elliott Hughes8daa0922011-09-11 13:46:25 -070025
Elliott Hughesb08e8a32012-04-02 10:51:41 -070026#if defined(__APPLE__)
27#include "AvailabilityMacros.h" // For MAC_OS_X_VERSION_MAX_ALLOWED
28#endif
29
Elliott Hughes8d768a92011-09-14 16:35:25 -070030#define CHECK_MUTEX_CALL(call, args) CHECK_PTHREAD_CALL(call, args, name_)
31
Elliott Hughesf8349362012-06-18 15:00:06 -070032extern int pthread_mutex_lock(pthread_mutex_t* mutex) EXCLUSIVE_LOCK_FUNCTION(mutex);
33extern int pthread_mutex_unlock(pthread_mutex_t* mutex) UNLOCK_FUNCTION(1);
34extern int pthread_mutex_trylock(pthread_mutex_t* mutex) EXCLUSIVE_TRYLOCK_FUNCTION(0, mutex);
35
Elliott Hughes8daa0922011-09-11 13:46:25 -070036namespace art {
37
Brian Carlstromf3a26412012-08-24 11:06:02 -070038// This works on Mac OS 10.6 but hasn't been tested on older releases.
Elliott Hughesf1498432012-03-28 19:34:27 -070039struct __attribute__((__may_alias__)) darwin_pthread_mutex_t {
Brian Carlstromf3a26412012-08-24 11:06:02 -070040 long padding0;
41 int padding1;
42 uint32_t padding2;
43 int16_t padding3;
44 int16_t padding4;
45 uint32_t padding5;
46 pthread_t darwin_pthread_mutex_owner;
Ian Rogers00f7d0e2012-07-19 15:28:27 -070047 // ...other stuff we don't care about.
48};
49
50struct __attribute__((__may_alias__)) darwin_pthread_rwlock_t {
Brian Carlstromf3a26412012-08-24 11:06:02 -070051 long padding0;
52 pthread_mutex_t padding1;
53 int padding2;
54 pthread_cond_t padding3;
55 pthread_cond_t padding4;
56 int padding5;
57 int padding6;
58 pthread_t darwin_pthread_rwlock_owner;
Elliott Hughesf1498432012-03-28 19:34:27 -070059 // ...other stuff we don't care about.
60};
61
62struct __attribute__((__may_alias__)) glibc_pthread_mutex_t {
Ian Rogers00f7d0e2012-07-19 15:28:27 -070063 int32_t padding0[2];
Elliott Hughesf1498432012-03-28 19:34:27 -070064 int owner;
65 // ...other stuff we don't care about.
66};
67
Ian Rogers00f7d0e2012-07-19 15:28:27 -070068struct __attribute__((__may_alias__)) glibc_pthread_rwlock_t {
69#ifdef __LP64__
70 int32_t padding0[6];
71#else
72 int32_t padding0[7];
73#endif
74 int writer;
75 // ...other stuff we don't care about.
76};
77
78ReaderWriterMutex* GlobalSynchronization::mutator_lock_ = NULL;
79Mutex* GlobalSynchronization::thread_list_lock_ = NULL;
80Mutex* GlobalSynchronization::classlinker_classes_lock_ = NULL;
81ReaderWriterMutex* GlobalSynchronization::heap_bitmap_lock_ = NULL;
82Mutex* GlobalSynchronization::abort_lock_ = NULL;
83Mutex* GlobalSynchronization::logging_lock_ = NULL;
84Mutex* GlobalSynchronization::unexpected_signal_lock_ = NULL;
85Mutex* GlobalSynchronization::thread_suspend_count_lock_ = NULL;
86
87void GlobalSynchronization::Init() {
88 if (logging_lock_ != NULL) {
89 // Already initialized.
90 DCHECK(mutator_lock_ != NULL);
91 DCHECK(thread_list_lock_ != NULL);
92 DCHECK(classlinker_classes_lock_ != NULL);
93 DCHECK(heap_bitmap_lock_ != NULL);
94 DCHECK(abort_lock_ != NULL);
95 DCHECK(logging_lock_ != NULL);
96 DCHECK(unexpected_signal_lock_ != NULL);
97 DCHECK(thread_suspend_count_lock_ != NULL);
98 } else {
99 logging_lock_ = new Mutex("logging lock", kLoggingLock, true);
100 abort_lock_ = new Mutex("abort lock", kAbortLock, true);
101 DCHECK(mutator_lock_ == NULL);
102 mutator_lock_ = new ReaderWriterMutex("mutator lock", kMutatorLock);
103 DCHECK(thread_list_lock_ == NULL);
104 thread_list_lock_ = new Mutex("thread list lock", kThreadListLock);
105 DCHECK(classlinker_classes_lock_ == NULL);
106 classlinker_classes_lock_ = new Mutex("ClassLinker classes lock", kClassLinkerClassesLock);
107 DCHECK(heap_bitmap_lock_ == NULL);
108 heap_bitmap_lock_ = new ReaderWriterMutex("heap bitmap lock", kHeapBitmapLock);
109 DCHECK(unexpected_signal_lock_ == NULL);
110 unexpected_signal_lock_ = new Mutex("unexpected signal lock", kUnexpectedSignalLock, true);
111 DCHECK(thread_suspend_count_lock_ == NULL);
112 thread_suspend_count_lock_ = new Mutex("thread suspend count lock", kThreadSuspendCountLock);
Elliott Hughes67d92002012-03-26 15:08:51 -0700113 }
Elliott Hughesa4060e52012-03-02 16:51:35 -0800114}
115
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700116BaseMutex::BaseMutex(const char* name, MutexLevel level) : level_(level), name_(name) {}
117
118static void CheckUnattachedThread(MutexLevel level) {
119 // The check below enumerates the cases where we expect not to be able to sanity check locks
120 // on a thread. TODO: tighten this check.
121 Runtime* runtime = Runtime::Current();
122 CHECK(runtime == NULL || !runtime->IsStarted() || runtime->IsShuttingDown() ||
123 level == kDefaultMutexLevel || level == kThreadListLock ||
124 level == kLoggingLock || level == kAbortLock);
Elliott Hughesffb465f2012-03-01 18:46:05 -0800125}
126
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700127void BaseMutex::RegisterAsLockedWithCurrentThread() {
128 Thread* self = Thread::Current();
129 if (self == NULL) {
130 CheckUnattachedThread(level_);
131 return;
132 }
133 // Check if a bad Mutex of this level or lower is held.
134 bool bad_mutexes_held = false;
135 for (int i = level_; i >= 0; --i) {
136 BaseMutex* held_mutex = self->GetHeldMutex(static_cast<MutexLevel>(i));
137 if (UNLIKELY(held_mutex != NULL)) {
138 LOG(ERROR) << "Lock level violation: holding \"" << held_mutex->name_ << "\" (level " << i
139 << ") while locking \"" << name_ << "\" (level " << static_cast<int>(level_) << ")";
140 if (i > kAbortLock) {
141 // Only abort in the check below if this is more than abort level lock.
142 bad_mutexes_held = true;
143 }
144 }
145 }
146 CHECK(!bad_mutexes_held);
147 // Don't record monitors as they are outside the scope of analysis. They may be inspected off of
148 // the monitor list.
149 if (level_ != kMonitorLock) {
150 self->SetHeldMutex(level_, this);
151 }
152}
153
154void BaseMutex::RegisterAsUnlockedWithCurrentThread() {
155 Thread* self = Thread::Current();
156 if (self == NULL) {
157 CheckUnattachedThread(level_);
158 return;
159 }
160 if (level_ != kMonitorLock) {
161 CHECK(self->GetHeldMutex(level_) == this) << "Unlocking on unacquired mutex: " << name_;
162 self->SetHeldMutex(level_, NULL);
163 }
164}
165
166void BaseMutex::CheckSafeToWait() {
167 Thread* self = Thread::Current();
168 if (self == NULL) {
169 CheckUnattachedThread(level_);
170 return;
171 }
172 CHECK(self->GetHeldMutex(level_) == this) << "Waiting on unacquired mutex: " << name_;
173 bool bad_mutexes_held = false;
174 for (int i = kMaxMutexLevel; i >= 0; --i) {
175 if (i != level_) {
176 BaseMutex* held_mutex = self->GetHeldMutex(static_cast<MutexLevel>(i));
177 if (held_mutex != NULL) {
178 LOG(ERROR) << "Holding " << held_mutex->name_ << " (level " << i
179 << ") while performing wait on: "
180 << name_ << " (level " << static_cast<int>(level_) << ")";
181 bad_mutexes_held = true;
182 }
183 }
184 }
185 CHECK(!bad_mutexes_held);
186}
187
188Mutex::Mutex(const char* name, MutexLevel level, bool recursive)
189 : BaseMutex(name, level), recursive_(recursive), recursion_count_(0) {
Brian Carlstromf3a26412012-08-24 11:06:02 -0700190#if defined(__BIONIC__) || defined(__APPLE__)
191 // Use recursive mutexes for bionic and Apple otherwise the
192 // non-recursive mutexes don't have TIDs to check lock ownership of.
Elliott Hughesbbd9d832011-11-07 14:40:00 -0800193 pthread_mutexattr_t attributes;
194 CHECK_MUTEX_CALL(pthread_mutexattr_init, (&attributes));
195 CHECK_MUTEX_CALL(pthread_mutexattr_settype, (&attributes, PTHREAD_MUTEX_RECURSIVE));
196 CHECK_MUTEX_CALL(pthread_mutex_init, (&mutex_, &attributes));
197 CHECK_MUTEX_CALL(pthread_mutexattr_destroy, (&attributes));
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700198#else
199 CHECK_MUTEX_CALL(pthread_mutex_init, (&mutex_, NULL));
200#endif
Elliott Hughes8daa0922011-09-11 13:46:25 -0700201}
202
203Mutex::~Mutex() {
Elliott Hughese62934d2012-04-09 11:24:29 -0700204 // We can't use CHECK_MUTEX_CALL here because on shutdown a suspended daemon thread
205 // may still be using locks.
Elliott Hughes6b355752012-01-13 16:49:08 -0800206 int rc = pthread_mutex_destroy(&mutex_);
207 if (rc != 0) {
208 errno = rc;
Elliott Hughesb3bd5f02012-03-08 21:05:27 -0800209 // TODO: should we just not log at all if shutting down? this could be the logging mutex!
Elliott Hughes6b355752012-01-13 16:49:08 -0800210 bool shutting_down = Runtime::Current()->IsShuttingDown();
211 PLOG(shutting_down ? WARNING : FATAL) << "pthread_mutex_destroy failed for " << name_;
212 }
Elliott Hughes8daa0922011-09-11 13:46:25 -0700213}
214
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700215void Mutex::ExclusiveLock() {
216 bool is_held = IsExclusiveHeld();
217 CHECK(recursive_ || !is_held)
218 << "Error attempt to recursively lock non-recursive lock \"" << name_ << "\"";
219 if (!is_held) {
220 CHECK_MUTEX_CALL(pthread_mutex_lock, (&mutex_));
221 RegisterAsLockedWithCurrentThread();
222 }
223 recursion_count_++;
224 DCHECK(recursion_count_ == 1 || recursive_) << "Unexpected recursion count on mutex: "
225 << name_ << " " << recursion_count_;
Ian Rogers105245c2012-01-27 11:42:43 -0800226 AssertHeld();
Elliott Hughes8daa0922011-09-11 13:46:25 -0700227}
228
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700229bool Mutex::ExclusiveTryLock() {
230 bool is_held = IsExclusiveHeld();
231 CHECK(recursive_ || !is_held)
232 << "Error attempt to recursively lock non-recursive lock \"" << name_ << "\"";
233 if (!is_held) {
234 int result = pthread_mutex_trylock(&mutex_);
235 if (result == EBUSY) {
236 return false;
237 }
238 if (result != 0) {
239 errno = result;
240 PLOG(FATAL) << "pthread_mutex_trylock failed for " << name_;
241 }
242 RegisterAsLockedWithCurrentThread();
Elliott Hughes8daa0922011-09-11 13:46:25 -0700243 }
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700244 recursion_count_++;
Ian Rogers105245c2012-01-27 11:42:43 -0800245 AssertHeld();
Elliott Hughes8daa0922011-09-11 13:46:25 -0700246 return true;
247}
248
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700249void Mutex::ExclusiveUnlock() {
Ian Rogers105245c2012-01-27 11:42:43 -0800250 AssertHeld();
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700251 recursion_count_--;
252 if (!recursive_ || recursion_count_ == 0) {
253 DCHECK(recursion_count_ == 0 || recursive_) << "Unexpected recursion count on mutex: "
254 << name_ << " " << recursion_count_;
255 RegisterAsUnlockedWithCurrentThread();
256 CHECK_MUTEX_CALL(pthread_mutex_unlock, (&mutex_));
257 }
Elliott Hughes8daa0922011-09-11 13:46:25 -0700258}
259
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700260bool Mutex::IsExclusiveHeld() const {
261 Thread* self = Thread::Current();
262 bool result;
263 if (self == NULL || level_ == kMonitorLock) { // Handle unattached threads and monitors.
264 result = (GetExclusiveOwnerTid() == static_cast<uint64_t>(GetTid()));
265 } else {
266 result = (self->GetHeldMutex(level_) == this);
267 // Sanity debug check that if we think it is locked, so does the pthread.
268 DCHECK(result == (GetExclusiveOwnerTid() == static_cast<uint64_t>(GetTid())));
269 }
270 return result;
Elliott Hughesf1498432012-03-28 19:34:27 -0700271}
272
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700273uint64_t Mutex::GetExclusiveOwnerTid() const {
Elliott Hughes3147a232011-10-12 15:55:07 -0700274#if defined(__BIONIC__)
Elliott Hughesf1498432012-03-28 19:34:27 -0700275 return static_cast<uint64_t>((mutex_.value >> 16) & 0xffff);
Elliott Hughes3147a232011-10-12 15:55:07 -0700276#elif defined(__GLIBC__)
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700277 return reinterpret_cast<const glibc_pthread_mutex_t*>(&mutex_)->owner;
Elliott Hughescf044312012-01-23 18:48:51 -0800278#elif defined(__APPLE__)
Brian Carlstromf3a26412012-08-24 11:06:02 -0700279 const darwin_pthread_mutex_t* dpmutex = reinterpret_cast<const darwin_pthread_mutex_t*>(&mutex_);
280 pthread_t owner = dpmutex->darwin_pthread_mutex_owner;
281 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 Rogers00f7d0e2012-07-19 15:28:27 -0700292ReaderWriterMutex::ReaderWriterMutex(const char* name, MutexLevel level) : BaseMutex(name, level) {
293 CHECK_MUTEX_CALL(pthread_rwlock_init, (&rwlock_, NULL));
294}
295
296ReaderWriterMutex::~ReaderWriterMutex() {
297 // We can't use CHECK_MUTEX_CALL here because on shutdown a suspended daemon thread
298 // may still be using locks.
299 int rc = pthread_rwlock_destroy(&rwlock_);
300 if (rc != 0) {
301 errno = rc;
302 // TODO: should we just not log at all if shutting down? this could be the logging mutex!
303 bool shutting_down = Runtime::Current()->IsShuttingDown();
304 PLOG(shutting_down ? WARNING : FATAL) << "pthread_mutex_destroy failed for " << name_;
Brian Carlstromcd74c4b2012-01-23 13:21:00 -0800305 }
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700306}
307
308void ReaderWriterMutex::ExclusiveLock() {
309 AssertNotExclusiveHeld();
310 CHECK_MUTEX_CALL(pthread_rwlock_wrlock, (&rwlock_));
311 RegisterAsLockedWithCurrentThread();
312 AssertExclusiveHeld();
313}
314
315void ReaderWriterMutex::ExclusiveUnlock() {
316 AssertExclusiveHeld();
317 RegisterAsUnlockedWithCurrentThread();
318 CHECK_MUTEX_CALL(pthread_rwlock_unlock, (&rwlock_));
319}
320
Ian Rogers66aee5c2012-08-15 17:17:47 -0700321#if HAVE_TIMED_RWLOCK
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700322bool ReaderWriterMutex::ExclusiveLockWithTimeout(const timespec& abs_timeout) {
323 int result = pthread_rwlock_timedwrlock(&rwlock_, &abs_timeout);
324 if (result == ETIMEDOUT) {
325 return false;
326 }
327 if (result != 0) {
328 errno = result;
Ian Rogersa5acfd32012-08-15 11:50:10 -0700329 PLOG(FATAL) << "pthread_rwlock_timedwrlock failed for " << name_;
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700330 }
331 RegisterAsLockedWithCurrentThread();
332 AssertSharedHeld();
333 return true;
334}
Ian Rogers66aee5c2012-08-15 17:17:47 -0700335#endif
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700336
337void ReaderWriterMutex::SharedLock() {
338 CHECK_MUTEX_CALL(pthread_rwlock_rdlock, (&rwlock_));
339 RegisterAsLockedWithCurrentThread();
340 AssertSharedHeld();
341}
342
343bool ReaderWriterMutex::SharedTryLock() {
344 int result = pthread_rwlock_tryrdlock(&rwlock_);
345 if (result == EBUSY) {
346 return false;
347 }
348 if (result != 0) {
349 errno = result;
350 PLOG(FATAL) << "pthread_mutex_trylock failed for " << name_;
351 }
352 RegisterAsLockedWithCurrentThread();
353 AssertSharedHeld();
354 return true;
355}
356
357void ReaderWriterMutex::SharedUnlock() {
358 AssertSharedHeld();
359 RegisterAsUnlockedWithCurrentThread();
360 CHECK_MUTEX_CALL(pthread_rwlock_unlock, (&rwlock_));
361}
362
363bool ReaderWriterMutex::IsExclusiveHeld() const {
364 bool result = (GetExclusiveOwnerTid() == static_cast<uint64_t>(GetTid()));
365 // Sanity that if the pthread thinks we own the lock the Thread agrees.
366 Thread* self = Thread::Current();
367 DCHECK((self == NULL) || !result || (self->GetHeldMutex(level_) == this));
368 return result;
369}
370
371bool ReaderWriterMutex::IsSharedHeld() const {
372 Thread* self = Thread::Current();
373 bool result;
374 if (UNLIKELY(self == NULL)) { // Handle unattached threads.
375 result = IsExclusiveHeld(); // TODO: a better best effort here.
376 } else {
377 result = (self->GetHeldMutex(level_) == this);
378 }
379 return result;
380}
381
382uint64_t ReaderWriterMutex::GetExclusiveOwnerTid() const {
Brian Carlstromcd74c4b2012-01-23 13:21:00 -0800383#if defined(__BIONIC__)
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700384 return rwlock_.writerThreadId;
Brian Carlstromcd74c4b2012-01-23 13:21:00 -0800385#elif defined(__GLIBC__)
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700386 return reinterpret_cast<const glibc_pthread_rwlock_t*>(&rwlock_)->writer;
Brian Carlstromcd74c4b2012-01-23 13:21:00 -0800387#elif defined(__APPLE__)
Brian Carlstromf3a26412012-08-24 11:06:02 -0700388 const darwin_pthread_rwlock_t* dprwlock = reinterpret_cast<const darwin_pthread_rwlock_t*>(&rwlock_);
389 pthread_t owner = dprwlock->darwin_pthread_rwlock_owner;
390 if (owner == (pthread_t)0) {
391 return 0;
392 }
393 uint64_t tid;
394 CHECK_PTHREAD_CALL(pthread_threadid_np, (owner, &tid), __FUNCTION__); // Requires Mac OS 10.6
395 return tid;
Brian Carlstromcd74c4b2012-01-23 13:21:00 -0800396#else
Elliott Hughesf1498432012-03-28 19:34:27 -0700397#error unsupported C library
Brian Carlstromcd74c4b2012-01-23 13:21:00 -0800398#endif
Brian Carlstromcd74c4b2012-01-23 13:21:00 -0800399}
400
Elliott Hughes5f791332011-09-15 17:45:30 -0700401ConditionVariable::ConditionVariable(const std::string& name) : name_(name) {
402 CHECK_MUTEX_CALL(pthread_cond_init, (&cond_, NULL));
403}
404
405ConditionVariable::~ConditionVariable() {
Elliott Hughese62934d2012-04-09 11:24:29 -0700406 // We can't use CHECK_MUTEX_CALL here because on shutdown a suspended daemon thread
407 // may still be using condition variables.
408 int rc = pthread_cond_destroy(&cond_);
409 if (rc != 0) {
410 errno = rc;
411 bool shutting_down = Runtime::Current()->IsShuttingDown();
412 PLOG(shutting_down ? WARNING : FATAL) << "pthread_cond_destroy failed for " << name_;
413 }
Elliott Hughes5f791332011-09-15 17:45:30 -0700414}
415
416void ConditionVariable::Broadcast() {
417 CHECK_MUTEX_CALL(pthread_cond_broadcast, (&cond_));
418}
419
420void ConditionVariable::Signal() {
421 CHECK_MUTEX_CALL(pthread_cond_signal, (&cond_));
422}
423
424void ConditionVariable::Wait(Mutex& mutex) {
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700425 mutex.CheckSafeToWait();
426 unsigned int old_recursion_count = mutex.recursion_count_;
427 mutex.recursion_count_ = 0;
Elliott Hughesf1498432012-03-28 19:34:27 -0700428 CHECK_MUTEX_CALL(pthread_cond_wait, (&cond_, &mutex.mutex_));
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700429 mutex.recursion_count_ = old_recursion_count;
Elliott Hughes5f791332011-09-15 17:45:30 -0700430}
431
432void ConditionVariable::TimedWait(Mutex& mutex, const timespec& ts) {
433#ifdef HAVE_TIMEDWAIT_MONOTONIC
434#define TIMEDWAIT pthread_cond_timedwait_monotonic
435#else
436#define TIMEDWAIT pthread_cond_timedwait
437#endif
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700438 mutex.CheckSafeToWait();
439 unsigned int old_recursion_count = mutex.recursion_count_;
440 mutex.recursion_count_ = 0;
Elliott Hughesf1498432012-03-28 19:34:27 -0700441 int rc = TIMEDWAIT(&cond_, &mutex.mutex_, &ts);
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700442 mutex.recursion_count_ = old_recursion_count;
Elliott Hughes5f791332011-09-15 17:45:30 -0700443 if (rc != 0 && rc != ETIMEDOUT) {
444 errno = rc;
445 PLOG(FATAL) << "TimedWait failed for " << name_;
446 }
447}
448
Elliott Hughese62934d2012-04-09 11:24:29 -0700449} // namespace art