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