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