35 // knows about ObjectWaiters, so we'll have to reconcile that code. |
35 // knows about ObjectWaiters, so we'll have to reconcile that code. |
36 // See next_waiter(), first_waiter(), etc. |
36 // See next_waiter(), first_waiter(), etc. |
37 |
37 |
38 class ObjectWaiter : public StackObj { |
38 class ObjectWaiter : public StackObj { |
39 public: |
39 public: |
40 enum TStates { TS_UNDEF, TS_READY, TS_RUN, TS_WAIT, TS_ENTER, TS_CXQ } ; |
40 enum TStates { TS_UNDEF, TS_READY, TS_RUN, TS_WAIT, TS_ENTER, TS_CXQ }; |
41 enum Sorted { PREPEND, APPEND, SORTED } ; |
41 enum Sorted { PREPEND, APPEND, SORTED }; |
42 ObjectWaiter * volatile _next; |
42 ObjectWaiter * volatile _next; |
43 ObjectWaiter * volatile _prev; |
43 ObjectWaiter * volatile _prev; |
44 Thread* _thread; |
44 Thread* _thread; |
45 jlong _notifier_tid; |
45 jlong _notifier_tid; |
46 ParkEvent * _event; |
46 ParkEvent * _event; |
47 volatile int _notified ; |
47 volatile int _notified; |
48 volatile TStates TState ; |
48 volatile TStates TState; |
49 Sorted _Sorted ; // List placement disposition |
49 Sorted _Sorted; // List placement disposition |
50 bool _active ; // Contention monitoring is enabled |
50 bool _active; // Contention monitoring is enabled |
51 public: |
51 public: |
52 ObjectWaiter(Thread* thread); |
52 ObjectWaiter(Thread* thread); |
53 |
53 |
54 void wait_reenter_begin(ObjectMonitor *mon); |
54 void wait_reenter_begin(ObjectMonitor *mon); |
55 void wait_reenter_end(ObjectMonitor *mon); |
55 void wait_reenter_end(ObjectMonitor *mon); |
90 static int header_offset_in_bytes() { return offset_of(ObjectMonitor, _header); } |
90 static int header_offset_in_bytes() { return offset_of(ObjectMonitor, _header); } |
91 static int object_offset_in_bytes() { return offset_of(ObjectMonitor, _object); } |
91 static int object_offset_in_bytes() { return offset_of(ObjectMonitor, _object); } |
92 static int owner_offset_in_bytes() { return offset_of(ObjectMonitor, _owner); } |
92 static int owner_offset_in_bytes() { return offset_of(ObjectMonitor, _owner); } |
93 static int count_offset_in_bytes() { return offset_of(ObjectMonitor, _count); } |
93 static int count_offset_in_bytes() { return offset_of(ObjectMonitor, _count); } |
94 static int recursions_offset_in_bytes() { return offset_of(ObjectMonitor, _recursions); } |
94 static int recursions_offset_in_bytes() { return offset_of(ObjectMonitor, _recursions); } |
95 static int cxq_offset_in_bytes() { return offset_of(ObjectMonitor, _cxq) ; } |
95 static int cxq_offset_in_bytes() { return offset_of(ObjectMonitor, _cxq); } |
96 static int succ_offset_in_bytes() { return offset_of(ObjectMonitor, _succ) ; } |
96 static int succ_offset_in_bytes() { return offset_of(ObjectMonitor, _succ); } |
97 static int EntryList_offset_in_bytes() { return offset_of(ObjectMonitor, _EntryList); } |
97 static int EntryList_offset_in_bytes() { return offset_of(ObjectMonitor, _EntryList); } |
98 static int FreeNext_offset_in_bytes() { return offset_of(ObjectMonitor, FreeNext); } |
98 static int FreeNext_offset_in_bytes() { return offset_of(ObjectMonitor, FreeNext); } |
99 static int WaitSet_offset_in_bytes() { return offset_of(ObjectMonitor, _WaitSet) ; } |
99 static int WaitSet_offset_in_bytes() { return offset_of(ObjectMonitor, _WaitSet); } |
100 static int Responsible_offset_in_bytes() { return offset_of(ObjectMonitor, _Responsible);} |
100 static int Responsible_offset_in_bytes() { return offset_of(ObjectMonitor, _Responsible); } |
101 static int Spinner_offset_in_bytes() { return offset_of(ObjectMonitor, _Spinner); } |
101 static int Spinner_offset_in_bytes() { return offset_of(ObjectMonitor, _Spinner); } |
102 |
102 |
103 public: |
103 public: |
104 // Eventually we'll make provisions for multiple callbacks, but |
104 // Eventually we'll make provisions for multiple callbacks, but |
105 // now one will suffice. |
105 // now one will suffice. |
106 static int (*SpinCallbackFunction)(intptr_t, int) ; |
106 static int (*SpinCallbackFunction)(intptr_t, int); |
107 static intptr_t SpinCallbackArgument ; |
107 static intptr_t SpinCallbackArgument; |
108 |
108 |
109 |
109 |
110 public: |
110 public: |
111 markOop header() const; |
111 markOop header() const; |
112 void set_header(markOop hdr); |
112 void set_header(markOop hdr); |
113 |
113 |
114 intptr_t is_busy() const { |
114 intptr_t is_busy() const { |
115 // TODO-FIXME: merge _count and _waiters. |
115 // TODO-FIXME: merge _count and _waiters. |
116 // TODO-FIXME: assert _owner == null implies _recursions = 0 |
116 // TODO-FIXME: assert _owner == null implies _recursions = 0 |
117 // TODO-FIXME: assert _WaitSet != null implies _count > 0 |
117 // TODO-FIXME: assert _WaitSet != null implies _count > 0 |
118 return _count|_waiters|intptr_t(_owner)|intptr_t(_cxq)|intptr_t(_EntryList ) ; |
118 return _count|_waiters|intptr_t(_owner)|intptr_t(_cxq)|intptr_t(_EntryList); |
119 } |
119 } |
120 |
120 |
121 intptr_t is_entered(Thread* current) const; |
121 intptr_t is_entered(Thread* current) const; |
122 |
122 |
123 void* owner() const; |
123 void* owner() const; |
125 |
125 |
126 intptr_t waiters() const; |
126 intptr_t waiters() const; |
127 |
127 |
128 intptr_t count() const; |
128 intptr_t count() const; |
129 void set_count(intptr_t count); |
129 void set_count(intptr_t count); |
130 intptr_t contentions() const ; |
130 intptr_t contentions() const; |
131 intptr_t recursions() const { return _recursions; } |
131 intptr_t recursions() const { return _recursions; } |
132 |
132 |
133 // JVM/DI GetMonitorInfo() needs this |
133 // JVM/DI GetMonitorInfo() needs this |
134 ObjectWaiter* first_waiter() { return _WaitSet; } |
134 ObjectWaiter* first_waiter() { return _WaitSet; } |
135 ObjectWaiter* next_waiter(ObjectWaiter* o) { return o->_next; } |
135 ObjectWaiter* next_waiter(ObjectWaiter* o) { return o->_next; } |
143 _waiters = 0, |
143 _waiters = 0, |
144 _recursions = 0; |
144 _recursions = 0; |
145 _object = NULL; |
145 _object = NULL; |
146 _owner = NULL; |
146 _owner = NULL; |
147 _WaitSet = NULL; |
147 _WaitSet = NULL; |
148 _WaitSetLock = 0 ; |
148 _WaitSetLock = 0; |
149 _Responsible = NULL ; |
149 _Responsible = NULL; |
150 _succ = NULL ; |
150 _succ = NULL; |
151 _cxq = NULL ; |
151 _cxq = NULL; |
152 FreeNext = NULL ; |
152 FreeNext = NULL; |
153 _EntryList = NULL ; |
153 _EntryList = NULL; |
154 _SpinFreq = 0 ; |
154 _SpinFreq = 0; |
155 _SpinClock = 0 ; |
155 _SpinClock = 0; |
156 OwnerIsThread = 0 ; |
156 OwnerIsThread = 0; |
157 _previous_owner_tid = 0; |
157 _previous_owner_tid = 0; |
158 } |
158 } |
159 |
159 |
160 ~ObjectMonitor() { |
160 ~ObjectMonitor() { |
161 // TODO: Add asserts ... |
161 // TODO: Add asserts ... |
162 // _cxq == 0 _succ == NULL _owner == NULL _waiters == 0 |
162 // _cxq == 0 _succ == NULL _owner == NULL _waiters == 0 |
163 // _count == 0 _EntryList == NULL etc |
163 // _count == 0 _EntryList == NULL etc |
164 } |
164 } |
165 |
165 |
166 private: |
166 private: |
167 void Recycle () { |
167 void Recycle() { |
168 // TODO: add stronger asserts ... |
168 // TODO: add stronger asserts ... |
169 // _cxq == 0 _succ == NULL _owner == NULL _waiters == 0 |
169 // _cxq == 0 _succ == NULL _owner == NULL _waiters == 0 |
170 // _count == 0 EntryList == NULL |
170 // _count == 0 EntryList == NULL |
171 // _recursions == 0 _WaitSet == NULL |
171 // _recursions == 0 _WaitSet == NULL |
172 // TODO: assert (is_busy()|_recursions) == 0 |
172 // TODO: assert (is_busy()|_recursions) == 0 |
173 _succ = NULL ; |
173 _succ = NULL; |
174 _EntryList = NULL ; |
174 _EntryList = NULL; |
175 _cxq = NULL ; |
175 _cxq = NULL; |
176 _WaitSet = NULL ; |
176 _WaitSet = NULL; |
177 _recursions = 0 ; |
177 _recursions = 0; |
178 _SpinFreq = 0 ; |
178 _SpinFreq = 0; |
179 _SpinClock = 0 ; |
179 _SpinClock = 0; |
180 OwnerIsThread = 0 ; |
180 OwnerIsThread = 0; |
181 } |
181 } |
182 |
182 |
183 public: |
183 public: |
184 |
184 |
185 void* object() const; |
185 void* object() const; |
204 // Use the following at your own risk |
204 // Use the following at your own risk |
205 intptr_t complete_exit(TRAPS); |
205 intptr_t complete_exit(TRAPS); |
206 void reenter(intptr_t recursions, TRAPS); |
206 void reenter(intptr_t recursions, TRAPS); |
207 |
207 |
208 private: |
208 private: |
209 void AddWaiter (ObjectWaiter * waiter) ; |
209 void AddWaiter(ObjectWaiter * waiter); |
210 static void DeferredInitialize(); |
210 static void DeferredInitialize(); |
211 |
211 |
212 ObjectWaiter * DequeueWaiter () ; |
212 ObjectWaiter * DequeueWaiter(); |
213 void DequeueSpecificWaiter (ObjectWaiter * waiter) ; |
213 void DequeueSpecificWaiter(ObjectWaiter * waiter); |
214 void EnterI (TRAPS) ; |
214 void EnterI(TRAPS); |
215 void ReenterI (Thread * Self, ObjectWaiter * SelfNode) ; |
215 void ReenterI(Thread * Self, ObjectWaiter * SelfNode); |
216 void UnlinkAfterAcquire (Thread * Self, ObjectWaiter * SelfNode) ; |
216 void UnlinkAfterAcquire(Thread * Self, ObjectWaiter * SelfNode); |
217 int TryLock (Thread * Self) ; |
217 int TryLock(Thread * Self); |
218 int NotRunnable (Thread * Self, Thread * Owner) ; |
218 int NotRunnable(Thread * Self, Thread * Owner); |
219 int TrySpin_Fixed (Thread * Self) ; |
219 int TrySpin_Fixed(Thread * Self); |
220 int TrySpin_VaryFrequency (Thread * Self) ; |
220 int TrySpin_VaryFrequency(Thread * Self); |
221 int TrySpin_VaryDuration (Thread * Self) ; |
221 int TrySpin_VaryDuration(Thread * Self); |
222 void ctAsserts () ; |
222 void ctAsserts(); |
223 void ExitEpilog (Thread * Self, ObjectWaiter * Wakee) ; |
223 void ExitEpilog(Thread * Self, ObjectWaiter * Wakee); |
224 bool ExitSuspendEquivalent (JavaThread * Self) ; |
224 bool ExitSuspendEquivalent(JavaThread * Self); |
225 void post_monitor_wait_event(EventJavaMonitorWait * event, |
225 void post_monitor_wait_event(EventJavaMonitorWait * event, |
226 jlong notifier_tid, |
226 jlong notifier_tid, |
227 jlong timeout, |
227 jlong timeout, |
228 bool timedout); |
228 bool timedout); |
229 |
229 |
238 // implicit 0 offset in emitted code. |
238 // implicit 0 offset in emitted code. |
239 |
239 |
240 volatile markOop _header; // displaced object header word - mark |
240 volatile markOop _header; // displaced object header word - mark |
241 void* volatile _object; // backward object pointer - strong root |
241 void* volatile _object; // backward object pointer - strong root |
242 |
242 |
243 double SharingPad [1] ; // temp to reduce false sharing |
243 double SharingPad[1]; // temp to reduce false sharing |
244 |
244 |
245 // All the following fields must be machine word aligned |
245 // All the following fields must be machine word aligned |
246 // The VM assumes write ordering wrt these fields, which can be |
246 // The VM assumes write ordering wrt these fields, which can be |
247 // read from other threads. |
247 // read from other threads. |
248 |
248 |
249 protected: // protected for jvmtiRawMonitor |
249 protected: // protected for jvmtiRawMonitor |
250 void * volatile _owner; // pointer to owning thread OR BasicLock |
250 void * volatile _owner; // pointer to owning thread OR BasicLock |
251 volatile jlong _previous_owner_tid; // thread id of the previous owner of the monitor |
251 volatile jlong _previous_owner_tid; // thread id of the previous owner of the monitor |
252 volatile intptr_t _recursions; // recursion count, 0 for first entry |
252 volatile intptr_t _recursions; // recursion count, 0 for first entry |
253 private: |
253 private: |
254 int OwnerIsThread ; // _owner is (Thread *) vs SP/BasicLock |
254 int OwnerIsThread; // _owner is (Thread *) vs SP/BasicLock |
255 ObjectWaiter * volatile _cxq ; // LL of recently-arrived threads blocked on entry. |
255 ObjectWaiter * volatile _cxq; // LL of recently-arrived threads blocked on entry. |
256 // The list is actually composed of WaitNodes, acting |
256 // The list is actually composed of WaitNodes, acting |
257 // as proxies for Threads. |
257 // as proxies for Threads. |
258 protected: |
258 protected: |
259 ObjectWaiter * volatile _EntryList ; // Threads blocked on entry or reentry. |
259 ObjectWaiter * volatile _EntryList; // Threads blocked on entry or reentry. |
260 private: |
260 private: |
261 Thread * volatile _succ ; // Heir presumptive thread - used for futile wakeup throttling |
261 Thread * volatile _succ; // Heir presumptive thread - used for futile wakeup throttling |
262 Thread * volatile _Responsible ; |
262 Thread * volatile _Responsible; |
263 int _PromptDrain ; // rqst to drain cxq into EntryList ASAP |
263 int _PromptDrain; // rqst to drain cxq into EntryList ASAP |
264 |
264 |
265 volatile int _Spinner ; // for exit->spinner handoff optimization |
265 volatile int _Spinner; // for exit->spinner handoff optimization |
266 volatile int _SpinFreq ; // Spin 1-out-of-N attempts: success rate |
266 volatile int _SpinFreq; // Spin 1-out-of-N attempts: success rate |
267 volatile int _SpinClock ; |
267 volatile int _SpinClock; |
268 volatile int _SpinDuration ; |
268 volatile int _SpinDuration; |
269 volatile intptr_t _SpinState ; // MCS/CLH list of spinners |
269 volatile intptr_t _SpinState; // MCS/CLH list of spinners |
270 |
270 |
271 // TODO-FIXME: _count, _waiters and _recursions should be of |
271 // TODO-FIXME: _count, _waiters and _recursions should be of |
272 // type int, or int32_t but not intptr_t. There's no reason |
272 // type int, or int32_t but not intptr_t. There's no reason |
273 // to use 64-bit fields for these variables on a 64-bit JVM. |
273 // to use 64-bit fields for these variables on a 64-bit JVM. |
274 |
274 |
282 ObjectWaiter * volatile _WaitSet; // LL of threads wait()ing on the monitor |
282 ObjectWaiter * volatile _WaitSet; // LL of threads wait()ing on the monitor |
283 private: |
283 private: |
284 volatile int _WaitSetLock; // protects Wait Queue - simple spinlock |
284 volatile int _WaitSetLock; // protects Wait Queue - simple spinlock |
285 |
285 |
286 public: |
286 public: |
287 int _QMix ; // Mixed prepend queue discipline |
287 int _QMix; // Mixed prepend queue discipline |
288 ObjectMonitor * FreeNext ; // Free list linkage |
288 ObjectMonitor * FreeNext; // Free list linkage |
289 intptr_t StatA, StatsB ; |
289 intptr_t StatA, StatsB; |
290 |
290 |
291 public: |
291 public: |
292 static void Initialize () ; |
292 static void Initialize(); |
293 static PerfCounter * _sync_ContendedLockAttempts ; |
293 static PerfCounter * _sync_ContendedLockAttempts; |
294 static PerfCounter * _sync_FutileWakeups ; |
294 static PerfCounter * _sync_FutileWakeups; |
295 static PerfCounter * _sync_Parks ; |
295 static PerfCounter * _sync_Parks; |
296 static PerfCounter * _sync_EmptyNotifications ; |
296 static PerfCounter * _sync_EmptyNotifications; |
297 static PerfCounter * _sync_Notifications ; |
297 static PerfCounter * _sync_Notifications; |
298 static PerfCounter * _sync_SlowEnter ; |
298 static PerfCounter * _sync_SlowEnter; |
299 static PerfCounter * _sync_SlowExit ; |
299 static PerfCounter * _sync_SlowExit; |
300 static PerfCounter * _sync_SlowNotify ; |
300 static PerfCounter * _sync_SlowNotify; |
301 static PerfCounter * _sync_SlowNotifyAll ; |
301 static PerfCounter * _sync_SlowNotifyAll; |
302 static PerfCounter * _sync_FailedSpins ; |
302 static PerfCounter * _sync_FailedSpins; |
303 static PerfCounter * _sync_SuccessfulSpins ; |
303 static PerfCounter * _sync_SuccessfulSpins; |
304 static PerfCounter * _sync_PrivateA ; |
304 static PerfCounter * _sync_PrivateA; |
305 static PerfCounter * _sync_PrivateB ; |
305 static PerfCounter * _sync_PrivateB; |
306 static PerfCounter * _sync_MonInCirculation ; |
306 static PerfCounter * _sync_MonInCirculation; |
307 static PerfCounter * _sync_MonScavenged ; |
307 static PerfCounter * _sync_MonScavenged; |
308 static PerfCounter * _sync_Inflations ; |
308 static PerfCounter * _sync_Inflations; |
309 static PerfCounter * _sync_Deflations ; |
309 static PerfCounter * _sync_Deflations; |
310 static PerfLongVariable * _sync_MonExtant ; |
310 static PerfLongVariable * _sync_MonExtant; |
311 |
311 |
312 public: |
312 public: |
313 static int Knob_Verbose; |
313 static int Knob_Verbose; |
314 static int Knob_SpinLimit; |
314 static int Knob_SpinLimit; |
315 void* operator new (size_t size) throw() { |
315 void* operator new (size_t size) throw() { |