Top


定義場所(file name)

hotspot/src/share/vm/runtime/objectMonitor.cpp

名前(function name)

void ObjectMonitor::DeferredInitialize () {

本体部(body)

  {- -------------------------------------------
  (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.