src/hotspot/share/prims/jvmtiRawMonitor.cpp
changeset 58488 165b193b30dd
parent 58196 cea6839598e8
child 58509 7b41c88f8432
--- a/src/hotspot/share/prims/jvmtiRawMonitor.cpp	Mon Oct 07 13:56:11 2019 -0700
+++ b/src/hotspot/share/prims/jvmtiRawMonitor.cpp	Mon Oct 07 18:44:53 2019 -0400
@@ -30,21 +30,23 @@
 #include "runtime/orderAccess.hpp"
 #include "runtime/thread.inline.hpp"
 
-GrowableArray<JvmtiRawMonitor*> *JvmtiPendingMonitors::_monitors = new (ResourceObj::C_HEAP, mtInternal) GrowableArray<JvmtiRawMonitor*>(1,true);
+JvmtiRawMonitor::QNode::QNode(Thread* thread) : _next(NULL), _prev(NULL),
+                                                _event(thread->_ParkEvent),
+                                                _notified(0), TState(TS_RUN) {
+}
+
+GrowableArray<JvmtiRawMonitor*> *JvmtiPendingMonitors::_monitors =
+  new (ResourceObj::C_HEAP, mtInternal) GrowableArray<JvmtiRawMonitor*>(1, true);
 
 void JvmtiPendingMonitors::transition_raw_monitors() {
   assert((Threads::number_of_threads()==1),
-         "Java thread has not created yet or more than one java thread \
+         "Java thread has not been created yet or more than one java thread \
 is running. Raw monitor transition will not work");
   JavaThread *current_java_thread = JavaThread::current();
   assert(current_java_thread->thread_state() == _thread_in_vm, "Must be in vm");
-  {
-    ThreadBlockInVM __tbivm(current_java_thread);
-    for(int i=0; i< count(); i++) {
-      JvmtiRawMonitor *rmonitor = monitors()->at(i);
-      int r = rmonitor->raw_enter(current_java_thread);
-      assert(r == ObjectMonitor::OM_OK, "raw_enter should have worked");
-    }
+  for(int i=0; i< count(); i++) {
+    JvmtiRawMonitor *rmonitor = monitors()->at(i);
+    rmonitor->raw_enter(current_java_thread);
   }
   // pending monitors are converted to real monitor so delete them all.
   dispose();
@@ -54,13 +56,16 @@
 // class JvmtiRawMonitor
 //
 
-JvmtiRawMonitor::JvmtiRawMonitor(const char *name) {
+JvmtiRawMonitor::JvmtiRawMonitor(const char *name) : _owner(NULL),
+                                                     _recursions(0),
+                                                     _EntryList(NULL),
+                                                     _WaitSet(NULL),
+                                                     _waiters(0),
+                                                     _magic(JVMTI_RM_MAGIC),
+                                                     _name(NULL) {
 #ifdef ASSERT
   _name = strcpy(NEW_C_HEAP_ARRAY(char, strlen(name) + 1, mtInternal), name);
-#else
-  _name = NULL;
 #endif
-  _magic = JVMTI_RM_MAGIC;
 }
 
 JvmtiRawMonitor::~JvmtiRawMonitor() {
@@ -100,41 +105,29 @@
 }
 
 // -------------------------------------------------------------------------
-// The raw monitor subsystem is entirely distinct from normal
-// java-synchronization or jni-synchronization.  raw monitors are not
+// The JVMTI raw monitor subsystem is entirely distinct from normal
+// java-synchronization or jni-synchronization.  JVMTI raw monitors are not
 // associated with objects.  They can be implemented in any manner
 // that makes sense.  The original implementors decided to piggy-back
-// the raw-monitor implementation on the existing Java objectMonitor mechanism.
-// This flaw needs to fixed.  We should reimplement raw monitors as sui-generis.
-// Specifically, we should not implement raw monitors via java monitors.
-// Time permitting, we should disentangle and deconvolve the two implementations
-// and move the resulting raw monitor implementation over to the JVMTI directories.
-// Ideally, the raw monitor implementation would be built on top of
-// park-unpark and nothing else.
-//
-// raw monitors are used mainly by JVMTI
-// The raw monitor implementation borrows the ObjectMonitor structure,
-// but the operators are degenerate and extremely simple.
-//
-// Mixed use of a single objectMonitor instance -- as both a raw monitor
-// and a normal java monitor -- is not permissible.
+// the raw-monitor implementation on the existing Java ObjectMonitor mechanism.
+// Now we just use a simplified form of that ObjectMonitor code.
 //
 // Note that we use the single RawMonitor_lock to protect queue operations for
 // _all_ raw monitors.  This is a scalability impediment, but since raw monitor usage
-// is deprecated and rare, this is not of concern.  The RawMonitor_lock can not
+// is fairly rare, this is not of concern.  The RawMonitor_lock can not
 // be held indefinitely.  The critical sections must be short and bounded.
 //
 // -------------------------------------------------------------------------
 
-int JvmtiRawMonitor::SimpleEnter (Thread * Self) {
+void JvmtiRawMonitor::SimpleEnter (Thread * Self) {
   for (;;) {
     if (Atomic::replace_if_null(Self, &_owner)) {
-       return OS_OK ;
+       return ;
     }
 
-    ObjectWaiter Node (Self) ;
+    QNode Node (Self) ;
     Self->_ParkEvent->reset() ;     // strictly optional
-    Node.TState = ObjectWaiter::TS_ENTER ;
+    Node.TState = QNode::TS_ENTER ;
 
     RawMonitor_lock->lock_without_safepoint_check() ;
     Node._next  = _EntryList ;
@@ -143,21 +136,21 @@
     if (_owner == NULL && Atomic::replace_if_null(Self, &_owner)) {
         _EntryList = Node._next ;
         RawMonitor_lock->unlock() ;
-        return OS_OK ;
+        return ;
     }
     RawMonitor_lock->unlock() ;
-    while (Node.TState == ObjectWaiter::TS_ENTER) {
+    while (Node.TState == QNode::TS_ENTER) {
        Self->_ParkEvent->park() ;
     }
   }
 }
 
-int JvmtiRawMonitor::SimpleExit (Thread * Self) {
+void JvmtiRawMonitor::SimpleExit (Thread * Self) {
   guarantee (_owner == Self, "invariant") ;
-  OrderAccess::release_store(&_owner, (void*)NULL) ;
+  OrderAccess::release_store(&_owner, (Thread*)NULL) ;
   OrderAccess::fence() ;
-  if (_EntryList == NULL) return OS_OK ;
-  ObjectWaiter * w ;
+  if (_EntryList == NULL) return ;
+  QNode * w ;
 
   RawMonitor_lock->lock_without_safepoint_check() ;
   w = _EntryList ;
@@ -166,27 +159,27 @@
   }
   RawMonitor_lock->unlock() ;
   if (w != NULL) {
-      guarantee (w ->TState == ObjectWaiter::TS_ENTER, "invariant") ;
+      guarantee (w ->TState == QNode::TS_ENTER, "invariant") ;
       // Once we set TState to TS_RUN the waiting thread can complete
       // SimpleEnter and 'w' is pointing into random stack space. So we have
       // to ensure we extract the ParkEvent (which is in type-stable memory)
       // before we set the state, and then don't access 'w'.
       ParkEvent * ev = w->_event ;
       OrderAccess::loadstore();
-      w->TState = ObjectWaiter::TS_RUN ;
+      w->TState = QNode::TS_RUN ;
       OrderAccess::fence() ;
       ev->unpark() ;
   }
-  return OS_OK ;
+  return ;
 }
 
 int JvmtiRawMonitor::SimpleWait (Thread * Self, jlong millis) {
   guarantee (_owner == Self  , "invariant") ;
   guarantee (_recursions == 0, "invariant") ;
 
-  ObjectWaiter Node (Self) ;
+  QNode Node (Self) ;
   Node._notified = 0 ;
-  Node.TState    = ObjectWaiter::TS_WAIT ;
+  Node.TState    = QNode::TS_WAIT ;
 
   RawMonitor_lock->lock_without_safepoint_check() ;
   Node._next     = _WaitSet ;
@@ -208,12 +201,12 @@
   // as TState is volatile and the lock-unlock operators are
   // serializing (barrier-equivalent).
 
-  if (Node.TState == ObjectWaiter::TS_WAIT) {
+  if (Node.TState == QNode::TS_WAIT) {
     RawMonitor_lock->lock_without_safepoint_check() ;
-    if (Node.TState == ObjectWaiter::TS_WAIT) {
+    if (Node.TState == QNode::TS_WAIT) {
       // Simple O(n) unlink, but performance isn't critical here.
-      ObjectWaiter * p ;
-      ObjectWaiter * q = NULL ;
+      QNode * p ;
+      QNode * q = NULL ;
       for (p = _WaitSet ; p != &Node; p = p->_next) {
          q = p ;
       }
@@ -225,12 +218,12 @@
         guarantee (p == q->_next, "invariant") ;
         q->_next = p->_next ;
       }
-      Node.TState = ObjectWaiter::TS_RUN ;
+      Node.TState = QNode::TS_RUN ;
     }
     RawMonitor_lock->unlock() ;
   }
 
-  guarantee (Node.TState == ObjectWaiter::TS_RUN, "invariant") ;
+  guarantee (Node.TState == QNode::TS_RUN, "invariant") ;
   SimpleEnter (Self) ;
 
   guarantee (_owner == Self, "invariant") ;
@@ -238,9 +231,9 @@
   return ret ;
 }
 
-int JvmtiRawMonitor::SimpleNotify (Thread * Self, bool All) {
+void JvmtiRawMonitor::SimpleNotify (Thread * Self, bool All) {
   guarantee (_owner == Self, "invariant") ;
-  if (_WaitSet == NULL) return OS_OK ;
+  if (_WaitSet == NULL) return ;
 
   // We have two options:
   // A. Transfer the threads from the WaitSet to the EntryList
@@ -252,29 +245,29 @@
   ParkEvent * ev = NULL ;       // consider using a small auto array ...
   RawMonitor_lock->lock_without_safepoint_check() ;
   for (;;) {
-      ObjectWaiter * w = _WaitSet ;
+      QNode * w = _WaitSet ;
       if (w == NULL) break ;
       _WaitSet = w->_next ;
       if (ev != NULL) { ev->unpark(); ev = NULL; }
       ev = w->_event ;
       OrderAccess::loadstore() ;
-      w->TState = ObjectWaiter::TS_RUN ;
+      w->TState = QNode::TS_RUN ;
       OrderAccess::storeload();
       if (!All) break ;
   }
   RawMonitor_lock->unlock() ;
   if (ev != NULL) ev->unpark();
-  return OS_OK ;
+  return ;
 }
 
 // Any JavaThread will enter here with state _thread_blocked
-int JvmtiRawMonitor::raw_enter(TRAPS) {
+void JvmtiRawMonitor::raw_enter(Thread * Self) {
   void * Contended ;
-
+  JavaThread * jt = NULL;
   // don't enter raw monitor if thread is being externally suspended, it will
   // surprise the suspender if a "suspended" thread can still enter monitor
-  JavaThread * jt = (JavaThread *)THREAD;
-  if (THREAD->is_Java_thread()) {
+  if (Self->is_Java_thread()) {
+    jt = (JavaThread*) Self;
     jt->SR_lock()->lock_without_safepoint_check();
     while (jt->is_external_suspend()) {
       jt->SR_lock()->unlock();
@@ -282,150 +275,136 @@
       jt->SR_lock()->lock_without_safepoint_check();
     }
     // guarded by SR_lock to avoid racing with new external suspend requests.
-    Contended = Atomic::cmpxchg(THREAD, &_owner, (void*)NULL);
+    Contended = Atomic::cmpxchg(jt, &_owner, (Thread*)NULL);
     jt->SR_lock()->unlock();
   } else {
-    Contended = Atomic::cmpxchg(THREAD, &_owner, (void*)NULL);
+    Contended = Atomic::cmpxchg(Self, &_owner, (Thread*)NULL);
   }
 
-  if (Contended == THREAD) {
+  if (Contended == Self) {
      _recursions ++ ;
-     return OM_OK ;
+     return ;
   }
 
   if (Contended == NULL) {
-     guarantee (_owner == THREAD, "invariant") ;
+     guarantee (_owner == Self, "invariant") ;
      guarantee (_recursions == 0, "invariant") ;
-     return OM_OK ;
+     return ;
   }
 
-  THREAD->set_current_pending_monitor(this);
+  Self->set_current_pending_raw_monitor(this);
 
-  if (!THREAD->is_Java_thread()) {
-     // No other non-Java threads besides VM thread would acquire
-     // a raw monitor.
-     assert(THREAD->is_VM_thread(), "must be VM thread");
-     SimpleEnter (THREAD) ;
-   } else {
-     guarantee (jt->thread_state() == _thread_blocked, "invariant") ;
-     for (;;) {
-       jt->set_suspend_equivalent();
-       // cleared by handle_special_suspend_equivalent_condition() or
-       // java_suspend_self()
-       SimpleEnter (THREAD) ;
-
-       // were we externally suspended while we were waiting?
-       if (!jt->handle_special_suspend_equivalent_condition()) break ;
+  if (!Self->is_Java_thread()) {
+     SimpleEnter (Self) ;
+  } else {
+    guarantee (jt->thread_state() == _thread_blocked, "invariant") ;
+    for (;;) {
+      jt->set_suspend_equivalent();
+      // cleared by handle_special_suspend_equivalent_condition() or
+      // java_suspend_self()
+      SimpleEnter (jt) ;
 
-       // This thread was externally suspended
-       //
-       // This logic isn't needed for JVMTI raw monitors,
-       // but doesn't hurt just in case the suspend rules change. This
-           // logic is needed for the JvmtiRawMonitor.wait() reentry phase.
-           // We have reentered the contended monitor, but while we were
-           // waiting another thread suspended us. We don't want to reenter
-           // the monitor while suspended because that would surprise the
-           // thread that suspended us.
-           //
-           // Drop the lock -
-       SimpleExit (THREAD) ;
+      // were we externally suspended while we were waiting?
+      if (!jt->handle_special_suspend_equivalent_condition()) break ;
 
-           jt->java_suspend_self();
-         }
+      // This thread was externally suspended
+      // We have reentered the contended monitor, but while we were
+      // waiting another thread suspended us. We don't want to reenter
+      // the monitor while suspended because that would surprise the
+      // thread that suspended us.
+      //
+      // Drop the lock
+      SimpleExit (jt) ;
 
-     assert(_owner == THREAD, "Fatal error with monitor owner!");
-     assert(_recursions == 0, "Fatal error with monitor recursions!");
+      jt->java_suspend_self();
+    }
   }
 
-  THREAD->set_current_pending_monitor(NULL);
+  Self->set_current_pending_raw_monitor(NULL);
+
+  guarantee (_owner == Self, "invariant") ;
   guarantee (_recursions == 0, "invariant") ;
-  return OM_OK;
 }
 
-// Used mainly for JVMTI raw monitor implementation
-// Also used for JvmtiRawMonitor::wait().
-int JvmtiRawMonitor::raw_exit(TRAPS) {
-  if (THREAD != _owner) {
-    return OM_ILLEGAL_MONITOR_STATE;
+int JvmtiRawMonitor::raw_exit(Thread * Self) {
+  if (Self != _owner) {
+    return M_ILLEGAL_MONITOR_STATE;
   }
   if (_recursions > 0) {
     --_recursions ;
-    return OM_OK ;
+  } else {
+    SimpleExit (Self) ;
   }
 
-  void * List = _EntryList ;
-  SimpleExit (THREAD) ;
-
-  return OM_OK;
+  return M_OK;
 }
 
-// Used for JVMTI raw monitor implementation.
 // All JavaThreads will enter here with state _thread_blocked
 
-int JvmtiRawMonitor::raw_wait(jlong millis, bool interruptible, TRAPS) {
-  if (THREAD != _owner) {
-    return OM_ILLEGAL_MONITOR_STATE;
+int JvmtiRawMonitor::raw_wait(jlong millis, bool interruptible, Thread * Self) {
+  if (Self != _owner) {
+    return M_ILLEGAL_MONITOR_STATE;
   }
 
   // To avoid spurious wakeups we reset the parkevent -- This is strictly optional.
   // The caller must be able to tolerate spurious returns from raw_wait().
-  THREAD->_ParkEvent->reset() ;
+  Self->_ParkEvent->reset() ;
   OrderAccess::fence() ;
 
+  JavaThread * jt = NULL;
   // check interrupt event
   if (interruptible) {
-    assert(THREAD->is_Java_thread(), "Only JavaThreads can be interruptible");
-    JavaThread* jt = (JavaThread*) THREAD;
+    assert(Self->is_Java_thread(), "Only JavaThreads can be interruptible");
+    jt = (JavaThread*) Self;
     if (jt->is_interrupted(true)) {
-      return OM_INTERRUPTED;
+      return M_INTERRUPTED;
     }
+  } else {
+    assert(!Self->is_Java_thread(), "JavaThreads must be interuptible");
   }
 
   intptr_t save = _recursions ;
   _recursions = 0 ;
   _waiters ++ ;
-  if (THREAD->is_Java_thread()) {
-    guarantee (((JavaThread *) THREAD)->thread_state() == _thread_blocked, "invariant") ;
-    ((JavaThread *)THREAD)->set_suspend_equivalent();
+  if (Self->is_Java_thread()) {
+    guarantee (jt->thread_state() == _thread_blocked, "invariant") ;
+    jt->set_suspend_equivalent();
   }
-  int rv = SimpleWait (THREAD, millis) ;
+  int rv = SimpleWait (Self, millis) ;
   _recursions = save ;
   _waiters -- ;
 
-  guarantee (THREAD == _owner, "invariant") ;
-  if (THREAD->is_Java_thread()) {
-     JavaThread * jSelf = (JavaThread *) THREAD ;
+  guarantee (Self == _owner, "invariant") ;
+  if (Self->is_Java_thread()) {
      for (;;) {
-        if (!jSelf->handle_special_suspend_equivalent_condition()) break ;
-        SimpleExit (THREAD) ;
-        jSelf->java_suspend_self();
-        SimpleEnter (THREAD) ;
-        jSelf->set_suspend_equivalent() ;
+        if (!jt->handle_special_suspend_equivalent_condition()) break ;
+        SimpleExit (jt) ;
+        jt->java_suspend_self();
+        SimpleEnter (jt) ;
+        jt->set_suspend_equivalent() ;
      }
+     guarantee (jt == _owner, "invariant") ;
   }
-  guarantee (THREAD == _owner, "invariant") ;
 
-  if (interruptible) {
-    JavaThread* jt = (JavaThread*) THREAD;
-    if (jt->is_interrupted(true)) {
-      return OM_INTERRUPTED;
-    }
+  if (interruptible && jt->is_interrupted(true)) {
+    return M_INTERRUPTED;
   }
-  return OM_OK ;
+
+  return M_OK ;
 }
 
-int JvmtiRawMonitor::raw_notify(TRAPS) {
-  if (THREAD != _owner) {
-    return OM_ILLEGAL_MONITOR_STATE;
+int JvmtiRawMonitor::raw_notify(Thread * Self) {
+  if (Self != _owner) {
+    return M_ILLEGAL_MONITOR_STATE;
   }
-  SimpleNotify (THREAD, false) ;
-  return OM_OK;
+  SimpleNotify (Self, false) ;
+  return M_OK;
 }
 
-int JvmtiRawMonitor::raw_notifyAll(TRAPS) {
-  if (THREAD != _owner) {
-    return OM_ILLEGAL_MONITOR_STATE;
+int JvmtiRawMonitor::raw_notifyAll(Thread * Self) {
+  if (Self != _owner) {
+    return M_ILLEGAL_MONITOR_STATE;
   }
-  SimpleNotify (THREAD, true) ;
-  return OM_OK;
+  SimpleNotify (Self, true) ;
+  return M_OK;
 }