< prev index next >

src/hotspot/share/runtime/thread.cpp

Print this page

        

*** 211,222 **** --- 211,226 ---- } // Base class for all threads: VMThread, WatcherThread, ConcurrentMarkSweepThread, // JavaThread + DEBUG_ONLY(Thread* Thread::_starting_thread = NULL;) Thread::Thread() { + + DEBUG_ONLY(_run_state = PRE_CALL_RUN;) + // stack and get_thread set_stack_base(NULL); set_stack_size(0); set_self_raw_id(0); set_lgrp_id(-1);
*** 312,326 **** // to BarrierSet::set_barrier_set(). BarrierSet* const barrier_set = BarrierSet::barrier_set(); if (barrier_set != NULL) { barrier_set->on_thread_create(this); } else { ! #ifdef ASSERT ! static bool initial_thread_created = false; ! assert(!initial_thread_created, "creating thread before barrier set"); ! initial_thread_created = true; ! #endif // ASSERT } } void Thread::initialize_thread_current() { #ifndef USE_LIBRARY_BASED_TLS_ONLY --- 316,330 ---- // to BarrierSet::set_barrier_set(). BarrierSet* const barrier_set = BarrierSet::barrier_set(); if (barrier_set != NULL) { barrier_set->on_thread_create(this); } else { ! // Only the main thread should be created before the barrier set ! // and that happens just before Thread::current is set. No other thread ! // can attach as the VM is not created yet, so they can't execute this code. ! // If the main thread creates other threads before the barrier set that is an error. ! assert(Thread::current_or_null() == NULL, "creating thread before barrier set"); } } void Thread::initialize_thread_current() { #ifndef USE_LIBRARY_BASED_TLS_ONLY
*** 366,406 **** 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(); JFR_ONLY(Jfr::on_thread_start(this);) 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() { // Notify the barrier set that a thread is being destroyed. Note that a barrier // set might not be available if we encountered errors during bootstrapping. BarrierSet* const barrier_set = BarrierSet::barrier_set(); if (barrier_set != NULL) { barrier_set->on_thread_destroy(this); --- 370,434 ---- MemTracker::record_thread_stack(stack_end(), stack_size()); } #endif // INCLUDE_NMT void Thread::call_run() { + DEBUG_ONLY(_run_state = CALL_RUN;) + // At this point, Thread object should be fully initialized and // Thread::current() should be set. + assert(Thread::current_or_null() != NULL, "current thread is unset"); + assert(Thread::current_or_null() == this, "current thread is wrong"); + + // Perform common initialization actions + register_thread_stack_with_NMT(); JFR_ONLY(Jfr::on_thread_start(this);) 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); + // Perform <ChildClass> initialization actions + DEBUG_ONLY(_run_state = PRE_RUN;) + this->pre_run(); + // Invoke <ChildClass>::run() + DEBUG_ONLY(_run_state = RUN;) this->run(); // Returned from <ChildClass>::run(). Thread finished. ! // Perform common tear-down actions ! assert(Thread::current_or_null() != NULL, "current thread is unset"); ! assert(Thread::current_or_null() == this, "current thread is wrong"); ! ! // Perform <ChildClass> tear-down actions ! DEBUG_ONLY(_run_state = POST_RUN;) ! this->post_run(); ! ! // Note: at this point the thread object may already have deleted itself, ! // so from here on do not dereference *this*. Not all thread types currently ! // delete themselves when they terminate. But no thread should ever be deleted ! // asynchronously with respect to its termination - that is what _run_state can ! // be used to check. + assert(Thread::current_or_null() == NULL, "current thread still present"); } Thread::~Thread() { + + // Attached threads will remain in PRE_CALL_RUN, as will threads that don't actually + // get started due to errors etc. Any active thread should at least reach post_run + // before it is deleted (usually in post_run()). + assert(_run_state == PRE_CALL_RUN || + _run_state == POST_RUN, "Active Thread deleted before post_run(): " + "_run_state=%d", (int)_run_state); + // Notify the barrier set that a thread is being destroyed. Note that a barrier // set might not be available if we encountered errors during bootstrapping. BarrierSet* const barrier_set = BarrierSet::barrier_set(); if (barrier_set != NULL) { barrier_set->on_thread_destroy(this);
*** 443,455 **** _SR_lock = NULL; // osthread() can be NULL, if creation of thread failed. if (osthread() != NULL) os::free_thread(osthread()); ! // clear Thread::current if thread is deleting itself. // Needed to ensure JNI correctly detects non-attached threads. ! if (this == Thread::current()) { Thread::clear_thread_current(); } CHECK_UNHANDLED_OOPS_ONLY(if (CheckUnhandledOops) delete unhandled_oops();) } --- 471,484 ---- _SR_lock = NULL; // osthread() can be NULL, if creation of thread failed. if (osthread() != NULL) os::free_thread(osthread()); ! // Clear Thread::current if thread is deleting itself and it has not ! // already been done. This must be done before the memory is deallocated. // Needed to ensure JNI correctly detects non-attached threads. ! if (this == Thread::current_or_null()) { Thread::clear_thread_current(); } CHECK_UNHANDLED_OOPS_ONLY(if (CheckUnhandledOops) delete unhandled_oops();) }
*** 1049,1059 **** --- 1078,1091 ---- bool Thread::is_lock_owned(address adr) const { return on_local_stack(adr); } bool Thread::set_as_starting_thread() { + assert(_starting_thread == NULL, "already initialized: " + "_starting_thread=" INTPTR_FORMAT, p2i(_starting_thread)); // NOTE: this must be called inside the main thread. + DEBUG_ONLY(_starting_thread = this;) return os::create_main_thread((JavaThread*)this); } static void initialize_class(Symbol* class_name, TRAPS) { Klass* klass = SystemDictionary::resolve_or_fail(class_name, true, CHECK);
*** 1252,1282 **** assert(!end(), "precondition"); _current = OrderAccess::load_acquire(&_current->_next); } NonJavaThread::NonJavaThread() : Thread(), _next(NULL) { ! // Add this thread to _the_list. MutexLockerEx lock(NonJavaThreadsList_lock, Mutex::_no_safepoint_check_flag); _next = _the_list._head; OrderAccess::release_store(&_the_list._head, this); } ! NonJavaThread::~NonJavaThread() { ! JFR_ONLY(Jfr::on_thread_exit(this);) ! // Remove this thread from _the_list. MutexLockerEx lock(NonJavaThreadsList_lock, Mutex::_no_safepoint_check_flag); NonJavaThread* volatile* p = &_the_list._head; for (NonJavaThread* t = *p; t != NULL; p = &t->_next, t = *p) { if (t == this) { *p = this->_next; ! // Wait for any in-progress iterators. _the_list._protect.synchronize(); break; } } } // NamedThread -- non-JavaThread subclasses with multiple // uniquely named instances should derive from this. NamedThread::NamedThread() : NonJavaThread(), _name(NULL), --- 1284,1335 ---- assert(!end(), "precondition"); _current = OrderAccess::load_acquire(&_current->_next); } NonJavaThread::NonJavaThread() : Thread(), _next(NULL) { ! assert(BarrierSet::barrier_set() != NULL, "NonJavaThread created too soon!"); ! } ! ! NonJavaThread::~NonJavaThread() { } ! ! void NonJavaThread::add_to_the_list() { MutexLockerEx lock(NonJavaThreadsList_lock, Mutex::_no_safepoint_check_flag); _next = _the_list._head; OrderAccess::release_store(&_the_list._head, this); } ! void NonJavaThread::remove_from_the_list() { MutexLockerEx lock(NonJavaThreadsList_lock, Mutex::_no_safepoint_check_flag); NonJavaThread* volatile* p = &_the_list._head; for (NonJavaThread* t = *p; t != NULL; p = &t->_next, t = *p) { if (t == this) { *p = this->_next; ! // Wait for any in-progress iterators. Concurrent synchronize is ! // not allowed, so do it while holding the list lock. _the_list._protect.synchronize(); break; } } } + void NonJavaThread::pre_run() { + assert(BarrierSet::barrier_set() != NULL, "invariant"); + add_to_the_list(); + + // This is slightly odd in that NamedThread is a subclass, but + // in fact name() is defined in Thread + assert(this->name() != NULL, "thread name was not set before it was started"); + this->set_native_thread_name(this->name()); + } + + void NonJavaThread::post_run() { + JFR_ONLY(Jfr::on_thread_exit(this);) + remove_from_the_list(); + // Ensure thread-local-storage is cleared before termination. + Thread::clear_thread_current(); + } + // NamedThread -- non-JavaThread subclasses with multiple // uniquely named instances should derive from this. NamedThread::NamedThread() : NonJavaThread(), _name(NULL),
*** 1299,1312 **** va_start(ap, format); jio_vsnprintf(_name, max_name_len, format, ap); va_end(ap); } - void NamedThread::initialize_named_thread() { - set_native_thread_name(name()); - } - void NamedThread::print_on(outputStream* st) const { st->print("\"%s\" ", name()); Thread::print_on(st); st->cr(); } --- 1352,1361 ----
*** 1399,1409 **** } void WatcherThread::run() { assert(this == watcher_thread(), "just checking"); - this->set_native_thread_name(this->name()); this->set_active_handles(JNIHandleBlock::allocate_block()); while (true) { assert(watcher_thread() == Thread::current(), "thread consistency check"); assert(watcher_thread() == this, "thread consistency check"); --- 1448,1457 ----
*** 1755,1777 **** } #endif // INCLUDE_JVMCI } ! // The first routine called by a new Java thread void JavaThread::run() { // initialize thread-local alloc buffer related fields this->initialize_tlab(); ! // used to test validity of stack trace backs this->record_base_of_stack_pointer(); this->create_stack_guard_pages(); this->cache_global_variables(); ! // Thread is now sufficient initialized to be handled by the safepoint code as being // in the VM. Change thread state from _thread_new to _thread_in_vm ThreadStateTransition::transition_and_fence(this, _thread_new, _thread_in_vm); assert(JavaThread::current() == this, "sanity check"); assert(!Thread::current()->owns_locks(), "sanity check"); --- 1803,1836 ---- } #endif // INCLUDE_JVMCI } ! // First JavaThread specific code executed by a new Java thread. ! void JavaThread::pre_run() { ! // empty - see comments in run() ! } ! ! // The main routine called by a new Java thread. This isn't overridden ! // by subclasses, instead different subclasses define a different "entry_point" ! // which defines the actual logic for that kind of thread. void JavaThread::run() { // initialize thread-local alloc buffer related fields this->initialize_tlab(); ! // Used to test validity of stack trace backs. ! // This can't be moved into pre_run() else we invalidate ! // the requirement that thread_main_inner is lower on ! // the stack. Consequently all the initialization logic ! // stays here in run() rather than pre_run(). this->record_base_of_stack_pointer(); this->create_stack_guard_pages(); this->cache_global_variables(); ! // Thread is now sufficiently initialized to be handled by the safepoint code as being // in the VM. Change thread state from _thread_new to _thread_in_vm ThreadStateTransition::transition_and_fence(this, _thread_new, _thread_in_vm); assert(JavaThread::current() == this, "sanity check"); assert(!Thread::current()->owns_locks(), "sanity check");
*** 1786,1802 **** JvmtiExport::post_thread_start(this); } // We call another function to do the rest so we are sure that the stack addresses used ! // from there will be lower than the stack base just computed thread_main_inner(); - - // Note, thread is no longer valid at this point! } - void JavaThread::thread_main_inner() { assert(JavaThread::current() == this, "sanity check"); assert(this->threadObj() != NULL, "just checking"); // Execute thread entry point unless this thread has a pending exception --- 1845,1858 ---- JvmtiExport::post_thread_start(this); } // We call another function to do the rest so we are sure that the stack addresses used ! // from there will be lower than the stack base just computed. thread_main_inner(); } void JavaThread::thread_main_inner() { assert(JavaThread::current() == this, "sanity check"); assert(this->threadObj() != NULL, "just checking"); // Execute thread entry point unless this thread has a pending exception
*** 1812,1826 **** this->entry_point()(this, this); } DTRACE_THREAD_PROBE(stop, this); this->exit(false); this->smr_delete(); } - static void ensure_join(JavaThread* thread) { // We do not need to grab the Threads_lock, since we are operating on ourself. Handle threadObj(thread, thread->threadObj()); assert(threadObj.not_null(), "java thread object must exist"); ObjectLocker lock(threadObj, thread); --- 1868,1888 ---- this->entry_point()(this, this); } DTRACE_THREAD_PROBE(stop, this); + // Cleanup is handled in post_run() + } + + // Shared teardown for all JavaThreads + void JavaThread::post_run() { this->exit(false); + // Defer deletion to here to ensure 'this' is still referenceable in call_run + // for any shared tear-down. this->smr_delete(); } static void ensure_join(JavaThread* thread) { // We do not need to grab the Threads_lock, since we are operating on ourself. Handle threadObj(thread, thread->threadObj()); assert(threadObj.not_null(), "java thread object must exist"); ObjectLocker lock(threadObj, thread);
< prev index next >