Home | History | Annotate | Download | only in runtime
      1 /*
      2  * Copyright (C) 2012 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_LOCKS_H_
     18 #define ART_RUNTIME_LOCKS_H_
     19 
     20 #include <ostream>
     21 
     22 #include "base/macros.h"
     23 
     24 namespace art {
     25 
     26 class LOCKABLE Mutex;
     27 class LOCKABLE ReaderWriterMutex;
     28 
     29 // LockLevel is used to impose a lock hierarchy [1] where acquisition of a Mutex at a higher or
     30 // equal level to a lock a thread holds is invalid. The lock hierarchy achieves a cycle free
     31 // partial ordering and thereby cause deadlock situations to fail checks.
     32 //
     33 // [1] http://www.drdobbs.com/parallel/use-lock-hierarchies-to-avoid-deadlock/204801163
     34 enum LockLevel {
     35   kLoggingLock = 0,
     36   kUnexpectedSignalLock,
     37   kThreadSuspendCountLock,
     38   kAbortLock,
     39   kJdwpSocketLock,
     40   kAllocSpaceLock,
     41   kMarkSweepMarkStackLock,
     42   kDefaultMutexLevel,
     43   kMarkSweepLargeObjectLock,
     44   kPinTableLock,
     45   kLoadLibraryLock,
     46   kJdwpObjectRegistryLock,
     47   kClassLinkerClassesLock,
     48   kBreakpointLock,
     49   kThreadListLock,
     50   kBreakpointInvokeLock,
     51   kTraceLock,
     52   kJdwpEventListLock,
     53   kJdwpAttachLock,
     54   kJdwpStartLock,
     55   kRuntimeShutdownLock,
     56   kHeapBitmapLock,
     57   kMonitorLock,
     58   kMutatorLock,
     59   kZygoteCreationLock,
     60 
     61   kLockLevelCount  // Must come last.
     62 };
     63 std::ostream& operator<<(std::ostream& os, const LockLevel& rhs);
     64 
     65 // Global mutexes corresponding to the levels above.
     66 class Locks {
     67  public:
     68   static void Init();
     69 
     70   // The mutator_lock_ is used to allow mutators to execute in a shared (reader) mode or to block
     71   // mutators by having an exclusive (writer) owner. In normal execution each mutator thread holds
     72   // a share on the mutator_lock_. The garbage collector may also execute with shared access but
     73   // at times requires exclusive access to the heap (not to be confused with the heap meta-data
     74   // guarded by the heap_lock_ below). When the garbage collector requires exclusive access it asks
     75   // the mutators to suspend themselves which also involves usage of the thread_suspend_count_lock_
     76   // to cover weaknesses in using ReaderWriterMutexes with ConditionVariables. We use a condition
     77   // variable to wait upon in the suspension logic as releasing and then re-acquiring a share on
     78   // the mutator lock doesn't necessarily allow the exclusive user (e.g the garbage collector)
     79   // chance to acquire the lock.
     80   //
     81   // Thread suspension:
     82   // Shared users                                  | Exclusive user
     83   // (holding mutator lock and in kRunnable state) |   .. running ..
     84   //   .. running ..                               | Request thread suspension by:
     85   //   .. running ..                               |   - acquiring thread_suspend_count_lock_
     86   //   .. running ..                               |   - incrementing Thread::suspend_count_ on
     87   //   .. running ..                               |     all mutator threads
     88   //   .. running ..                               |   - releasing thread_suspend_count_lock_
     89   //   .. running ..                               | Block trying to acquire exclusive mutator lock
     90   // Poll Thread::suspend_count_ and enter full    |   .. blocked ..
     91   // suspend code.                                 |   .. blocked ..
     92   // Change state to kSuspended                    |   .. blocked ..
     93   // x: Release share on mutator_lock_             | Carry out exclusive access
     94   // Acquire thread_suspend_count_lock_            |   .. exclusive ..
     95   // while Thread::suspend_count_ > 0              |   .. exclusive ..
     96   //   - wait on Thread::resume_cond_              |   .. exclusive ..
     97   //     (releases thread_suspend_count_lock_)     |   .. exclusive ..
     98   //   .. waiting ..                               | Release mutator_lock_
     99   //   .. waiting ..                               | Request thread resumption by:
    100   //   .. waiting ..                               |   - acquiring thread_suspend_count_lock_
    101   //   .. waiting ..                               |   - decrementing Thread::suspend_count_ on
    102   //   .. waiting ..                               |     all mutator threads
    103   //   .. waiting ..                               |   - notifying on Thread::resume_cond_
    104   //    - re-acquire thread_suspend_count_lock_    |   - releasing thread_suspend_count_lock_
    105   // Release thread_suspend_count_lock_            |  .. running ..
    106   // Acquire share on mutator_lock_                |  .. running ..
    107   //  - This could block but the thread still      |  .. running ..
    108   //    has a state of kSuspended and so this      |  .. running ..
    109   //    isn't an issue.                            |  .. running ..
    110   // Acquire thread_suspend_count_lock_            |  .. running ..
    111   //  - we poll here as we're transitioning into   |  .. running ..
    112   //    kRunnable and an individual thread suspend |  .. running ..
    113   //    request (e.g for debugging) won't try      |  .. running ..
    114   //    to acquire the mutator lock (which would   |  .. running ..
    115   //    block as we hold the mutator lock). This   |  .. running ..
    116   //    poll ensures that if the suspender thought |  .. running ..
    117   //    we were suspended by incrementing our      |  .. running ..
    118   //    Thread::suspend_count_ and then reading    |  .. running ..
    119   //    our state we go back to waiting on         |  .. running ..
    120   //    Thread::resume_cond_.                      |  .. running ..
    121   // can_go_runnable = Thread::suspend_count_ == 0 |  .. running ..
    122   // Release thread_suspend_count_lock_            |  .. running ..
    123   // if can_go_runnable                            |  .. running ..
    124   //   Change state to kRunnable                   |  .. running ..
    125   // else                                          |  .. running ..
    126   //   Goto x                                      |  .. running ..
    127   //  .. running ..                                |  .. running ..
    128   static ReaderWriterMutex* mutator_lock_;
    129 
    130   // Allow reader-writer mutual exclusion on the mark and live bitmaps of the heap.
    131   static ReaderWriterMutex* heap_bitmap_lock_ ACQUIRED_AFTER(mutator_lock_);
    132 
    133   // Guards shutdown of the runtime.
    134   static Mutex* runtime_shutdown_lock_ ACQUIRED_AFTER(heap_bitmap_lock_);
    135 
    136   // The thread_list_lock_ guards ThreadList::list_. It is also commonly held to stop threads
    137   // attaching and detaching.
    138   static Mutex* thread_list_lock_ ACQUIRED_AFTER(runtime_shutdown_lock_);
    139 
    140   // Guards breakpoints and single-stepping.
    141   static Mutex* breakpoint_lock_ ACQUIRED_AFTER(thread_list_lock_);
    142 
    143   // Guards trace requests.
    144   static Mutex* trace_lock_ ACQUIRED_AFTER(breakpoint_lock_);
    145 
    146   // Guards lists of classes within the class linker.
    147   static ReaderWriterMutex* classlinker_classes_lock_ ACQUIRED_AFTER(trace_lock_);
    148 
    149   // When declaring any Mutex add DEFAULT_MUTEX_ACQUIRED_AFTER to use annotalysis to check the code
    150   // doesn't try to hold a higher level Mutex.
    151   #define DEFAULT_MUTEX_ACQUIRED_AFTER ACQUIRED_AFTER(classlinker_classes_lock_)
    152 
    153   // Have an exclusive aborting thread.
    154   static Mutex* abort_lock_ ACQUIRED_AFTER(classlinker_classes_lock_);
    155 
    156   // Allow mutual exclusion when manipulating Thread::suspend_count_.
    157   // TODO: Does the trade-off of a per-thread lock make sense?
    158   static Mutex* thread_suspend_count_lock_ ACQUIRED_AFTER(abort_lock_);
    159 
    160   // One unexpected signal at a time lock.
    161   static Mutex* unexpected_signal_lock_ ACQUIRED_AFTER(thread_suspend_count_lock_);
    162 
    163   // Have an exclusive logging thread.
    164   static Mutex* logging_lock_ ACQUIRED_AFTER(unexpected_signal_lock_);
    165 };
    166 
    167 }  // namespace art
    168 
    169 #endif  // ART_RUNTIME_LOCKS_H_
    170