Top


定義場所(file name)

hotspot/src/os/solaris/vm/os_solaris.cpp

説明(description)

// Thread start routine for all new Java threads

名前(function name)

extern "C" void* java_start(void* thread_addr) {

本体部(body)

  {- -------------------------------------------
  (1) alloca() を呼んで, スタックの位置を多少増減させておく.
      (増減させる量は, 自分自身の process id と 
       static な int 変数(以下の counter)に基づいて決めている)

      (なおコメントによると, これはキャッシュ上での競合を減らすための措置.
       他のスレッドのスタックとキャッシュラインがかぶっていると, お互いに invalidate しあうことになるので.
       競合は同じ HotSpot プロセス内のスレッド同士でも起こりうるし, 
       別の HotSpot プロセス内のスレッドとも起こりうる.
       特に, Hyperthreading 環境ではずらすことによる効果が大きい, とのこと.)
      ---------------------------------------- -}

      // Try to randomize the cache line index of hot stack frames.
      // This helps when threads of the same stack traces evict each other's
      // cache lines. The threads can be either from the same JVM instance, or
      // from different JVM instances. The benefit is especially true for
      // processors with hyperthreading technology.
      static int counter = 0;
      int pid = os::current_process_id();
      alloca(((pid ^ counter++) & 7) * 128);

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

      int prio;
      Thread* thread = (Thread*)thread_addr;
      OSThread* osthr = thread->osthread();

  {- -------------------------------------------
  (1) _lwp_self() でカレントスレッドに対応する LWP ID を取得し, lwp_id フィールドに記録しておく.
      ---------------------------------------- -}

      osthr->set_lwp_id( _lwp_self() );  // Store lwp in case we are bound

  {- -------------------------------------------
  (1) フィールドの初期化
      (取得した schedctl_t は何に使われる?? 現在の実装ではどこからも使われていないような... #TODO)
      ---------------------------------------- -}

      thread->_schedctl = (void *) schedctl_init () ;

  {- -------------------------------------------
  (1) UseNUMA オプションが指定されている場合は, 
      os::numa_get_group_id() で id を取得し, 
      カレントスレッドの lgrp_id フィールドにセットしておく.
      (See: [here](no28916ddy.html) for details)
      ---------------------------------------- -}

      if (UseNUMA) {
        int lgrp_id = os::numa_get_group_id();
        if (lgrp_id != -1) {
          thread->set_lgrp_id(lgrp_id);
        }
      }

  {- -------------------------------------------
  (1) 処理対象の OSThread が対応する thread_t を持っており
        (<= 持っていないのはどういうケース?? メインスレッド?? JNI スレッド?? #TODO)
      かつ UseThreadPriorities オプションが指定されている場合には, 
      thr_setprio() でスレッドの優先度が設定されていたはず (See: os::create_thread()).

      ただし, その段階では LWP との対応が決まっていなかったので, 
      改めて os::set_native_priority() を呼び出して LWP レベルでも優先度を設定しておく.
      ---------------------------------------- -}

      // If the creator called set priority before we started,
      // we need to call set priority now that we have an lwp.
      // Get the priority from libthread and set the priority
      // for the new Solaris lwp.
      if ( osthr->thread_id() != -1 ) {
        if ( UseThreadPriorities ) {
          thr_getprio(osthr->thread_id(), &prio);
          if (ThreadPriorityVerbose) {
            tty->print_cr("Starting Thread " INTPTR_FORMAT ", LWP is " INTPTR_FORMAT ", setting priority: %d\n",
                          osthr->thread_id(), osthr->lwp_id(), prio );
          }
          os::set_native_priority(thread, prio);
        }
      } else if (ThreadPriorityVerbose) {
        warning("Can't set priority in _start routine, thread id hasn't been set\n");
      }

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

      assert(osthr->get_state() == RUNNABLE, "invalid os thread state");

  {- -------------------------------------------
  (1) os::Solaris::hotspot_sigmask() を呼び出して, 適切なシグナルマスクを設定しておく.
      ---------------------------------------- -}

      // initialize signal mask for this thread
      os::Solaris::hotspot_sigmask(thread);

  {- -------------------------------------------
  (1) Thread::run() (もしくはサブクラスでオーバーライドされたメソッド) を呼び出して, 
      スレッドのメイン処理を実行する.
      ---------------------------------------- -}

      thread->run();

  {- -------------------------------------------
  (1) os::Solaris::_os_thread_count フィールドの値を減少させておく.
      (この値は, os::create_thread() 内でのランタイムチェックや調整処理に使われている.
       See: os::create_thread())

      ただし, 処理対象のスレッドが VM Thread の場合は, この処理は行わない.
      (コメントによると, 
      ここの処理では Atomic::dec を使用するが, VM Thread の場合は
      メインスレッドが Atomic::dec のコードを含んでいる CodeHeap を開放済みかもしれない, 
      とのこと.)

      また, VMThread::vm_thread() が NULL の場合もこの処理を行わないようだが, 
      これは VM Thread が死んだ後にここに到達したスレッドがいた場合?? #TODO
      (ネイティブコードを実行していたスレッドが VM Thread 死亡後に到達するケース??)
      ---------------------------------------- -}

      // One less thread is executing
      // When the VMThread gets here, the main thread may have already exited
      // which frees the CodeHeap containing the Atomic::dec code
      if (thread != VMThread::vm_thread() && VMThread::vm_thread() != NULL) {
        Atomic::dec(&os::Solaris::_os_thread_count);
      }

  {- -------------------------------------------
  (1) UseDetachedThreads オプションが指定されている場合は, 
      ここで thr_exit() システムコールを呼んでスレッドを終了させる.
      (この場合, スレッド自体が無くなるので, ここで実行は終了)
      ---------------------------------------- -}

      if (UseDetachedThreads) {
        thr_exit(NULL);
        ShouldNotReachHere();
      }

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

      return NULL;
    }

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