hotspot/src/os/linux/vm/os_linux.cpp
なお, guard page にする予定の領域に既にメモリがマッピングされていた場合, そのままだと後で guard page を munmap() した際に スタック上のメモリマッピングで穴のような領域ができて変になる恐れがある. そこで, guard page の領域より下の部分については, 全て munmap() している.
こういうケースが起こるのは, 現状ではメインスレッド(初期スレッド)の場合のみ. ただし, 将来的には OS の変更によって他のスレッドでもそういう事態が起こるかもしれない.
// If the (growable) stack mapping already extends beyond the point
// where we're going to put our guard pages, truncate the mapping at
// that point by munmap()ping it. This ensures that when we later
// munmap() the guard pages we don't leave a hole in the stack
// mapping. This only affects the main/initial thread, but guard
// against future OS changes
bool os::create_stack_guard_pages(char* addr, size_t size) {
{- -------------------------------------------
(1) (変数宣言など)
---------------------------------------- -}
uintptr_t stack_extent, stack_base;
bool chk_bounds = NOT_DEBUG(os::Linux::is_initial_thread()) DEBUG_ONLY(true);
{- -------------------------------------------
(1) guard page にする予定の領域に既にメモリがマッピングされていた場合,
guard page 領域より下の領域は 全て munmap() しておく.
(理由は上述)
---------------------------------------- -}
if (chk_bounds && get_stack_bounds(&stack_extent, &stack_base)) {
assert(os::Linux::is_initial_thread(),
"growable stack in non-initial thread");
if (stack_extent < (uintptr_t)addr)
::munmap((void*)stack_extent, (uintptr_t)addr - stack_extent);
}
{- -------------------------------------------
(1) os::commit_memory() を呼んで, 指定範囲をコミット.
---------------------------------------- -}
return os::commit_memory(addr, size);
}
This document is available under the GNU GENERAL PUBLIC LICENSE Version 2.