Top


定義場所(file name)

hotspot/src/os/windows/vm/os_windows.cpp

名前(function name)

void os::PlatformEvent::park () {

本体部(body)

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