8212173: Thread._stack_base/_stack_size initialized too late for new threads
authorstuefe
Fri, 19 Oct 2018 09:39:29 +0200
changeset 52302 912b79d983d9
parent 52301 fbfcdc5bf694
child 52303 91a57277c419
8212173: Thread._stack_base/_stack_size initialized too late for new threads Reviewed-by: dholmes, simonis
src/hotspot/os/aix/os_aix.cpp
src/hotspot/os/bsd/os_bsd.cpp
src/hotspot/os/linux/os_linux.cpp
src/hotspot/os/solaris/os_solaris.cpp
src/hotspot/os/solaris/os_solaris.hpp
src/hotspot/os/windows/os_windows.cpp
src/hotspot/os_cpu/aix_ppc/os_aix_ppc.cpp
src/hotspot/os_cpu/bsd_x86/os_bsd_x86.cpp
src/hotspot/os_cpu/bsd_zero/os_bsd_zero.cpp
src/hotspot/os_cpu/linux_aarch64/os_linux_aarch64.cpp
src/hotspot/os_cpu/linux_arm/os_linux_arm.cpp
src/hotspot/os_cpu/linux_ppc/os_linux_ppc.cpp
src/hotspot/os_cpu/linux_s390/os_linux_s390.cpp
src/hotspot/os_cpu/linux_sparc/os_linux_sparc.cpp
src/hotspot/os_cpu/linux_x86/os_linux_x86.cpp
src/hotspot/os_cpu/linux_zero/os_linux_zero.cpp
src/hotspot/os_cpu/windows_x86/os_windows_x86.cpp
src/hotspot/share/gc/parallel/gcTaskThread.cpp
src/hotspot/share/gc/shared/concurrentGCThread.cpp
src/hotspot/share/gc/shared/workgroup.cpp
src/hotspot/share/jfr/periodic/sampling/jfrThreadSampler.cpp
src/hotspot/share/prims/jni.cpp
src/hotspot/share/runtime/os.hpp
src/hotspot/share/runtime/thread.cpp
src/hotspot/share/runtime/thread.hpp
src/hotspot/share/runtime/vmThread.cpp
--- a/src/hotspot/os/aix/os_aix.cpp	Fri Oct 26 08:23:52 2018 -0400
+++ b/src/hotspot/os/aix/os_aix.cpp	Fri Oct 19 09:39:29 2018 +0200
@@ -776,12 +776,7 @@
 // Thread start routine for all newly created threads
 static void *thread_native_entry(Thread *thread) {
 
-  // find out my own stack dimensions
-  {
-    // actually, this should do exactly the same as thread->record_stack_base_and_size...
-    thread->set_stack_base(os::current_stack_base());
-    thread->set_stack_size(os::current_stack_size());
-  }
+  thread->record_stack_base_and_size();
 
   const pthread_t pthread_id = ::pthread_self();
   const tid_t kernel_thread_id = ::thread_self();
@@ -834,20 +829,15 @@
   assert(osthread->get_state() == RUNNABLE, "invalid os thread state");
 
   // Call one more level start routine.
-  thread->run();
+  thread->call_run();
+
+  // Note: at this point the thread object may already have deleted itself.
+  // Prevent dereferencing it from here on out.
+  thread = NULL;
 
   log_info(os, thread)("Thread finished (tid: " UINTX_FORMAT ", kernel thread id: " UINTX_FORMAT ").",
     os::current_thread_id(), (uintx) kernel_thread_id);
 
-  // If a thread has not deleted itself ("delete this") as part of its
-  // termination sequence, we have to ensure thread-local-storage is
-  // cleared before we actually terminate. No threads should ever be
-  // deleted asynchronously with respect to their termination.
-  if (Thread::current_or_null_safe() != NULL) {
-    assert(Thread::current_or_null_safe() == thread, "current thread is wrong");
-    thread->clear_thread_current();
-  }
-
   return 0;
 }
 
--- a/src/hotspot/os/bsd/os_bsd.cpp	Fri Oct 26 08:23:52 2018 -0400
+++ b/src/hotspot/os/bsd/os_bsd.cpp	Fri Oct 19 09:39:29 2018 +0200
@@ -644,6 +644,9 @@
 
 // Thread start routine for all newly created threads
 static void *thread_native_entry(Thread *thread) {
+
+  thread->record_stack_base_and_size();
+
   // Try to randomize the cache line index of hot stack frames.
   // This helps when threads of the same stack traces evict each other's
   // cache lines. The threads can be either from the same JVM instance, or
@@ -696,20 +699,15 @@
   }
 
   // call one more level start routine
