Home | History | Annotate | Download | only in base
      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 #ifndef ART_RUNTIME_BASE_MUTEX_H_
     18 #define ART_RUNTIME_BASE_MUTEX_H_
     19 
     20 #include <limits.h>  // for INT_MAX
     21 #include <pthread.h>
     22 #include <stdint.h>
     23 #include <unistd.h>  // for pid_t
     24 
     25 #include <iosfwd>
     26 #include <string>
     27 
     28 #include <android-base/logging.h>
     29 
     30 #include "base/aborting.h"
     31 #include "base/atomic.h"
     32 #include "runtime_globals.h"
     33 #include "base/macros.h"
     34 #include "locks.h"
     35 
     36 #if defined(__linux__)
     37 #define ART_USE_FUTEXES 1
     38 #else
     39 #define ART_USE_FUTEXES 0
     40 #endif
     41 
     42 // Currently Darwin doesn't support locks with timeouts.
     43 #if !defined(__APPLE__)
     44 #define HAVE_TIMED_RWLOCK 1
     45 #else
     46 #define HAVE_TIMED_RWLOCK 0
     47 #endif
     48 
     49 namespace art {
     50 
     51 class SHARED_LOCKABLE ReaderWriterMutex;
     52 class SHARED_LOCKABLE MutatorMutex;
     53 class ScopedContentionRecorder;
     54 class Thread;
     55 class LOCKABLE Mutex;
     56 
     57 constexpr bool kDebugLocking = kIsDebugBuild;
     58 
     59 // Record Log contention information, dumpable via SIGQUIT.
     60 #ifdef ART_USE_FUTEXES
     61 // To enable lock contention logging, set this to true.
     62 constexpr bool kLogLockContentions = false;
     63 // FUTEX_WAKE first argument:
     64 constexpr int kWakeOne = 1;
     65 constexpr int kWakeAll = INT_MAX;
     66 #else
     67 // Keep this false as lock contention logging is supported only with
     68 // futex.
     69 constexpr bool kLogLockContentions = false;
     70 #endif
     71 constexpr size_t kContentionLogSize = 4;
     72 constexpr size_t kContentionLogDataSize = kLogLockContentions ? 1 : 0;
     73 constexpr size_t kAllMutexDataSize = kLogLockContentions ? 1 : 0;
     74 
     75 // Base class for all Mutex implementations
     76 class BaseMutex {
     77  public:
     78   const char* GetName() const {
     79     return name_;
     80   }
     81 
     82   virtual bool IsMutex() const { return false; }
     83   virtual bool IsReaderWriterMutex() const { return false; }
     84   virtual bool IsMutatorMutex() const { return false; }
     85 
     86   virtual void Dump(std::ostream& os) const = 0;
     87 
     88   static void DumpAll(std::ostream& os);
     89 
     90   bool ShouldRespondToEmptyCheckpointRequest() const {
     91     return should_respond_to_empty_checkpoint_request_;
     92   }
     93 
     94   void SetShouldRespondToEmptyCheckpointRequest(bool value) {
     95     should_respond_to_empty_checkpoint_request_ = value;
     96   }
     97 
     98   virtual void WakeupToRespondToEmptyCheckpoint() = 0;
     99 
    100  protected:
    101   friend class ConditionVariable;
    102 
    103   BaseMutex(const char* name, LockLevel level);
    104   virtual ~BaseMutex();
    105   void RegisterAsLocked(Thread* self);
    106   void RegisterAsUnlocked(Thread* self);
    107   void CheckSafeToWait(Thread* self);
    108 
    109   friend class ScopedContentionRecorder;
    110 
    111   void RecordContention(uint64_t blocked_tid, uint64_t owner_tid, uint64_t nano_time_blocked);
    112   void DumpContention(std::ostream& os) const;
    113 
    114   const char* const name_;
    115 
    116   // A log entry that records contention but makes no guarantee that either tid will be held live.
    117   struct ContentionLogEntry {
    118     ContentionLogEntry() : blocked_tid(0), owner_tid(0) {}
    119     uint64_t blocked_tid;
    120     uint64_t owner_tid;
    121     AtomicInteger count;
    122   };
    123   struct ContentionLogData {
    124     ContentionLogEntry contention_log[kContentionLogSize];
    125     // The next entry in the contention log to be updated. Value ranges from 0 to
    126     // kContentionLogSize - 1.
    127     AtomicInteger cur_content_log_entry;
    128     // Number of times the Mutex has been contended.
    129     AtomicInteger contention_count;
    130     // Sum of time waited by all contenders in ns.
    131     Atomic<uint64_t> wait_time;
    132     void AddToWaitTime(uint64_t value);
    133     ContentionLogData() : wait_time(0) {}
    134   };
    135   ContentionLogData contention_log_data_[kContentionLogDataSize];
    136 
    137   const LockLevel level_;  // Support for lock hierarchy.
    138   bool should_respond_to_empty_checkpoint_request_;
    139 
    140  public:
    141   bool HasEverContended() const {
    142     if (kLogLockContentions) {
    143       return contention_log_data_->contention_count.load(std::memory_order_seq_cst) > 0;
    144     }
    145     return false;
    146   }
    147 };
    148 
    149 // A Mutex is used to achieve mutual exclusion between threads. A Mutex can be used to gain
    150 // exclusive access to what it guards. A Mutex can be in one of two states:
    151 // - Free - not owned by any thread,
    152 // - Exclusive - owned by a single thread.
    153 //
    154 // The effect of locking and unlocking operations on the state is:
    155 // State     | ExclusiveLock | ExclusiveUnlock
    156 // -------------------------------------------
    157 // Free      | Exclusive     | error
    158 // Exclusive | Block*        | Free
    159 // * Mutex is not reentrant and so an attempt to ExclusiveLock on the same thread will result in
    160 //   an error. Being non-reentrant simplifies Waiting on ConditionVariables.
    161 std::ostream& operator<<(std::ostream& os, const Mutex& mu);
    162 class LOCKABLE Mutex : public BaseMutex {
    163  public:
    164   explicit Mutex(const char* name, LockLevel level = kDefaultMutexLevel, bool recursive = false);
    165   ~Mutex();
    166 
    167   bool IsMutex() const override { return true; }
    168 
    169   // Block until mutex is free then acquire exclusive access.
    170   void ExclusiveLock(Thread* self) ACQUIRE();
    171   void Lock(Thread* self) ACQUIRE() {  ExclusiveLock(self); }
    172 
    173   // Returns true if acquires exclusive access, false otherwise.
    174   bool ExclusiveTryLock(Thread* self) TRY_ACQUIRE(true);
    175   bool TryLock(Thread* self) TRY_ACQUIRE(true) { return ExclusiveTryLock(self); }
    176 
    177   // Release exclusive access.
    178   void ExclusiveUnlock(Thread* self) RELEASE();
    179   void Unlock(Thread* self) RELEASE() {  ExclusiveUnlock(self); }
    180 
    181   // Is the current thread the exclusive holder of the Mutex.
    182   ALWAYS_INLINE bool IsExclusiveHeld(const Thread* self) const;
    183 
    184   // Assert that the Mutex is exclusively held by the current thread.
    185   ALWAYS_INLINE void AssertExclusiveHeld(const Thread* self) const ASSERT_CAPABILITY(this);
    186   ALWAYS_INLINE void AssertHeld(const Thread* self) const ASSERT_CAPABILITY(this);
    187 
    188   // Assert that the Mutex is not held by the current thread.
    189   void AssertNotHeldExclusive(const Thread* self) ASSERT_CAPABILITY(!*this) {
    190     if (kDebugLocking && (gAborting == 0)) {
    191       CHECK(!IsExclusiveHeld(self)) << *this;
    192     }
    193   }
    194   void AssertNotHeld(const Thread* self) ASSERT_CAPABILITY(!*this) {
    195     AssertNotHeldExclusive(self);
    196   }
    197 
    198   // Id associated with exclusive owner. No memory ordering semantics if called from a thread
    199   // other than the owner. GetTid() == GetExclusiveOwnerTid() is a reliable way to determine
    200   // whether we hold the lock; any other information may be invalidated before we return.
    201   pid_t GetExclusiveOwnerTid() const;
    202 
    203   // Returns how many times this Mutex has been locked, it is better to use AssertHeld/NotHeld.
    204   unsigned int GetDepth() const {
    205     return recursion_count_;
    206   }
    207 
    208   void Dump(std::ostream& os) const override;
    209 
    210   // For negative capabilities in clang annotations.
    211   const Mutex& operator!() const { return *this; }
    212 
    213   void WakeupToRespondToEmptyCheckpoint() override;
    214 
    215  private:
    216 #if ART_USE_FUTEXES
    217   // Low order bit: 0 is unheld, 1 is held.
    218   // High order bits: Number of waiting contenders.
    219   AtomicInteger state_and_contenders_;
    220 
    221   static constexpr int32_t kHeldMask = 1;
    222 
    223   static constexpr int32_t kContenderShift = 1;
    224 
    225   static constexpr int32_t kContenderIncrement = 1 << kContenderShift;
    226 
    227   void increment_contenders() {
    228     state_and_contenders_.fetch_add(kContenderIncrement);
    229   }
    230 
    231   void decrement_contenders() {
    232     state_and_contenders_.fetch_sub(kContenderIncrement);
    233   }
    234 
    235   int32_t get_contenders() {
    236     // Result is guaranteed to include any contention added by this thread; otherwise approximate.
    237     // Treat contenders as unsigned because we're paranoid about overflow; should never matter.
    238     return static_cast<uint32_t>(state_and_contenders_.load(std::memory_order_relaxed))
    239         >> kContenderShift;
    240   }
    241 
    242   // Exclusive owner.
    243   Atomic<pid_t> exclusive_owner_;
    244 #else
    245   pthread_mutex_t mutex_;
    246   Atomic<pid_t> exclusive_owner_;  // Guarded by mutex_. Asynchronous reads are OK.
    247 #endif
    248 
    249   unsigned int recursion_count_;
    250   const bool recursive_;  // Can the lock be recursively held?
    251 
    252   friend class ConditionVariable;
    253   DISALLOW_COPY_AND_ASSIGN(Mutex);
    254 };
    255 
    256 // A ReaderWriterMutex is used to achieve mutual exclusion between threads, similar to a Mutex.
    257 // Unlike a Mutex a ReaderWriterMutex can be used to gain exclusive (writer) or shared (reader)
    258 // access to what it guards. A flaw in relation to a Mutex is that it cannot be used with a
    259 // condition variable. A ReaderWriterMutex can be in one of three states:
    260 // - Free - not owned by any thread,
    261 // - Exclusive - owned by a single thread,
    262 // - Shared(n) - shared amongst n threads.
    263 //
    264 // The effect of locking and unlocking operations on the state is:
    265 //
    266 // State     | ExclusiveLock | ExclusiveUnlock | SharedLock       | SharedUnlock
    267 // ----------------------------------------------------------------------------
    268 // Free      | Exclusive     | error           | SharedLock(1)    | error
    269 // Exclusive | Block         | Free            | Block            | error
    270 // Shared(n) | Block         | error           | SharedLock(n+1)* | Shared(n-1) or Free
    271 // * for large values of n the SharedLock may block.
    272 std::ostream& operator<<(std::ostream& os, const ReaderWriterMutex& mu);
    273 class SHARED_LOCKABLE ReaderWriterMutex : public BaseMutex {
    274  public:
    275   explicit ReaderWriterMutex(const char* name, LockLevel level = kDefaultMutexLevel);
    276   ~ReaderWriterMutex();
    277 
    278   bool IsReaderWriterMutex() const override { return true; }
    279 
    280   // Block until ReaderWriterMutex is free then acquire exclusive access.
    281   void ExclusiveLock(Thread* self) ACQUIRE();
    282   void WriterLock(Thread* self) ACQUIRE() {  ExclusiveLock(self); }
    283 
    284   // Release exclusive access.
    285   void ExclusiveUnlock(Thread* self) RELEASE();
    286   void WriterUnlock(Thread* self) RELEASE() {  ExclusiveUnlock(self); }
    287 
    288   // Block until ReaderWriterMutex is free and acquire exclusive access. Returns true on success
    289   // or false if timeout is reached.
    290 #if HAVE_TIMED_RWLOCK
    291   bool ExclusiveLockWithTimeout(Thread* self, int64_t ms, int32_t ns)
    292       EXCLUSIVE_TRYLOCK_FUNCTION(true);
    293 #endif
    294 
    295   // Block until ReaderWriterMutex is shared or free then acquire a share on the access.
    296   void SharedLock(Thread* self) ACQUIRE_SHARED() ALWAYS_INLINE;
    297   void ReaderLock(Thread* self) ACQUIRE_SHARED() { SharedLock(self); }
    298 
    299   // Try to acquire share of ReaderWriterMutex.
    300   bool SharedTryLock(Thread* self) SHARED_TRYLOCK_FUNCTION(true);
    301 
    302   // Release a share of the access.
    303   void SharedUnlock(Thread* self) RELEASE_SHARED() ALWAYS_INLINE;
    304   void ReaderUnlock(Thread* self) RELEASE_SHARED() { SharedUnlock(self); }
    305 
    306   // Is the current thread the exclusive holder of the ReaderWriterMutex.
    307   ALWAYS_INLINE bool IsExclusiveHeld(const Thread* self) const;
    308 
    309   // Assert the current thread has exclusive access to the ReaderWriterMutex.
    310   ALWAYS_INLINE void AssertExclusiveHeld(const Thread* self) const ASSERT_CAPABILITY(this);
    311   ALWAYS_INLINE void AssertWriterHeld(const Thread* self) const ASSERT_CAPABILITY(this);
    312 
    313   // Assert the current thread doesn't have exclusive access to the ReaderWriterMutex.
    314   void AssertNotExclusiveHeld(const Thread* self) ASSERT_CAPABILITY(!this) {
    315     if (kDebugLocking && (gAborting == 0)) {
    316       CHECK(!IsExclusiveHeld(self)) << *this;
    317     }
    318   }
    319   void AssertNotWriterHeld(const Thread* self) ASSERT_CAPABILITY(!this) {
    320     AssertNotExclusiveHeld(self);
    321   }
    322 
    323   // Is the current thread a shared holder of the ReaderWriterMutex.
    324   bool IsSharedHeld(const Thread* self) const;
    325 
    326   // Assert the current thread has shared access to the ReaderWriterMutex.
    327   ALWAYS_INLINE void AssertSharedHeld(const Thread* self) ASSERT_SHARED_CAPABILITY(this) {
    328     if (kDebugLocking && (gAborting == 0)) {
    329       // TODO: we can only assert this well when self != null.
    330       CHECK(IsSharedHeld(self) || self == nullptr) << *this;
    331     }
    332   }
    333   ALWAYS_INLINE void AssertReaderHeld(const Thread* self) ASSERT_SHARED_CAPABILITY(this) {
    334     AssertSharedHeld(self);
    335   }
    336 
    337   // Assert the current thread doesn't hold this ReaderWriterMutex either in shared or exclusive
    338   // mode.
    339   ALWAYS_INLINE void AssertNotHeld(const Thread* self) ASSERT_SHARED_CAPABILITY(!this) {
    340     if (kDebugLocking && (gAborting == 0)) {
    341       CHECK(!IsSharedHeld(self)) << *this;
    342     }
    343   }
    344 
    345   // Id associated with exclusive owner. No memory ordering semantics if called from a thread other
    346   // than the owner. Returns 0 if the lock is not held. Returns either 0 or -1 if it is held by
    347   // one or more readers.
    348   pid_t GetExclusiveOwnerTid() const;
    349 
    350   void Dump(std::ostream& os) const override;
    351 
    352   // For negative capabilities in clang annotations.
    353   const ReaderWriterMutex& operator!() const { return *this; }
    354 
    355   void WakeupToRespondToEmptyCheckpoint() override;
    356 
    357  private:
    358 #if ART_USE_FUTEXES
    359   // Out-of-inline path for handling contention for a SharedLock.
    360   void HandleSharedLockContention(Thread* self, int32_t cur_state);
    361 
    362   // -1 implies held exclusive, +ve shared held by state_ many owners.
    363   AtomicInteger state_;
    364   // Exclusive owner. Modification guarded by this mutex.
    365   Atomic<pid_t> exclusive_owner_;
    366   // Number of contenders waiting for a reader share.
    367   AtomicInteger num_pending_readers_;
    368   // Number of contenders waiting to be the writer.
    369   AtomicInteger num_pending_writers_;
    370 #else
    371   pthread_rwlock_t rwlock_;
    372   Atomic<pid_t> exclusive_owner_;  // Writes guarded by rwlock_. Asynchronous reads are OK.
    373 #endif
    374   DISALLOW_COPY_AND_ASSIGN(ReaderWriterMutex);
    375 };
    376 
    377 // MutatorMutex is a special kind of ReaderWriterMutex created specifically for the
    378 // Locks::mutator_lock_ mutex. The behaviour is identical to the ReaderWriterMutex except that
    379 // thread state changes also play a part in lock ownership. The mutator_lock_ will not be truly
    380 // held by any mutator threads. However, a thread in the kRunnable state is considered to have
    381 // shared ownership of the mutator lock and therefore transitions in and out of the kRunnable
    382 // state have associated implications on lock ownership. Extra methods to handle the state
    383 // transitions have been added to the interface but are only accessible to the methods dealing
    384 // with state transitions. The thread state and flags attributes are used to ensure thread state
    385 // transitions are consistent with the permitted behaviour of the mutex.
    386 //
    387 // *) The most important consequence of this behaviour is that all threads must be in one of the
    388 // suspended states before exclusive ownership of the mutator mutex is sought.
    389 //
    390 std::ostream& operator<<(std::ostream& os, const MutatorMutex& mu);
    391 class SHARED_LOCKABLE MutatorMutex : public ReaderWriterMutex {
    392  public:
    393   explicit MutatorMutex(const char* name, LockLevel level = kDefaultMutexLevel)
    394     : ReaderWriterMutex(name, level) {}
    395   ~MutatorMutex() {}
    396 
    397   virtual bool IsMutatorMutex() const { return true; }
    398 
    399   // For negative capabilities in clang annotations.
    400   const MutatorMutex& operator!() const { return *this; }
    401 
    402  private:
    403   friend class Thread;
    404   void TransitionFromRunnableToSuspended(Thread* self) UNLOCK_FUNCTION() ALWAYS_INLINE;
    405   void TransitionFromSuspendedToRunnable(Thread* self) SHARED_LOCK_FUNCTION() ALWAYS_INLINE;
    406 
    407   DISALLOW_COPY_AND_ASSIGN(MutatorMutex);
    408 };
    409 
    410 // ConditionVariables allow threads to queue and sleep. Threads may then be resumed individually
    411 // (Signal) or all at once (Broadcast).
    412 class ConditionVariable {
    413  public:
    414   ConditionVariable(const char* name, Mutex& mutex);
    415   ~ConditionVariable();
    416 
    417   // Requires the mutex to be held.
    418   void Broadcast(Thread* self);
    419   // Requires the mutex to be held.
    420   void Signal(Thread* self);
    421   // TODO: No thread safety analysis on Wait and TimedWait as they call mutex operations via their
    422   //       pointer copy, thereby defeating annotalysis.
    423   void Wait(Thread* self) NO_THREAD_SAFETY_ANALYSIS;
    424   bool TimedWait(Thread* self, int64_t ms, int32_t ns) NO_THREAD_SAFETY_ANALYSIS;
    425   // Variant of Wait that should be used with caution. Doesn't validate that no mutexes are held
    426   // when waiting.
    427   // TODO: remove this.
    428   void WaitHoldingLocks(Thread* self) NO_THREAD_SAFETY_ANALYSIS;
    429 
    430   void CheckSafeToWait(Thread* self) NO_THREAD_SAFETY_ANALYSIS {
    431     if (kDebugLocking) {
    432       guard_.CheckSafeToWait(self);
    433     }
    434   }
    435 
    436  private:
    437   const char* const name_;
    438   // The Mutex being used by waiters. It is an error to mix condition variables between different
    439   // Mutexes.
    440   Mutex& guard_;
    441 #if ART_USE_FUTEXES
    442   // A counter that is modified by signals and broadcasts. This ensures that when a waiter gives up
    443   // their Mutex and another thread takes it and signals, the waiting thread observes that sequence_
    444   // changed and doesn't enter the wait. Modified while holding guard_, but is read by futex wait
    445   // without guard_ held.
    446   AtomicInteger sequence_;
    447   // Number of threads that have come into to wait, not the length of the waiters on the futex as
    448   // waiters may have been requeued onto guard_. Guarded by guard_.
    449   int32_t num_waiters_;
    450 
    451   void RequeueWaiters(int32_t count);
    452 #else
    453   pthread_cond_t cond_;
    454 #endif
    455   DISALLOW_COPY_AND_ASSIGN(ConditionVariable);
    456 };
    457 
    458 // Scoped locker/unlocker for a regular Mutex that acquires mu upon construction and releases it
    459 // upon destruction.
    460 class SCOPED_CAPABILITY MutexLock {
    461  public:
    462   MutexLock(Thread* self, Mutex& mu) ACQUIRE(mu) : self_(self), mu_(mu) {
    463     mu_.ExclusiveLock(self_);
    464   }
    465 
    466   ~MutexLock() RELEASE() {
    467     mu_.ExclusiveUnlock(self_);
    468   }
    469 
    470  private:
    471   Thread* const self_;
    472   Mutex& mu_;
    473   DISALLOW_COPY_AND_ASSIGN(MutexLock);
    474 };
    475 
    476 // Scoped locker/unlocker for a ReaderWriterMutex that acquires read access to mu upon
    477 // construction and releases it upon destruction.
    478 class SCOPED_CAPABILITY ReaderMutexLock {
    479  public:
    480   ALWAYS_INLINE ReaderMutexLock(Thread* self, ReaderWriterMutex& mu) ACQUIRE(mu);
    481 
    482   ALWAYS_INLINE ~ReaderMutexLock() RELEASE();
    483 
    484  private:
    485   Thread* const self_;
    486   ReaderWriterMutex& mu_;
    487   DISALLOW_COPY_AND_ASSIGN(ReaderMutexLock);
    488 };
    489 
    490 // Scoped locker/unlocker for a ReaderWriterMutex that acquires write access to mu upon
    491 // construction and releases it upon destruction.
    492 class SCOPED_CAPABILITY WriterMutexLock {
    493  public:
    494   WriterMutexLock(Thread* self, ReaderWriterMutex& mu) EXCLUSIVE_LOCK_FUNCTION(mu) :
    495       self_(self), mu_(mu) {
    496     mu_.ExclusiveLock(self_);
    497   }
    498 
    499   ~WriterMutexLock() UNLOCK_FUNCTION() {
    500     mu_.ExclusiveUnlock(self_);
    501   }
    502 
    503  private:
    504   Thread* const self_;
    505   ReaderWriterMutex& mu_;
    506   DISALLOW_COPY_AND_ASSIGN(WriterMutexLock);
    507 };
    508 
    509 }  // namespace art
    510 
    511 #endif  // ART_RUNTIME_BASE_MUTEX_H_
    512