hotspot/src/share/vm/runtime/objectMonitor.cpp
void ObjectMonitor::DeferredInitialize () {
{- -------------------------------------------
(1) 既に初期化済みであれば, もうすることはない. ここでリターン.
---------------------------------------- -}
if (InitDone > 0) return ;
{- -------------------------------------------
(1) 初期化作業を排他的に行うために, CAS で InitDone を 0 から -1 に変更する.
(CAS が失敗したら, InitDone が 1 になるまで(= 誰かが初期化が完了させるまで)ここで待機してからリターン)
---------------------------------------- -}
if (Atomic::cmpxchg (-1, &InitDone, 0) != 0) {
while (InitDone != 1) ;
return ;
}
{- -------------------------------------------
(1) (以下で初期化処理を行う.
なお, この初期化処理は何度やっても同じ(冪等)なので, 実のところロックは必要ない.
また, この処理は os::init_2() の中でやってもいいかもしれない.
この初期化処理では, SyncKnobs オプションで指定された値を Knob_* 変数群に設定していく.
SyncKnobs は環境変数のように "<Key1>=<Value1>:<Key2>=<Value2>:..." という書式になっている.
以下の処理では, まず ':' を NULL 文字に置き換えてからパースする.)
---------------------------------------- -}
// One-shot global initialization ...
// The initialization is idempotent, so we don't need locks.
// In the future consider doing this via os::init_2().
// SyncKnobs consist of <Key>=<Value> pairs in the style
// of environment variables. Start by converting ':' to NUL.
{- -------------------------------------------
(1) SyncKnobs オプションが指定されていない場合は, 空文字列とする.
---------------------------------------- -}
if (SyncKnobs == NULL) SyncKnobs = "" ;
{- -------------------------------------------
(1) 処理のために, SyncKnobs オプションと同サイズのメモリを malloc() し,
':' を NULL 文字に置き換えておく.
(なお, malloc() に失敗したら vm_exit_out_of_memory()
See: [here](no9662DlT.html) for details)
---------------------------------------- -}
size_t sz = strlen (SyncKnobs) ;
char * knobs = (char *) malloc (sz + 2) ;
if (knobs == NULL) {
vm_exit_out_of_memory (sz + 2, "Parse SyncKnobs") ;
guarantee (0, "invariant") ;
}
strcpy (knobs, SyncKnobs) ;
knobs[sz+1] = 0 ;
for (char * p = knobs ; *p ; p++) {
if (*p == ':') *p = 0 ;
}
{- -------------------------------------------
(1) 以下, kvGetInt() で SyncKnobs オプションの値をパースして, それぞれの Knob_* 変数の値をセットする.
---------------------------------------- -}
#define SETKNOB(x) { Knob_##x = kvGetInt (knobs, #x, Knob_##x); }
SETKNOB(ReportSettings) ;
SETKNOB(Verbose) ;
SETKNOB(FixedSpin) ;
SETKNOB(SpinLimit) ;
SETKNOB(SpinBase) ;
SETKNOB(SpinBackOff);
SETKNOB(CASPenalty) ;
SETKNOB(OXPenalty) ;
SETKNOB(LogSpins) ;
SETKNOB(SpinSetSucc) ;
SETKNOB(SuccEnabled) ;
SETKNOB(SuccRestrict) ;
SETKNOB(Penalty) ;
SETKNOB(Bonus) ;
SETKNOB(BonusB) ;
SETKNOB(Poverty) ;
SETKNOB(SpinAfterFutile) ;
SETKNOB(UsePause) ;
SETKNOB(SpinEarly) ;
SETKNOB(OState) ;
SETKNOB(MaxSpinners) ;
SETKNOB(PreSpin) ;
SETKNOB(ExitPolicy) ;
SETKNOB(QMode);
SETKNOB(ResetEvent) ;
SETKNOB(MoveNotifyee) ;
SETKNOB(FastHSSEC) ;
#undef SETKNOB
{- -------------------------------------------
(1) マルチプロセッサ環境の場合, BackOffMask 変数の値を Knob_SpinBackOff に対応する値に設定しておく (ついでに(トレース出力)も出している).
逆にマルチプロセッサでない場合, (意味が無いので) 以下の Knob_* の値をリセットしておく.
* Knob_SpinLimit = 0 ;
* Knob_SpinBase = 0 ;
* Knob_PreSpin = 0 ;
* Knob_FixedSpin = -1 ;
---------------------------------------- -}
if (os::is_MP()) {
BackOffMask = (1 << Knob_SpinBackOff) - 1 ;
if (Knob_ReportSettings) ::printf ("BackOffMask=%X\n", BackOffMask) ;
// CONSIDER: BackOffMask = ROUNDUP_NEXT_POWER2 (ncpus-1)
} else {
Knob_SpinLimit = 0 ;
Knob_SpinBase = 0 ;
Knob_PreSpin = 0 ;
Knob_FixedSpin = -1 ;
}
{- -------------------------------------------
(1) (プロファイル情報取得用の初期化処理) (See: UsePerfData) (See: sun.rt._sync_FailedSpins)
もし Knob_LogSpins がセットされていなければ,
sun.rt._sync_FailedSpins の取得は行わない.
(ObjectMonitor::_sync_FailedSpins を NULL にしておく).
---------------------------------------- -}
if (Knob_LogSpins == 0) {
ObjectMonitor::_sync_FailedSpins = NULL ;
}
{- -------------------------------------------
(1) 初期化が終わったので, malloc() で確保したメモリを解放しておく.
---------------------------------------- -}
free (knobs) ;
{- -------------------------------------------
(1) 初期化が終わったので, InitDone を 1 にする.
(なお, 初期化用の store を追い抜かないように, OrderAccess::fence() でメモリバリアも張っている)
---------------------------------------- -}
OrderAccess::fence() ;
InitDone = 1 ;
}
This document is available under the GNU GENERAL PUBLIC LICENSE Version 2.