src/share/vm/prims/jvmtiRawMonitor.cpp

changeset 0
f90c822e73f8
child 6876
710a3c8b516e
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/src/share/vm/prims/jvmtiRawMonitor.cpp	Wed Apr 27 01:25:04 2016 +0800
     1.3 @@ -0,0 +1,422 @@
     1.4 +/*
     1.5 + * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved.
     1.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     1.7 + *
     1.8 + * This code is free software; you can redistribute it and/or modify it
     1.9 + * under the terms of the GNU General Public License version 2 only, as
    1.10 + * published by the Free Software Foundation.
    1.11 + *
    1.12 + * This code is distributed in the hope that it will be useful, but WITHOUT
    1.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    1.14 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    1.15 + * version 2 for more details (a copy is included in the LICENSE file that
    1.16 + * accompanied this code).
    1.17 + *
    1.18 + * You should have received a copy of the GNU General Public License version
    1.19 + * 2 along with this work; if not, write to the Free Software Foundation,
    1.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    1.21 + *
    1.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    1.23 + * or visit www.oracle.com if you need additional information or have any
    1.24 + * questions.
    1.25 + *
    1.26 + */
    1.27 +
    1.28 +#include "precompiled.hpp"
    1.29 +#include "prims/jvmtiRawMonitor.hpp"
    1.30 +#include "runtime/interfaceSupport.hpp"
    1.31 +#include "runtime/thread.hpp"
    1.32 +
    1.33 +GrowableArray<JvmtiRawMonitor*> *JvmtiPendingMonitors::_monitors = new (ResourceObj::C_HEAP, mtInternal) GrowableArray<JvmtiRawMonitor*>(1,true);
    1.34 +
    1.35 +void JvmtiPendingMonitors::transition_raw_monitors() {
    1.36 +  assert((Threads::number_of_threads()==1),
    1.37 +         "Java thread has not created yet or more than one java thread \
    1.38 +is running. Raw monitor transition will not work");
    1.39 +  JavaThread *current_java_thread = JavaThread::current();
    1.40 +  assert(current_java_thread->thread_state() == _thread_in_vm, "Must be in vm");
    1.41 +  {
    1.42 +    ThreadBlockInVM __tbivm(current_java_thread);
    1.43 +    for(int i=0; i< count(); i++) {
    1.44 +      JvmtiRawMonitor *rmonitor = monitors()->at(i);
    1.45 +      int r = rmonitor->raw_enter(current_java_thread);
    1.46 +      assert(r == ObjectMonitor::OM_OK, "raw_enter should have worked");
    1.47 +    }
    1.48 +  }
    1.49 +  // pending monitors are converted to real monitor so delete them all.
    1.50 +  dispose();
    1.51 +}
    1.52 +
    1.53 +//
    1.54 +// class JvmtiRawMonitor
    1.55 +//
    1.56 +
    1.57 +JvmtiRawMonitor::JvmtiRawMonitor(const char *name) {
    1.58 +#ifdef ASSERT
    1.59 +  _name = strcpy(NEW_C_HEAP_ARRAY(char, strlen(name) + 1, mtInternal), name);
    1.60 +#else
    1.61 +  _name = NULL;
    1.62 +#endif
    1.63 +  _magic = JVMTI_RM_MAGIC;
    1.64 +}
    1.65 +
    1.66 +JvmtiRawMonitor::~JvmtiRawMonitor() {
    1.67 +#ifdef ASSERT
    1.68 +  FreeHeap(_name);
    1.69 +#endif
    1.70 +  _magic = 0;
    1.71 +}
    1.72 +
    1.73 +
    1.74 +bool
    1.75 +JvmtiRawMonitor::is_valid() {
    1.76 +  int value = 0;
    1.77 +
    1.78 +  // This object might not be a JvmtiRawMonitor so we can't assume
    1.79 +  // the _magic field is properly aligned. Get the value in a safe
    1.80 +  // way and then check against JVMTI_RM_MAGIC.
    1.81 +
    1.82 +  switch (sizeof(_magic)) {
    1.83 +  case 2:
    1.84 +    value = Bytes::get_native_u2((address)&_magic);
    1.85 +    break;
    1.86 +
    1.87 +  case 4:
    1.88 +    value = Bytes::get_native_u4((address)&_magic);
    1.89 +    break;
    1.90 +
    1.91 +  case 8:
    1.92 +    value = Bytes::get_native_u8((address)&_magic);
    1.93 +    break;
    1.94 +
    1.95 +  default:
    1.96 +    guarantee(false, "_magic field is an unexpected size");
    1.97 +  }
    1.98 +
    1.99 +  return value == JVMTI_RM_MAGIC;
   1.100 +}
   1.101 +
   1.102 +// -------------------------------------------------------------------------
   1.103 +// The raw monitor subsystem is entirely distinct from normal
   1.104 +// java-synchronization or jni-synchronization.  raw monitors are not
   1.105 +// associated with objects.  They can be implemented in any manner
   1.106 +// that makes sense.  The original implementors decided to piggy-back
   1.107 +// the raw-monitor implementation on the existing Java objectMonitor mechanism.
   1.108 +// This flaw needs to fixed.  We should reimplement raw monitors as sui-generis.
   1.109 +// Specifically, we should not implement raw monitors via java monitors.
   1.110 +// Time permitting, we should disentangle and deconvolve the two implementations
   1.111 +// and move the resulting raw monitor implementation over to the JVMTI directories.
   1.112 +// Ideally, the raw monitor implementation would be built on top of
   1.113 +// park-unpark and nothing else.
   1.114 +//
   1.115 +// raw monitors are used mainly by JVMTI
   1.116 +// The raw monitor implementation borrows the ObjectMonitor structure,
   1.117 +// but the operators are degenerate and extremely simple.
   1.118 +//
   1.119 +// Mixed use of a single objectMonitor instance -- as both a raw monitor
   1.120 +// and a normal java monitor -- is not permissible.
   1.121 +//
   1.122 +// Note that we use the single RawMonitor_lock to protect queue operations for
   1.123 +// _all_ raw monitors.  This is a scalability impediment, but since raw monitor usage
   1.124 +// is deprecated and rare, this is not of concern.  The RawMonitor_lock can not
   1.125 +// be held indefinitely.  The critical sections must be short and bounded.
   1.126 +//
   1.127 +// -------------------------------------------------------------------------
   1.128 +
   1.129 +int JvmtiRawMonitor::SimpleEnter (Thread * Self) {
   1.130 +  for (;;) {
   1.131 +    if (Atomic::cmpxchg_ptr (Self, &_owner, NULL) == NULL) {
   1.132 +       return OS_OK ;
   1.133 +    }
   1.134 +
   1.135 +    ObjectWaiter Node (Self) ;
   1.136 +    Self->_ParkEvent->reset() ;     // strictly optional
   1.137 +    Node.TState = ObjectWaiter::TS_ENTER ;
   1.138 +
   1.139 +    RawMonitor_lock->lock_without_safepoint_check() ;
   1.140 +    Node._next  = _EntryList ;
   1.141 +    _EntryList  = &Node ;
   1.142 +    OrderAccess::fence() ;
   1.143 +    if (_owner == NULL && Atomic::cmpxchg_ptr (Self, &_owner, NULL) == NULL) {
   1.144 +        _EntryList = Node._next ;
   1.145 +        RawMonitor_lock->unlock() ;
   1.146 +        return OS_OK ;
   1.147 +    }
   1.148 +    RawMonitor_lock->unlock() ;
   1.149 +    while (Node.TState == ObjectWaiter::TS_ENTER) {
   1.150 +       Self->_ParkEvent->park() ;
   1.151 +    }
   1.152 +  }
   1.153 +}
   1.154 +
   1.155 +int JvmtiRawMonitor::SimpleExit (Thread * Self) {
   1.156 +  guarantee (_owner == Self, "invariant") ;
   1.157 +  OrderAccess::release_store_ptr (&_owner, NULL) ;
   1.158 +  OrderAccess::fence() ;
   1.159 +  if (_EntryList == NULL) return OS_OK ;
   1.160 +  ObjectWaiter * w ;
   1.161 +
   1.162 +  RawMonitor_lock->lock_without_safepoint_check() ;
   1.163 +  w = _EntryList ;
   1.164 +  if (w != NULL) {
   1.165 +      _EntryList = w->_next ;
   1.166 +  }
   1.167 +  RawMonitor_lock->unlock() ;
   1.168 +  if (w != NULL) {
   1.169 +      guarantee (w ->TState == ObjectWaiter::TS_ENTER, "invariant") ;
   1.170 +      ParkEvent * ev = w->_event ;
   1.171 +      w->TState = ObjectWaiter::TS_RUN ;
   1.172 +      OrderAccess::fence() ;
   1.173 +      ev->unpark() ;
   1.174 +  }
   1.175 +  return OS_OK ;
   1.176 +}
   1.177 +
   1.178 +int JvmtiRawMonitor::SimpleWait (Thread * Self, jlong millis) {
   1.179 +  guarantee (_owner == Self  , "invariant") ;
   1.180 +  guarantee (_recursions == 0, "invariant") ;
   1.181 +
   1.182 +  ObjectWaiter Node (Self) ;
   1.183 +  Node._notified = 0 ;
   1.184 +  Node.TState    = ObjectWaiter::TS_WAIT ;
   1.185 +
   1.186 +  RawMonitor_lock->lock_without_safepoint_check() ;
   1.187 +  Node._next     = _WaitSet ;
   1.188 +  _WaitSet       = &Node ;
   1.189 +  RawMonitor_lock->unlock() ;
   1.190 +
   1.191 +  SimpleExit (Self) ;
   1.192 +  guarantee (_owner != Self, "invariant") ;
   1.193 +
   1.194 +  int ret = OS_OK ;
   1.195 +  if (millis <= 0) {
   1.196 +    Self->_ParkEvent->park();
   1.197 +  } else {
   1.198 +    ret = Self->_ParkEvent->park(millis);
   1.199 +  }
   1.200 +
   1.201 +  // If thread still resides on the waitset then unlink it.
   1.202 +  // Double-checked locking -- the usage is safe in this context
   1.203 +  // as we TState is volatile and the lock-unlock operators are
   1.204 +  // serializing (barrier-equivalent).
   1.205 +
   1.206 +  if (Node.TState == ObjectWaiter::TS_WAIT) {
   1.207 +    RawMonitor_lock->lock_without_safepoint_check() ;
   1.208 +    if (Node.TState == ObjectWaiter::TS_WAIT) {
   1.209 +      // Simple O(n) unlink, but performance isn't critical here.
   1.210 +      ObjectWaiter * p ;
   1.211 +      ObjectWaiter * q = NULL ;
   1.212 +      for (p = _WaitSet ; p != &Node; p = p->_next) {
   1.213 +         q = p ;
   1.214 +      }
   1.215 +      guarantee (p == &Node, "invariant") ;
   1.216 +      if (q == NULL) {
   1.217 +        guarantee (p == _WaitSet, "invariant") ;
   1.218 +        _WaitSet = p->_next ;
   1.219 +      } else {
   1.220 +        guarantee (p == q->_next, "invariant") ;
   1.221 +        q->_next = p->_next ;
   1.222 +      }
   1.223 +      Node.TState = ObjectWaiter::TS_RUN ;
   1.224 +    }
   1.225 +    RawMonitor_lock->unlock() ;
   1.226 +  }
   1.227 +
   1.228 +  guarantee (Node.TState == ObjectWaiter::TS_RUN, "invariant") ;
   1.229 +  SimpleEnter (Self) ;
   1.230 +
   1.231 +  guarantee (_owner == Self, "invariant") ;
   1.232 +  guarantee (_recursions == 0, "invariant") ;
   1.233 +  return ret ;
   1.234 +}
   1.235 +
   1.236 +int JvmtiRawMonitor::SimpleNotify (Thread * Self, bool All) {
   1.237 +  guarantee (_owner == Self, "invariant") ;
   1.238 +  if (_WaitSet == NULL) return OS_OK ;
   1.239 +
   1.240 +  // We have two options:
   1.241 +  // A. Transfer the threads from the WaitSet to the EntryList
   1.242 +  // B. Remove the thread from the WaitSet and unpark() it.
   1.243 +  //
   1.244 +  // We use (B), which is crude and results in lots of futile
   1.245 +  // context switching.  In particular (B) induces lots of contention.
   1.246 +
   1.247 +  ParkEvent * ev = NULL ;       // consider using a small auto array ...
   1.248 +  RawMonitor_lock->lock_without_safepoint_check() ;
   1.249 +  for (;;) {
   1.250 +      ObjectWaiter * w = _WaitSet ;
   1.251 +      if (w == NULL) break ;
   1.252 +      _WaitSet = w->_next ;
   1.253 +      if (ev != NULL) { ev->unpark(); ev = NULL; }
   1.254 +      ev = w->_event ;
   1.255 +      OrderAccess::loadstore() ;
   1.256 +      w->TState = ObjectWaiter::TS_RUN ;
   1.257 +      OrderAccess::storeload();
   1.258 +      if (!All) break ;
   1.259 +  }
   1.260 +  RawMonitor_lock->unlock() ;
   1.261 +  if (ev != NULL) ev->unpark();
   1.262 +  return OS_OK ;
   1.263 +}
   1.264 +
   1.265 +// Any JavaThread will enter here with state _thread_blocked
   1.266 +int JvmtiRawMonitor::raw_enter(TRAPS) {
   1.267 +  TEVENT (raw_enter) ;
   1.268 +  void * Contended ;
   1.269 +
   1.270 +  // don't enter raw monitor if thread is being externally suspended, it will
   1.271 +  // surprise the suspender if a "suspended" thread can still enter monitor
   1.272 +  JavaThread * jt = (JavaThread *)THREAD;
   1.273 +  if (THREAD->is_Java_thread()) {
   1.274 +    jt->SR_lock()->lock_without_safepoint_check();
   1.275 +    while (jt->is_external_suspend()) {
   1.276 +      jt->SR_lock()->unlock();
   1.277 +      jt->java_suspend_self();
   1.278 +      jt->SR_lock()->lock_without_safepoint_check();
   1.279 +    }
   1.280 +    // guarded by SR_lock to avoid racing with new external suspend requests.
   1.281 +    Contended = Atomic::cmpxchg_ptr (THREAD, &_owner, NULL) ;
   1.282 +    jt->SR_lock()->unlock();
   1.283 +  } else {
   1.284 +    Contended = Atomic::cmpxchg_ptr (THREAD, &_owner, NULL) ;
   1.285 +  }
   1.286 +
   1.287 +  if (Contended == THREAD) {
   1.288 +     _recursions ++ ;
   1.289 +     return OM_OK ;
   1.290 +  }
   1.291 +
   1.292 +  if (Contended == NULL) {
   1.293 +     guarantee (_owner == THREAD, "invariant") ;
   1.294 +     guarantee (_recursions == 0, "invariant") ;
   1.295 +     return OM_OK ;
   1.296 +  }
   1.297 +
   1.298 +  THREAD->set_current_pending_monitor(this);
   1.299 +
   1.300 +  if (!THREAD->is_Java_thread()) {
   1.301 +     // No other non-Java threads besides VM thread would acquire
   1.302 +     // a raw monitor.
   1.303 +     assert(THREAD->is_VM_thread(), "must be VM thread");
   1.304 +     SimpleEnter (THREAD) ;
   1.305 +   } else {
   1.306 +     guarantee (jt->thread_state() == _thread_blocked, "invariant") ;
   1.307 +     for (;;) {
   1.308 +       jt->set_suspend_equivalent();
   1.309 +       // cleared by handle_special_suspend_equivalent_condition() or
   1.310 +       // java_suspend_self()
   1.311 +       SimpleEnter (THREAD) ;
   1.312 +
   1.313 +       // were we externally suspended while we were waiting?
   1.314 +       if (!jt->handle_special_suspend_equivalent_condition()) break ;
   1.315 +
   1.316 +       // This thread was externally suspended
   1.317 +       //
   1.318 +       // This logic isn't needed for JVMTI raw monitors,
   1.319 +       // but doesn't hurt just in case the suspend rules change. This
   1.320 +           // logic is needed for the JvmtiRawMonitor.wait() reentry phase.
   1.321 +           // We have reentered the contended monitor, but while we were
   1.322 +           // waiting another thread suspended us. We don't want to reenter
   1.323 +           // the monitor while suspended because that would surprise the
   1.324 +           // thread that suspended us.
   1.325 +           //
   1.326 +           // Drop the lock -
   1.327 +       SimpleExit (THREAD) ;
   1.328 +
   1.329 +           jt->java_suspend_self();
   1.330 +         }
   1.331 +
   1.332 +     assert(_owner == THREAD, "Fatal error with monitor owner!");
   1.333 +     assert(_recursions == 0, "Fatal error with monitor recursions!");
   1.334 +  }
   1.335 +
   1.336 +  THREAD->set_current_pending_monitor(NULL);
   1.337 +  guarantee (_recursions == 0, "invariant") ;
   1.338 +  return OM_OK;
   1.339 +}
   1.340 +
   1.341 +// Used mainly for JVMTI raw monitor implementation
   1.342 +// Also used for JvmtiRawMonitor::wait().
   1.343 +int JvmtiRawMonitor::raw_exit(TRAPS) {
   1.344 +  TEVENT (raw_exit) ;
   1.345 +  if (THREAD != _owner) {
   1.346 +    return OM_ILLEGAL_MONITOR_STATE;
   1.347 +  }
   1.348 +  if (_recursions > 0) {
   1.349 +    --_recursions ;
   1.350 +    return OM_OK ;
   1.351 +  }
   1.352 +
   1.353 +  void * List = _EntryList ;
   1.354 +  SimpleExit (THREAD) ;
   1.355 +
   1.356 +  return OM_OK;
   1.357 +}
   1.358 +
   1.359 +// Used for JVMTI raw monitor implementation.
   1.360 +// All JavaThreads will enter here with state _thread_blocked
   1.361 +
   1.362 +int JvmtiRawMonitor::raw_wait(jlong millis, bool interruptible, TRAPS) {
   1.363 +  TEVENT (raw_wait) ;
   1.364 +  if (THREAD != _owner) {
   1.365 +    return OM_ILLEGAL_MONITOR_STATE;
   1.366 +  }
   1.367 +
   1.368 +  // To avoid spurious wakeups we reset the parkevent -- This is strictly optional.
   1.369 +  // The caller must be able to tolerate spurious returns from raw_wait().
   1.370 +  THREAD->_ParkEvent->reset() ;
   1.371 +  OrderAccess::fence() ;
   1.372 +
   1.373 +  // check interrupt event
   1.374 +  if (interruptible && Thread::is_interrupted(THREAD, true)) {
   1.375 +    return OM_INTERRUPTED;
   1.376 +  }
   1.377 +
   1.378 +  intptr_t save = _recursions ;
   1.379 +  _recursions = 0 ;
   1.380 +  _waiters ++ ;
   1.381 +  if (THREAD->is_Java_thread()) {
   1.382 +    guarantee (((JavaThread *) THREAD)->thread_state() == _thread_blocked, "invariant") ;
   1.383 +    ((JavaThread *)THREAD)->set_suspend_equivalent();
   1.384 +  }
   1.385 +  int rv = SimpleWait (THREAD, millis) ;
   1.386 +  _recursions = save ;
   1.387 +  _waiters -- ;
   1.388 +
   1.389 +  guarantee (THREAD == _owner, "invariant") ;
   1.390 +  if (THREAD->is_Java_thread()) {
   1.391 +     JavaThread * jSelf = (JavaThread *) THREAD ;
   1.392 +     for (;;) {
   1.393 +        if (!jSelf->handle_special_suspend_equivalent_condition()) break ;
   1.394 +        SimpleExit (THREAD) ;
   1.395 +        jSelf->java_suspend_self();
   1.396 +        SimpleEnter (THREAD) ;
   1.397 +        jSelf->set_suspend_equivalent() ;
   1.398 +     }
   1.399 +  }
   1.400 +  guarantee (THREAD == _owner, "invariant") ;
   1.401 +
   1.402 +  if (interruptible && Thread::is_interrupted(THREAD, true)) {
   1.403 +    return OM_INTERRUPTED;
   1.404 +  }
   1.405 +  return OM_OK ;
   1.406 +}
   1.407 +
   1.408 +int JvmtiRawMonitor::raw_notify(TRAPS) {
   1.409 +  TEVENT (raw_notify) ;
   1.410 +  if (THREAD != _owner) {
   1.411 +    return OM_ILLEGAL_MONITOR_STATE;
   1.412 +  }
   1.413 +  SimpleNotify (THREAD, false) ;
   1.414 +  return OM_OK;
   1.415 +}
   1.416 +
   1.417 +int JvmtiRawMonitor::raw_notifyAll(TRAPS) {
   1.418 +  TEVENT (raw_notifyAll) ;
   1.419 +  if (THREAD != _owner) {
   1.420 +    return OM_ILLEGAL_MONITOR_STATE;
   1.421 +  }
   1.422 +  SimpleNotify (THREAD, true) ;
   1.423 +  return OM_OK;
   1.424 +}
   1.425 +

mercurial