-  thread->run();
+  thread->call_run();
+
+  // Note: at this point the thread object may already have deleted itself.
+  // Prevent dereferencing it from here on out.
+  thread = NULL;
 
   log_info(os, thread)("Thread finished (tid: " UINTX_FORMAT ", pthread id: " UINTX_FORMAT ").",
     os::current_thread_id(), (uintx) pthread_self());
 
-  // If a thread has not deleted itself ("delete this") as part of its
-  // termination sequence, we have to ensure thread-local-storage is
-  // cleared before we actually terminate. No threads should ever be
-  // deleted asynchronously with respect to their termination.
-  if (Thread::current_or_null_safe() != NULL) {
-    assert(Thread::current_or_null_safe() == thread, "current thread is wrong");
-    thread->clear_thread_current();
-  }
-
   return 0;
 }
 
--- a/src/hotspot/os/linux/os_linux.cpp	Fri Oct 26 08:23:52 2018 -0400
+++ b/src/hotspot/os/linux/os_linux.cpp	Fri Oct 19 09:39:29 2018 +0200
@@ -649,6 +649,9 @@
 
 // Thread start routine for all newly created threads
 static void *thread_native_entry(Thread *thread) {
+
+  thread->record_stack_base_and_size();
+
   // Try to randomize the cache line index of hot stack frames.
   // This helps when threads of the same stack traces evict each other's
   // cache lines. The threads can be either from the same JVM instance, or
@@ -695,20 +698,15 @@
   }
 
   // call one more level start routine
-  thread->run();
+  thread->call_run();
+
+  // Note: at this point the thread object may already have deleted itself.
+  // Prevent dereferencing it from here on out.
+  thread = NULL;
 
   log_info(os, thread)("Thread finished (tid: " UINTX_FORMAT ", pthread id: " UINTX_FORMAT ").",
     os::current_thread_id(), (uintx) pthread_self());
 
-  // If a thread has not deleted itself ("delete this") as part of its
-  // termination sequence, we have to ensure thread-local-storage is
-  // cleared before we actually terminate. No threads should ever be
-  // deleted asynchronously with respect to their termination.
-  if (Thread::current_or_null_safe() != NULL) {
-    assert(Thread::current_or_null_safe() == thread, "current thread is wrong");
-    thread->clear_thread_current();
-  }
-
   return 0;
 }
 
--- a/src/hotspot/os/solaris/os_solaris.cpp	Fri Oct 26 08:23:52 2018 -0400
+++ b/src/hotspot/os/solaris/os_solaris.cpp	Fri Oct 19 09:39:29 2018 +0200
@@ -199,6 +199,10 @@
   return st;
 }
 
