hotspot/src/share/vm/gc_implementation/g1/concurrentMark.cpp
void work(int worker_i) {
{- -------------------------------------------
(1) (assert)
---------------------------------------- -}
assert(Thread::current()->is_ConcurrentGC_thread(),
"this should only be done by a conc GC thread");
{- -------------------------------------------
(1) (変数宣言など)
---------------------------------------- -}
ResourceMark rm;
{- -------------------------------------------
(1) (変数宣言など)
(処理の開始時間を記録しておく)
---------------------------------------- -}
double start_vtime = os::elapsedVTime();
{- -------------------------------------------
(1) ConcurrentGCThread::stsJoin() を呼んで,
カレントスレッドを SuspendibleThreadSet による制御対象に登録しておく.
(以降の処理は, 適宜 SuspendibleThreadSet::yield() しながら実行するため)
---------------------------------------- -}
ConcurrentGCThread::stsJoin();
{- -------------------------------------------
(1) (assert)
---------------------------------------- -}
assert((size_t) worker_i < _cm->active_tasks(), "invariant");
{- -------------------------------------------
(1) ConcurrentMark::task() を呼んで, 自分が担当する CMTask を取得する.
---------------------------------------- -}
CMTask* the_task = _cm->task(worker_i);
{- -------------------------------------------
(1) (以降の if ブロック内で Concurrent marking 処理を行う.
なお, 処理の前後で CMTask::record_start_time() と CMTask::record_end_time() を呼び出して
処理に掛かった時間を _elapsed_time_ms フィールドに記録しているが,
これはトレース出力用の処理 (現在は CMTask::print_stats() 内でのみ参照されている))
---------------------------------------- -}
the_task->record_start_time();
{- -------------------------------------------
(1.1) (既に処理が終了していたら (= CMTask::has_aborted() が false の場合), 以降のブロックの処理は省略)
(これはどういうケース? #TODO)
---------------------------------------- -}
if (!_cm->has_aborted()) {
{- -------------------------------------------
(1.1) 以降の do...while ブロック内で, 以下のどちらかが成り立つまで CMTask::do_marking_step() を呼び続け,
Concurrent marking 処理を行う.
* 並行して Full GC が発生してしまった場合 (= ConcurrentMark::has_aborted() が true の場合)
(この場合は Concurrent marking を続けても意味が無いので終了する)
* 途中で処理が中断されず, 出来る仕事は全てやりきった場合 (= CMTask::has_aborted() が false の場合)
(この場合は Concurrent marking が完了したので終了する)
---------------------------------------- -}
do {
{- -------------------------------------------
(1.1.1) (変数宣言など)
---------------------------------------- -}
double start_vtime_sec = os::elapsedVTime();
double start_time_sec = os::elapsedTime();
double mark_step_duration_ms = G1ConcMarkStepDurationMillis;
{- -------------------------------------------
(1.1.1) CMTask::do_marking_step() を呼んで, Concurrent marking 処理を行う.
---------------------------------------- -}
the_task->do_marking_step(mark_step_duration_ms,
true /* do_stealing */,
true /* do_termination */);
{- -------------------------------------------
(1.1.1) (変数宣言など)
---------------------------------------- -}
double end_time_sec = os::elapsedTime();
double end_vtime_sec = os::elapsedVTime();
double elapsed_vtime_sec = end_vtime_sec - start_vtime_sec;
double elapsed_time_sec = end_time_sec - start_time_sec;
{- -------------------------------------------
(1.1.1)
---------------------------------------- -}
_cm->clear_has_overflown();
{- -------------------------------------------
(1.1.1) ConcurrentMark::do_yield_check() を呼んでおく.
(この中では, 登録している SuspendibleThreadSet に対して
SuspendibleThreadSet::suspend_all() が呼ばれていれば, 待機処理を行う.
この待機は SuspendibleThreadSet::resume_all() が呼ばれると解ける)
---------------------------------------- -}
bool ret = _cm->do_yield_check(worker_i);
{- -------------------------------------------
(1.1.1) まだループの終了条件が満たされていなければ (= 次のループも行う予定であれば),
Concurrent marking によるオーバーヘッドを平準化するため,
次のループを開始する前に適当な時間だけ os::sleep() で待機しておく
(待機時間は今回の処理に掛かった時間(elapsed_vtime_sec)に比例).
(なお, 待機している間だけはカレントスレッドを SuspendibleThreadSet による制御対象から削除しておく)
---------------------------------------- -}
jlong sleep_time_ms;
if (!_cm->has_aborted() && the_task->has_aborted()) {
sleep_time_ms =
(jlong) (elapsed_vtime_sec * _cm->sleep_factor() * 1000.0);
ConcurrentGCThread::stsLeave();
os::sleep(Thread::current(), sleep_time_ms, false);
ConcurrentGCThread::stsJoin();
}
{- -------------------------------------------
(1.1.1) (トレース出力)(#if 0 で消されているが...??)
---------------------------------------- -}
double end_time2_sec = os::elapsedTime();
double elapsed_time2_sec = end_time2_sec - start_time_sec;
#if 0
gclog_or_tty->print_cr("CM: elapsed %1.4lf ms, sleep %1.4lf ms, "
"overhead %1.4lf",
elapsed_vtime_sec * 1000.0, (double) sleep_time_ms,
the_task->conc_overhead(os::elapsedTime()) * 8.0);
gclog_or_tty->print_cr("elapsed time %1.4lf ms, time 2: %1.4lf ms",
elapsed_time_sec * 1000.0, elapsed_time2_sec * 1000.0);
#endif
} while (!_cm->has_aborted() && the_task->has_aborted());
}
the_task->record_end_time();
{- -------------------------------------------
(1) (assert)
---------------------------------------- -}
guarantee(!the_task->has_aborted() || _cm->has_aborted(), "invariant");
{- -------------------------------------------
(1) 処理が終わったので, ConcurrentGCThread::stsLeave() を呼んで,
カレントスレッドを SuspendibleThreadSet による制御対象から削除する.
---------------------------------------- -}
ConcurrentGCThread::stsLeave();
{- -------------------------------------------
(1) (トレース出力用の処理)
(ConcurrentMark::update_accum_task_vtime() を呼んで
処理に掛かった時間を記録している.
この結果は ConcurrentMark::_accum_task_vtime フィールドに格納され,
現在は以下のパスでのみ参照されている.
before_exit()
-> G1CollectedHeap::print_tracing_info()
-> ConcurrentMark::print_summary_info() (G1SummarizeConcMark オプション指定時のみ)
-> ConcurrentMarkThread::vtime_accum() または ConcurrentMarkThread::vtime_mark_accum()
-> ConcurrentMark::all_task_accum_vtime())
---------------------------------------- -}
double end_vtime = os::elapsedVTime();
_cm->update_accum_task_vtime(worker_i, end_vtime - start_vtime);
}
This document is available under the GNU GENERAL PUBLIC LICENSE Version 2.