hotspot/src/share/vm/runtime/objectMonitor.cpp
void ObjectMonitor::ExitEpilog (Thread * Self, ObjectWaiter * Wakee) {
{- -------------------------------------------
(1) (assert)
---------------------------------------- -}
assert (_owner == Self, "invariant") ;
{- -------------------------------------------
(1) (スレッドを起床させる際の処理順序は, 以下のコメントの通り)
---------------------------------------- -}
// Exit protocol:
// 1. ST _succ = wakee
// 2. membar #loadstore|#storestore;
// 2. ST _owner = NULL
// 3. unpark(wakee)
{- -------------------------------------------
(1) まず, 起床させるスレッド(Wakee)を _succ にセットする.
(これは, 以降の unlock() 処理の際に,
既に後続が決まっているので起床処理を省略してもいいと伝えるためのもの.
See: ObjectMonitor::exit())
(ただし, Knob_SuccEnabled が 0 の場合は _succ は使用しない.
この場合は _succ は NULL にしておく.)
---------------------------------------- -}
_succ = Knob_SuccEnabled ? Wakee->_thread : NULL ;
{- -------------------------------------------
(1) (変数宣言など)
---------------------------------------- -}
ParkEvent * Trigger = Wakee->_event ;
{- -------------------------------------------
(1) (ロックを落として以降は, Wakee はダングリングポインタになっているかもしれない.
この関数の残りの処理でうっかり参照しないよう, NULL にしている)
---------------------------------------- -}
// Hygiene -- once we've set _owner = NULL we can't safely dereference Wakee again.
// The thread associated with Wakee may have grabbed the lock and "Wakee" may be
// out-of-scope (non-extant).
Wakee = NULL ;
{- -------------------------------------------
(1) ロックを解放する (= owner を NULL にする).
ついでに, メモリバリアも張っている.
(owner を NULL にするまでが critical section なので.
critical section 内の load/store が critical section 後に re-order されるのは禁止)
(OrderAccess::fence() は, owner の変更が unpark() 処理中での load に抜かれるのを防止するため.
OrderAccess::release_store_ptr() だけだと, loadstore と storestore の追い抜きは防げても,
storeload の追い抜きは防げない.)
---------------------------------------- -}
// Drop the lock
OrderAccess::release_store_ptr (&_owner, NULL) ;
OrderAccess::fence() ; // ST _owner vs LD in unpark()
{- -------------------------------------------
(1) (トレース出力)
---------------------------------------- -}
if (SafepointSynchronize::do_call_back()) {
TEVENT (unpark before SAFEPOINT) ;
}
{- -------------------------------------------
(1) (DTrace のフック点)
---------------------------------------- -}
DTRACE_MONITOR_PROBE(contended__exit, this, object(), Self);
{- -------------------------------------------
(1) os::PlatformEvent::unpark() を呼んで, 対象のスレッドを実際に起床させる.
---------------------------------------- -}
Trigger->unpark() ;
{- -------------------------------------------
(1) (プロファイル情報の記録) (See: UsePerfData) (See: sun.rt._sync_Parks)
---------------------------------------- -}
// Maintain stats and report events to JVMTI
if (ObjectMonitor::_sync_Parks != NULL) {
ObjectMonitor::_sync_Parks->inc() ;
}
}
This document is available under the GNU GENERAL PUBLIC LICENSE Version 2.