hotspot/src/share/vm/runtime/mutex.cpp
bool Monitor::wait(bool no_safepoint_check, long timeout, bool as_suspend_equivalent) {
{- -------------------------------------------
(1) (変数宣言など)
---------------------------------------- -}
Thread * const Self = Thread::current() ;
{- -------------------------------------------
(1) (assert)
---------------------------------------- -}
assert (_owner == Self, "invariant") ;
assert (ILocked(), "invariant") ;
// as_suspend_equivalent logically implies !no_safepoint_check
guarantee (!as_suspend_equivalent || !no_safepoint_check, "invariant") ;
// !no_safepoint_check logically implies java_thread
guarantee (no_safepoint_check || Self->is_Java_thread(), "invariant") ;
{- -------------------------------------------
(1) (デバッグ用の処理) (#ifdef ASSERT 時にのみ実行)
---------------------------------------- -}
#ifdef ASSERT
Monitor * least = get_least_ranked_lock_besides_this(Self->owned_locks());
assert(least != this, "Specification of get_least_... call above");
if (least != NULL && least->rank() <= special) {
tty->print("Attempting to wait on monitor %s/%d while holding"
" lock %s/%d -- possible deadlock",
name(), rank(), least->name(), least->rank());
assert(false, "Shouldn't block(wait) while holding a lock of rank special");
}
#endif // ASSERT
{- -------------------------------------------
(1) (変数宣言など)
---------------------------------------- -}
int wait_status ;
{- -------------------------------------------
(1) Monitor::set_owner() で, owner をリセットしておく.
(これは意味合いとしては wait 用のロックを解放する感じの処理)
---------------------------------------- -}
// conceptually set the owner to NULL in anticipation of
// abdicating the lock in wait
set_owner(NULL);
{- -------------------------------------------
(1) Monitor::IWait() を呼んで, 実際の待機処理を行う.
(なお, 引数で safepoint チェックをしなくてよいと指定されている場合 (= no_safepoint_check が false の場合)は,
いきなり Monitor::IWait() を呼び出すだけ.
そうでなければ, ThreadBlockInVM 及び OSThreadWaitState で Safepoint チェックを行ってから
Monitor::IWait() を呼び出す.)
(また, 引数でこの wait 処理を suspend-equivalent condition で行うように
指定されている場合 (= as_suspend_equivalent が true の場合)は,
眠っている間に suspend された場合のために
Monitor::IWait() から返ってきた後で
JavaThread::handle_special_suspend_equivalent_condition() による確認を行っている.
suspend されていた場合は, (せっかくロックは取れたがこのまま実行を続けるとおかしなことになるので)
Monitor::IUnlock() でロックを解放し,
さらに JavaThread::java_suspend_self() でサスペンドが解除されるまで眠りにつく.
サスペンドが解除された後は, 再度 Monitor::ILock() を呼び出して, ロック確保を行う.)
#TODO JavaThread::set_suspend_equivalent() はどういう意味がある??
---------------------------------------- -}
if (no_safepoint_check) {
wait_status = IWait (Self, timeout) ;
} else {
assert (Self->is_Java_thread(), "invariant") ;
JavaThread *jt = (JavaThread *)Self;
// Enter safepoint region - ornate and Rococo ...
ThreadBlockInVM tbivm(jt);
OSThreadWaitState osts(Self->osthread(), false /* not Object.wait() */);
if (as_suspend_equivalent) {
jt->set_suspend_equivalent();
// cleared by handle_special_suspend_equivalent_condition() or
// java_suspend_self()
}
wait_status = IWait (Self, timeout) ;
// were we externally suspended while we were waiting?
if (as_suspend_equivalent && jt->handle_special_suspend_equivalent_condition()) {
// Our event wait has finished and we own the lock, but
// while we were waiting another thread suspended us. We don't
// want to hold the lock while suspended because that
// would surprise the thread that suspended us.
assert (ILocked(), "invariant") ;
IUnlock (true) ;
jt->java_suspend_self();
ILock (Self) ;
assert (ILocked(), "invariant") ;
}
}
{- -------------------------------------------
(1) Monitor::set_owner() でカレントスレッドを owner に設定しておく.
(意味合いとしては wait 用のロックを再取得する感じの処理.
なお, 実際のロック(LockByte)は IWait() の中で取得されている.)
---------------------------------------- -}
// Conceptually reestablish ownership of the lock.
// The "real" lock -- the LockByte -- was reacquired by IWait().
assert (ILocked(), "invariant") ;
assert (_owner == NULL, "invariant") ;
set_owner (Self) ;
{- -------------------------------------------
(1) 結果をリターン
---------------------------------------- -}
return wait_status != 0 ; // return true IFF timeout
}
This document is available under the GNU GENERAL PUBLIC LICENSE Version 2.