--- old/src/hotspot/os/linux/os_linux.cpp 2019-05-23 15:32:21.949669363 -0700 +++ new/src/hotspot/os/linux/os_linux.cpp 2019-05-23 15:32:21.629665154 -0700 @@ -800,6 +800,61 @@ return 0; } +#ifdef __GLIBC__ +// The code below is used to figure out the size of the TLS space used +// by the main executable (DSO's TLS space is allocated separately). +// TLS variables live in the stack space allocated for each thread, so +// the function is used to automatically adjust requested stack sizes. +// This code only works with glibc since it relies on an internal symbol +// in glibc. When doing a profile collection run with FDO, the +// compiler will define several TLS variables per object file (making +// this function call frequently necessary during FDO collection). +// p_dl_get_tls_static_info is initialized in InitGetTLSSize(). +// +// The goal is to make sure that stacks have enough space for TLS. +// There is an upstream bug to make this happen in glibc: +// http://sourceware.org/bugzilla/show_bug.cgi?id=11787 +// This code can presumably be retired when that fix is available +// pervasively. +extern "C" void _dl_get_tls_static_info(size_t*, size_t*) __attribute__((weak)); + +typedef void (*GetTLSType)(size_t*, size_t*); + +GetTLSType p_dl_get_tls_static_info = NULL; + +static void InitGetTLSSize() { + // This complicated sequence is used to support both static and + // dynamic linking when using the gold linker. + // _dl_get_tls_static_info is defined in libc.a and ld-linux.so. + // When linking statically, the symbol is available. When linking + // dynamically, the symbol is *not* available because gold does not + // consider ld-linux.so to be part of the link unless explicitly + // specified. The code below uses the static symbol if available. + // If not, it will use dlsym to search for the symbol at runtime. + p_dl_get_tls_static_info = &_dl_get_tls_static_info; + if (p_dl_get_tls_static_info == NULL) { + p_dl_get_tls_static_info = + (GetTLSType)dlsym(RTLD_NEXT, "_dl_get_tls_static_info"); + } +} + +static size_t GetTLSSize() { + size_t tls_size = 0; + size_t tls_align; + + if (p_dl_get_tls_static_info) { + (*p_dl_get_tls_static_info)(&tls_size, &tls_align); + } + return tls_size; +} +#else +static void InitGetTLSSize() { +} +static size_t GetTLSSize() { + return 0; +} +#endif + bool os::create_thread(Thread* thread, ThreadType thr_type, size_t req_stack_size) { assert(thread->osthread() == NULL, "caller responsible"); @@ -836,6 +891,9 @@ if (stack_size <= SIZE_MAX - guard_size) { stack_size += guard_size; } + // Always, always, always give the user more for TLS, even if they + // haven't asked for it. + stack_size += GetTLSSize(); assert(is_aligned(stack_size, os::vm_page_size()), "stack_size not aligned"); int status = pthread_attr_setstacksize(&attr, stack_size); @@ -5153,6 +5211,8 @@ jdk_misc_signal_init(); } + InitGetTLSSize(); + // Check and sets minimum stack sizes against command line options if (Posix::set_minimum_stack_sizes() == JNI_ERR) { return JNI_ERR;