+static void _handle_uncaught_cxx_exception() {
+  VMError::report_and_die("An uncaught C++ exception");
+}
+
 bool os::is_primordial_thread(void) {
   int r = thr_main();
   guarantee(r == 0 || r == 1, "CR6501650 or CR6493689");
@@ -724,6 +728,11 @@
 
 // Thread start routine for all newly created threads
 extern "C" void* thread_native_entry(void* thread_addr) {
+
+  Thread* thread = (Thread*)thread_addr;
+
+  thread->record_stack_base_and_size();
+
   // Try to randomize the cache line index of hot stack frames.
   // This helps when threads of the same stack traces evict each other's
   // cache lines. The threads can be either from the same JVM instance, or
@@ -734,7 +743,6 @@
   alloca(((pid ^ counter++) & 7) * 128);
 
   int prio;
-  Thread* thread = (Thread*)thread_addr;
 
   thread->initialize_thread_current();
 
@@ -775,7 +783,13 @@
   // initialize signal mask for this thread
   os::Solaris::hotspot_sigmask(thread);
 
-  thread->run();
+  os::Solaris::init_thread_fpu_state();
+  std::set_terminate(_handle_uncaught_cxx_exception);
+
+  thread->call_run();
+
+  // Note: at this point the thread object may already have deleted itself.
+  // Do not dereference it from here on out.
 
   // One less thread is executing
   // When the VMThread gets here, the main thread may have already exited
@@ -786,15 +800,6 @@
 
   log_info(os, thread)("Thread finished (tid: " UINTX_FORMAT ").", os::current_thread_id());
 
-  // If a thread has not deleted itself ("delete this") as part of its
-  // termination sequence, we have to ensure thread-local-storage is
-  // cleared before we actually terminate. No threads should ever be
-  // deleted asynchronously with respect to their termination.
-  if (Thread::current_or_null_safe() != NULL) {
-    assert(Thread::current_or_null_safe() == thread, "current thread is wrong");
-    thread->clear_thread_current();
-  }
-
   if (UseDetachedThreads) {
     thr_exit(NULL);
     ShouldNotReachHere();
@@ -1090,67 +1095,58 @@
   return &vm_sigs;
 }
 
-void _handle_uncaught_cxx_exception() {
-  VMError::report_and_die("An uncaught C++ exception");
-}
-
-
-// First crack at OS-specific initialization, from inside the new thread.
-void os::initialize_thread(Thread* thr) {
-  if (is_primordial_thread()) {
-    JavaThread* jt = (JavaThread *)thr;
-    assert(jt != NULL, "Sanity check");
-    size_t stack_size;
-    address base = jt->stack_base();
-    if (Arguments::created_by_java_launcher()) {
-      // Use 2MB to allow for Solaris 7 64 bit mode.
-      stack_size = JavaThread::stack_size_at_create() == 0
-        ? 2048*K : JavaThread::stack_size_at_create();
-
-      // There are rare cases when we may have already used more than
-      // the basic stack size allotment before this method is invoked.
-      // Attempt to allow for a normally sized java_stack.
-      size_t current_stack_offset = (size_t)(base - (address)&stack_size);
-      stack_size += ReservedSpace::page_align_size_down(current_stack_offset);
-    } else {
-      // 6269555: If we were not created by a Java launcher, i.e. if we are
-      // running embedded in a native application, treat the primordial thread
-      // as much like a native attached thread as possible.  This means using
-      // the current stack size from thr_stksegment(), unless it is too large
-      // to reliably setup guard pages.  A reasonable max size is 8MB.
-      size_t current_size = current_stack_size();
-      // This should never happen, but just in case....
-      if (current_size == 0) current_size = 2 * K * K;
-      stack_size = current_size > (8 * K * K) ? (8 * K * K) : current_size;
-    }
-    address bottom = align_up(base - stack_size, os::vm_page_size());;
-    stack_size = (size_t)(base - bottom);
-
-    assert(stack_size > 0, "Stack size calculation problem");
-
-    if (stack_size > jt->stack_size()) {
+// CR 7190089: on Solaris, primordial thread's stack needs adjusting.
+// Without the adjustment, stack size is incorrect if stack is set to unlimited (ulimit -s unlimited).
+void os::Solaris::correct_stack_boundaries_for_primordial_thread(Thread* thr) {
+  assert(is_primordial_thread(), "Call only for primordial thread");
+
+  JavaThread* jt = (JavaThread *)thr;
+  assert(jt != NULL, "Sanity check");
+  size_t stack_size;
+  address base = jt->stack_base();
+  if (Arguments::created_by_java_launcher()) {
+    // Use 2MB to allow for Solaris 7 64 bit mode.
+    stack_size = JavaThread::stack_size_at_create() == 0
+      ? 2048*K : JavaThread::stack_size_at_create();
+
+    // There are rare cases when we may have already used more than
+    // the basic stack size allotment before this method is invoked.
+    // Attempt to allow for a normally sized java_stack.
+    size_t current_stack_offset = (size_t)(base - (address)&stack_size);
+    stack_size += ReservedSpace::page_align_size_down(current_stack_offset);
+  } else {
+    // 6269555: If we were not created by a Java launcher, i.e. if we are
+    // running embedded in a native application, treat the primordial thread
+    // as much like a native attached thread as possible.  This means using
+    // the current stack size from thr_stksegment(), unless it is too large
+    // to reliably setup guard pages.  A reasonable max size is 8MB.
+    size_t current_size = os::current_stack_size();
+    // This should never happen, but just in case....
+    if (current_size == 0) current_size = 2 * K * K;
+    stack_size = current_size > (8 * K * K) ? (8 * K * K) : current_size;
+  }
+  address bottom = align_up(base - stack_size, os::vm_page_size());;
+  stack_size = (size_t)(base - bottom);
+
+  assert(stack_size > 0, "Stack size calculation problem");
+
+  if (stack_size > jt->stack_size()) {
 #ifndef PRODUCT
-      struct rlimit limits;
-      getrlimit(RLIMIT_STACK, &limits);
-      size_t size = adjust_stack_size(base, (size_t)limits.rlim_cur);
-      assert(size >= jt->stack_size(), "Stack size problem in main thread");
+    struct rlimit limits;
+    getrlimit(RLIMIT_STACK, &limits);
+    size_t size = adjust_stack_size(base, (size_t)limits.rlim_cur);
+    assert(size >= jt->stack_size(), "Stack size problem in main thread");
 #endif
-      tty->print_cr("Stack size of %d Kb exceeds current limit of %d Kb.\n"
-                    "(Stack sizes are rounded up to a multiple of the system page size.)\n"
-                    "See limit(1) to increase the stack size limit.",
-                    stack_size / K, jt->stack_size() / K);
-      vm_exit(1);
-    }
-    assert(jt->stack_size() >= stack_size,
-           "Attempt to map more stack than was allocated");
-    jt->set_stack_size(stack_size);
-  }
-
-  // With the T2 libthread (T1 is no longer supported) threads are always bound
-  // and we use stackbanging in all cases.
-
-  os::Solaris::init_thread_fpu_state();
-  std::set_terminate(_handle_uncaught_cxx_exception);
+    tty->print_cr("Stack size of %d Kb exceeds current limit of %d Kb.\n"
+                  "(Stack sizes are rounded up to a multiple of the system page size.)\n"
+                  "See limit(1) to increase the stack size limit.",
+                  stack_size / K, jt->stack_size() / K);
+    vm_exit(1);
+  }
+  assert(jt->stack_size() >= stack_size,
+         "Attempt to map more stack than was allocated");
+  jt->set_stack_size(stack_size);
+
 }
 
 
--- a/src/hotspot/os/solaris/os_solaris.hpp	Fri Oct 26 08:23:52 2018 -0400
+++ b/src/hotspot/os/solaris/os_solaris.hpp	Fri Oct 19 09:39:29 2018 +0200
@@ -102,8 +102,6 @@
   static size_t page_size_for_alignment(size_t alignment);
   static bool setup_large_pages(caddr_t start, size_t bytes, size_t align);
 
-  static void init_thread_fpu_state(void);
-
   static void try_enable_extended_io();
 
   static struct sigaction *(*get_signal_action)(int);
@@ -148,6 +146,9 @@
 
   // SR_handler
   static void SR_handler(Thread* thread, ucontext_t* uc);
+
+  static void init_thread_fpu_state(void);
+
  protected:
   // Solaris-specific interface goes here
   static julong available_memory();
@@ -268,6 +269,7 @@
   static          jint  _os_thread_limit;
   static volatile jint  _os_thread_count;
 
+  static void correct_stack_boundaries_for_primordial_thread(Thread* thr);
 
   // Stack overflow handling
 
--- a/src/hotspot/os/windows/os_windows.cpp	Fri Oct 26 08:23:52 2018 -0400
+++ b/src/hotspot/os/windows/os_windows.cpp	Fri Oct 19 09:39:29 2018 +0200
@@ -420,6 +420,9 @@
 
 // Thread start routine for all newly created threads
 static unsigned __stdcall thread_native_entry(Thread* thread) {
+
+  thread->record_stack_base_and_size();
+
   // Try to randomize the cache line index of hot stack frames.
   // This helps when threads of the same stack traces evict each other's
   // cache lines. The threads can be either from the same JVM instance, or
@@ -453,12 +456,15 @@
   // by VM, so VM can generate error dump when an exception occurred in non-
   // Java thread (e.g. VM thread).
   __try {
-    thread->run();
+    thread->call_run();
   } __except(topLevelExceptionFilter(
                                      (_EXCEPTION_POINTERS*)_exception_info())) {
     // Nothing to do.
   }
 
+  // Note: at this point the thread object may already have deleted itself.
+  // Do not dereference it from here on out.
+
   log_info(os, thread)("Thread finished (tid: " UINTX_FORMAT ").", os::current_thread_id());
 
   // One less thread is executing
@@ -468,15 +474,6 @@
     Atomic::dec(&os::win32::_os_thread_count);
   }
 
-  // If a thread has not deleted itself ("delete this") as part of its
-  // termination sequence, we have to ensure thread-local-storage is
-  // cleared before we actually terminate. No threads should ever be
-  // deleted asynchronously with respect to their termination.
-  if (Thread::current_or_null_safe() != NULL) {
-    assert(Thread::current_or_null_safe() == thread, "current thread is wrong");
-    thread->clear_thread_current();
-  }
-
   // Thread must not return from exit_process_or_thread(), but if it does,
   // let it proceed to exit normally
   return (unsigned)os::win32::exit_process_or_thread(os::win32::EPT_THREAD, res);
--- a/src/hotspot/os_cpu/aix_ppc/os_aix_ppc.cpp	Fri Oct 26 08:23:52 2018 -0400
+++ b/src/hotspot/os_cpu/aix_ppc/os_aix_ppc.cpp	Fri Oct 19 09:39:29 2018 +0200
@@ -85,11 +85,6 @@
   return (char*) -1;
 }
 
-// OS specific thread initialization
-//
-// Calculate and store the limits of the memory stack.
-void os::initialize_thread(Thread *thread) { }
-
 // Frame information (pc, sp, fp) retrieved via ucontext
 // always looks like a C-frame according to the frame
 // conventions in frame_ppc.hpp.
--- a/src/hotspot/os_cpu/bsd_x86/os_bsd_x86.cpp	Fri Oct 26 08:23:52 2018 -0400
+++ b/src/hotspot/os_cpu/bsd_x86/os_bsd_x86.cpp	Fri Oct 19 09:39:29 2018 +0200
@@ -300,10 +300,6 @@
   return (char*) -1;
 }
 
-void os::initialize_thread(Thread* thr) {
-// Nothing to do.
-}
-
 address os::Bsd::ucontext_get_pc(const ucontext_t * uc) {
   return (address)uc->context_pc;
 }
--- a/src/hotspot/os_cpu/bsd_zero/os_bsd_zero.cpp	Fri Oct 26 08:23:52 2018 -0400
+++ b/src/hotspot/os_cpu/bsd_zero/os_bsd_zero.cpp	Fri Oct 19 09:39:29 2018 +0200
@@ -100,10 +100,6 @@
 #endif // SPARC
 }
 
