hotspot/src/share/vm/prims/jvmtiRawMonitor.cpp
changeset 6975 dc9b63952682
child 7397 5b173b4ca846
equal deleted inserted replaced
6971:11c11e616b91 6975:dc9b63952682
       
     1 /*
       
     2  * Copyright (c) 2003, 2007, Oracle and/or its affiliates. All rights reserved.
       
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
       
     4  *
       
     5  * This code is free software; you can redistribute it and/or modify it
       
     6  * under the terms of the GNU General Public License version 2 only, as
       
     7  * published by the Free Software Foundation.
       
     8  *
       
     9  * This code is distributed in the hope that it will be useful, but WITHOUT
       
    10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
       
    11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
       
    12  * version 2 for more details (a copy is included in the LICENSE file that
       
    13  * accompanied this code).
       
    14  *
       
    15  * You should have received a copy of the GNU General Public License version
       
    16  * 2 along with this work; if not, write to the Free Software Foundation,
       
    17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
       
    18  *
       
    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
       
    21  * questions.
       
    22  *
       
    23  */
       
    24 
       
    25 # include "incls/_precompiled.incl"
       
    26 # include "incls/_jvmtiRawMonitor.cpp.incl"
       
    27 
       
    28 GrowableArray<JvmtiRawMonitor*> *JvmtiPendingMonitors::_monitors = new (ResourceObj::C_HEAP) GrowableArray<JvmtiRawMonitor*>(1,true);
       
    29 
       
    30 void JvmtiPendingMonitors::transition_raw_monitors() {
       
    31   assert((Threads::number_of_threads()==1),
       
    32          "Java thread has not created yet or more than one java thread \
       
    33 is running. Raw monitor transition will not work");
       
    34   JavaThread *current_java_thread = JavaThread::current();
       
    35   assert(current_java_thread->thread_state() == _thread_in_vm, "Must be in vm");
       
    36   {
       
    37     ThreadBlockInVM __tbivm(current_java_thread);
       
    38     for(int i=0; i< count(); i++) {
       
    39       JvmtiRawMonitor *rmonitor = monitors()->at(i);
       
    40       int r = rmonitor->raw_enter(current_java_thread);
       
    41       assert(r == ObjectMonitor::OM_OK, "raw_enter should have worked");
       
    42     }
       
    43   }
       
    44   // pending monitors are converted to real monitor so delete them all.
       
    45   dispose();
       
    46 }
       
    47 
       
    48 //
       
    49 // class JvmtiRawMonitor
       
    50 //
       
    51 
       
    52 JvmtiRawMonitor::JvmtiRawMonitor(const char *name) {
       
    53 #ifdef ASSERT
       
    54   _name = strcpy(NEW_C_HEAP_ARRAY(char, strlen(name) + 1), name);
       
    55 #else
       
    56   _name = NULL;
       
    57 #endif
       
    58   _magic = JVMTI_RM_MAGIC;
       
    59 }
       
    60 
       
    61 JvmtiRawMonitor::~JvmtiRawMonitor() {
       
    62 #ifdef ASSERT
       
    63   FreeHeap(_name);
       
    64 #endif
       
    65   _magic = 0;
       
    66 }
       
    67 
       
    68 
       
    69 bool
       
    70 JvmtiRawMonitor::is_valid() {
       
    71   int value = 0;
       
    72 
       
    73   // This object might not be a JvmtiRawMonitor so we can't assume
       
    74   // the _magic field is properly aligned. Get the value in a safe
       
    75   // way and then check against JVMTI_RM_MAGIC.
       
    76 
       
    77   switch (sizeof(_magic)) {
       
    78   case 2:
       
    79     value = Bytes::get_native_u2((address)&_magic);
       
    80     break;
       
    81 
       
    82   case 4:
       
    83     value = Bytes::get_native_u4((address)&_magic);
       
    84     break;
       
    85 
       
    86   case 8:
       
    87     value = Bytes::get_native_u8((address)&_magic);
       
    88     break;
       
    89 
       
    90   default:
       
    91     guarantee(false, "_magic field is an unexpected size");
       
    92   }
       
    93 
       
    94   return value == JVMTI_RM_MAGIC;
       
    95 }
       
    96 
       
    97 // -------------------------------------------------------------------------
       
    98 // The raw monitor subsystem is entirely distinct from normal
       
    99 // java-synchronization or jni-synchronization.  raw monitors are not
       
   100 // associated with objects.  They can be implemented in any manner
       
   101 // that makes sense.  The original implementors decided to piggy-back
       
   102 // the raw-monitor implementation on the existing Java objectMonitor mechanism.
       
   103 // This flaw needs to fixed.  We should reimplement raw monitors as sui-generis.
       
   104 // Specifically, we should not implement raw monitors via java monitors.
       
   105 // Time permitting, we should disentangle and deconvolve the two implementations
       
   106 // and move the resulting raw monitor implementation over to the JVMTI directories.
       
   107 // Ideally, the raw monitor implementation would be built on top of
       
   108 // park-unpark and nothing else.
       
   109 //
       
   110 // raw monitors are used mainly by JVMTI
       
   111 // The raw monitor implementation borrows the ObjectMonitor structure,
       
   112 // but the operators are degenerate and extremely simple.
       
   113 //
       
   114 // Mixed use of a single objectMonitor instance -- as both a raw monitor
       
   115 // and a normal java monitor -- is not permissible.
       
   116 //
       
   117 // Note that we use the single RawMonitor_lock to protect queue operations for
       
   118 // _all_ raw monitors.  This is a scalability impediment, but since raw monitor usage
       
   119 // is deprecated and rare, this is not of concern.  The RawMonitor_lock can not
       
   120 // be held indefinitely.  The critical sections must be short and bounded.
       
   121 //
       
   122 // -------------------------------------------------------------------------
       
   123 
       
   124 int JvmtiRawMonitor::SimpleEnter (Thread * Self) {
       
   125   for (;;) {
       
   126     if (Atomic::cmpxchg_ptr (Self, &_owner, NULL) == NULL) {
       
   127        return OS_OK ;
       
   128     }
       
   129 
       
   130     ObjectWaiter Node (Self) ;
       
   131     Self->_ParkEvent->reset() ;     // strictly optional
       
   132     Node.TState = ObjectWaiter::TS_ENTER ;
       
   133 
       
   134     RawMonitor_lock->lock_without_safepoint_check() ;
       
   135     Node._next  = _EntryList ;
       
   136     _EntryList  = &Node ;
       
   137     OrderAccess::fence() ;
       
   138     if (_owner == NULL && Atomic::cmpxchg_ptr (Self, &_owner, NULL) == NULL) {
       
   139         _EntryList = Node._next ;
       
   140         RawMonitor_lock->unlock() ;
       
   141         return OS_OK ;
       
   142     }
       
   143     RawMonitor_lock->unlock() ;
       
   144     while (Node.TState == ObjectWaiter::TS_ENTER) {
       
   145        Self->_ParkEvent->park() ;
       
   146     }
       
   147   }
       
   148 }
       
   149 
       
   150 int JvmtiRawMonitor::SimpleExit (Thread * Self) {
       
   151   guarantee (_owner == Self, "invariant") ;
       
   152   OrderAccess::release_store_ptr (&_owner, NULL) ;
       
   153   OrderAccess::fence() ;
       
   154   if (_EntryList == NULL) return OS_OK ;
       
   155   ObjectWaiter * w ;
       
   156 
       
   157   RawMonitor_lock->lock_without_safepoint_check() ;
       
   158   w = _EntryList ;
       
   159   if (w != NULL) {
       
   160       _EntryList = w->_next ;
       
   161   }
       
   162   RawMonitor_lock->unlock() ;
       
   163   if (w != NULL) {
       
   164       guarantee (w ->TState == ObjectWaiter::TS_ENTER, "invariant") ;
       
   165       ParkEvent * ev = w->_event ;
       
   166       w->TState = ObjectWaiter::TS_RUN ;
       
   167       OrderAccess::fence() ;
       
   168       ev->unpark() ;
       
   169   }
       
   170   return OS_OK ;
       
   171 }
       
   172 
       
   173 int JvmtiRawMonitor::SimpleWait (Thread * Self, jlong millis) {
       
   174   guarantee (_owner == Self  , "invariant") ;
       
   175   guarantee (_recursions == 0, "invariant") ;
       
   176 
       
   177   ObjectWaiter Node (Self) ;
       
   178   Node._notified = 0 ;
       
   179   Node.TState    = ObjectWaiter::TS_WAIT ;
       
   180 
       
   181   RawMonitor_lock->lock_without_safepoint_check() ;
       
   182   Node._next     = _WaitSet ;
       
   183   _WaitSet       = &Node ;
       
   184   RawMonitor_lock->unlock() ;
       
   185 
       
   186   SimpleExit (Self) ;
       
   187   guarantee (_owner != Self, "invariant") ;
       
   188 
       
   189   int ret = OS_OK ;
       
   190   if (millis <= 0) {
       
   191     Self->_ParkEvent->park();
       
   192   } else {
       
   193     ret = Self->_ParkEvent->park(millis);
       
   194   }
       
   195 
       
   196   // If thread still resides on the waitset then unlink it.
       
   197   // Double-checked locking -- the usage is safe in this context
       
   198   // as we TState is volatile and the lock-unlock operators are
       
   199   // serializing (barrier-equivalent).
       
   200 
       
   201   if (Node.TState == ObjectWaiter::TS_WAIT) {
       
   202     RawMonitor_lock->lock_without_safepoint_check() ;
       
   203     if (Node.TState == ObjectWaiter::TS_WAIT) {
       
   204       // Simple O(n) unlink, but performance isn't critical here.
       
   205       ObjectWaiter * p ;
       
   206       ObjectWaiter * q = NULL ;
       
   207       for (p = _WaitSet ; p != &Node; p = p->_next) {
       
   208          q = p ;
       
   209       }
       
   210       guarantee (p == &Node, "invariant") ;
       
   211       if (q == NULL) {
       
   212         guarantee (p == _WaitSet, "invariant") ;
       
   213         _WaitSet = p->_next ;
       
   214       } else {
       
   215         guarantee (p == q->_next, "invariant") ;
       
   216         q->_next = p->_next ;
       
   217       }
       
   218       Node.TState = ObjectWaiter::TS_RUN ;
       
   219     }
       
   220     RawMonitor_lock->unlock() ;
       
   221   }
       
   222 
       
   223   guarantee (Node.TState == ObjectWaiter::TS_RUN, "invariant") ;
       
   224   SimpleEnter (Self) ;
       
   225 
       
   226   guarantee (_owner == Self, "invariant") ;
       
   227   guarantee (_recursions == 0, "invariant") ;
       
   228   return ret ;
       
   229 }
       
   230 
       
   231 int JvmtiRawMonitor::SimpleNotify (Thread * Self, bool All) {
       
   232   guarantee (_owner == Self, "invariant") ;
       
   233   if (_WaitSet == NULL) return OS_OK ;
       
   234 
       
   235   // We have two options:
       
   236   // A. Transfer the threads from the WaitSet to the EntryList
       
   237   // B. Remove the thread from the WaitSet and unpark() it.
       
   238   //
       
   239   // We use (B), which is crude and results in lots of futile
       
   240   // context switching.  In particular (B) induces lots of contention.
       
   241 
       
   242   ParkEvent * ev = NULL ;       // consider using a small auto array ...
       
   243   RawMonitor_lock->lock_without_safepoint_check() ;
       
   244   for (;;) {
       
   245       ObjectWaiter * w = _WaitSet ;
       
   246       if (w == NULL) break ;
       
   247       _WaitSet = w->_next ;
       
   248       if (ev != NULL) { ev->unpark(); ev = NULL; }
       
   249       ev = w->_event ;
       
   250       OrderAccess::loadstore() ;
       
   251       w->TState = ObjectWaiter::TS_RUN ;
       
   252       OrderAccess::storeload();
       
   253       if (!All) break ;
       
   254   }
       
   255   RawMonitor_lock->unlock() ;
       
   256   if (ev != NULL) ev->unpark();
       
   257   return OS_OK ;
       
   258 }
       
   259 
       
   260 // Any JavaThread will enter here with state _thread_blocked
       
   261 int JvmtiRawMonitor::raw_enter(TRAPS) {
       
   262   TEVENT (raw_enter) ;
       
   263   void * Contended ;
       
   264 
       
   265   // don't enter raw monitor if thread is being externally suspended, it will
       
   266   // surprise the suspender if a "suspended" thread can still enter monitor
       
   267   JavaThread * jt = (JavaThread *)THREAD;
       
   268   if (THREAD->is_Java_thread()) {
       
   269     jt->SR_lock()->lock_without_safepoint_check();
       
   270     while (jt->is_external_suspend()) {
       
   271       jt->SR_lock()->unlock();
       
   272       jt->java_suspend_self();
       
   273       jt->SR_lock()->lock_without_safepoint_check();
       
   274     }
       
   275     // guarded by SR_lock to avoid racing with new external suspend requests.
       
   276     Contended = Atomic::cmpxchg_ptr (THREAD, &_owner, NULL) ;
       
   277     jt->SR_lock()->unlock();
       
   278   } else {
       
   279     Contended = Atomic::cmpxchg_ptr (THREAD, &_owner, NULL) ;
       
   280   }
       
   281 
       
   282   if (Contended == THREAD) {
       
   283      _recursions ++ ;
       
   284      return OM_OK ;
       
   285   }
       
   286 
       
   287   if (Contended == NULL) {
       
   288      guarantee (_owner == THREAD, "invariant") ;
       
   289      guarantee (_recursions == 0, "invariant") ;
       
   290      return OM_OK ;
       
   291   }
       
   292 
       
   293   THREAD->set_current_pending_monitor(this);
       
   294 
       
   295   if (!THREAD->is_Java_thread()) {
       
   296      // No other non-Java threads besides VM thread would acquire
       
   297      // a raw monitor.
       
   298      assert(THREAD->is_VM_thread(), "must be VM thread");
       
   299      SimpleEnter (THREAD) ;
       
   300    } else {
       
   301      guarantee (jt->thread_state() == _thread_blocked, "invariant") ;
       
   302      for (;;) {
       
   303        jt->set_suspend_equivalent();
       
   304        // cleared by handle_special_suspend_equivalent_condition() or
       
   305        // java_suspend_self()
       
   306        SimpleEnter (THREAD) ;
       
   307 
       
   308        // were we externally suspended while we were waiting?
       
   309        if (!jt->handle_special_suspend_equivalent_condition()) break ;
       
   310 
       
   311        // This thread was externally suspended
       
   312        //
       
   313        // This logic isn't needed for JVMTI raw monitors,
       
   314        // but doesn't hurt just in case the suspend rules change. This
       
   315            // logic is needed for the JvmtiRawMonitor.wait() reentry phase.
       
   316            // We have reentered the contended monitor, but while we were
       
   317            // waiting another thread suspended us. We don't want to reenter
       
   318            // the monitor while suspended because that would surprise the
       
   319            // thread that suspended us.
       
   320            //
       
   321            // Drop the lock -
       
   322        SimpleExit (THREAD) ;
       
   323 
       
   324            jt->java_suspend_self();
       
   325          }
       
   326 
       
   327      assert(_owner == THREAD, "Fatal error with monitor owner!");
       
   328      assert(_recursions == 0, "Fatal error with monitor recursions!");
       
   329   }
       
   330 
       
   331   THREAD->set_current_pending_monitor(NULL);
       
   332   guarantee (_recursions == 0, "invariant") ;
       
   333   return OM_OK;
       
   334 }
       
   335 
       
   336 // Used mainly for JVMTI raw monitor implementation
       
   337 // Also used for JvmtiRawMonitor::wait().
       
   338 int JvmtiRawMonitor::raw_exit(TRAPS) {
       
   339   TEVENT (raw_exit) ;
       
   340   if (THREAD != _owner) {
       
   341     return OM_ILLEGAL_MONITOR_STATE;
       
   342   }
       
   343   if (_recursions > 0) {
       
   344     --_recursions ;
       
   345     return OM_OK ;
       
   346   }
       
   347 
       
   348   void * List = _EntryList ;
       
   349   SimpleExit (THREAD) ;
       
   350 
       
   351   return OM_OK;
       
   352 }
       
   353 
       
   354 // Used for JVMTI raw monitor implementation.
       
   355 // All JavaThreads will enter here with state _thread_blocked
       
   356 
       
   357 int JvmtiRawMonitor::raw_wait(jlong millis, bool interruptible, TRAPS) {
       
   358   TEVENT (raw_wait) ;
       
   359   if (THREAD != _owner) {
       
   360     return OM_ILLEGAL_MONITOR_STATE;
       
   361   }
       
   362 
       
   363   // To avoid spurious wakeups we reset the parkevent -- This is strictly optional.
       
   364   // The caller must be able to tolerate spurious returns from raw_wait().
       
   365   THREAD->_ParkEvent->reset() ;
       
   366   OrderAccess::fence() ;
       
   367 
       
   368   // check interrupt event
       
   369   if (interruptible && Thread::is_interrupted(THREAD, true)) {
       
   370     return OM_INTERRUPTED;
       
   371   }
       
   372 
       
   373   intptr_t save = _recursions ;
       
   374   _recursions = 0 ;
       
   375   _waiters ++ ;
       
   376   if (THREAD->is_Java_thread()) {
       
   377     guarantee (((JavaThread *) THREAD)->thread_state() == _thread_blocked, "invariant") ;
       
   378     ((JavaThread *)THREAD)->set_suspend_equivalent();
       
   379   }
       
   380   int rv = SimpleWait (THREAD, millis) ;
       
   381   _recursions = save ;
       
   382   _waiters -- ;
       
   383 
       
   384   guarantee (THREAD == _owner, "invariant") ;
       
   385   if (THREAD->is_Java_thread()) {
       
   386      JavaThread * jSelf = (JavaThread *) THREAD ;
       
   387      for (;;) {
       
   388         if (!jSelf->handle_special_suspend_equivalent_condition()) break ;
       
   389         SimpleExit (THREAD) ;
       
   390         jSelf->java_suspend_self();
       
   391         SimpleEnter (THREAD) ;
       
   392         jSelf->set_suspend_equivalent() ;
       
   393      }
       
   394   }
       
   395   guarantee (THREAD == _owner, "invariant") ;
       
   396 
       
   397   if (interruptible && Thread::is_interrupted(THREAD, true)) {
       
   398     return OM_INTERRUPTED;
       
   399   }
       
   400   return OM_OK ;
       
   401 }
       
   402 
       
   403 int JvmtiRawMonitor::raw_notify(TRAPS) {
       
   404   TEVENT (raw_notify) ;
       
   405   if (THREAD != _owner) {
       
   406     return OM_ILLEGAL_MONITOR_STATE;
       
   407   }
       
   408   SimpleNotify (THREAD, false) ;
       
   409   return OM_OK;
       
   410 }
       
   411 
       
   412 int JvmtiRawMonitor::raw_notifyAll(TRAPS) {
       
   413   TEVENT (raw_notifyAll) ;
       
   414   if (THREAD != _owner) {
       
   415     return OM_ILLEGAL_MONITOR_STATE;
       
   416   }
       
   417   SimpleNotify (THREAD, true) ;
       
   418   return OM_OK;
       
   419 }
       
   420