hotspot/src/os/linux/vm/os_linux.cpp
bool os::create_thread(Thread* thread, ThreadType thr_type, size_t stack_size) {
{- -------------------------------------------
(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.