-void os::initialize_thread(Thread* thr) {
-  // Nothing to do.
-}
-
 address os::Bsd::ucontext_get_pc(const ucontext_t* uc) {
   ShouldNotCallThis();
   return NULL;
--- a/src/hotspot/os_cpu/linux_aarch64/os_linux_aarch64.cpp	Fri Oct 26 08:23:52 2018 -0400
+++ b/src/hotspot/os_cpu/linux_aarch64/os_linux_aarch64.cpp	Fri Oct 19 09:39:29 2018 +0200
@@ -106,9 +106,6 @@
   return (char*) 0xffffffffffff;
 }
 
-void os::initialize_thread(Thread *thr) {
-}
-
 address os::Linux::ucontext_get_pc(const ucontext_t * uc) {
 #ifdef BUILTIN_SIM
   return (address)uc->uc_mcontext.gregs[REG_PC];
--- a/src/hotspot/os_cpu/linux_arm/os_linux_arm.cpp	Fri Oct 26 08:23:52 2018 -0400
+++ b/src/hotspot/os_cpu/linux_arm/os_linux_arm.cpp	Fri Oct 19 09:39:29 2018 +0200
@@ -91,10 +91,6 @@
   return (char*) -1;
 }
 
-void os::initialize_thread(Thread* thr) {
-  // Nothing to do
-}
-
 #ifdef AARCH64
 
 #define arm_pc pc
