Mercurial > hg > graal-compiler
comparison src/share/vm/runtime/objectMonitor.hpp @ 1878:fa83ab460c54
6988353: refactor contended sync subsystem
Summary: reduce complexity by factoring synchronizer.cpp
Reviewed-by: dholmes, never, coleenp
author | acorn |
---|---|
date | Fri, 22 Oct 2010 15:59:34 -0400 |
parents | c18cbe5936b8 |
children | f95d63e2154a |
comparison
equal
deleted
inserted
replaced
1874:75ab0162aa84 | 1878:fa83ab460c54 |
---|---|
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA | 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
20 * or visit www.oracle.com if you need additional information or have any | 20 * or visit www.oracle.com if you need additional information or have any |
21 * questions. | 21 * questions. |
22 * | 22 * |
23 */ | 23 */ |
24 | |
25 | |
26 // ObjectWaiter serves as a "proxy" or surrogate thread. | |
27 // TODO-FIXME: Eliminate ObjectWaiter and use the thread-specific | |
28 // ParkEvent instead. Beware, however, that the JVMTI code | |
29 // knows about ObjectWaiters, so we'll have to reconcile that code. | |
30 // See next_waiter(), first_waiter(), etc. | |
31 | |
32 class ObjectWaiter : public StackObj { | |
33 public: | |
34 enum TStates { TS_UNDEF, TS_READY, TS_RUN, TS_WAIT, TS_ENTER, TS_CXQ } ; | |
35 enum Sorted { PREPEND, APPEND, SORTED } ; | |
36 ObjectWaiter * volatile _next; | |
37 ObjectWaiter * volatile _prev; | |
38 Thread* _thread; | |
39 ParkEvent * _event; | |
40 volatile int _notified ; | |
41 volatile TStates TState ; | |
42 Sorted _Sorted ; // List placement disposition | |
43 bool _active ; // Contention monitoring is enabled | |
44 public: | |
45 ObjectWaiter(Thread* thread); | |
46 | |
47 void wait_reenter_begin(ObjectMonitor *mon); | |
48 void wait_reenter_end(ObjectMonitor *mon); | |
49 }; | |
24 | 50 |
25 // WARNING: | 51 // WARNING: |
26 // This is a very sensitive and fragile class. DO NOT make any | 52 // This is a very sensitive and fragile class. DO NOT make any |
27 // change unless you are fully aware of the underlying semantics. | 53 // change unless you are fully aware of the underlying semantics. |
28 | 54 |
35 // transformed from the lightweight structure of the thread stack to a | 61 // transformed from the lightweight structure of the thread stack to a |
36 // heavy weight lock due to contention | 62 // heavy weight lock due to contention |
37 | 63 |
38 // It is also used as RawMonitor by the JVMTI | 64 // It is also used as RawMonitor by the JVMTI |
39 | 65 |
40 | |
41 class ObjectWaiter; | |
42 | 66 |
43 class ObjectMonitor { | 67 class ObjectMonitor { |
44 public: | 68 public: |
45 enum { | 69 enum { |
46 OM_OK, // no error | 70 OM_OK, // no error |
72 static int (*SpinCallbackFunction)(intptr_t, int) ; | 96 static int (*SpinCallbackFunction)(intptr_t, int) ; |
73 static intptr_t SpinCallbackArgument ; | 97 static intptr_t SpinCallbackArgument ; |
74 | 98 |
75 | 99 |
76 public: | 100 public: |
77 ObjectMonitor(); | |
78 ~ObjectMonitor(); | |
79 | |
80 markOop header() const; | 101 markOop header() const; |
81 void set_header(markOop hdr); | 102 void set_header(markOop hdr); |
82 | 103 |
83 intptr_t is_busy() const; | 104 intptr_t is_busy() const { |
105 // TODO-FIXME: merge _count and _waiters. | |
106 // TODO-FIXME: assert _owner == null implies _recursions = 0 | |
107 // TODO-FIXME: assert _WaitSet != null implies _count > 0 | |
108 return _count|_waiters|intptr_t(_owner)|intptr_t(_cxq)|intptr_t(_EntryList ) ; | |
109 } | |
110 | |
84 intptr_t is_entered(Thread* current) const; | 111 intptr_t is_entered(Thread* current) const; |
85 | 112 |
86 void* owner() const; | 113 void* owner() const; |
87 void set_owner(void* owner); | 114 void set_owner(void* owner); |
88 | 115 |
89 intptr_t waiters() const; | 116 intptr_t waiters() const; |
90 | 117 |
91 intptr_t count() const; | 118 intptr_t count() const; |
92 void set_count(intptr_t count); | 119 void set_count(intptr_t count); |
93 intptr_t contentions() const ; | 120 intptr_t contentions() const ; |
121 intptr_t recursions() const { return _recursions; } | |
94 | 122 |
95 // JVM/DI GetMonitorInfo() needs this | 123 // JVM/DI GetMonitorInfo() needs this |
96 Thread * thread_of_waiter (ObjectWaiter *) ; | 124 ObjectWaiter* first_waiter() { return _WaitSet; } |
97 ObjectWaiter * first_waiter () ; | 125 ObjectWaiter* next_waiter(ObjectWaiter* o) { return o->_next; } |
98 ObjectWaiter * next_waiter(ObjectWaiter* o); | 126 Thread* thread_of_waiter(ObjectWaiter* o) { return o->_thread; } |
99 | 127 |
100 intptr_t recursions() const { return _recursions; } | 128 // initialize the monitor, exception the semaphore, all other fields |
129 // are simple integers or pointers | |
130 ObjectMonitor() { | |
131 _header = NULL; | |
132 _count = 0; | |
133 _waiters = 0, | |
134 _recursions = 0; | |
135 _object = NULL; | |
136 _owner = NULL; | |
137 _WaitSet = NULL; | |
138 _WaitSetLock = 0 ; | |
139 _Responsible = NULL ; | |
140 _succ = NULL ; | |
141 _cxq = NULL ; | |
142 FreeNext = NULL ; | |
143 _EntryList = NULL ; | |
144 _SpinFreq = 0 ; | |
145 _SpinClock = 0 ; | |
146 OwnerIsThread = 0 ; | |
147 } | |
148 | |
149 ~ObjectMonitor() { | |
150 // TODO: Add asserts ... | |
151 // _cxq == 0 _succ == NULL _owner == NULL _waiters == 0 | |
152 // _count == 0 _EntryList == NULL etc | |
153 } | |
154 | |
155 private: | |
156 void Recycle () { | |
157 // TODO: add stronger asserts ... | |
158 // _cxq == 0 _succ == NULL _owner == NULL _waiters == 0 | |
159 // _count == 0 EntryList == NULL | |
160 // _recursions == 0 _WaitSet == NULL | |
161 // TODO: assert (is_busy()|_recursions) == 0 | |
162 _succ = NULL ; | |
163 _EntryList = NULL ; | |
164 _cxq = NULL ; | |
165 _WaitSet = NULL ; | |
166 _recursions = 0 ; | |
167 _SpinFreq = 0 ; | |
168 _SpinClock = 0 ; | |
169 OwnerIsThread = 0 ; | |
170 } | |
171 | |
172 public: | |
101 | 173 |
102 void* object() const; | 174 void* object() const; |
103 void* object_addr(); | 175 void* object_addr(); |
104 void set_object(void* obj); | 176 void set_object(void* obj); |
105 | 177 |
120 | 192 |
121 // Use the following at your own risk | 193 // Use the following at your own risk |
122 intptr_t complete_exit(TRAPS); | 194 intptr_t complete_exit(TRAPS); |
123 void reenter(intptr_t recursions, TRAPS); | 195 void reenter(intptr_t recursions, TRAPS); |
124 | 196 |
125 int raw_enter(TRAPS); | 197 private: |
126 int raw_exit(TRAPS); | |
127 int raw_wait(jlong millis, bool interruptable, TRAPS); | |
128 int raw_notify(TRAPS); | |
129 int raw_notifyAll(TRAPS); | |
130 | |
131 private: | |
132 // JVMTI support -- remove ASAP | |
133 int SimpleEnter (Thread * Self) ; | |
134 int SimpleExit (Thread * Self) ; | |
135 int SimpleWait (Thread * Self, jlong millis) ; | |
136 int SimpleNotify (Thread * Self, bool All) ; | |
137 | |
138 private: | |
139 void Recycle () ; | |
140 void AddWaiter (ObjectWaiter * waiter) ; | 198 void AddWaiter (ObjectWaiter * waiter) ; |
199 static void DeferredInitialize(); | |
141 | 200 |
142 ObjectWaiter * DequeueWaiter () ; | 201 ObjectWaiter * DequeueWaiter () ; |
143 void DequeueSpecificWaiter (ObjectWaiter * waiter) ; | 202 void DequeueSpecificWaiter (ObjectWaiter * waiter) ; |
144 void EnterI (TRAPS) ; | 203 void EnterI (TRAPS) ; |
145 void ReenterI (Thread * Self, ObjectWaiter * SelfNode) ; | 204 void ReenterI (Thread * Self, ObjectWaiter * SelfNode) ; |
170 | 229 |
171 // All the following fields must be machine word aligned | 230 // All the following fields must be machine word aligned |
172 // The VM assumes write ordering wrt these fields, which can be | 231 // The VM assumes write ordering wrt these fields, which can be |
173 // read from other threads. | 232 // read from other threads. |
174 | 233 |
234 protected: // protected for jvmtiRawMonitor | |
175 void * volatile _owner; // pointer to owning thread OR BasicLock | 235 void * volatile _owner; // pointer to owning thread OR BasicLock |
176 volatile intptr_t _recursions; // recursion count, 0 for first entry | 236 volatile intptr_t _recursions; // recursion count, 0 for first entry |
237 private: | |
177 int OwnerIsThread ; // _owner is (Thread *) vs SP/BasicLock | 238 int OwnerIsThread ; // _owner is (Thread *) vs SP/BasicLock |
178 ObjectWaiter * volatile _cxq ; // LL of recently-arrived threads blocked on entry. | 239 ObjectWaiter * volatile _cxq ; // LL of recently-arrived threads blocked on entry. |
179 // The list is actually composed of WaitNodes, acting | 240 // The list is actually composed of WaitNodes, acting |
180 // as proxies for Threads. | 241 // as proxies for Threads. |
242 protected: | |
181 ObjectWaiter * volatile _EntryList ; // Threads blocked on entry or reentry. | 243 ObjectWaiter * volatile _EntryList ; // Threads blocked on entry or reentry. |
244 private: | |
182 Thread * volatile _succ ; // Heir presumptive thread - used for futile wakeup throttling | 245 Thread * volatile _succ ; // Heir presumptive thread - used for futile wakeup throttling |
183 Thread * volatile _Responsible ; | 246 Thread * volatile _Responsible ; |
184 int _PromptDrain ; // rqst to drain cxq into EntryList ASAP | 247 int _PromptDrain ; // rqst to drain cxq into EntryList ASAP |
185 | 248 |
186 volatile int _Spinner ; // for exit->spinner handoff optimization | 249 volatile int _Spinner ; // for exit->spinner handoff optimization |
194 // to use 64-bit fields for these variables on a 64-bit JVM. | 257 // to use 64-bit fields for these variables on a 64-bit JVM. |
195 | 258 |
196 volatile intptr_t _count; // reference count to prevent reclaimation/deflation | 259 volatile intptr_t _count; // reference count to prevent reclaimation/deflation |
197 // at stop-the-world time. See deflate_idle_monitors(). | 260 // at stop-the-world time. See deflate_idle_monitors(). |
198 // _count is approximately |_WaitSet| + |_EntryList| | 261 // _count is approximately |_WaitSet| + |_EntryList| |
262 protected: | |
199 volatile intptr_t _waiters; // number of waiting threads | 263 volatile intptr_t _waiters; // number of waiting threads |
264 private: | |
265 protected: | |
200 ObjectWaiter * volatile _WaitSet; // LL of threads wait()ing on the monitor | 266 ObjectWaiter * volatile _WaitSet; // LL of threads wait()ing on the monitor |
267 private: | |
201 volatile int _WaitSetLock; // protects Wait Queue - simple spinlock | 268 volatile int _WaitSetLock; // protects Wait Queue - simple spinlock |
202 | 269 |
203 public: | 270 public: |
204 int _QMix ; // Mixed prepend queue discipline | 271 int _QMix ; // Mixed prepend queue discipline |
205 ObjectMonitor * FreeNext ; // Free list linkage | 272 ObjectMonitor * FreeNext ; // Free list linkage |
206 intptr_t StatA, StatsB ; | 273 intptr_t StatA, StatsB ; |
207 | 274 |
275 public: | |
276 static void Initialize () ; | |
277 static PerfCounter * _sync_ContendedLockAttempts ; | |
278 static PerfCounter * _sync_FutileWakeups ; | |
279 static PerfCounter * _sync_Parks ; | |
280 static PerfCounter * _sync_EmptyNotifications ; | |
281 static PerfCounter * _sync_Notifications ; | |
282 static PerfCounter * _sync_SlowEnter ; | |
283 static PerfCounter * _sync_SlowExit ; | |
284 static PerfCounter * _sync_SlowNotify ; | |
285 static PerfCounter * _sync_SlowNotifyAll ; | |
286 static PerfCounter * _sync_FailedSpins ; | |
287 static PerfCounter * _sync_SuccessfulSpins ; | |
288 static PerfCounter * _sync_PrivateA ; | |
289 static PerfCounter * _sync_PrivateB ; | |
290 static PerfCounter * _sync_MonInCirculation ; | |
291 static PerfCounter * _sync_MonScavenged ; | |
292 static PerfCounter * _sync_Inflations ; | |
293 static PerfCounter * _sync_Deflations ; | |
294 static PerfLongVariable * _sync_MonExtant ; | |
295 | |
296 public: | |
297 static int Knob_Verbose; | |
298 static int Knob_SpinLimit; | |
208 }; | 299 }; |
300 | |
301 #undef TEVENT | |
302 #define TEVENT(nom) {if (SyncVerbose) FEVENT(nom); } | |
303 | |
304 #define FEVENT(nom) { static volatile int ctr = 0 ; int v = ++ctr ; if ((v & (v-1)) == 0) { ::printf (#nom " : %d \n", v); ::fflush(stdout); }} | |
305 | |
306 #undef TEVENT | |
307 #define TEVENT(nom) {;} | |
308 |