8189170: Add option to disable stack overflow checking in primordial thread for use with JNI_CreateJavaJVM

Reviewed-by: stuefe, dcubed
This commit is contained in:
David Holmes 2017-11-20 15:56:32 -05:00
parent cdf8de893e
commit 687c2c5412
12 changed files with 78 additions and 54 deletions

View file

@ -853,8 +853,8 @@ bool os::create_attached_thread(JavaThread* thread) {
}
}
if (os::Linux::is_initial_thread()) {
// If current thread is initial thread, its stack is mapped on demand,
if (os::is_primordial_thread()) {
// If current thread is primordial thread, its stack is mapped on demand,
// see notes about MAP_GROWSDOWN. Here we try to force kernel to map
// the entire stack region to avoid SEGV in stack banging.
// It is also useful to get around the heap-stack-gap problem on SuSE
@ -915,19 +915,20 @@ void os::free_thread(OSThread* osthread) {
}
//////////////////////////////////////////////////////////////////////////////
// initial thread
// primordial thread
// Check if current thread is the initial thread, similar to Solaris thr_main.
bool os::Linux::is_initial_thread(void) {
// Check if current thread is the primordial thread, similar to Solaris thr_main.
bool os::is_primordial_thread(void) {
char dummy;
// If called before init complete, thread stack bottom will be null.
// Can be called if fatal error occurs before initialization.
if (initial_thread_stack_bottom() == NULL) return false;
assert(initial_thread_stack_bottom() != NULL &&
initial_thread_stack_size() != 0,
"os::init did not locate initial thread's stack region");
if ((address)&dummy >= initial_thread_stack_bottom() &&
(address)&dummy < initial_thread_stack_bottom() + initial_thread_stack_size()) {
if (os::Linux::initial_thread_stack_bottom() == NULL) return false;
assert(os::Linux::initial_thread_stack_bottom() != NULL &&
os::Linux::initial_thread_stack_size() != 0,
"os::init did not locate primordial thread's stack region");
if ((address)&dummy >= os::Linux::initial_thread_stack_bottom() &&
(address)&dummy < os::Linux::initial_thread_stack_bottom() +
os::Linux::initial_thread_stack_size()) {
return true;
} else {
return false;
@ -958,7 +959,7 @@ static bool find_vma(address addr, address* vma_low, address* vma_high) {
return false;
}
// Locate initial thread stack. This special handling of initial thread stack
// Locate primordial thread stack. This special handling of primordial thread stack
// is needed because pthread_getattr_np() on most (all?) Linux distros returns
// bogus value for the primordial process thread. While the launcher has created
// the VM in a new thread since JDK 6, we still have to allow for the use of the
@ -982,7 +983,10 @@ void os::Linux::capture_initial_stack(size_t max_size) {
// 6308388: a bug in ld.so will relocate its own .data section to the
// lower end of primordial stack; reduce ulimit -s value a little bit
// so we won't install guard page on ld.so's data section.
stack_size -= 2 * page_size();
// But ensure we don't underflow the stack size - allow 1 page spare
if (stack_size >= (size_t)(3 * page_size())) {
stack_size -= 2 * page_size();
}
// Try to figure out where the stack base (top) is. This is harder.
//
@ -1103,16 +1107,16 @@ void os::Linux::capture_initial_stack(size_t max_size) {
if (i != 28 - 2) {
assert(false, "Bad conversion from /proc/self/stat");
// product mode - assume we are the initial thread, good luck in the
// product mode - assume we are the primordial thread, good luck in the
// embedded case.
warning("Can't detect initial thread stack location - bad conversion");
warning("Can't detect primordial thread stack location - bad conversion");
stack_start = (uintptr_t) &rlim;
}
} else {
// For some reason we can't open /proc/self/stat (for example, running on
// FreeBSD with a Linux emulator, or inside chroot), this should work for
// most cases, so don't abort:
warning("Can't detect initial thread stack location - no /proc/self/stat");
warning("Can't detect primordial thread stack location - no /proc/self/stat");
stack_start = (uintptr_t) &rlim;
}
}
@ -1132,7 +1136,7 @@ void os::Linux::capture_initial_stack(size_t max_size) {
stack_top = (uintptr_t)high;
} else {
// failed, likely because /proc/self/maps does not exist
warning("Can't detect initial thread stack location - find_vma failed");
warning("Can't detect primordial thread stack location - find_vma failed");
// best effort: stack_start is normally within a few pages below the real
// stack top, use it as stack top, and reduce stack size so we won't put
// guard page outside stack.
@ -3136,10 +3140,10 @@ static address get_stack_commited_bottom(address bottom, size_t size) {
// 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
// mapping. This only affects the main/primordial thread
bool os::pd_create_stack_guard_pages(char* addr, size_t size) {
if (os::Linux::is_initial_thread()) {
if (os::is_primordial_thread()) {
// As we manually grow stack up to bottom inside create_attached_thread(),
// it's likely that os::Linux::initial_thread_stack_bottom is mapped and
// we don't need to do anything special.
@ -3164,14 +3168,14 @@ bool os::pd_create_stack_guard_pages(char* addr, size_t size) {
// If this is a growable mapping, remove the guard pages entirely by
// munmap()ping them. If not, just call uncommit_memory(). This only
// affects the main/initial thread, but guard against future OS changes
// It's safe to always unmap guard pages for initial thread because we
// always place it right after end of the mapped region
// affects the main/primordial thread, but guard against future OS changes.
// It's safe to always unmap guard pages for primordial thread because we
// always place it right after end of the mapped region.
bool os::remove_stack_guard_pages(char* addr, size_t size) {
uintptr_t stack_extent, stack_base;
if (os::Linux::is_initial_thread()) {
if (os::is_primordial_thread()) {
return ::munmap(addr, size) == 0;
}
@ -4860,10 +4864,9 @@ void os::Linux::check_signal_handler(int sig) {
extern void report_error(char* file_name, int line_no, char* title,
char* format, ...);
// this is called _before_ the most of global arguments have been parsed
// this is called _before_ most of the global arguments have been parsed
void os::init(void) {
char dummy; // used to get a guess on initial stack address
// first_hrtime = gethrtime();
clock_tics_per_sec = sysconf(_SC_CLK_TCK);
@ -4880,7 +4883,7 @@ void os::init(void) {
Linux::initialize_os_info();
// main_thread points to the aboriginal thread
// _main_thread points to the thread that created/loaded the JVM.
Linux::_main_thread = pthread_self();
Linux::clock_init();
@ -5851,8 +5854,8 @@ bool os::start_debugging(char *buf, int buflen) {
//
#ifndef ZERO
static void current_stack_region(address * bottom, size_t * size) {
if (os::Linux::is_initial_thread()) {
// initial thread needs special handling because pthread_getattr_np()
if (os::is_primordial_thread()) {
// primordial thread needs special handling because pthread_getattr_np()
// may return bogus value.
*bottom = os::Linux::initial_thread_stack_bottom();
*size = os::Linux::initial_thread_stack_size();