--- a/src/hotspot/os_cpu/linux_ppc/os_linux_ppc.cpp	Fri Oct 26 08:23:52 2018 -0400
+++ b/src/hotspot/os_cpu/linux_ppc/os_linux_ppc.cpp	Fri Oct 19 09:39:29 2018 +0200
@@ -94,8 +94,6 @@
   return (char*) -1;
 }
 
-void os::initialize_thread(Thread *thread) { }
-
 // Frame information (pc, sp, fp) retrieved via ucontext
 // always looks like a C-frame according to the frame
 // conventions in frame_ppc64.hpp.
--- a/src/hotspot/os_cpu/linux_s390/os_linux_s390.cpp	Fri Oct 26 08:23:52 2018 -0400
+++ b/src/hotspot/os_cpu/linux_s390/os_linux_s390.cpp	Fri Oct 19 09:39:29 2018 +0200
@@ -95,9 +95,6 @@
   return (char*) -1;
 }
 
-// OS specific thread initialization.
-void os::initialize_thread(Thread* thread) { }
-
 // Frame information (pc, sp, fp) retrieved via ucontext
 // always looks like a C-frame according to the frame
 // conventions in frame_s390.hpp.
--- a/src/hotspot/os_cpu/linux_sparc/os_linux_sparc.cpp	Fri Oct 26 08:23:52 2018 -0400
+++ b/src/hotspot/os_cpu/linux_sparc/os_linux_sparc.cpp	Fri Oct 19 09:39:29 2018 +0200
@@ -159,8 +159,6 @@
   return (char*) 0;
 }
 
