mutex.cc revision d9c4fc94fa618617f94e1de9af5f034549100753
1/*
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#include <sys/time.h>
21
22#include "atomic.h"
23#include "base/logging.h"
24#include "cutils/atomic.h"
25#include "cutils/atomic-inline.h"
26#include "mutex-inl.h"
27#include "runtime.h"
28#include "scoped_thread_state_change.h"
29#include "thread-inl.h"
30#include "utils.h"
31
32namespace art {
33
34#if ART_USE_FUTEXES
35static bool ComputeRelativeTimeSpec(timespec* result_ts, const timespec& lhs, const timespec& rhs) {
36  const int32_t one_sec = 1000 * 1000 * 1000;  // one second in nanoseconds.
37  result_ts->tv_sec = lhs.tv_sec - rhs.tv_sec;
38  result_ts->tv_nsec = lhs.tv_nsec - rhs.tv_nsec;
39  if (result_ts->tv_nsec < 0) {
40    result_ts->tv_sec--;
41    result_ts->tv_nsec += one_sec;
42  } else if (result_ts->tv_nsec > one_sec) {
43    result_ts->tv_sec++;
44    result_ts->tv_nsec -= one_sec;
45  }
46  return result_ts->tv_sec < 0;
47}
48#endif
49
50struct AllMutexData {
51  // A guard for all_mutexes_ that's not a mutex (Mutexes must CAS to acquire and busy wait).
52  AtomicInteger all_mutexes_guard;
53  // All created mutexes guarded by all_mutexes_guard_.
54  std::set<BaseMutex*>* all_mutexes;
55  AllMutexData() : all_mutexes(NULL) {}
56};
57static struct AllMutexData gAllMutexData[kAllMutexDataSize];
58
59class ScopedAllMutexesLock {
60 public:
61  explicit ScopedAllMutexesLock(const BaseMutex* mutex) : mutex_(mutex) {
62    while (!gAllMutexData->all_mutexes_guard.compare_and_swap(0, reinterpret_cast<int32_t>(mutex))) {
63      NanoSleep(100);
64    }
65  }
66  ~ScopedAllMutexesLock() {
67    while (!gAllMutexData->all_mutexes_guard.compare_and_swap(reinterpret_cast<int32_t>(mutex_), 0)) {
68      NanoSleep(100);
69    }
70  }
71 private:
72  const BaseMutex* const mutex_;
73};
74
75BaseMutex::BaseMutex(const char* name, LockLevel level) : level_(level), name_(name) {
76  if (kLogLockContentions) {
77    ScopedAllMutexesLock mu(this);
78    std::set<BaseMutex*>** all_mutexes_ptr = &gAllMutexData->all_mutexes;
79    if (*all_mutexes_ptr == NULL) {
80      // We leak the global set of all mutexes to avoid ordering issues in global variable
81      // construction/destruction.
82      *all_mutexes_ptr = new std::set<BaseMutex*>();
83    }
84    (*all_mutexes_ptr)->insert(this);
85  }
86}
87
88BaseMutex::~BaseMutex() {
89  if (kLogLockContentions) {
90    ScopedAllMutexesLock mu(this);
91    gAllMutexData->all_mutexes->erase(this);
92  }
93}
94
95void BaseMutex::DumpAll(std::ostream& os) {
96  if (kLogLockContentions) {
97    os << "Mutex logging:\n";
98    ScopedAllMutexesLock mu(reinterpret_cast<const BaseMutex*>(-1));
99    std::set<BaseMutex*>* all_mutexes = gAllMutexData->all_mutexes;
100    if (all_mutexes == NULL) {
101      // No mutexes have been created yet during at startup.
102      return;
103    }
104    typedef std::set<BaseMutex*>::const_iterator It;
105    os << "(Contended)\n";
106    for (It it = all_mutexes->begin(); it != all_mutexes->end(); ++it) {
107      BaseMutex* mutex = *it;
108      if (mutex->HasEverContended()) {
109        mutex->Dump(os);
110        os << "\n";
111      }
112    }
113    os << "(Never contented)\n";
114    for (It it = all_mutexes->begin(); it != all_mutexes->end(); ++it) {
115      BaseMutex* mutex = *it;
116      if (!mutex->HasEverContended()) {
117        mutex->Dump(os);
118        os << "\n";
119      }
120    }
121  }
122}
123
124void BaseMutex::CheckSafeToWait(Thread* self) {
125  if (self == NULL) {
126    CheckUnattachedThread(level_);
127    return;
128  }
129  if (kDebugLocking) {
130    CHECK(self->GetHeldMutex(level_) == this || level_ == kMonitorLock)
131        << "Waiting on unacquired mutex: " << name_;
132    bool bad_mutexes_held = false;
133    for (int i = kLockLevelCount - 1; i >= 0; --i) {
134      if (i != level_) {
135        BaseMutex* held_mutex = self->GetHeldMutex(static_cast<LockLevel>(i));
136        if (held_mutex != NULL) {
137          LOG(ERROR) << "Holding \"" << held_mutex->name_ << "\" "
138                     << "(level " << LockLevel(i) << ") while performing wait on "
139                     << "\"" << name_ << "\" (level " << level_ << ")";
140          bad_mutexes_held = true;
141        }
142      }
143    }
144    CHECK(!bad_mutexes_held);
145  }
146}
147
148inline void BaseMutex::ContentionLogData::AddToWaitTime(uint64_t value) {
149  if (kLogLockContentions) {
150    // Atomically add value to wait_time.
151    uint64_t new_val, old_val;
152    volatile int64_t* addr = reinterpret_cast<volatile int64_t*>(&wait_time);
153    volatile const int64_t* caddr = const_cast<volatile const int64_t*>(addr);
154    do {
155      old_val = static_cast<uint64_t>(QuasiAtomic::Read64(caddr));
156      new_val = old_val + value;
157    } while (!QuasiAtomic::Cas64(static_cast<int64_t>(old_val), static_cast<int64_t>(new_val), addr));
158  }
159}
160
161void BaseMutex::RecordContention(uint64_t blocked_tid,
162                                 uint64_t owner_tid,
163                                 uint64_t nano_time_blocked) {
164  if (kLogLockContentions) {
165    ContentionLogData* data = contetion_log_data_;
166    ++(data->contention_count);
167    data->AddToWaitTime(nano_time_blocked);
168    ContentionLogEntry* log = data->contention_log;
169    // This code is intentionally racy as it is only used for diagnostics.
170    uint32_t slot = data->cur_content_log_entry;
171    if (log[slot].blocked_tid == blocked_tid &&
172        log[slot].owner_tid == blocked_tid) {
173      ++log[slot].count;
174    } else {
175      uint32_t new_slot;
176      do {
177        slot = data->cur_content_log_entry;
178        new_slot = (slot + 1) % kContentionLogSize;
179      } while (!data->cur_content_log_entry.compare_and_swap(slot, new_slot));
180      log[new_slot].blocked_tid = blocked_tid;
181      log[new_slot].owner_tid = owner_tid;
182      log[new_slot].count = 1;
183    }
184  }
185}
186
187void BaseMutex::DumpContention(std::ostream& os) const {
188  if (kLogLockContentions) {
189    const ContentionLogData* data = contetion_log_data_;
190    const ContentionLogEntry* log = data->contention_log;
191    uint64_t wait_time = data->wait_time;
192    uint32_t contention_count = data->contention_count;
193    if (contention_count == 0) {
194      os << "never contended";
195    } else {
196      os << "contended " << contention_count
197         << " times, average wait of contender " << PrettyDuration(wait_time / contention_count);
198      SafeMap<uint64_t, size_t> most_common_blocker;
199      SafeMap<uint64_t, size_t> most_common_blocked;
200      typedef SafeMap<uint64_t, size_t>::const_iterator It;
201      for (size_t i = 0; i < kContentionLogSize; ++i) {
202        uint64_t blocked_tid = log[i].blocked_tid;
203        uint64_t owner_tid = log[i].owner_tid;
204        uint32_t count = log[i].count;
205        if (count > 0) {
206          It it = most_common_blocked.find(blocked_tid);
207          if (it != most_common_blocked.end()) {
208            most_common_blocked.Overwrite(blocked_tid, it->second + count);
209          } else {
210            most_common_blocked.Put(blocked_tid, count);
211          }
212          it = most_common_blocker.find(owner_tid);
213          if (it != most_common_blocker.end()) {
214            most_common_blocker.Overwrite(owner_tid, it->second + count);
215          } else {
216            most_common_blocker.Put(owner_tid, count);
217          }
218        }
219      }
220      uint64_t max_tid = 0;
221      size_t max_tid_count = 0;
222      for (It it = most_common_blocked.begin(); it != most_common_blocked.end(); ++it) {
223        if (it->second > max_tid_count) {
224          max_tid = it->first;
225          max_tid_count = it->second;
226        }
227      }
228      if (max_tid != 0) {
229        os << " sample shows most blocked tid=" << max_tid;
230      }
231      max_tid = 0;
232      max_tid_count = 0;
233      for (It it = most_common_blocker.begin(); it != most_common_blocker.end(); ++it) {
234        if (it->second > max_tid_count) {
235          max_tid = it->first;
236          max_tid_count = it->second;
237        }
238      }
239      if (max_tid != 0) {
240        os << " sample shows tid=" << max_tid << " owning during this time";
241      }
242    }
243  }
244}
245
246
247Mutex::Mutex(const char* name, LockLevel level, bool recursive)
248    : BaseMutex(name, level), recursive_(recursive), recursion_count_(0) {
249#if ART_USE_FUTEXES
250  state_ = 0;
251  exclusive_owner_ = 0;
252  num_contenders_ = 0;
253#elif defined(__BIONIC__) || defined(__APPLE__)
254  // Use recursive mutexes for bionic and Apple otherwise the
255  // non-recursive mutexes don't have TIDs to check lock ownership of.
256  pthread_mutexattr_t attributes;
257  CHECK_MUTEX_CALL(pthread_mutexattr_init, (&attributes));
258  CHECK_MUTEX_CALL(pthread_mutexattr_settype, (&attributes, PTHREAD_MUTEX_RECURSIVE));
259  CHECK_MUTEX_CALL(pthread_mutex_init, (&mutex_, &attributes));
260  CHECK_MUTEX_CALL(pthread_mutexattr_destroy, (&attributes));
261#else
262  CHECK_MUTEX_CALL(pthread_mutex_init, (&mutex_, NULL));
263#endif
264}
265
266Mutex::~Mutex() {
267#if ART_USE_FUTEXES
268  if (state_ != 0) {
269    MutexLock mu(Thread::Current(), *Locks::runtime_shutdown_lock_);
270    Runtime* runtime = Runtime::Current();
271    bool shutting_down = (runtime == NULL) || runtime->IsShuttingDown();
272    LOG(shutting_down ? WARNING : FATAL) << "destroying mutex with owner: " << exclusive_owner_;
273  } else {
274    CHECK_EQ(exclusive_owner_, 0U)  << "unexpectedly found an owner on unlocked mutex " << name_;
275    CHECK_EQ(num_contenders_, 0) << "unexpectedly found a contender on mutex " << name_;
276  }
277#else
278  // We can't use CHECK_MUTEX_CALL here because on shutdown a suspended daemon thread
279  // may still be using locks.
280  int rc = pthread_mutex_destroy(&mutex_);
281  if (rc != 0) {
282    errno = rc;
283    // TODO: should we just not log at all if shutting down? this could be the logging mutex!
284    MutexLock mu(Thread::Current(), *Locks::runtime_shutdown_lock_);
285    Runtime* runtime = Runtime::Current();
286    bool shutting_down = (runtime == NULL) || runtime->IsShuttingDown();
287    PLOG(shutting_down ? WARNING : FATAL) << "pthread_mutex_destroy failed for " << name_;
288  }
289#endif
290}
291
292void Mutex::ExclusiveLock(Thread* self) {
293  DCHECK(self == NULL || self == Thread::Current());
294  if (kDebugLocking && !recursive_) {
295    AssertNotHeld(self);
296  }
297  if (!recursive_ || !IsExclusiveHeld(self)) {
298#if ART_USE_FUTEXES
299    bool done = false;
300    do {
301      int32_t cur_state = state_;
302      if (LIKELY(cur_state == 0)) {
303        // Change state from 0 to 1.
304        done = android_atomic_acquire_cas(0, 1, &state_) == 0;
305      } else {
306        // Failed to acquire, hang up.
307        ScopedContentionRecorder scr(this, SafeGetTid(self), GetExclusiveOwnerTid());
308        android_atomic_inc(&num_contenders_);
309        if (futex(&state_, FUTEX_WAIT, 1, NULL, NULL, 0) != 0) {
310          // EAGAIN and EINTR both indicate a spurious failure, try again from the beginning.
311          // We don't use TEMP_FAILURE_RETRY so we can intentionally retry to acquire the lock.
312          if ((errno != EAGAIN) && (errno != EINTR)) {
313            PLOG(FATAL) << "futex wait failed for " << name_;
314          }
315        }
316        android_atomic_dec(&num_contenders_);
317      }
318    } while (!done);
319    DCHECK_EQ(state_, 1);
320    exclusive_owner_ = SafeGetTid(self);
321#else
322    CHECK_MUTEX_CALL(pthread_mutex_lock, (&mutex_));
323#endif
324    RegisterAsLocked(self);
325  }
326  recursion_count_++;
327  if (kDebugLocking) {
328    CHECK(recursion_count_ == 1 || recursive_) << "Unexpected recursion count on mutex: "
329        << name_ << " " << recursion_count_;
330    AssertHeld(self);
331  }
332}
333
334bool Mutex::ExclusiveTryLock(Thread* self) {
335  DCHECK(self == NULL || self == Thread::Current());
336  if (kDebugLocking && !recursive_) {
337    AssertNotHeld(self);
338  }
339  if (!recursive_ || !IsExclusiveHeld(self)) {
340#if ART_USE_FUTEXES
341    bool done = false;
342    do {
343      int32_t cur_state = state_;
344      if (cur_state == 0) {
345        // Change state from 0 to 1.
346        done = android_atomic_acquire_cas(0, 1, &state_) == 0;
347      } else {
348        return false;
349      }
350    } while (!done);
351    DCHECK_EQ(state_, 1);
352    exclusive_owner_ = SafeGetTid(self);
353#else
354    int result = pthread_mutex_trylock(&mutex_);
355    if (result == EBUSY) {
356      return false;
357    }
358    if (result != 0) {
359      errno = result;
360      PLOG(FATAL) << "pthread_mutex_trylock failed for " << name_;
361    }
362#endif
363    RegisterAsLocked(self);
364  }
365  recursion_count_++;
366  if (kDebugLocking) {
367    CHECK(recursion_count_ == 1 || recursive_) << "Unexpected recursion count on mutex: "
368        << name_ << " " << recursion_count_;
369    AssertHeld(self);
370  }
371  return true;
372}
373
374void Mutex::ExclusiveUnlock(Thread* self) {
375  DCHECK(self == NULL || self == Thread::Current());
376  AssertHeld(self);
377  recursion_count_--;
378  if (!recursive_ || recursion_count_ == 0) {
379    if (kDebugLocking) {
380      CHECK(recursion_count_ == 0 || recursive_) << "Unexpected recursion count on mutex: "
381          << name_ << " " << recursion_count_;
382    }
383    RegisterAsUnlocked(self);
384#if ART_USE_FUTEXES
385  bool done = false;
386  do {
387    int32_t cur_state = state_;
388    if (LIKELY(cur_state == 1)) {
389      // We're no longer the owner.
390      exclusive_owner_ = 0;
391      // Change state to 0.
392      done = android_atomic_release_cas(cur_state, 0, &state_) == 0;
393      if (LIKELY(done)) {  // Spurious fail?
394        // Wake a contender
395        if (UNLIKELY(num_contenders_ > 0)) {
396          futex(&state_, FUTEX_WAKE, 1, NULL, NULL, 0);
397        }
398      }
399    } else {
400      // Logging acquires the logging lock, avoid infinite recursion in that case.
401      if (this != Locks::logging_lock_) {
402        LOG(FATAL) << "Unexpected state_ in unlock " << cur_state << " for " << name_;
403      } else {
404        LogMessageData data(__FILE__, __LINE__, INTERNAL_FATAL, -1);
405        LogMessage::LogLine(data, StringPrintf("Unexpected state_ %d in unlock for %s",
406                                               cur_state, name_).c_str());
407        _exit(1);
408      }
409    }
410  } while (!done);
411#else
412    CHECK_MUTEX_CALL(pthread_mutex_unlock, (&mutex_));
413#endif
414  }
415}
416
417void Mutex::Dump(std::ostream& os) const {
418  os << (recursive_ ? "recursive " : "non-recursive ")
419      << name_
420      << " level=" << static_cast<int>(level_)
421      << " rec=" << recursion_count_
422      << " owner=" << GetExclusiveOwnerTid() << " ";
423  DumpContention(os);
424}
425
426std::ostream& operator<<(std::ostream& os, const Mutex& mu) {
427  mu.Dump(os);
428  return os;
429}
430
431ReaderWriterMutex::ReaderWriterMutex(const char* name, LockLevel level)
432    : BaseMutex(name, level)
433#if ART_USE_FUTEXES
434    , state_(0), exclusive_owner_(0), num_pending_readers_(0), num_pending_writers_(0)
435#endif
436{  // NOLINT(whitespace/braces)
437#if !ART_USE_FUTEXES
438  CHECK_MUTEX_CALL(pthread_rwlock_init, (&rwlock_, NULL));
439#endif
440}
441
442ReaderWriterMutex::~ReaderWriterMutex() {
443#if ART_USE_FUTEXES
444  CHECK_EQ(state_, 0);
445  CHECK_EQ(exclusive_owner_, 0U);
446  CHECK_EQ(num_pending_readers_, 0);
447  CHECK_EQ(num_pending_writers_, 0);
448#else
449  // We can't use CHECK_MUTEX_CALL here because on shutdown a suspended daemon thread
450  // may still be using locks.
451  int rc = pthread_rwlock_destroy(&rwlock_);
452  if (rc != 0) {
453    errno = rc;
454    // TODO: should we just not log at all if shutting down? this could be the logging mutex!
455    MutexLock mu(Thread::Current(), *Locks::runtime_shutdown_lock_);
456    Runtime* runtime = Runtime::Current();
457    bool shutting_down = runtime == NULL || runtime->IsShuttingDown();
458    PLOG(shutting_down ? WARNING : FATAL) << "pthread_rwlock_destroy failed for " << name_;
459  }
460#endif
461}
462
463void ReaderWriterMutex::ExclusiveLock(Thread* self) {
464  DCHECK(self == NULL || self == Thread::Current());
465  AssertNotExclusiveHeld(self);
466#if ART_USE_FUTEXES
467  bool done = false;
468  do {
469    int32_t cur_state = state_;
470    if (LIKELY(cur_state == 0)) {
471      // Change state from 0 to -1.
472      done = android_atomic_acquire_cas(0, -1, &state_) == 0;
473    } else {
474      // Failed to acquire, hang up.
475      ScopedContentionRecorder scr(this, SafeGetTid(self), GetExclusiveOwnerTid());
476      android_atomic_inc(&num_pending_writers_);
477      if (futex(&state_, FUTEX_WAIT, cur_state, NULL, NULL, 0) != 0) {
478        // EAGAIN and EINTR both indicate a spurious failure, try again from the beginning.
479        // We don't use TEMP_FAILURE_RETRY so we can intentionally retry to acquire the lock.
480        if ((errno != EAGAIN) && (errno != EINTR)) {
481          PLOG(FATAL) << "futex wait failed for " << name_;
482        }
483      }
484      android_atomic_dec(&num_pending_writers_);
485    }
486  } while (!done);
487  DCHECK_EQ(state_, -1);
488  exclusive_owner_ = SafeGetTid(self);
489#else
490  CHECK_MUTEX_CALL(pthread_rwlock_wrlock, (&rwlock_));
491#endif
492  RegisterAsLocked(self);
493  AssertExclusiveHeld(self);
494}
495
496void ReaderWriterMutex::ExclusiveUnlock(Thread* self) {
497  DCHECK(self == NULL || self == Thread::Current());
498  AssertExclusiveHeld(self);
499  RegisterAsUnlocked(self);
500#if ART_USE_FUTEXES
501  bool done = false;
502  do {
503    int32_t cur_state = state_;
504    if (LIKELY(cur_state == -1)) {
505      // We're no longer the owner.
506      exclusive_owner_ = 0;
507      // Change state from -1 to 0.
508      done = android_atomic_release_cas(-1, 0, &state_) == 0;
509      if (LIKELY(done)) {  // cmpxchg may fail due to noise?
510        // Wake any waiters.
511        if (UNLIKELY(num_pending_readers_ > 0 || num_pending_writers_ > 0)) {
512          futex(&state_, FUTEX_WAKE, -1, NULL, NULL, 0);
513        }
514      }
515    } else {
516      LOG(FATAL) << "Unexpected state_:" << cur_state << " for " << name_;
517    }
518  } while (!done);
519#else
520  CHECK_MUTEX_CALL(pthread_rwlock_unlock, (&rwlock_));
521#endif
522}
523
524#if HAVE_TIMED_RWLOCK
525bool ReaderWriterMutex::ExclusiveLockWithTimeout(Thread* self, int64_t ms, int32_t ns) {
526  DCHECK(self == NULL || self == Thread::Current());
527#if ART_USE_FUTEXES
528  bool done = false;
529  timespec end_abs_ts;
530  InitTimeSpec(true, CLOCK_REALTIME, ms, ns, &end_abs_ts);
531  do {
532    int32_t cur_state = state_;
533    if (cur_state == 0) {
534      // Change state from 0 to -1.
535      done = android_atomic_acquire_cas(0, -1, &state_) == 0;
536    } else {
537      // Failed to acquire, hang up.
538      timespec now_abs_ts;
539      InitTimeSpec(true, CLOCK_REALTIME, 0, 0, &now_abs_ts);
540      timespec rel_ts;
541      if (ComputeRelativeTimeSpec(&rel_ts, end_abs_ts, now_abs_ts)) {
542        return false;  // Timed out.
543      }
544      ScopedContentionRecorder scr(this, SafeGetTid(self), GetExclusiveOwnerTid());
545      android_atomic_inc(&num_pending_writers_);
546      if (futex(&state_, FUTEX_WAIT, cur_state, &rel_ts, NULL, 0) != 0) {
547        if (errno == ETIMEDOUT) {
548          android_atomic_dec(&num_pending_writers_);
549          return false;  // Timed out.
550        } else if ((errno != EAGAIN) && (errno != EINTR)) {
551          // EAGAIN and EINTR both indicate a spurious failure,
552          // recompute the relative time out from now and try again.
553          // We don't use TEMP_FAILURE_RETRY so we can recompute rel_ts;
554          PLOG(FATAL) << "timed futex wait failed for " << name_;
555        }
556      }
557      android_atomic_dec(&num_pending_writers_);
558    }
559  } while (!done);
560  exclusive_owner_ = SafeGetTid(self);
561#else
562  timespec ts;
563  InitTimeSpec(true, CLOCK_REALTIME, ms, ns, &ts);
564  int result = pthread_rwlock_timedwrlock(&rwlock_, &ts);
565  if (result == ETIMEDOUT) {
566    return false;
567  }
568  if (result != 0) {
569    errno = result;
570    PLOG(FATAL) << "pthread_rwlock_timedwrlock failed for " << name_;
571  }
572#endif
573  RegisterAsLocked(self);
574  AssertSharedHeld(self);
575  return true;
576}
577#endif
578
579bool ReaderWriterMutex::SharedTryLock(Thread* self) {
580  DCHECK(self == NULL || self == Thread::Current());
581#if ART_USE_FUTEXES
582  bool done = false;
583  do {
584    int32_t cur_state = state_;
585    if (cur_state >= 0) {
586      // Add as an extra reader.
587      done = android_atomic_acquire_cas(cur_state, cur_state + 1, &state_) == 0;
588    } else {
589      // Owner holds it exclusively.
590      return false;
591    }
592  } while (!done);
593#else
594  int result = pthread_rwlock_tryrdlock(&rwlock_);
595  if (result == EBUSY) {
596    return false;
597  }
598  if (result != 0) {
599    errno = result;
600    PLOG(FATAL) << "pthread_mutex_trylock failed for " << name_;
601  }
602#endif
603  RegisterAsLocked(self);
604  AssertSharedHeld(self);
605  return true;
606}
607
608bool ReaderWriterMutex::IsSharedHeld(const Thread* self) const {
609  DCHECK(self == NULL || self == Thread::Current());
610  bool result;
611  if (UNLIKELY(self == NULL)) {  // Handle unattached threads.
612    result = IsExclusiveHeld(self);  // TODO: a better best effort here.
613  } else {
614    result = (self->GetHeldMutex(level_) == this);
615  }
616  return result;
617}
618
619void ReaderWriterMutex::Dump(std::ostream& os) const {
620  os << name_
621      << " level=" << static_cast<int>(level_)
622      << " owner=" << GetExclusiveOwnerTid() << " ";
623  DumpContention(os);
624}
625
626std::ostream& operator<<(std::ostream& os, const ReaderWriterMutex& mu) {
627  mu.Dump(os);
628  return os;
629}
630
631ConditionVariable::ConditionVariable(const char* name, Mutex& guard)
632    : name_(name), guard_(guard) {
633#if ART_USE_FUTEXES
634  sequence_ = 0;
635  num_waiters_ = 0;
636#else
637  CHECK_MUTEX_CALL(pthread_cond_init, (&cond_, NULL));
638#endif
639}
640
641ConditionVariable::~ConditionVariable() {
642#if ART_USE_FUTEXES
643  if (num_waiters_!= 0) {
644    MutexLock mu(Thread::Current(), *Locks::runtime_shutdown_lock_);
645    Runtime* runtime = Runtime::Current();
646    bool shutting_down = (runtime == NULL) || runtime->IsShuttingDown();
647    LOG(shutting_down ? WARNING : FATAL) << "ConditionVariable::~ConditionVariable for " << name_
648        << " called with " << num_waiters_ << " waiters.";
649  }
650#else
651  // We can't use CHECK_MUTEX_CALL here because on shutdown a suspended daemon thread
652  // may still be using condition variables.
653  int rc = pthread_cond_destroy(&cond_);
654  if (rc != 0) {
655    errno = rc;
656    MutexLock mu(Thread::Current(), *Locks::runtime_shutdown_lock_);
657    Runtime* runtime = Runtime::Current();
658    bool shutting_down = (runtime == NULL) || runtime->IsShuttingDown();
659    PLOG(shutting_down ? WARNING : FATAL) << "pthread_cond_destroy failed for " << name_;
660  }
661#endif
662}
663
664void ConditionVariable::Broadcast(Thread* self) {
665  DCHECK(self == NULL || self == Thread::Current());
666  // TODO: enable below, there's a race in thread creation that causes false failures currently.
667  // guard_.AssertExclusiveHeld(self);
668  DCHECK_EQ(guard_.GetExclusiveOwnerTid(), SafeGetTid(self));
669#if ART_USE_FUTEXES
670  if (num_waiters_ > 0) {
671    android_atomic_inc(&sequence_);  // Indicate the broadcast occurred.
672    bool done = false;
673    do {
674      int32_t cur_sequence = sequence_;
675      // Requeue waiters onto mutex. The waiter holds the contender count on the mutex high ensuring
676      // mutex unlocks will awaken the requeued waiter thread.
677      done = futex(&sequence_, FUTEX_CMP_REQUEUE, 0,
678                   reinterpret_cast<const timespec*>(std::numeric_limits<int32_t>::max()),
679                   &guard_.state_, cur_sequence) != -1;
680      if (!done) {
681        if (errno != EAGAIN) {
682          PLOG(FATAL) << "futex cmp requeue failed for " << name_;
683        }
684      }
685    } while (!done);
686  }
687#else
688  CHECK_MUTEX_CALL(pthread_cond_broadcast, (&cond_));
689#endif
690}
691
692void ConditionVariable::Signal(Thread* self) {
693  DCHECK(self == NULL || self == Thread::Current());
694  guard_.AssertExclusiveHeld(self);
695#if ART_USE_FUTEXES
696  if (num_waiters_ > 0) {
697    android_atomic_inc(&sequence_);  // Indicate a signal occurred.
698    // Futex wake 1 waiter who will then come and in contend on mutex. It'd be nice to requeue them
699    // to avoid this, however, requeueing can only move all waiters.
700    int num_woken = futex(&sequence_, FUTEX_WAKE, 1, NULL, NULL, 0);
701    // Check something was woken or else we changed sequence_ before they had chance to wait.
702    CHECK((num_woken == 0) || (num_woken == 1));
703  }
704#else
705  CHECK_MUTEX_CALL(pthread_cond_signal, (&cond_));
706#endif
707}
708
709void ConditionVariable::Wait(Thread* self) {
710  guard_.CheckSafeToWait(self);
711  WaitHoldingLocks(self);
712}
713
714void ConditionVariable::WaitHoldingLocks(Thread* self) {
715  DCHECK(self == NULL || self == Thread::Current());
716  guard_.AssertExclusiveHeld(self);
717  unsigned int old_recursion_count = guard_.recursion_count_;
718#if ART_USE_FUTEXES
719  num_waiters_++;
720  // Ensure the Mutex is contended so that requeued threads are awoken.
721  android_atomic_inc(&guard_.num_contenders_);
722  guard_.recursion_count_ = 1;
723  int32_t cur_sequence = sequence_;
724  guard_.ExclusiveUnlock(self);
725  if (futex(&sequence_, FUTEX_WAIT, cur_sequence, NULL, NULL, 0) != 0) {
726    // Futex failed, check it is an expected error.
727    // EAGAIN == EWOULDBLK, so we let the caller try again.
728    // EINTR implies a signal was sent to this thread.
729    if ((errno != EINTR) && (errno != EAGAIN)) {
730      PLOG(FATAL) << "futex wait failed for " << name_;
731    }
732  }
733  guard_.ExclusiveLock(self);
734  CHECK_GE(num_waiters_, 0);
735  num_waiters_--;
736  // We awoke and so no longer require awakes from the guard_'s unlock.
737  CHECK_GE(guard_.num_contenders_, 0);
738  android_atomic_dec(&guard_.num_contenders_);
739#else
740  guard_.recursion_count_ = 0;
741  CHECK_MUTEX_CALL(pthread_cond_wait, (&cond_, &guard_.mutex_));
742#endif
743  guard_.recursion_count_ = old_recursion_count;
744}
745
746void ConditionVariable::TimedWait(Thread* self, int64_t ms, int32_t ns) {
747  DCHECK(self == NULL || self == Thread::Current());
748  guard_.AssertExclusiveHeld(self);
749  guard_.CheckSafeToWait(self);
750  unsigned int old_recursion_count = guard_.recursion_count_;
751#if ART_USE_FUTEXES
752  timespec rel_ts;
753  InitTimeSpec(false, CLOCK_REALTIME, ms, ns, &rel_ts);
754  num_waiters_++;
755  // Ensure the Mutex is contended so that requeued threads are awoken.
756  android_atomic_inc(&guard_.num_contenders_);
757  guard_.recursion_count_ = 1;
758  int32_t cur_sequence = sequence_;
759  guard_.ExclusiveUnlock(self);
760  if (futex(&sequence_, FUTEX_WAIT, cur_sequence, &rel_ts, NULL, 0) != 0) {
761    if (errno == ETIMEDOUT) {
762      // Timed out we're done.
763    } else if ((errno == EAGAIN) || (errno == EINTR)) {
764      // A signal or ConditionVariable::Signal/Broadcast has come in.
765    } else {
766      PLOG(FATAL) << "timed futex wait failed for " << name_;
767    }
768  }
769  guard_.ExclusiveLock(self);
770  CHECK_GE(num_waiters_, 0);
771  num_waiters_--;
772  // We awoke and so no longer require awakes from the guard_'s unlock.
773  CHECK_GE(guard_.num_contenders_, 0);
774  android_atomic_dec(&guard_.num_contenders_);
775#else
776#ifdef HAVE_TIMEDWAIT_MONOTONIC
777#define TIMEDWAIT pthread_cond_timedwait_monotonic
778  int clock = CLOCK_MONOTONIC;
779#else
780#define TIMEDWAIT pthread_cond_timedwait
781  int clock = CLOCK_REALTIME;
782#endif
783  guard_.recursion_count_ = 0;
784  timespec ts;
785  InitTimeSpec(true, clock, ms, ns, &ts);
786  int rc = TEMP_FAILURE_RETRY(TIMEDWAIT(&cond_, &guard_.mutex_, &ts));
787  if (rc != 0 && rc != ETIMEDOUT) {
788    errno = rc;
789    PLOG(FATAL) << "TimedWait failed for " << name_;
790  }
791#endif
792  guard_.recursion_count_ = old_recursion_count;
793}
794
795}  // namespace art
796