hotspot/src/os/solaris/vm/os_solaris.cpp
void os::PlatformEvent::park() { // AKA: down()
{- -------------------------------------------
(1) (コメントによると
os::PlatformEvent::park() を呼び出していいのは
この os::PlatformEvent オブジェクトに関連付いているスレッドだけ)
---------------------------------------- -}
// Invariant: Only the thread associated with the Event/PlatformEvent
// may call park().
{- -------------------------------------------
(1) (変数宣言など)
---------------------------------------- -}
int v ;
{- -------------------------------------------
(1) Atomic::cmpxchg() で _Event フィールドの値を 1デクリメントする.
(Atomic::cmpxchg() は失敗することもあるが, 成功するまで繰り返す)
---------------------------------------- -}
for (;;) {
v = _Event ;
if (Atomic::cmpxchg (v-1, &_Event, v) == v) break ;
}
{- -------------------------------------------
(1) (assert)
---------------------------------------- -}
guarantee (v >= 0, "invariant") ;
{- -------------------------------------------
(1) もし変更前の _Event フィールドの値が 0 だった場合は,
os::Solaris::cond_wait() を呼んで
誰かが unpark() してくれるまで眠りにつく.
(なお, 以下の処理は _mutex で排他された critical section 内で行う)
(間違って起きてしまうこともあるので,
目が覚めた後で _Event フィールドもチェックしている.
_Event フィールドが負値のままであれば,
0 以上の値になるまで os::Solaris::cond_wait() を呼び続ける.)
(なお, 眠っているスレッドがいることを unpark() する側に伝えるために,
眠りにつく前に _nParked フィールドの値をインクリメントし,
unpark() されたら _nParked フィールドの値を戻している.)
(なお, ClearFPUAtPark オプションが指定されている場合は... #TODO)
(unpark() されて待機が解けたら, _Event フィールドの値は 0 にしている)
---------------------------------------- -}
if (v == 0) {
// Do this the hard way by blocking ...
// See http://monaco.sfbay/detail.jsf?cr=5094058.
// TODO-FIXME: for Solaris SPARC set fprs.FEF=0 prior to parking.
// Only for SPARC >= V8PlusA
#if defined(__sparc) && defined(COMPILER2)
if (ClearFPUAtPark) { _mark_fpu_nosave() ; }
#endif
int status = os::Solaris::mutex_lock(_mutex);
assert_status(status == 0, status, "mutex_lock");
guarantee (_nParked == 0, "invariant") ;
++ _nParked ;
while (_Event < 0) {
// for some reason, under 2.7 lwp_cond_wait() may return ETIME ...
// Treat this the same as if the wait was interrupted
// With usr/lib/lwp going to kernel, always handle ETIME
status = os::Solaris::cond_wait(_cond, _mutex);
if (status == ETIME) status = EINTR ;
assert_status(status == 0 || status == EINTR, status, "cond_wait");
}
-- _nParked ;
_Event = 0 ;
status = os::Solaris::mutex_unlock(_mutex);
assert_status(status == 0, status, "mutex_unlock");
}
}
This document is available under the GNU GENERAL PUBLIC LICENSE Version 2.