8169373: Work around linux NPTL stack guard error

Also skip libc guard page for compiler thread, merge similar code on linux platforms, and streamline libc guard page handling on linuxs390, linuxppc, aixppc.

Reviewed-by: dholmes, dcubed, kvn
This commit is contained in:
Goetz Lindenmaier 2016-11-08 16:30:36 +01:00
parent c2b261c9f5
commit c5a2c4af0e
13 changed files with 165 additions and 425 deletions

View File

@ -848,13 +848,13 @@ bool os::create_thread(Thread* thread, ThreadType thr_type,
assert(thread->osthread() == NULL, "caller responsible");
// Allocate the OSThread object
// Allocate the OSThread object.
OSThread* osthread = new OSThread(NULL, NULL);
if (osthread == NULL) {
return false;
}
// set the correct thread state
// Set the correct thread state.
osthread->set_thread_type(thr_type);
// Initial state is ALLOCATED but not INITIALIZED
@ -862,7 +862,7 @@ bool os::create_thread(Thread* thread, ThreadType thr_type,
thread->set_osthread(osthread);
// init thread attributes
// Init thread attributes.
pthread_attr_t attr;
pthread_attr_init(&attr);
guarantee(pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED) == 0, "???");
@ -871,15 +871,18 @@ bool os::create_thread(Thread* thread, ThreadType thr_type,
if (os::Aix::on_aix()) {
guarantee(pthread_attr_setscope(&attr, PTHREAD_SCOPE_SYSTEM) == 0, "???");
guarantee(pthread_attr_setinheritsched(&attr, PTHREAD_EXPLICIT_SCHED) == 0, "???");
} // end: aix
}
// Start in suspended state, and in os::thread_start, wake the thread up.
guarantee(pthread_attr_setsuspendstate_np(&attr, PTHREAD_CREATE_SUSPENDED_NP) == 0, "???");
// calculate stack size if it's not specified by caller
// Calculate stack size if it's not specified by caller.
size_t stack_size = os::Posix::get_initial_stack_size(thr_type, req_stack_size);
pthread_attr_setstacksize(&attr, stack_size);
// Configure libc guard page.
pthread_attr_setguardsize(&attr, os::Aix::default_guard_size(thr_type));
pthread_t tid;
int ret = pthread_create(&tid, &attr, (void* (*)(void*)) thread_native_entry, thread);
@ -895,7 +898,7 @@ bool os::create_thread(Thread* thread, ThreadType thr_type,
pthread_attr_destroy(&attr);
if (ret != 0) {
// Need to clean up stuff we've allocated so far
// Need to clean up stuff we've allocated so far.
thread->set_osthread(NULL);
delete osthread;
return false;
@ -3032,6 +3035,19 @@ bool os::Aix::chained_handler(int sig, siginfo_t* siginfo, void* context) {
return chained;
}
size_t os::Aix::default_guard_size(os::ThreadType thr_type) {
// Creating guard page is very expensive. Java thread has HotSpot
// guard pages, only enable glibc guard page for non-Java threads.
// (Remember: compiler thread is a Java thread, too!)
//
// Aix can have different page sizes for stack (4K) and heap (64K).
// As Hotspot knows only one page size, we assume the stack has
// the same page size as the heap. Returning page_size() here can
// cause 16 guard pages which we want to avoid. Thus we return 4K
// which will be rounded to the real page size by the OS.
return ((thr_type == java_thread || thr_type == compiler_thread) ? 0 : 4 * K);
}
struct sigaction* os::Aix::get_preinstalled_handler(int sig) {
if (sigismember(&sigs, sig)) {
return &sigact[sig];

View File

@ -140,6 +140,9 @@ class Aix {
// libpthread version string
static void libpthread_init();
// Return default libc guard size for the specified thread type.
static size_t default_guard_size(os::ThreadType thr_type);
// Function returns true if we run on OS/400 (pase), false if we run
// on AIX.
static bool on_pase() {

View File

@ -716,11 +716,18 @@ bool os::create_thread(Thread* thread, ThreadType thr_type,
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
// calculate stack size if it's not specified by caller
// Calculate stack size if it's not specified by caller.
size_t stack_size = os::Posix::get_initial_stack_size(thr_type, req_stack_size);
// In the Linux NPTL pthread implementation the guard size mechanism
// is not implemented properly. The posix standard requires adding
// the size of the guard pages to the stack size, instead Linux
// takes the space out of 'stacksize'. Thus we adapt the requested
// stack_size by the size of the guard pages to mimick proper
// behaviour.
stack_size = align_size_up(stack_size + os::Linux::default_guard_size(thr_type), vm_page_size());
pthread_attr_setstacksize(&attr, stack_size);
// glibc guard page
// Configure glibc guard page.
pthread_attr_setguardsize(&attr, os::Linux::default_guard_size(thr_type));
ThreadState state;
@ -2833,6 +2840,13 @@ bool os::Linux::libnuma_init() {
return false;
}
size_t os::Linux::default_guard_size(os::ThreadType thr_type) {
// Creating guard page is very expensive. Java thread has HotSpot
// guard pages, only enable glibc guard page for non-Java threads.
// (Remember: compiler thread is a Java thread, too!)
return ((thr_type == java_thread || thr_type == compiler_thread) ? 0 : page_size());
}
// rebuild_cpu_to_node_map() constructs a table mapping cpud id to node id.
// The table is later used in get_node_by_cpu().
void os::Linux::rebuild_cpu_to_node_map() {
@ -6065,6 +6079,101 @@ bool os::start_debugging(char *buf, int buflen) {
return yes;
}
// Java/Compiler thread:
//
// Low memory addresses
// P0 +------------------------+
// | |\ Java thread created by VM does not have glibc
// | glibc guard page | - guard page, attached Java thread usually has
// | |/ 1 glibc guard page.
// P1 +------------------------+ Thread::stack_base() - Thread::stack_size()
// | |\
// | HotSpot Guard Pages | - red, yellow and reserved pages
// | |/
// +------------------------+ JavaThread::stack_reserved_zone_base()
// | |\
// | Normal Stack | -
// | |/
// P2 +------------------------+ Thread::stack_base()
//
// Non-Java thread:
//
// Low memory addresses
// P0 +------------------------+
// | |\
// | glibc guard page | - usually 1 page
// | |/
// P1 +------------------------+ Thread::stack_base() - Thread::stack_size()
// | |\
// | Normal Stack | -
// | |/
// P2 +------------------------+ Thread::stack_base()
//
// ** P1 (aka bottom) and size (P2 = P1 - size) are the address and stack size
// returned from pthread_attr_getstack().
// ** Due to NPTL implementation error, linux takes the glibc guard page out
// 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;
int rslt = pthread_getattr_np(pthread_self(), &attr);
// JVM needs to know exact stack location, abort if it fails
if (rslt != 0) {
if (rslt == ENOMEM) {
vm_exit_out_of_memory(0, OOM_MMAP_ERROR, "pthread_getattr_np");
} else {
fatal("pthread_getattr_np failed with error = %d", rslt);
}
}
if (pthread_attr_getstack(&attr, (void **)bottom, size) != 0) {
fatal("Cannot locate current stack attributes!");
}
// Work around NPTL stack guard error.
size_t guard_size = 0;
rslt = pthread_attr_getguardsize(&attr, &guard_size);
if (rslt != 0) {
fatal("pthread_attr_getguardsize failed with error = %d", rslt);
}
*bottom += guard_size;
*size -= guard_size;
pthread_attr_destroy(&attr);
}
assert(os::current_stack_pointer() >= *bottom &&
os::current_stack_pointer() < *bottom + *size, "just checking");
}
address os::current_stack_base() {
address bottom;
size_t size;
current_stack_region(&bottom, &size);
return (bottom + size);
}
size_t os::current_stack_size() {
// This stack size includes the usable stack and HotSpot guard pages
// (for the threads that have Hotspot guard pages).
address bottom;
size_t size;
current_stack_region(&bottom, &size);
return size;
}
#endif
static inline struct timespec get_mtime(const char* filename) {
struct stat st;
int ret = os::stat(filename, &st);

View File

@ -1096,6 +1096,8 @@ char* os::Posix::describe_pthread_attr(char* buf, size_t buflen, const pthread_a
int detachstate = 0;
pthread_attr_getstacksize(attr, &stack_size);
pthread_attr_getguardsize(attr, &guard_size);
// Work around linux NPTL implementation error, see also os::create_thread() in os_linux.cpp.
LINUX_ONLY(stack_size -= guard_size);
pthread_attr_getdetachstate(attr, &detachstate);
jio_snprintf(buf, buflen, "stacksize: " SIZE_FORMAT "k, guardsize: " SIZE_FORMAT "k, %s",
stack_size / 1024, guard_size / 1024,

View File

@ -535,13 +535,15 @@ void os::Aix::init_thread_fpu_state(void) {
////////////////////////////////////////////////////////////////////////////////
// thread stack
size_t os::Posix::_compiler_thread_min_stack_allowed = 128 * K;
size_t os::Posix::_java_thread_min_stack_allowed = 128 * K;
// These sizes exclude libc stack guard pages, but include
// the HotSpot guard pages.
size_t os::Posix::_compiler_thread_min_stack_allowed = 512 * K;
size_t os::Posix::_java_thread_min_stack_allowed = 512 * K;
size_t os::Posix::_vm_internal_thread_min_stack_allowed = 128 * K;
// return default stack size for thr_type
// Return default stack size for thr_type.
size_t os::Posix::default_stack_size(os::ThreadType thr_type) {
// default stack size (compiler thread needs larger stack)
// Default stack size (compiler thread needs larger stack).
size_t s = (thr_type == os::compiler_thread ? 4 * M : 1 * M);
return s;
}

View File

@ -870,14 +870,14 @@ size_t os::Posix::default_stack_size(os::ThreadType thr_type) {
//
// Low memory addresses
// +------------------------+
// | |\ JavaThread created by VM does not have glibc
// | |\ Java thread created by VM does not have glibc
// | glibc guard page | - guard, attached Java thread usually has
// | |/ 1 page glibc guard.
// | |/ 1 glibc guard page.
// P1 +------------------------+ Thread::stack_base() - Thread::stack_size()
// | |\
// | HotSpot Guard Pages | - red and yellow pages
// | HotSpot Guard Pages | - red, yellow and reserved pages
// | |/
// +------------------------+ JavaThread::stack_yellow_zone_base()
// +------------------------+ JavaThread::stack_reserved_zone_base()
// | |\
// | Normal Stack | -
// | |/
@ -925,7 +925,7 @@ static void current_stack_region(address * bottom, size_t * size) {
int rslt = pthread_stackseg_np(pthread_self(), &ss);
if (rslt != 0)
fatal("pthread_stackseg_np failed with err = %d", rslt);
fatal("pthread_stackseg_np failed with error = %d", rslt);
*bottom = (address)((char *)ss.ss_sp - ss.ss_size);
*size = ss.ss_size;
@ -936,12 +936,12 @@ static void current_stack_region(address * bottom, size_t * size) {
// JVM needs to know exact stack location, abort if it fails
if (rslt != 0)
fatal("pthread_attr_init failed with err = %d", rslt);
fatal("pthread_attr_init failed with error = %d", rslt);
rslt = pthread_attr_get_np(pthread_self(), &attr);
if (rslt != 0)
fatal("pthread_attr_get_np failed with err = %d", rslt);
fatal("pthread_attr_get_np failed with error = %d", rslt);
if (pthread_attr_getstackaddr(&attr, (void **)bottom) != 0 ||
pthread_attr_getstacksize(&attr, size) != 0) {

View File

@ -310,7 +310,7 @@ static void current_stack_region(address *bottom, size_t *size) {
int rslt = pthread_stackseg_np(pthread_self(), &ss);
if (rslt != 0)
fatal("pthread_stackseg_np failed with err = " INT32_FORMAT, rslt);
fatal("pthread_stackseg_np failed with error = " INT32_FORMAT, rslt);
stack_top = (address) ss.ss_sp;
stack_bytes = ss.ss_size;
@ -322,12 +322,12 @@ static void current_stack_region(address *bottom, size_t *size) {
// JVM needs to know exact stack location, abort if it fails
if (rslt != 0)
fatal("pthread_attr_init failed with err = " INT32_FORMAT, rslt);
fatal("pthread_attr_init failed with error = " INT32_FORMAT, rslt);
rslt = pthread_attr_get_np(pthread_self(), &attr);
if (rslt != 0)
fatal("pthread_attr_get_np failed with err = " INT32_FORMAT, rslt);
fatal("pthread_attr_get_np failed with error = " INT32_FORMAT, rslt);
if (pthread_attr_getstackaddr(&attr, (void **) &stack_bottom) != 0 ||
pthread_attr_getstacksize(&attr, &stack_bytes) != 0) {

View File

@ -484,91 +484,6 @@ size_t os::Posix::default_stack_size(os::ThreadType thr_type) {
return s;
}
size_t os::Linux::default_guard_size(os::ThreadType thr_type) {
// Creating guard page is very expensive. Java thread has HotSpot
// guard page, only enable glibc guard page for non-Java threads.
return (thr_type == java_thread ? 0 : page_size());
}
// Java thread:
//
// Low memory addresses
// +------------------------+
// | |\ JavaThread created by VM does not have glibc
// | glibc guard page | - guard, attached Java thread usually has
// | |/ 1 page glibc guard.
// P1 +------------------------+ Thread::stack_base() - Thread::stack_size()
// | |\
// | HotSpot Guard Pages | - red and yellow pages
// | |/
// +------------------------+ JavaThread::stack_yellow_zone_base()
// | |\
// | Normal Stack | -
// | |/
// P2 +------------------------+ Thread::stack_base()
//
// Non-Java thread:
//
// Low memory addresses
// +------------------------+
// | |\
// | glibc guard page | - usually 1 page
// | |/
// P1 +------------------------+ Thread::stack_base() - Thread::stack_size()
// | |\
// | Normal Stack | -
// | |/
// P2 +------------------------+ Thread::stack_base()
//
// ** P1 (aka bottom) and size ( P2 = P1 - size) are the address and stack size returned from
// pthread_attr_getstack()
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;
int rslt = pthread_getattr_np(pthread_self(), &attr);
// JVM needs to know exact stack location, abort if it fails
if (rslt != 0) {
if (rslt == ENOMEM) {
vm_exit_out_of_memory(0, OOM_MMAP_ERROR, "pthread_getattr_np");
} else {
fatal("pthread_getattr_np failed with errno = %d", rslt);
}
}
if (pthread_attr_getstack(&attr, (void **)bottom, size) != 0) {
fatal("Can not locate current stack attributes!");
}
pthread_attr_destroy(&attr);
}
assert(os::current_stack_pointer() >= *bottom &&
os::current_stack_pointer() < *bottom + *size, "just checking");
}
address os::current_stack_base() {
address bottom;
size_t size;
current_stack_region(&bottom, &size);
return (bottom + size);
}
size_t os::current_stack_size() {
// stack size includes normal stack and HotSpot guard pages
address bottom;
size_t size;
current_stack_region(&bottom, &size);
return size;
}
/////////////////////////////////////////////////////////////////////////////
// helper functions for fatal error handler

View File

@ -535,8 +535,10 @@ void os::Linux::set_fpu_control_word(int fpu_control) {
////////////////////////////////////////////////////////////////////////////////
// thread stack
size_t os::Posix::_compiler_thread_min_stack_allowed = 128 * K;
size_t os::Posix::_java_thread_min_stack_allowed = 128 * K;
// These sizes exclude libc stack guard pages, but include
// the HotSpot guard pages.
size_t os::Posix::_compiler_thread_min_stack_allowed = 384 * K;
size_t os::Posix::_java_thread_min_stack_allowed = 384 * K;
size_t os::Posix::_vm_internal_thread_min_stack_allowed = 128 * K;
// return default stack size for thr_type
@ -546,89 +548,6 @@ size_t os::Posix::default_stack_size(os::ThreadType thr_type) {
return s;
}
size_t os::Linux::default_guard_size(os::ThreadType thr_type) {
return 2 * page_size();
}
// Java thread:
//
// Low memory addresses
// +------------------------+
// | |\ JavaThread created by VM does not have glibc
// | glibc guard page | - guard, attached Java thread usually has
// | |/ 1 page glibc guard.
// P1 +------------------------+ Thread::stack_base() - Thread::stack_size()
// | |\
// | HotSpot Guard Pages | - red and yellow pages
// | |/
// +------------------------+ JavaThread::stack_yellow_zone_base()
// | |\
// | Normal Stack | -
// | |/
// P2 +------------------------+ Thread::stack_base()
//
// Non-Java thread:
//
// Low memory addresses
// +------------------------+
// | |\
// | glibc guard page | - usually 1 page
// | |/
// P1 +------------------------+ Thread::stack_base() - Thread::stack_size()
// | |\
// | Normal Stack | -
// | |/
// P2 +------------------------+ Thread::stack_base()
//
// ** P1 (aka bottom) and size ( P2 = P1 - size) are the address and stack size returned from
// pthread_attr_getstack()
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;
int rslt = pthread_getattr_np(pthread_self(), &attr);
// JVM needs to know exact stack location, abort if it fails
if (rslt != 0) {
if (rslt == ENOMEM) {
vm_exit_out_of_memory(0, OOM_MMAP_ERROR, "pthread_getattr_np");
} else {
fatal("pthread_getattr_np failed with errno = %d", rslt);
}
}
if (pthread_attr_getstack(&attr, (void **)bottom, size) != 0) {
fatal("Can not locate current stack attributes!");
}
pthread_attr_destroy(&attr);
}
assert(os::current_stack_pointer() >= *bottom &&
os::current_stack_pointer() < *bottom + *size, "just checking");
}
address os::current_stack_base() {
address bottom;
size_t size;
current_stack_region(&bottom, &size);
return (bottom + size);
}
size_t os::current_stack_size() {
// stack size includes normal stack and HotSpot guard pages
address bottom;
size_t size;
current_stack_region(&bottom, &size);
return size;
}
/////////////////////////////////////////////////////////////////////////////
// helper functions for fatal error handler

View File

@ -473,103 +473,19 @@ void os::Linux::set_fpu_control_word(int fpu_control) {
////////////////////////////////////////////////////////////////////////////////
// thread stack
// These sizes exclude libc stack guard pages, but include
// the HotSpot guard pages.
size_t os::Posix::_compiler_thread_min_stack_allowed = 128 * K;
size_t os::Posix::_java_thread_min_stack_allowed = 128 * K;
size_t os::Posix::_java_thread_min_stack_allowed = 236 * K;
size_t os::Posix::_vm_internal_thread_min_stack_allowed = 128 * K;
// return default stack size for thr_type
// Return default stack size for thr_type.
size_t os::Posix::default_stack_size(os::ThreadType thr_type) {
// default stack size (compiler thread needs larger stack)
// Default stack size (compiler thread needs larger stack).
size_t s = (thr_type == os::compiler_thread ? 4 * M : 1024 * K);
return s;
}
size_t os::Linux::default_guard_size(os::ThreadType thr_type) {
// z/Architecture: put 2 guard pages right in the middle of thread stack. This value
// should be consistent with the value used by register stack handling code.
return 2 * page_size();
}
// Java thread:
//
// Low memory addresses
// +------------------------+
// | |\
// | glibc guard page | - Right in the middle of stack, 2 pages
// | |/
// P1 +------------------------+ Thread::stack_base() - Thread::stack_size()
// | |\
// | HotSpot Guard Pages | - red and yellow pages
// | |/
// +------------------------+ JavaThread::stack_yellow_zone_base()
// | |\
// | Normal Stack | -
// | |/
// P2 +------------------------+ Thread::stack_base()
//
// Non-Java thread:
//
// Low memory addresses
// +------------------------+
// | |\
// | glibc guard page | - Right in the middle of stack, 2 pages
// | |/
// P1 +------------------------+ Thread::stack_base() - Thread::stack_size()
// | |\
// | Normal Stack | -
// | |/
// P2 +------------------------+ Thread::stack_base()
//
// ** P2 is the address returned from pthread_attr_getstackaddr(), P2 - P1
// is the stack size returned by pthread_attr_getstacksize().
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;
int rslt = pthread_getattr_np(pthread_self(), &attr);
// JVM needs to know exact stack location, abort if it fails
if (rslt != 0) {
if (rslt == ENOMEM) {
vm_exit_out_of_memory(0, OOM_MMAP_ERROR, "pthread_getattr_np");
} else {
fatal("pthread_getattr_np failed with errno = %d", rslt);
}
}
if (pthread_attr_getstack(&attr, (void **)bottom, size) != 0) {
fatal("Can not locate current stack attributes!");
}
pthread_attr_destroy(&attr);
}
assert(os::current_stack_pointer() >= *bottom &&
os::current_stack_pointer() < *bottom + *size, "just checking");
}
address os::current_stack_base() {
address bottom;
size_t size;
current_stack_region(&bottom, &size);
return (bottom + size);
}
size_t os::current_stack_size() {
// stack size includes normal stack and HotSpot guard pages
address bottom;
size_t size;
current_stack_region(&bottom, &size);
return size;
}
/////////////////////////////////////////////////////////////////////////////
// helper functions for fatal error handler

View File

@ -156,51 +156,6 @@ address os::current_stack_pointer() {
return (address)sp;
}
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;
int rslt = pthread_getattr_np(pthread_self(), &attr);
// JVM needs to know exact stack location, abort if it fails
if (rslt != 0) {
if (rslt == ENOMEM) {
vm_exit_out_of_memory(0, OOM_MMAP_ERROR, "pthread_getattr_np");
} else {
fatal("pthread_getattr_np failed with errno = %d", rslt);
}
}
if (pthread_attr_getstack(&attr, (void**)bottom, size) != 0) {
fatal("Can not locate current stack attributes!");
}
pthread_attr_destroy(&attr);
}
assert(os::current_stack_pointer() >= *bottom &&
os::current_stack_pointer() < *bottom + *size, "just checking");
}
address os::current_stack_base() {
address bottom;
size_t size;
current_stack_region(&bottom, &size);
return bottom + size;
}
size_t os::current_stack_size() {
// stack size includes normal stack and HotSpot guard pages
address bottom;
size_t size;
current_stack_region(&bottom, &size);
return size;
}
char* os::non_memory_address_word() {
// Must never look like an address returned by reserve_memory,
// even in its subfields (as defined by the CPU immediate fields,
@ -737,12 +692,6 @@ size_t os::Posix::default_stack_size(os::ThreadType thr_type) {
return s;
}
size_t os::Linux::default_guard_size(os::ThreadType thr_type) {
// Creating guard page is very expensive. Java thread has HotSpot
// guard page, only enable glibc guard page for non-Java threads.
return (thr_type == java_thread ? 0 : page_size());
}
#ifndef PRODUCT
void os::verify_stack_alignment() {
}

View File

@ -698,91 +698,6 @@ size_t os::Posix::default_stack_size(os::ThreadType thr_type) {
return s;
}
size_t os::Linux::default_guard_size(os::ThreadType thr_type) {
// Creating guard page is very expensive. Java thread has HotSpot
// guard page, only enable glibc guard page for non-Java threads.
return (thr_type == java_thread ? 0 : page_size());
}
// Java thread:
//
// Low memory addresses
// +------------------------+
// | |\ JavaThread created by VM does not have glibc
// | glibc guard page | - guard, attached Java thread usually has
// | |/ 1 page glibc guard.
// P1 +------------------------+ Thread::stack_base() - Thread::stack_size()
// | |\
// | HotSpot Guard Pages | - red and yellow pages
// | |/
// +------------------------+ JavaThread::stack_yellow_zone_base()
// | |\
// | Normal Stack | -
// | |/
// P2 +------------------------+ Thread::stack_base()
//
// Non-Java thread:
//
// Low memory addresses
// +------------------------+
// | |\
// | glibc guard page | - usually 1 page
// | |/
// P1 +------------------------+ Thread::stack_base() - Thread::stack_size()
// | |\
// | Normal Stack | -
// | |/
// P2 +------------------------+ Thread::stack_base()
//
// ** P1 (aka bottom) and size ( P2 = P1 - size) are the address and stack size returned from
// pthread_attr_getstack()
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;
int rslt = pthread_getattr_np(pthread_self(), &attr);
// JVM needs to know exact stack location, abort if it fails
if (rslt != 0) {
if (rslt == ENOMEM) {
vm_exit_out_of_memory(0, OOM_MMAP_ERROR, "pthread_getattr_np");
} else {
fatal("pthread_getattr_np failed with errno = %d", rslt);
}
}
if (pthread_attr_getstack(&attr, (void **)bottom, size) != 0) {
fatal("Can not locate current stack attributes!");
}
pthread_attr_destroy(&attr);
}
assert(os::current_stack_pointer() >= *bottom &&
os::current_stack_pointer() < *bottom + *size, "just checking");
}
address os::current_stack_base() {
address bottom;
size_t size;
current_stack_region(&bottom, &size);
return (bottom + size);
}
size_t os::current_stack_size() {
// stack size includes normal stack and HotSpot guard pages
address bottom;
size_t size;
current_stack_region(&bottom, &size);
return size;
}
/////////////////////////////////////////////////////////////////////////////
// helper functions for fatal error handler

View File

@ -320,12 +320,6 @@ size_t os::Posix::default_stack_size(os::ThreadType thr_type) {
return s;
}
size_t os::Linux::default_guard_size(os::ThreadType thr_type) {
// Only enable glibc guard pages for non-Java threads
// (Java threads have HotSpot guard pages)
return (thr_type == java_thread ? 0 : page_size());
}
static void current_stack_region(address *bottom, size_t *size) {
pthread_attr_t attr;
int res = pthread_getattr_np(pthread_self(), &attr);
@ -334,7 +328,7 @@ static void current_stack_region(address *bottom, size_t *size) {
vm_exit_out_of_memory(0, OOM_MMAP_ERROR, "pthread_getattr_np");
}
else {
fatal("pthread_getattr_np failed with errno = %d", res);
fatal("pthread_getattr_np failed with error = %d", res);
}
}
@ -342,7 +336,7 @@ static void current_stack_region(address *bottom, size_t *size) {
size_t stack_bytes;
res = pthread_attr_getstack(&attr, (void **) &stack_bottom, &stack_bytes);
if (res != 0) {
fatal("pthread_attr_getstack failed with errno = %d", res);
fatal("pthread_attr_getstack failed with error = %d", res);
}
address stack_top = stack_bottom + stack_bytes;