< 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 >