< prev index next >
src/hotspot/os/linux/os_linux.cpp
Print this page
@@ -798,10 +798,65 @@
os::current_thread_id(), (uintx) pthread_self());
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");
// Allocate the OSThread object
@@ -834,10 +889,13 @@
// of zero due to overflow. Don't add the guard page in that case.
size_t guard_size = os::Linux::default_guard_size(thr_type);
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);
assert_status(status == 0, status, "pthread_attr_setstacksize");
@@ -5151,10 +5209,12 @@
// Initialize data for jdk.internal.misc.Signal
if (!ReduceSignalUsage) {
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;
}
< prev index next >