Top


定義場所(file name)

hotspot/src/share/vm/prims/jvmtiRawMonitor.cpp

名前(function name)

int JvmtiRawMonitor::SimpleNotify (Thread * Self, bool All) {

本体部(body)

  {- -------------------------------------------
  (1) (assert)
      ---------------------------------------- -}

      guarantee (_owner == Self, "invariant") ;

  {- -------------------------------------------
  (1) もし _WaitSet も誰もいなければ, 何もすることはないので, ここでリターン.
      ---------------------------------------- -}

      if (_WaitSet == NULL) return OS_OK ;

  {- -------------------------------------------
  (1) (ここでの処理には2つの方式が考えられるが, 現在は B. を採用している, とのこと.
       A. WaitSet の中身を EntryList に移すだけにする
       B. WaitSet の中身を取り出し unpark() まで行う

       ただし, 余りいい方法ではなく futile context switing や contention が多発する. とのこと.)
      ---------------------------------------- -}

      // We have two options:
      // A. Transfer the threads from the WaitSet to the EntryList
      // B. Remove the thread from the WaitSet and unpark() it.
      //
      // We use (B), which is crude and results in lots of futile
      // context switching.  In particular (B) induces lots of contention.

  {- -------------------------------------------
  (1) (変数宣言など)
      ---------------------------------------- -}

      ParkEvent * ev = NULL ;       // consider using a small auto array ...

  {- -------------------------------------------
  (1) 以下の for ループの中で, _WaitSet 中の ObjectWaiter に対して, 
      その TState を ObjectWaiter::TS_RUN に変更し (てメモリバリアも張っ) た後, 
      os::PlatformEvent::unpark() で起床させている.

      All 引数が false の場合は, 最初の一個だけで処理は終了.
      All 引数が true の場合は, 全部の ObjectWaiter に対して処理を行う.

      (なお, ループの処理が少し変則的で, 最後の一個はループ外で起床させる形になる)
      (また, このループの処理は RawMonitor_lock で排他した状態で行う)
      ---------------------------------------- -}

      RawMonitor_lock->lock_without_safepoint_check() ;
      for (;;) {
          ObjectWaiter * w = _WaitSet ;
          if (w == NULL) break ;
          _WaitSet = w->_next ;
          if (ev != NULL) { ev->unpark(); ev = NULL; }
          ev = w->_event ;
          OrderAccess::loadstore() ;
          w->TState = ObjectWaiter::TS_RUN ;
          OrderAccess::storeload();
          if (!All) break ;
      }
      RawMonitor_lock->unlock() ;

  {- -------------------------------------------
  (1) 最後の一個を os::PlatformEvent::unpark() で起床させる.
      ---------------------------------------- -}

      if (ev != NULL) ev->unpark();

  {- -------------------------------------------
  (1) リターン
      ---------------------------------------- -}

      return OS_OK ;
    }

This document is available under the GNU GENERAL PUBLIC LICENSE Version 2.