< prev index next > src/hotspot/share/runtime/objectMonitor.cpp
Print this page
_wait_set_lock(0)
{ }
ObjectMonitor::~ObjectMonitor() {
_object.release(_oop_storage);
+ _object_strong.release(JavaThread::thread_oop_storage());
}
oop ObjectMonitor::object() const {
check_object_context();
return _object.resolve();
}
+ // Keep object protected during ObjectLocker preemption.
+ void ObjectMonitor::set_object_strong() {
+ check_object_context();
+ if (_object_strong.is_empty()) {
+ if (Thread::TrySpinAcquire(&_object_strong_lock)) {
+ if (_object_strong.is_empty()) {
+ assert(_object.resolve() != nullptr, "");
+ _object_strong = OopHandle(JavaThread::thread_oop_storage(), _object.resolve());
+ }
+ Thread::SpinRelease(&_object_strong_lock);
+ }
+ }
+ }
+
void ObjectMonitor::ExitOnSuspend::operator()(JavaThread* current) {
if (current->is_suspended()) {
_om->_recursions = 0;
_om->clear_successor();
// Don't need a full fence after clearing successor here because of the call to exit().
JvmtiExport::post_monitor_wait(current, object(), millis);
}
current->set_current_waiting_monitor(this);
result = Continuation::try_preempt(current, ce->cont_oop(current));
if (result == freeze_ok) {
! vthread_wait(current, millis);
current->set_current_waiting_monitor(nullptr);
return;
}
}
// The jtiows does nothing for non-interruptible.
JvmtiExport::post_monitor_wait(current, object(), millis);
}
current->set_current_waiting_monitor(this);
result = Continuation::try_preempt(current, ce->cont_oop(current));
if (result == freeze_ok) {
! vthread_wait(current, millis, interruptible);
current->set_current_waiting_monitor(nullptr);
return;
}
}
// The jtiows does nothing for non-interruptible.
if ((tally > 0) && event.should_commit()) {
post_monitor_notify_event(&event, this, /* notified_count = */ tally);
}
}
! void ObjectMonitor::vthread_wait(JavaThread* current, jlong millis) {
oop vthread = current->vthread();
ObjectWaiter* node = new ObjectWaiter(vthread, this);
node->_is_wait = true;
node->TState = ObjectWaiter::TS_WAIT;
java_lang_VirtualThread::set_notified(vthread, false); // Reset notified flag
// Enter the waiting queue, which is a circular doubly linked list in this case
// but it could be a priority queue or any data structure.
// _wait_set_lock protects the wait queue. Normally the wait queue is accessed only
// by the owner of the monitor *except* in the case where park()
if ((tally > 0) && event.should_commit()) {
post_monitor_notify_event(&event, this, /* notified_count = */ tally);
}
}
! void ObjectMonitor::vthread_wait(JavaThread* current, jlong millis, bool interruptible) {
oop vthread = current->vthread();
ObjectWaiter* node = new ObjectWaiter(vthread, this);
node->_is_wait = true;
+ node->_interruptible = interruptible;
node->TState = ObjectWaiter::TS_WAIT;
java_lang_VirtualThread::set_notified(vthread, false); // Reset notified flag
+ java_lang_VirtualThread::set_interruptible_wait(vthread, interruptible);
// Enter the waiting queue, which is a circular doubly linked list in this case
// but it could be a priority queue or any data structure.
// _wait_set_lock protects the wait queue. Normally the wait queue is accessed only
// by the owner of the monitor *except* in the case where park()
// If this was an interrupted case, set the _interrupted boolean so that
// once we re-acquire the monitor we know if we need to throw IE or not.
ObjectWaiter::TStates state = node->TState;
bool was_notified = state == ObjectWaiter::TS_ENTER;
assert(was_notified || state == ObjectWaiter::TS_RUN, "");
! node->_interrupted = !was_notified && current->is_interrupted(false);
! // Post JFR and JVMTI events.
EventJavaMonitorWait wait_event;
! if (wait_event.should_commit() || JvmtiExport::should_post_monitor_waited()) {
vthread_monitor_waited_event(current, node, cont, &wait_event, !was_notified && !node->_interrupted);
}
// Mark that we are at reenter so that we don't call this method again.
node->_at_reenter = true;
// If this was an interrupted case, set the _interrupted boolean so that
// once we re-acquire the monitor we know if we need to throw IE or not.
ObjectWaiter::TStates state = node->TState;
bool was_notified = state == ObjectWaiter::TS_ENTER;
assert(was_notified || state == ObjectWaiter::TS_RUN, "");
! node->_interrupted = node->_interruptible && !was_notified && current->is_interrupted(false);
! // Post JFR and JVMTI events. If non-interruptible we are in
+ // ObjectLocker case so we don't post anything.
EventJavaMonitorWait wait_event;
! if (node->_interruptible && (wait_event.should_commit() || JvmtiExport::should_post_monitor_waited())) {
vthread_monitor_waited_event(current, node, cont, &wait_event, !was_notified && !node->_interrupted);
}
// Mark that we are at reenter so that we don't call this method again.
node->_at_reenter = true;
< prev index next >