# HG changeset patch # User goetz # Date 1478619036 -3600 # Node ID 83eaa65c355f9f14a369ba529f42e099ba73754d # Parent cfd9e8c96d1d636a38bb02591920af140de93d42 8169373: Work around linux NPTL stack guard error. Summary: Also streamline OS guard page handling on linuxs390, linuxppc, aixppc. diff --git a/src/os/aix/vm/os_aix.cpp b/src/os/aix/vm/os_aix.cpp --- a/src/os/aix/vm/os_aix.cpp +++ b/src/os/aix/vm/os_aix.cpp @@ -852,13 +852,13 @@ 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 @@ -866,7 +866,7 @@ 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, "???"); @@ -875,15 +875,18 @@ 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); + // 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); @@ -899,7 +902,7 @@ 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; diff --git a/src/os/aix/vm/os_aix.hpp b/src/os/aix/vm/os_aix.hpp --- a/src/os/aix/vm/os_aix.hpp +++ b/src/os/aix/vm/os_aix.hpp @@ -140,6 +140,9 @@ // libpthread version string static void libpthread_init(); + // Return default OS 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() { diff --git a/src/os/linux/vm/os_linux.cpp b/src/os/linux/vm/os_linux.cpp --- a/src/os/linux/vm/os_linux.cpp +++ b/src/os/linux/vm/os_linux.cpp @@ -723,8 +723,15 @@ 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 to add + // 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 diff --git a/src/os/posix/vm/os_posix.cpp b/src/os/posix/vm/os_posix.cpp --- a/src/os/posix/vm/os_posix.cpp +++ b/src/os/posix/vm/os_posix.cpp @@ -1096,6 +1096,8 @@ 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, diff --git a/src/os_cpu/aix_ppc/vm/os_aix_ppc.cpp b/src/os_cpu/aix_ppc/vm/os_aix_ppc.cpp --- a/src/os_cpu/aix_ppc/vm/os_aix_ppc.cpp +++ b/src/os_cpu/aix_ppc/vm/os_aix_ppc.cpp @@ -535,17 +535,31 @@ //////////////////////////////////////////////////////////////////////////////// // thread stack +// These sizes exclude OS stack guard pages, but include +// the VM 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::_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; } +size_t os::Aix::default_guard_size(os::ThreadType thr_type) { + // Creating guard pages is very expensive. Java thread has HotSpot + // guard pages, so only enable libc guard pages for non-Java threads. + // + // 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 ? 0 : 4*K); +} + ///////////////////////////////////////////////////////////////////////////// // helper functions for fatal error handler diff --git a/src/os_cpu/linux_aarch64/vm/os_linux_aarch64.cpp b/src/os_cpu/linux_aarch64/vm/os_linux_aarch64.cpp --- a/src/os_cpu/linux_aarch64/vm/os_linux_aarch64.cpp +++ b/src/os_cpu/linux_aarch64/vm/os_linux_aarch64.cpp @@ -525,30 +525,36 @@ 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(); + // 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); - + 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!"); + } + + // Work around NPTL stack guard error. + size_t guard_size = 0; + pthread_attr_getguardsize(&attr, &guard_size); + *bottom += guard_size; + *size -= guard_size; + + pthread_attr_destroy(&attr); + } assert(os::current_stack_pointer() >= *bottom && os::current_stack_pointer() < *bottom + *size, "just checking"); diff --git a/src/os_cpu/linux_ppc/vm/os_linux_ppc.cpp b/src/os_cpu/linux_ppc/vm/os_linux_ppc.cpp --- a/src/os_cpu/linux_ppc/vm/os_linux_ppc.cpp +++ b/src/os_cpu/linux_ppc/vm/os_linux_ppc.cpp @@ -547,7 +547,9 @@ } size_t os::Linux::default_guard_size(os::ThreadType thr_type) { - return 2 * page_size(); + // 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: @@ -607,6 +609,12 @@ fatal("Can not locate current stack attributes!"); } + // Work around NPTL stack guard error. + size_t guard_size = 0; + pthread_attr_getguardsize(&attr, &guard_size); + *bottom += guard_size; + *size -= guard_size; + pthread_attr_destroy(&attr); } diff --git a/src/os_cpu/linux_s390/vm/os_linux_s390.cpp b/src/os_cpu/linux_s390/vm/os_linux_s390.cpp --- a/src/os_cpu/linux_s390/vm/os_linux_s390.cpp +++ b/src/os_cpu/linux_s390/vm/os_linux_s390.cpp @@ -473,21 +473,23 @@ //////////////////////////////////////////////////////////////////////////////// // thread stack +// These sizes exclude OS stack guard pages, but include +// the VM 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::_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(); + // 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: @@ -547,6 +549,12 @@ if (pthread_attr_getstack(&attr, (void **)bottom, size) != 0) { fatal("Can not locate current stack attributes!"); } + + // Work around NPTL stack guard error. + size_t guard_size = 0; + pthread_attr_getguardsize(&attr, &guard_size); + *bottom += guard_size; + *size -= guard_size; pthread_attr_destroy(&attr); diff --git a/src/os_cpu/linux_sparc/vm/os_linux_sparc.cpp b/src/os_cpu/linux_sparc/vm/os_linux_sparc.cpp --- a/src/os_cpu/linux_sparc/vm/os_linux_sparc.cpp +++ b/src/os_cpu/linux_sparc/vm/os_linux_sparc.cpp @@ -179,6 +179,12 @@ if (pthread_attr_getstack(&attr, (void**)bottom, size) != 0) { fatal("Can not locate current stack attributes!"); } + + // Work around NPTL stack guard error. + size_t guard_size = 0; + pthread_attr_getguardsize(&attr, &guard_size); + *bottom += guard_size; + *size -= guard_size; pthread_attr_destroy(&attr); } diff --git a/src/os_cpu/linux_x86/vm/os_linux_x86.cpp b/src/os_cpu/linux_x86/vm/os_linux_x86.cpp --- a/src/os_cpu/linux_x86/vm/os_linux_x86.cpp +++ b/src/os_cpu/linux_x86/vm/os_linux_x86.cpp @@ -739,29 +739,35 @@ 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(); + // 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; + pthread_attr_t attr; - int rslt = pthread_getattr_np(pthread_self(), &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); - } - } + // 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!"); - } + if (pthread_attr_getstack(&attr, (void **)bottom, size) != 0) { + fatal("Can not locate current stack attributes!"); + } - pthread_attr_destroy(&attr); + // Work around NPTL stack guard error. + size_t guard_size = 0; + pthread_attr_getguardsize(&attr, &guard_size); + *bottom += guard_size; + *size -= guard_size; + + pthread_attr_destroy(&attr); } assert(os::current_stack_pointer() >= *bottom &&