8212173: Thread._stack_base/_stack_size initialized too late for new threads
Reviewed-by: dholmes, simonis
--- 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