172 ev->unpark(); |
172 ev->unpark(); |
173 } |
173 } |
174 return; |
174 return; |
175 } |
175 } |
176 |
176 |
177 int JvmtiRawMonitor::simple_wait(Thread* self, jlong millis) { |
177 inline void JvmtiRawMonitor::enqueue_waiter(QNode& node) { |
178 guarantee(_owner == self , "invariant"); |
|
179 guarantee(_recursions == 0, "invariant"); |
|
180 |
|
181 QNode node(self); |
|
182 node._notified = 0; |
178 node._notified = 0; |
183 node._t_state = QNode::TS_WAIT; |
179 node._t_state = QNode::TS_WAIT; |
184 |
|
185 RawMonitor_lock->lock_without_safepoint_check(); |
180 RawMonitor_lock->lock_without_safepoint_check(); |
186 node._next = _wait_set; |
181 node._next = _wait_set; |
187 _wait_set = &node; |
182 _wait_set = &node; |
188 RawMonitor_lock->unlock(); |
183 RawMonitor_lock->unlock(); |
189 |
184 } |
190 simple_exit(self); |
185 |
191 guarantee(_owner != self, "invariant"); |
186 inline void JvmtiRawMonitor::dequeue_waiter(QNode& node) { |
192 |
|
193 int ret = OS_OK; |
|
194 if (millis <= 0) { |
|
195 self->_ParkEvent->park(); |
|
196 } else { |
|
197 ret = self->_ParkEvent->park(millis); |
|
198 } |
|
199 |
|
200 // If thread still resides on the waitset then unlink it. |
187 // If thread still resides on the waitset then unlink it. |
201 // Double-checked locking -- the usage is safe in this context |
188 // Double-checked locking -- the usage is safe in this context |
202 // as _t_state is volatile and the lock-unlock operators are |
189 // as _t_state is volatile and the lock-unlock operators are |
203 // serializing (barrier-equivalent). |
190 // serializing (barrier-equivalent). |
204 |
191 |
223 } |
210 } |
224 RawMonitor_lock->unlock(); |
211 RawMonitor_lock->unlock(); |
225 } |
212 } |
226 |
213 |
227 guarantee(node._t_state == QNode::TS_RUN, "invariant"); |
214 guarantee(node._t_state == QNode::TS_RUN, "invariant"); |
|
215 } |
|
216 |
|
217 // simple_wait is not quite so simple as we have to deal with the interaction |
|
218 // with the Thread interrupt state, which resides in the java.lang.Thread object. |
|
219 // That state must only be accessed while _thread_in_vm and requires proper thread-state |
|
220 // transitions. However, we cannot perform such transitions whilst we hold the RawMonitor, |
|
221 // else we can deadlock with the VMThread (which may also use RawMonitors as part of |
|
222 // executing various callbacks). |
|
223 // Returns M_OK usually, but M_INTERRUPTED if the thread is a JavaThread and was |
|
224 // interrupted. |
|
225 int JvmtiRawMonitor::simple_wait(Thread* self, jlong millis) { |
|
226 guarantee(_owner == self , "invariant"); |
|
227 guarantee(_recursions == 0, "invariant"); |
|
228 |
|
229 QNode node(self); |
|
230 enqueue_waiter(node); |
|
231 |
|
232 simple_exit(self); |
|
233 guarantee(_owner != self, "invariant"); |
|
234 |
|
235 int ret = M_OK; |
|
236 if (self->is_Java_thread()) { |
|
237 JavaThread* jt = (JavaThread*) self; |
|
238 // Transition to VM so we can check interrupt state |
|
239 ThreadInVMfromNative tivm(jt); |
|
240 if (jt->is_interrupted(true)) { |
|
241 ret = M_INTERRUPTED; |
|
242 } else { |
|
243 ThreadBlockInVM tbivm(jt); |
|
244 jt->set_suspend_equivalent(); |
|
245 if (millis <= 0) { |
|
246 self->_ParkEvent->park(); |
|
247 } else { |
|
248 self->_ParkEvent->park(millis); |
|
249 } |
|
250 // Return to VM before post-check of interrupt state |
|
251 } |
|
252 if (jt->is_interrupted(true)) { |
|
253 ret = M_INTERRUPTED; |
|
254 } |
|
255 } else { |
|
256 if (millis <= 0) { |
|
257 self->_ParkEvent->park(); |
|
258 } else { |
|
259 self->_ParkEvent->park(millis); |
|
260 } |
|
261 } |
|
262 |
|
263 dequeue_waiter(node); |
|
264 |
228 simple_enter(self); |
265 simple_enter(self); |
229 |
|
230 guarantee(_owner == self, "invariant"); |
266 guarantee(_owner == self, "invariant"); |
231 guarantee(_recursions == 0, "invariant"); |
267 guarantee(_recursions == 0, "invariant"); |
|
268 |
232 return ret; |
269 return ret; |
233 } |
270 } |
234 |
271 |
235 void JvmtiRawMonitor::simple_notify(Thread* self, bool all) { |
272 void JvmtiRawMonitor::simple_notify(Thread* self, bool all) { |
236 guarantee(_owner == self, "invariant"); |
273 guarantee(_owner == self, "invariant"); |
349 } |
386 } |
350 |
387 |
351 return M_OK; |
388 return M_OK; |
352 } |
389 } |
353 |
390 |
354 // All JavaThreads will enter here with state _thread_blocked |
391 int JvmtiRawMonitor::raw_wait(jlong millis, Thread* self) { |
355 |
|
356 int JvmtiRawMonitor::raw_wait(jlong millis, bool interruptible, Thread* self) { |
|
357 if (self != _owner) { |
392 if (self != _owner) { |
358 return M_ILLEGAL_MONITOR_STATE; |
393 return M_ILLEGAL_MONITOR_STATE; |
359 } |
394 } |
|
395 |
|
396 int ret = M_OK; |
360 |
397 |
361 // To avoid spurious wakeups we reset the parkevent. This is strictly optional. |
398 // To avoid spurious wakeups we reset the parkevent. This is strictly optional. |
362 // The caller must be able to tolerate spurious returns from raw_wait(). |
399 // The caller must be able to tolerate spurious returns from raw_wait(). |
363 self->_ParkEvent->reset(); |
400 self->_ParkEvent->reset(); |
364 OrderAccess::fence(); |
401 OrderAccess::fence(); |
365 |
402 |
366 JavaThread* jt = NULL; |
|
367 // check interrupt event |
|
368 if (interruptible) { |
|
369 assert(self->is_Java_thread(), "Only JavaThreads can be interruptible"); |
|
370 jt = (JavaThread*)self; |
|
371 if (jt->is_interrupted(true)) { |
|
372 return M_INTERRUPTED; |
|
373 } |
|
374 } else { |
|
375 assert(!self->is_Java_thread(), "JavaThreads must be interuptible"); |
|
376 } |
|
377 |
|
378 intptr_t save = _recursions; |
403 intptr_t save = _recursions; |
379 _recursions = 0; |
404 _recursions = 0; |
380 _waiters++; |
405 _waiters++; |
381 if (self->is_Java_thread()) { |
406 ret = simple_wait(self, millis); |
382 guarantee(jt->thread_state() == _thread_blocked, "invariant"); |
|
383 jt->set_suspend_equivalent(); |
|
384 } |
|
385 int rv = simple_wait(self, millis); |
|
386 _recursions = save; |
407 _recursions = save; |
387 _waiters--; |
408 _waiters--; |
388 |
409 |
389 guarantee(self == _owner, "invariant"); |
410 guarantee(self == _owner, "invariant"); |
|
411 |
390 if (self->is_Java_thread()) { |
412 if (self->is_Java_thread()) { |
|
413 JavaThread* jt = (JavaThread*)self; |
391 for (;;) { |
414 for (;;) { |
|
415 jt->set_suspend_equivalent(); |
392 if (!jt->handle_special_suspend_equivalent_condition()) { |
416 if (!jt->handle_special_suspend_equivalent_condition()) { |
393 break; |
417 break; |
|
418 } else { |
|
419 // We've been suspended whilst waiting and so we have to |
|
420 // relinquish the raw monitor until we are resumed. Of course |
|
421 // after reacquiring we have to re-check for suspension again. |
|
422 // Suspension requires we are _thread_blocked, and we also have to |
|
423 // recheck for being interrupted. |
|
424 simple_exit(jt); |
|
425 { |
|
426 ThreadInVMfromNative tivm(jt); |
|
427 { |
|
428 ThreadBlockInVM tbivm(jt); |
|
429 jt->java_suspend_self(); |
|
430 } |
|
431 if (jt->is_interrupted(true)) { |
|
432 ret = M_INTERRUPTED; |
|
433 } |
|
434 } |
|
435 simple_enter(jt); |
394 } |
436 } |
395 simple_exit(jt); |
|
396 jt->java_suspend_self(); |
|
397 simple_enter(jt); |
|
398 jt->set_suspend_equivalent(); |
|
399 } |
437 } |
400 guarantee(jt == _owner, "invariant"); |
438 guarantee(jt == _owner, "invariant"); |
401 } |
439 } else { |
402 |
440 assert(ret != M_INTERRUPTED, "Only JavaThreads can be interrupted"); |
403 if (interruptible && jt->is_interrupted(true)) { |
441 } |
404 return M_INTERRUPTED; |
442 |
405 } |
443 return ret; |
406 |
|
407 return M_OK; |
|
408 } |
444 } |
409 |
445 |
410 int JvmtiRawMonitor::raw_notify(Thread* self) { |
446 int JvmtiRawMonitor::raw_notify(Thread* self) { |
411 if (self != _owner) { |
447 if (self != _owner) { |
412 return M_ILLEGAL_MONITOR_STATE; |
448 return M_ILLEGAL_MONITOR_STATE; |