hotspot/src/os/solaris/vm/os_solaris.cpp
Solaris においては, 1 msec だけの sleep() では 他のスレッドにプロセッサ(というか lwp)が割り当たらないことがある.
このため, os::yield_all() を試みた回数を引数で渡してもらうことにし, 8 回以上失敗したら, sleep 時間を増加させることとした. さらに, それでも失敗するようなら, thr_setconcurrency() で concurrency level を増加させることにした.
// On Solaris we found that yield_all doesn't always yield to all other threads.
// There have been cases where there is a thread ready to execute but it doesn't
// get an lwp as the VM thread continues to spin with sleeps of 1 millisecond.
// The 1 millisecond wait doesn't seem long enough for the kernel to issue a
// SIGWAITING signal which will cause a new lwp to be created. So we count the
// number of times yield_all is called in the one loop and increase the sleep
// time after 8 attempts. If this fails too we increase the concurrency level
// so that the starving thread would get an lwp
void os::yield_all(int attempts) {
{- -------------------------------------------
(1) 引数で指定された失敗回数(attempts)に応じて, 以下のように yield 処理を行う.
* 失敗回数(attempts)が 0 の場合 (初回の yield の場合):
os::sleep() で 1msec だけ待機.
* 失敗回数(attempts)が 25 未満の場合:
os::sleep() で 1msec だけ待機.
* 失敗回数(attempts)が 25 以上の場合:
os::sleep() で 10ms だけ待機.
* 失敗回数(attempts)が 30 に達した場合 (かつ T2 libthread ではない場合): (<= 正確には 30 の倍数に達した場合)
thr_setconcurrency() を呼んで, LWP 数を設定.
---------------------------------------- -}
// Yields to all threads, including threads with lower priorities
if (attempts == 0) {
os::sleep(Thread::current(), 1, false);
} else {
int iterations = attempts % 30;
if (iterations == 0 && !os::Solaris::T2_libthread()) {
// thr_setconcurrency and _getconcurrency make sense only under T1.
int noofLWPS = thr_getconcurrency();
if (noofLWPS < (Threads::number_of_threads() + 2)) {
thr_setconcurrency(thr_getconcurrency() + 1);
}
} else if (iterations < 25) {
os::sleep(Thread::current(), 1, false);
} else {
os::sleep(Thread::current(), 10, false);
}
}
}
This document is available under the GNU GENERAL PUBLIC LICENSE Version 2.