-void os::initialize_thread(Thread* thr) {}
-
 void os::print_context(outputStream *st, const void *context) {
   if (context == NULL) return;
 
--- a/src/hotspot/os_cpu/linux_x86/os_linux_x86.cpp	Fri Oct 26 08:23:52 2018 -0400
+++ b/src/hotspot/os_cpu/linux_x86/os_linux_x86.cpp	Fri Oct 19 09:39:29 2018 +0200
@@ -116,10 +116,6 @@
   return (char*) -1;
 }
 
-void os::initialize_thread(Thread* thr) {
-// Nothing to do.
-}
-
 address os::Linux::ucontext_get_pc(const ucontext_t * uc) {
   return (address)uc->uc_mcontext.gregs[REG_PC];
 }
--- a/src/hotspot/os_cpu/linux_zero/os_linux_zero.cpp	Fri Oct 26 08:23:52 2018 -0400
+++ b/src/hotspot/os_cpu/linux_zero/os_linux_zero.cpp	Fri Oct 19 09:39:29 2018 +0200
@@ -96,10 +96,6 @@
 #endif // SPARC
 }
 
-void os::initialize_thread(Thread * thr){
-  // Nothing to do.
-}
-
 address os::Linux::ucontext_get_pc(const ucontext_t* uc) {
   ShouldNotCallThis();
   return NULL; // silence compile warnings
--- a/src/hotspot/os_cpu/windows_x86/os_windows_x86.cpp	Fri Oct 26 08:23:52 2018 -0400
+++ b/src/hotspot/os_cpu/windows_x86/os_windows_x86.cpp	Fri Oct 19 09:39:29 2018 +0200
@@ -212,10 +212,6 @@
   return true;
 }
 
-void os::initialize_thread(Thread* thr) {
-// Nothing to do.
-}
-
 // Atomics and Stub Functions
 
 typedef int32_t   xchg_func_t            (int32_t,  volatile int32_t*);
