Path: blob/aarch64-shenandoah-jdk8u272-b10/hotspot/src/share/vm/prims/jvmtiRawMonitor.cpp
32285 views
/*1* Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*22*/2324#include "precompiled.hpp"25#include "prims/jvmtiRawMonitor.hpp"26#include "runtime/interfaceSupport.hpp"27#include "runtime/orderAccess.inline.hpp"28#include "runtime/thread.inline.hpp"2930GrowableArray<JvmtiRawMonitor*> *JvmtiPendingMonitors::_monitors = new (ResourceObj::C_HEAP, mtInternal) GrowableArray<JvmtiRawMonitor*>(1,true);3132void JvmtiPendingMonitors::transition_raw_monitors() {33assert((Threads::number_of_threads()==1),34"Java thread has not created yet or more than one java thread \35is running. Raw monitor transition will not work");36JavaThread *current_java_thread = JavaThread::current();37assert(current_java_thread->thread_state() == _thread_in_vm, "Must be in vm");38{39ThreadBlockInVM __tbivm(current_java_thread);40for(int i=0; i< count(); i++) {41JvmtiRawMonitor *rmonitor = monitors()->at(i);42int r = rmonitor->raw_enter(current_java_thread);43assert(r == ObjectMonitor::OM_OK, "raw_enter should have worked");44}45}46// pending monitors are converted to real monitor so delete them all.47dispose();48}4950//51// class JvmtiRawMonitor52//5354JvmtiRawMonitor::JvmtiRawMonitor(const char *name) {55#ifdef ASSERT56_name = strcpy(NEW_C_HEAP_ARRAY(char, strlen(name) + 1, mtInternal), name);57#else58_name = NULL;59#endif60_magic = JVMTI_RM_MAGIC;61}6263JvmtiRawMonitor::~JvmtiRawMonitor() {64#ifdef ASSERT65FreeHeap(_name);66#endif67_magic = 0;68}697071bool72JvmtiRawMonitor::is_valid() {73int value = 0;7475// This object might not be a JvmtiRawMonitor so we can't assume76// the _magic field is properly aligned. Get the value in a safe77// way and then check against JVMTI_RM_MAGIC.7879switch (sizeof(_magic)) {80case 2:81value = Bytes::get_native_u2((address)&_magic);82break;8384case 4:85value = Bytes::get_native_u4((address)&_magic);86break;8788case 8:89value = Bytes::get_native_u8((address)&_magic);90break;9192default:93guarantee(false, "_magic field is an unexpected size");94}9596return value == JVMTI_RM_MAGIC;97}9899// -------------------------------------------------------------------------100// The raw monitor subsystem is entirely distinct from normal101// java-synchronization or jni-synchronization. raw monitors are not102// associated with objects. They can be implemented in any manner103// that makes sense. The original implementors decided to piggy-back104// the raw-monitor implementation on the existing Java objectMonitor mechanism.105// This flaw needs to fixed. We should reimplement raw monitors as sui-generis.106// Specifically, we should not implement raw monitors via java monitors.107// Time permitting, we should disentangle and deconvolve the two implementations108// and move the resulting raw monitor implementation over to the JVMTI directories.109// Ideally, the raw monitor implementation would be built on top of110// park-unpark and nothing else.111//112// raw monitors are used mainly by JVMTI113// The raw monitor implementation borrows the ObjectMonitor structure,114// but the operators are degenerate and extremely simple.115//116// Mixed use of a single objectMonitor instance -- as both a raw monitor117// and a normal java monitor -- is not permissible.118//119// Note that we use the single RawMonitor_lock to protect queue operations for120// _all_ raw monitors. This is a scalability impediment, but since raw monitor usage121// is deprecated and rare, this is not of concern. The RawMonitor_lock can not122// be held indefinitely. The critical sections must be short and bounded.123//124// -------------------------------------------------------------------------125126int JvmtiRawMonitor::SimpleEnter (Thread * Self) {127for (;;) {128if (Atomic::cmpxchg_ptr (Self, &_owner, NULL) == NULL) {129return OS_OK ;130}131132ObjectWaiter Node (Self) ;133Self->_ParkEvent->reset() ; // strictly optional134Node.TState = ObjectWaiter::TS_ENTER ;135136RawMonitor_lock->lock_without_safepoint_check() ;137Node._next = _EntryList ;138_EntryList = &Node ;139OrderAccess::fence() ;140if (_owner == NULL && Atomic::cmpxchg_ptr (Self, &_owner, NULL) == NULL) {141_EntryList = Node._next ;142RawMonitor_lock->unlock() ;143return OS_OK ;144}145RawMonitor_lock->unlock() ;146while (Node.TState == ObjectWaiter::TS_ENTER) {147Self->_ParkEvent->park() ;148}149}150}151152int JvmtiRawMonitor::SimpleExit (Thread * Self) {153guarantee (_owner == Self, "invariant") ;154OrderAccess::release_store_ptr (&_owner, NULL) ;155OrderAccess::fence() ;156if (_EntryList == NULL) return OS_OK ;157ObjectWaiter * w ;158159RawMonitor_lock->lock_without_safepoint_check() ;160w = _EntryList ;161if (w != NULL) {162_EntryList = w->_next ;163}164RawMonitor_lock->unlock() ;165if (w != NULL) {166guarantee (w ->TState == ObjectWaiter::TS_ENTER, "invariant") ;167ParkEvent * ev = w->_event ;168w->TState = ObjectWaiter::TS_RUN ;169OrderAccess::fence() ;170ev->unpark() ;171}172return OS_OK ;173}174175int JvmtiRawMonitor::SimpleWait (Thread * Self, jlong millis) {176guarantee (_owner == Self , "invariant") ;177guarantee (_recursions == 0, "invariant") ;178179ObjectWaiter Node (Self) ;180Node._notified = 0 ;181Node.TState = ObjectWaiter::TS_WAIT ;182183RawMonitor_lock->lock_without_safepoint_check() ;184Node._next = _WaitSet ;185_WaitSet = &Node ;186RawMonitor_lock->unlock() ;187188SimpleExit (Self) ;189guarantee (_owner != Self, "invariant") ;190191int ret = OS_OK ;192if (millis <= 0) {193Self->_ParkEvent->park();194} else {195ret = Self->_ParkEvent->park(millis);196}197198// If thread still resides on the waitset then unlink it.199// Double-checked locking -- the usage is safe in this context200// as we TState is volatile and the lock-unlock operators are201// serializing (barrier-equivalent).202203if (Node.TState == ObjectWaiter::TS_WAIT) {204RawMonitor_lock->lock_without_safepoint_check() ;205if (Node.TState == ObjectWaiter::TS_WAIT) {206// Simple O(n) unlink, but performance isn't critical here.207ObjectWaiter * p ;208ObjectWaiter * q = NULL ;209for (p = _WaitSet ; p != &Node; p = p->_next) {210q = p ;211}212guarantee (p == &Node, "invariant") ;213if (q == NULL) {214guarantee (p == _WaitSet, "invariant") ;215_WaitSet = p->_next ;216} else {217guarantee (p == q->_next, "invariant") ;218q->_next = p->_next ;219}220Node.TState = ObjectWaiter::TS_RUN ;221}222RawMonitor_lock->unlock() ;223}224225guarantee (Node.TState == ObjectWaiter::TS_RUN, "invariant") ;226SimpleEnter (Self) ;227228guarantee (_owner == Self, "invariant") ;229guarantee (_recursions == 0, "invariant") ;230return ret ;231}232233int JvmtiRawMonitor::SimpleNotify (Thread * Self, bool All) {234guarantee (_owner == Self, "invariant") ;235if (_WaitSet == NULL) return OS_OK ;236237// We have two options:238// A. Transfer the threads from the WaitSet to the EntryList239// B. Remove the thread from the WaitSet and unpark() it.240//241// We use (B), which is crude and results in lots of futile242// context switching. In particular (B) induces lots of contention.243244ParkEvent * ev = NULL ; // consider using a small auto array ...245RawMonitor_lock->lock_without_safepoint_check() ;246for (;;) {247ObjectWaiter * w = _WaitSet ;248if (w == NULL) break ;249_WaitSet = w->_next ;250if (ev != NULL) { ev->unpark(); ev = NULL; }251ev = w->_event ;252OrderAccess::loadstore() ;253w->TState = ObjectWaiter::TS_RUN ;254OrderAccess::storeload();255if (!All) break ;256}257RawMonitor_lock->unlock() ;258if (ev != NULL) ev->unpark();259return OS_OK ;260}261262// Any JavaThread will enter here with state _thread_blocked263int JvmtiRawMonitor::raw_enter(TRAPS) {264TEVENT (raw_enter) ;265void * Contended ;266267// don't enter raw monitor if thread is being externally suspended, it will268// surprise the suspender if a "suspended" thread can still enter monitor269JavaThread * jt = (JavaThread *)THREAD;270if (THREAD->is_Java_thread()) {271jt->SR_lock()->lock_without_safepoint_check();272while (jt->is_external_suspend()) {273jt->SR_lock()->unlock();274jt->java_suspend_self();275jt->SR_lock()->lock_without_safepoint_check();276}277// guarded by SR_lock to avoid racing with new external suspend requests.278Contended = Atomic::cmpxchg_ptr (THREAD, &_owner, NULL) ;279jt->SR_lock()->unlock();280} else {281Contended = Atomic::cmpxchg_ptr (THREAD, &_owner, NULL) ;282}283284if (Contended == THREAD) {285_recursions ++ ;286return OM_OK ;287}288289if (Contended == NULL) {290guarantee (_owner == THREAD, "invariant") ;291guarantee (_recursions == 0, "invariant") ;292return OM_OK ;293}294295THREAD->set_current_pending_monitor(this);296297if (!THREAD->is_Java_thread()) {298// No other non-Java threads besides VM thread would acquire299// a raw monitor.300assert(THREAD->is_VM_thread(), "must be VM thread");301SimpleEnter (THREAD) ;302} else {303guarantee (jt->thread_state() == _thread_blocked, "invariant") ;304for (;;) {305jt->set_suspend_equivalent();306// cleared by handle_special_suspend_equivalent_condition() or307// java_suspend_self()308SimpleEnter (THREAD) ;309310// were we externally suspended while we were waiting?311if (!jt->handle_special_suspend_equivalent_condition()) break ;312313// This thread was externally suspended314//315// This logic isn't needed for JVMTI raw monitors,316// but doesn't hurt just in case the suspend rules change. This317// logic is needed for the JvmtiRawMonitor.wait() reentry phase.318// We have reentered the contended monitor, but while we were319// waiting another thread suspended us. We don't want to reenter320// the monitor while suspended because that would surprise the321// thread that suspended us.322//323// Drop the lock -324SimpleExit (THREAD) ;325326jt->java_suspend_self();327}328329assert(_owner == THREAD, "Fatal error with monitor owner!");330assert(_recursions == 0, "Fatal error with monitor recursions!");331}332333THREAD->set_current_pending_monitor(NULL);334guarantee (_recursions == 0, "invariant") ;335return OM_OK;336}337338// Used mainly for JVMTI raw monitor implementation339// Also used for JvmtiRawMonitor::wait().340int JvmtiRawMonitor::raw_exit(TRAPS) {341TEVENT (raw_exit) ;342if (THREAD != _owner) {343return OM_ILLEGAL_MONITOR_STATE;344}345if (_recursions > 0) {346--_recursions ;347return OM_OK ;348}349350void * List = _EntryList ;351SimpleExit (THREAD) ;352353return OM_OK;354}355356// Used for JVMTI raw monitor implementation.357// All JavaThreads will enter here with state _thread_blocked358359int JvmtiRawMonitor::raw_wait(jlong millis, bool interruptible, TRAPS) {360TEVENT (raw_wait) ;361if (THREAD != _owner) {362return OM_ILLEGAL_MONITOR_STATE;363}364365// To avoid spurious wakeups we reset the parkevent -- This is strictly optional.366// The caller must be able to tolerate spurious returns from raw_wait().367THREAD->_ParkEvent->reset() ;368OrderAccess::fence() ;369370// check interrupt event371if (interruptible && Thread::is_interrupted(THREAD, true)) {372return OM_INTERRUPTED;373}374375intptr_t save = _recursions ;376_recursions = 0 ;377_waiters ++ ;378if (THREAD->is_Java_thread()) {379guarantee (((JavaThread *) THREAD)->thread_state() == _thread_blocked, "invariant") ;380((JavaThread *)THREAD)->set_suspend_equivalent();381}382int rv = SimpleWait (THREAD, millis) ;383_recursions = save ;384_waiters -- ;385386guarantee (THREAD == _owner, "invariant") ;387if (THREAD->is_Java_thread()) {388JavaThread * jSelf = (JavaThread *) THREAD ;389for (;;) {390if (!jSelf->handle_special_suspend_equivalent_condition()) break ;391SimpleExit (THREAD) ;392jSelf->java_suspend_self();393SimpleEnter (THREAD) ;394jSelf->set_suspend_equivalent() ;395}396}397guarantee (THREAD == _owner, "invariant") ;398399if (interruptible && Thread::is_interrupted(THREAD, true)) {400return OM_INTERRUPTED;401}402return OM_OK ;403}404405int JvmtiRawMonitor::raw_notify(TRAPS) {406TEVENT (raw_notify) ;407if (THREAD != _owner) {408return OM_ILLEGAL_MONITOR_STATE;409}410SimpleNotify (THREAD, false) ;411return OM_OK;412}413414int JvmtiRawMonitor::raw_notifyAll(TRAPS) {415TEVENT (raw_notifyAll) ;416if (THREAD != _owner) {417return OM_ILLEGAL_MONITOR_STATE;418}419SimpleNotify (THREAD, true) ;420return OM_OK;421}422423424425