< prev index next >
src/hotspot/os/linux/os_linux.cpp
Print this page
*** 811,822 ****
if (lgrp_id != -1) {
thread->set_lgrp_id(lgrp_id);
}
}
! if (os::Linux::is_initial_thread()) {
! // If current thread is initial 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
// kernel (see 4821821 for details). We first expand stack to the top
// of yellow zone, then enable stack yellow zone (order is significant,
--- 811,822 ----
if (lgrp_id != -1) {
thread->set_lgrp_id(lgrp_id);
}
}
! 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
// kernel (see 4821821 for details). We first expand stack to the top
// of yellow zone, then enable stack yellow zone (order is significant,
*** 873,895 ****
delete osthread;
}
//////////////////////////////////////////////////////////////////////////////
! // initial thread
! // Check if current thread is the initial thread, similar to Solaris thr_main.
! bool os::Linux::is_initial_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()) {
return true;
} else {
return false;
}
}
--- 873,896 ----
delete osthread;
}
//////////////////////////////////////////////////////////////////////////////
! // primordial thread
! // 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 (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;
}
}
*** 916,926 ****
fclose(fp);
}
return false;
}
! // Locate initial thread stack. This special handling of initial 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
// JNI invocation API from a primordial thread.
void os::Linux::capture_initial_stack(size_t max_size) {
--- 917,927 ----
fclose(fp);
}
return false;
}
! // 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
// JNI invocation API from a primordial thread.
void os::Linux::capture_initial_stack(size_t max_size) {
*** 940,949 ****
--- 941,952 ----
size_t stack_size = rlim.rlim_cur;
// 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.
+ // 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.
//
// When an application is started, glibc saves the initial stack pointer in
*** 1061,1080 ****
#undef _UFM
#undef _DFM
if (i != 28 - 2) {
assert(false, "Bad conversion from /proc/self/stat");
! // product mode - assume we are the initial thread, good luck in the
// embedded case.
! warning("Can't detect initial 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");
stack_start = (uintptr_t) &rlim;
}
}
// Now we have a pointer (stack_start) very close to the stack top, the
--- 1064,1083 ----
#undef _UFM
#undef _DFM
if (i != 28 - 2) {
assert(false, "Bad conversion from /proc/self/stat");
! // product mode - assume we are the primordial thread, good luck in the
// embedded case.
! 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 primordial thread stack location - no /proc/self/stat");
stack_start = (uintptr_t) &rlim;
}
}
// Now we have a pointer (stack_start) very close to the stack top, the
*** 1090,1100 ****
// success, "high" is the true stack top. (ignore "low", because initial
// thread stack grows on demand, its real bottom is high - RLIMIT_STACK.)
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");
// 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.
stack_top = stack_start;
stack_size -= 16 * page_size();
--- 1093,1103 ----
// success, "high" is the true stack top. (ignore "low", because initial
// thread stack grows on demand, its real bottom is high - RLIMIT_STACK.)
stack_top = (uintptr_t)high;
} else {
// failed, likely because /proc/self/maps does not exist
! 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.
stack_top = stack_start;
stack_size -= 16 * page_size();
*** 3032,3045 ****
// 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
bool os::pd_create_stack_guard_pages(char* addr, size_t size) {
! if (os::Linux::is_initial_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.
// Check it first, before calling heavy function.
uintptr_t stack_extent = (uintptr_t) os::Linux::initial_thread_stack_bottom();
--- 3035,3048 ----
// 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/primordial thread
bool os::pd_create_stack_guard_pages(char* addr, size_t size) {
! 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.
// Check it first, before calling heavy function.
uintptr_t stack_extent = (uintptr_t) os::Linux::initial_thread_stack_bottom();
*** 3060,3077 ****
return os::commit_memory(addr, size, !ExecMem);
}
// 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
bool os::remove_stack_guard_pages(char* addr, size_t size) {
uintptr_t stack_extent, stack_base;
! if (os::Linux::is_initial_thread()) {
return ::munmap(addr, size) == 0;
}
return os::uncommit_memory(addr, size);
}
--- 3063,3080 ----
return os::commit_memory(addr, size, !ExecMem);
}
// 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/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::is_primordial_thread()) {
return ::munmap(addr, size) == 0;
}
return os::uncommit_memory(addr, size);
}
*** 5709,5720 ****
// of the stack size given in pthread_attr. We work around this for
// threads created by the VM. (We adapt bottom to be P1 and size accordingly.)
//
#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()
// may return bogus value.
*bottom = os::Linux::initial_thread_stack_bottom();
*size = os::Linux::initial_thread_stack_size();
} else {
pthread_attr_t attr;
--- 5712,5723 ----
// of the stack size given in pthread_attr. We work around this for
// threads created by the VM. (We adapt bottom to be P1 and size accordingly.)
//
#ifndef ZERO
static void current_stack_region(address * bottom, size_t * size) {
! 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();
} else {
pthread_attr_t attr;
< prev index next >