hotspot/src/os/windows/vm/os_windows.cpp
void os::PlatformEvent::park () {
{- -------------------------------------------
(1) (assert)
---------------------------------------- -}
guarantee (_ParkHandle != NULL, "Invariant") ;
{- -------------------------------------------
(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) || (v == 1), "invariant") ;
{- -------------------------------------------
(1) もし変更前の _Event フィールドの値が
0 以外だった場合は (つまりは 1 だった場合は),
ここでリターン
---------------------------------------- -}
if (v != 0) return ;
{- -------------------------------------------
(1) 変更前の _Event フィールドの値が 0 だった場合は,
以下で WaitForSingleObject() を呼んで
誰かが unpark() してくれるまで眠りにつく.
(間違って起きてしまうこともあるので(?),
目が覚めた後で _Event フィールドもチェックしている.
_Event フィールドが負値のままであれば,
0 以上の値になるまで WaitForSingleObject() を呼び続ける.)
(unpark() されて待機が解けたら, _Event フィールドの値は 0 にしている.
たいていの場合は, この時点では既に 0 だからクリアしなくてもいいけど,
複数回 unpark() されて _Event フィールドの値が 1 を超えた場合を
ここでリセットする意味合いがあるらしい.
ついでに, この _Event フィールドのクリア処理が
この後に行われる load/store に追い抜かれないよう,
OrderAccess::fence() も張っている.)
---------------------------------------- -}
// Do this the hard way by blocking ...
// TODO: consider a brief spin here, gated on the success of recent
// spin attempts by this thread.
while (_Event < 0) {
DWORD rv = ::WaitForSingleObject (_ParkHandle, INFINITE) ;
assert (rv == WAIT_OBJECT_0, "WaitForSingleObject failed") ;
}
// Usually we'll find _Event == 0 at this point, but as
// an optional optimization we clear it, just in case can
// multiple unpark() operations drove _Event up to 1.
_Event = 0 ;
OrderAccess::fence() ;
guarantee (_Event >= 0, "invariant") ;
}
This document is available under the GNU GENERAL PUBLIC LICENSE Version 2.