--- a/src/hotspot/share/gc/parallel/gcTaskThread.cpp	Fri Oct 26 08:23:52 2018 -0400
+++ b/src/hotspot/share/gc/parallel/gcTaskThread.cpp	Fri Oct 19 09:39:29 2018 +0200
@@ -114,8 +114,6 @@
 // for tasks to be enqueued for execution.
 
 void GCTaskThread::run() {
-  // Set up the thread for stack overflow support
-  this->record_stack_base_and_size();
   this->initialize_named_thread();
   // Bind yourself to your processor.
   if (processor_id() != GCTaskManager::sentinel_worker()) {
--- a/src/hotspot/share/gc/shared/concurrentGCThread.cpp	Fri Oct 26 08:23:52 2018 -0400
+++ b/src/hotspot/share/gc/shared/concurrentGCThread.cpp	Fri Oct 19 09:39:29 2018 +0200
@@ -49,7 +49,6 @@
 }
 
 void ConcurrentGCThread::initialize_in_thread() {
-  this->record_stack_base_and_size();
   this->initialize_named_thread();
   this->set_active_handles(JNIHandleBlock::allocate_block());
   // From this time Thread::current() should be working.
--- a/src/hotspot/share/gc/shared/workgroup.cpp	Fri Oct 26 08:23:52 2018 -0400
+++ b/src/hotspot/share/gc/shared/workgroup.cpp	Fri Oct 19 09:39:29 2018 +0200
@@ -297,7 +297,6 @@
 }
 
 void AbstractGangWorker::initialize() {
-  this->record_stack_base_and_size();
   this->initialize_named_thread();
   assert(_gang != NULL, "No gang to run in");
   os::set_priority(this, NearMaxPriority);
--- a/src/hotspot/share/jfr/periodic/sampling/jfrThreadSampler.cpp	Fri Oct 26 08:23:52 2018 -0400
+++ b/src/hotspot/share/jfr/periodic/sampling/jfrThreadSampler.cpp	Fri Oct 19 09:39:29 2018 +0200
@@ -455,8 +455,6 @@
 void JfrThreadSampler::run() {
   assert(_sampler_thread == NULL, "invariant");
 
-  record_stack_base_and_size();
-
   _sampler_thread = this;
 
   jlong last_java_ms = get_monotonic_ms();
--- a/src/hotspot/share/prims/jni.cpp	Fri Oct 26 08:23:52 2018 -0400
+++ b/src/hotspot/share/prims/jni.cpp	Fri Oct 19 09:39:29 2018 +0200
@@ -4132,6 +4132,7 @@
   // be set in order for the Safepoint code to deal with it correctly.
   thread->set_thread_state(_thread_in_vm);
   thread->record_stack_base_and_size();
+  thread->register_thread_stack_with_NMT();
   thread->initialize_thread_current();
 
   if (!os::create_attached_thread(thread)) {
--- a/src/hotspot/share/runtime/os.hpp	Fri Oct 26 08:23:52 2018 -0400
+++ b/src/hotspot/share/runtime/os.hpp	Fri Oct 19 09:39:29 2018 +0200
@@ -505,7 +505,6 @@
   static void pd_start_thread(Thread* thread);
   static void start_thread(Thread* thread);
 
-  static void initialize_thread(Thread* thr);
   static void free_thread(OSThread* osthread);
 
   // thread id on Linux/64bit is 64bit, on Windows and Solaris, it's 32bit
--- a/src/hotspot/share/runtime/thread.cpp	Fri Oct 26 08:23:52 2018 -0400
+++ b/src/hotspot/share/runtime/thread.cpp	Fri Oct 19 09:39:29 2018 +0200
@@ -338,32 +338,61 @@
 }
 
 void Thread::record_stack_base_and_size() {
+  // Note: at this point, Thread object is not yet initialized. Do not rely on
+  // any members being initialized. Do not rely on Thread::current() being set.
+  // If possible, refrain from doing anything which may crash or assert since
+  // quite probably those crash dumps will be useless.
   set_stack_base(os::current_stack_base());
   set_stack_size(os::current_stack_size());
-  // CR 7190089: on Solaris, primordial thread's stack is adjusted
-  // in initialize_thread(). Without the adjustment, stack size is
-  // incorrect if stack is set to unlimited (ulimit -s unlimited).
-  // So far, only Solaris has real implementation of initialize_thread().
-  //
-  // set up any platform-specific state.
-  os::initialize_thread(this);
+
+#ifdef SOLARIS
+  if (os::is_primordial_thread()) {
+    os::Solaris::correct_stack_boundaries_for_primordial_thread(this);
+  }
+#endif
 
   // Set stack limits after thread is initialized.
   if (is_Java_thread()) {
     ((JavaThread*) this)->set_stack_overflow_limit();
     ((JavaThread*) this)->set_reserved_stack_activation(stack_base());
   }
+}
+
 #if INCLUDE_NMT
-  // record thread's native stack, stack grows downward
+void Thread::register_thread_stack_with_NMT() {
   MemTracker::record_thread_stack(stack_end(), stack_size());
+}
 #endif // INCLUDE_NMT
+
+void Thread::call_run() {
+  // At this point, Thread object should be fully initialized and
+  // Thread::current() should be set.
+
+  register_thread_stack_with_NMT();
+
   log_debug(os, thread)("Thread " UINTX_FORMAT " stack dimensions: "
     PTR_FORMAT "-" PTR_FORMAT " (" SIZE_FORMAT "k).",
     os::current_thread_id(), p2i(stack_base() - stack_size()),
     p2i(stack_base()), stack_size()/1024);
+
+  // Invoke <ChildClass>::run()
+  this->run();
+  // Returned from <ChildClass>::run(). Thread finished.
+
+  // Note: at this point the thread object may already have deleted itself.
+  // So from here on do not dereference *this*.
+
+  // If a thread has not deleted itself ("delete this") as part of its
+  // termination sequence, we have to ensure thread-local-storage is
+  // cleared before we actually terminate. No threads should ever be
+  // deleted asynchronously with respect to their termination.
+  if (Thread::current_or_null_safe() != NULL) {
+    assert(Thread::current_or_null_safe() == this, "current thread is wrong");
+    Thread::clear_thread_current();
+  }
+
 }
 
-
 Thread::~Thread() {
   JFR_ONLY(Jfr::on_thread_destruct(this);)
 
@@ -417,17 +446,12 @@
   // clear Thread::current if thread is deleting itself.
   // Needed to ensure JNI correctly detects non-attached threads.
   if (this == Thread::current()) {
-    clear_thread_current();
+    Thread::clear_thread_current();
   }
 
   CHECK_UNHANDLED_OOPS_ONLY(if (CheckUnhandledOops) delete unhandled_oops();)
 }
 
-// NOTE: dummy function for assertion purpose.
-void Thread::run() {
-  ShouldNotReachHere();
-}
-
 #ifdef ASSERT
 // A JavaThread is considered "dangling" if it is not the current
 // thread, has been added the Threads list, the system is not at a
@@ -1374,7 +1398,6 @@
 void WatcherThread::run() {
   assert(this == watcher_thread(), "just checking");
 
-  this->record_stack_base_and_size();
   this->set_native_thread_name(this->name());
   this->set_active_handles(JNIHandleBlock::allocate_block());
   while (true) {
@@ -1740,9 +1763,6 @@
   // used to test validity of stack trace backs
   this->record_base_of_stack_pointer();
 
-  // Record real stack base and size.
-  this->record_stack_base_and_size();
-
   this->create_stack_guard_pages();
 
   this->cache_global_variables();
@@ -3709,6 +3729,7 @@
   main_thread->initialize_thread_current();
   // must do this before set_active_handles
   main_thread->record_stack_base_and_size();
+  main_thread->register_thread_stack_with_NMT();
   main_thread->set_active_handles(JNIHandleBlock::allocate_block());
 
   if (!main_thread->set_as_starting_thread()) {
--- a/src/hotspot/share/runtime/thread.hpp	Fri Oct 26 08:23:52 2018 -0400
+++ b/src/hotspot/share/runtime/thread.hpp	Fri Oct 19 09:39:29 2018 +0200
@@ -397,11 +397,15 @@
 
   // Manage Thread::current()
   void initialize_thread_current();
-  void clear_thread_current(); // TLS cleanup needed before threads terminate
+  static void clear_thread_current(); // TLS cleanup needed before threads terminate
+
+ protected:
+  // To be implemented by children.
+  virtual void run() = 0;
 
  public:
-  // thread entry point
-  virtual void run();
+  // invokes <ChildThreadClass>::run(), with common preparations and cleanups.
+  void call_run();
 
   // Testers
   virtual bool is_VM_thread()       const            { return false; }
@@ -643,6 +647,7 @@
   void    set_stack_size(size_t size)  { _stack_size = size; }
   address stack_end()  const           { return stack_base() - stack_size(); }
   void    record_stack_base_and_size();
+  void    register_thread_stack_with_NMT() NOT_NMT_RETURN;
 
   bool    on_local_stack(address adr) const {
     // QQQ this has knowledge of direction, ought to be a stack method
--- a/src/hotspot/share/runtime/vmThread.cpp	Fri Oct 26 08:23:52 2018 -0400
+++ b/src/hotspot/share/runtime/vmThread.cpp	Fri Oct 19 09:39:29 2018 +0200
@@ -243,7 +243,7 @@
   assert(this == vm_thread(), "check");
 
   this->initialize_named_thread();
-  this->record_stack_base_and_size();
+
   // Notify_lock wait checks on active_handles() to rewait in
   // case of spurious wakeup, it should wait on the last
   // value set prior to the notify