Top


定義場所(file name)

hotspot/src/os/linux/vm/os_linux.cpp

名前(function name)

bool os::create_thread(Thread* thread, ThreadType thr_type, size_t stack_size) {

本体部(body)

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

      assert(thread->osthread() == NULL, "caller responsible");

  {- -------------------------------------------
  (1) OSThread オブジェクトを生成する (失敗したらここでリターン)
      ---------------------------------------- -}

      // Allocate the OSThread object
      OSThread* osthread = new OSThread(NULL, NULL);
      if (osthread == NULL) {
        return false;
      }

  {- -------------------------------------------
  (1) 引数で指定されたスレッド種別情報を thread_type フィールドに記録しておく.
      (この情報は何に使われる?? 現在の実装ではどこからも使われていないような... #TODO)
      ---------------------------------------- -}

      // set the correct thread state
      osthread->set_thread_type(thr_type);

  {- -------------------------------------------
  (1) 生成したスレッドの ThreadState を ALLOCATED に変更する.
      ---------------------------------------- -}

      // Initial state is ALLOCATED but not INITIALIZED
      osthread->set_state(ALLOCATED);

  {- -------------------------------------------
  (1) Thread::set_osthread() を呼んで, 生成した OSThread を
      引数で渡された Thread オブジェクトに対応づける
      ---------------------------------------- -}

      thread->set_osthread(osthread);

  {- -------------------------------------------
  (1) 以下の pthread 属性の設定を行う

      * デタッチ状態  (pthread_attr_setdetachstate() で設定)
        PTHREAD_CREATE_DETACHED に設定 (= 終了しても pthread_join() で回収する必要は無い).

      * スタックサイズ   (pthread_attr_setstacksize() で設定)
        (ただし, スタックサイズを変えられない場合  (<= LinuxThread だと変えられない) にはデフォルト値のままとする.
         See: os::Linux::supports_variable_stack_size())

        * 引数でスタックサイズが指定されている場合 (引数の stack_size が 0 ではない場合)
          その値に設定する
        * 引数でスタックサイズが指定されていない場合 (引数の stack_size が 0 の場合)
          スレッド種別に応じた以下のデフォルト値に設定する
          * JavaThread の場合
            JavaThread::stack_size_at_create() の値を使用
            (これは -Xss オプションで指定した値.
             See: Arguments::parse_each_vm_init_arg(), os::init_2())
          * CompilerThread の場合
            CompilerThreadStackSize オプションの値を使用.
            (ただし, CompilerThreadStackSize オプションが指定されていない場合(値が 0 の場合)には, 
             VMThread 等と同じ方法で決める)
          * VMThread, Parallel GC thread, Concurrent GC thread, WatcherThread の場合
            VMThreadStackSize オプションの値を使用.
            (ただし, VMThreadStackSize オプションが指定されていない場合(値が 0 の場合)には, 
             os::Linux::default_stack_size() の値を使用する)

       * ガードエリアサイズ  (pthread_attr_setguardsize() で設定)
         os::Linux::default_guard_size() の値に設定
      ---------------------------------------- -}

      // init thread attributes
      pthread_attr_t attr;
      pthread_attr_init(&attr);
      pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);

      // stack size
      if (os::Linux::supports_variable_stack_size()) {
        // calculate stack size if it's not specified by caller
        if (stack_size == 0) {
          stack_size = os::Linux::default_stack_size(thr_type);

          switch (thr_type) {
          case os::java_thread:
            // Java threads use ThreadStackSize which default value can be
            // changed with the flag -Xss
            assert (JavaThread::stack_size_at_create() > 0, "this should be set");
            stack_size = JavaThread::stack_size_at_create();
            break;
          case os::compiler_thread:
            if (CompilerThreadStackSize > 0) {
              stack_size = (size_t)(CompilerThreadStackSize * K);
              break;
            } // else fall through:
              // use VMThreadStackSize if CompilerThreadStackSize is not defined
          case os::vm_thread:
          case os::pgc_thread:
          case os::cgc_thread:
          case os::watcher_thread:
            if (VMThreadStackSize > 0) stack_size = (size_t)(VMThreadStackSize * K);
            break;
          }
        }

        stack_size = MAX2(stack_size, os::Linux::min_stack_allowed);
        pthread_attr_setstacksize(&attr, stack_size);
      } else {
        // let pthread_create() pick the default value.
      }

      // glibc guard page
      pthread_attr_setguardsize(&attr, os::Linux::default_guard_size(thr_type));

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

      ThreadState state;

      {

  {- -------------------------------------------
  (1) 使用するスレッドが fixed stack LinuxThreads の場合, 
      以下のスレッド生成処理は os::Linux::createThread_lock() で排他した状態で行う.
      (これは, 生成された側での _thread_safety_check() によるチェックを排他して行うため?? #TODO)
      ---------------------------------------- -}

        // Serialize thread creation if we are running with fixed stack LinuxThreads
        bool lock = os::Linux::is_LinuxThreads() && !os::Linux::is_floating_stack();
        if (lock) {
          os::Linux::createThread_lock()->lock_without_safepoint_check();
        }

  {- -------------------------------------------
  (1) pthread_create() でスレッドを生成する.
      (なお, スレッドのエントリポイントは java_start() としている)

      (生成し終わったら, 使い終わった pthread_attr_t はここで破棄)
      ---------------------------------------- -}

        pthread_t tid;
        int ret = pthread_create(&tid, &attr, (void* (*)(void*)) java_start, thread);

        pthread_attr_destroy(&attr);

  {- -------------------------------------------
  (1) スレッド生成に失敗していた場合は, 
      生成したりソースを解放し, ここでリターン.
      ---------------------------------------- -}

        if (ret != 0) {
          if (PrintMiscellaneous && (Verbose || WizardMode)) {
            perror("pthread_create()");
          }
          // Need to clean up stuff we've allocated so far
          thread->set_osthread(NULL);
          delete osthread;
          if (lock) os::Linux::createThread_lock()->unlock();
          return false;
        }

  {- -------------------------------------------
  (1) OSThread::set_pthread_id() を呼んで, 生成したスレッドの pthread_t を 
      OSThread に対応づける
      ---------------------------------------- -}

        // Store pthread info into the OSThread
        osthread->set_pthread_id(tid);

  {- -------------------------------------------
  (1) 生成したスレッドの startThread_lock に対して Monitor::wait() を呼び出し, 
      生成したスレッドの初期化が終わるまでここで待ち合わせる.
      (See: java_start())
      ---------------------------------------- -}

        // Wait until child thread is either initialized or aborted
        {
          Monitor* sync_with_child = osthread->startThread_lock();
          MutexLockerEx ml(sync_with_child, Mutex::_no_safepoint_check_flag);
          while ((state = osthread->get_state()) == ALLOCATED) {
            sync_with_child->wait(Mutex::_no_safepoint_check_flag);
          }
        }

  {- -------------------------------------------
  (1) ここまでが, os::Linux::createThread_lock() で排他された critical section.
      ---------------------------------------- -}

        if (lock) {
          os::Linux::createThread_lock()->unlock();
        }
      }

  {- -------------------------------------------
  (1) スレッドの開始に失敗していた場合は, 
      生成したりソースを解放し, ここでリターン.
      (See: java_start())
      ---------------------------------------- -}

      // Aborted due to thread limit being reached
      if (state == ZOMBIE) {
          thread->set_osthread(NULL);
          delete osthread;
          return false;
      }

  {- -------------------------------------------
  (1) リターン
      (この段階では, 生成したスレッドは INITIALIZED 状態で有り, 稼働はしていない(suspend されている状態).
       スレッドの開始処理は, ここからリターンした後の関数によって行われる.)
      ---------------------------------------- -}

      // The thread is returned suspended (in state INITIALIZED),
      // and is started higher up in the call chain
      assert(state == INITIALIZED, "race condition");
      return true;
    }

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