diff -r 75f6a833a444 -r e90b4960bcd6 src/hotspot/share/runtime/thread.cpp --- a/src/hotspot/share/runtime/thread.cpp Wed Mar 06 20:32:03 2019 +0100 +++ b/src/hotspot/share/runtime/thread.cpp Sat Apr 20 19:24:51 2019 +0200 @@ -240,8 +240,8 @@ set_last_handle_mark(NULL); DEBUG_ONLY(_missed_ic_stub_refill_verifier = NULL); - // This initial value ==> never claimed. - _oops_do_parity = 0; + // Initial value of zero ==> never claimed. + _threads_do_token = 0; _threads_hazard_ptr = NULL; _threads_list_ptr = NULL; _nested_threads_hazard_ptr_cnt = 0; @@ -887,16 +887,14 @@ // GC Support -bool Thread::claim_oops_do_par_case(int strong_roots_parity) { - int thread_parity = _oops_do_parity; - if (thread_parity != strong_roots_parity) { - jint res = Atomic::cmpxchg(strong_roots_parity, &_oops_do_parity, thread_parity); - if (res == thread_parity) { +bool Thread::claim_par_threads_do(uintx claim_token) { + uintx token = _threads_do_token; + if (token != claim_token) { + uintx res = Atomic::cmpxchg(claim_token, &_threads_do_token, token); + if (res == token) { return true; - } else { - guarantee(res == strong_roots_parity, "Or else what?"); - return false; } + guarantee(res == claim_token, "invariant"); } return false; } @@ -1293,29 +1291,35 @@ NonJavaThread::~NonJavaThread() { } void NonJavaThread::add_to_the_list() { - MutexLockerEx lock(NonJavaThreadsList_lock, Mutex::_no_safepoint_check_flag); - _next = _the_list._head; + MutexLockerEx ml(NonJavaThreadsList_lock, Mutex::_no_safepoint_check_flag); + // Initialize BarrierSet-related data before adding to list. + BarrierSet::barrier_set()->on_thread_attach(this); + OrderAccess::release_store(&_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; + { + MutexLockerEx ml(NonJavaThreadsList_lock, Mutex::_no_safepoint_check_flag); + // Cleanup BarrierSet-related data before removing from list. + BarrierSet::barrier_set()->on_thread_detach(this); + NonJavaThread* volatile* p = &_the_list._head; + for (NonJavaThread* t = *p; t != NULL; p = &t->_next, t = *p) { + if (t == this) { + *p = _next; + break; + } } } + // Wait for any in-progress iterators. Concurrent synchronize is not + // allowed, so do it while holding a dedicated lock. Outside and distinct + // from NJTList_lock in case an iteration attempts to lock it. + MutexLockerEx ml(NonJavaThreadsListSync_lock, Mutex::_no_safepoint_check_flag); + _the_list._protect.synchronize(); + _next = NULL; // Safe to drop the link now. } void NonJavaThread::pre_run() { - // Initialize BarrierSet-related data before adding to list. - assert(BarrierSet::barrier_set() != NULL, "invariant"); - BarrierSet::barrier_set()->on_thread_attach(this); add_to_the_list(); // This is slightly odd in that NamedThread is a subclass, but @@ -1326,8 +1330,6 @@ void NonJavaThread::post_run() { JFR_ONLY(Jfr::on_thread_exit(this);) - // Clean up BarrierSet data before removing from list. - BarrierSet::barrier_set()->on_thread_detach(this); remove_from_the_list(); // Ensure thread-local-storage is cleared before termination. Thread::clear_thread_current(); @@ -1508,7 +1510,7 @@ { MutexLockerEx mu(Terminator_lock, Mutex::_no_safepoint_check_flag); _watcher_thread = NULL; - Terminator_lock->notify(); + Terminator_lock->notify_all(); } } @@ -1837,7 +1839,11 @@ // 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); + ThreadStateTransition::transition(this, _thread_new, _thread_in_vm); + // Before a thread is on the threads list it is always safe, so after leaving the + // _thread_new we should emit a instruction barrier. The distance to modified code + // from here is probably far enough, but this is consistent and safe. + OrderAccess::cross_modify_fence(); assert(JavaThread::current() == this, "sanity check"); assert(!Thread::current()->owns_locks(), "sanity check"); @@ -2017,6 +2023,10 @@ _timer_exit_phase1.stop(); _timer_exit_phase2.start(); } + + // Capture daemon status before the thread is marked as terminated. + bool daemon = is_daemon(threadObj()); + // Notify waiters on thread object. This has to be done after exit() is called // on the thread (if the thread is the last thread in a daemon ThreadGroup the // group should have the destroyed bit set before waiters are notified). @@ -2085,7 +2095,7 @@ _timer_exit_phase4.start(); } // Remove from list of active threads list, and notify VM thread if we are the last non-daemon thread - Threads::remove(this); + Threads::remove(this, daemon); if (log_is_enabled(Debug, os, thread, timer)) { _timer_exit_phase4.stop(); @@ -2103,7 +2113,7 @@ } } -void JavaThread::cleanup_failed_attach_current_thread() { +void JavaThread::cleanup_failed_attach_current_thread(bool is_daemon) { if (active_handles() != NULL) { JNIHandleBlock* block = active_handles(); set_active_handles(NULL); @@ -2125,7 +2135,7 @@ BarrierSet::barrier_set()->on_thread_detach(this); - Threads::remove(this); + Threads::remove(this, is_daemon); this->smr_delete(); } @@ -2266,48 +2276,19 @@ void JavaThread::handle_special_runtime_exit_condition(bool check_asyncs) { // - // Check for pending external suspend. Internal suspend requests do - // not use handle_special_runtime_exit_condition(). + // Check for pending external suspend. // If JNIEnv proxies are allowed, don't self-suspend if the target // thread is not the current thread. In older versions of jdbx, jdbx // threads could call into the VM with another thread's JNIEnv so we // can be here operating on behalf of a suspended thread (4432884). bool do_self_suspend = is_external_suspend_with_lock(); if (do_self_suspend && (!AllowJNIEnvProxy || this == JavaThread::current())) { - // - // Because thread is external suspended the safepoint code will count - // thread as at a safepoint. This can be odd because we can be here - // as _thread_in_Java which would normally transition to _thread_blocked - // at a safepoint. We would like to mark the thread as _thread_blocked - // before calling java_suspend_self like all other callers of it but - // we must then observe proper safepoint protocol. (We can't leave - // _thread_blocked with a safepoint in progress). However we can be - // here as _thread_in_native_trans so we can't use a normal transition - // constructor/destructor pair because they assert on that type of - // transition. We could do something like: - // - // JavaThreadState state = thread_state(); - // set_thread_state(_thread_in_vm); - // { - // ThreadBlockInVM tbivm(this); - // java_suspend_self() - // } - // set_thread_state(_thread_in_vm_trans); - // if (safepoint) block; - // set_thread_state(state); - // - // but that is pretty messy. Instead we just go with the way the - // code has worked before and note that this is the only path to - // java_suspend_self that doesn't put the thread in _thread_blocked - // mode. - frame_anchor()->make_walkable(this); - java_suspend_self(); - - // We might be here for reasons in addition to the self-suspend request - // so check for other async requests. - } - + java_suspend_self_with_safepoint_check(); + } + + // We might be here for reasons in addition to the self-suspend request + // so check for other async requests. if (check_asyncs) { check_and_handle_async_exceptions(); } @@ -2426,6 +2407,7 @@ // to complete an external suspend request. // int JavaThread::java_suspend_self() { + assert(thread_state() == _thread_blocked, "wrong state for java_suspend_self()"); int ret = 0; // we are in the process of exiting so don't suspend @@ -2469,10 +2451,41 @@ this->SR_lock()->wait(Mutex::_no_safepoint_check_flag); } } - return ret; } +// Helper routine to set up the correct thread state before calling java_suspend_self. +// This is called when regular thread-state transition helpers can't be used because +// we can be in various states, in particular _thread_in_native_trans. +// Because this thread is external suspended the safepoint code will count it as at +// a safepoint, regardless of what its actual current thread-state is. But +// is_ext_suspend_completed() may be waiting to see a thread transition from +// _thread_in_native_trans to _thread_blocked. So we set the thread state directly +// to _thread_blocked. The problem with setting thread state directly is that a +// safepoint could happen just after java_suspend_self() returns after being resumed, +// and the VM thread will see the _thread_blocked state. So we must check for a safepoint +// after restoring the state to make sure we won't leave while a safepoint is in progress. +// However, not all initial-states are allowed when performing a safepoint check, as we +// should never be blocking at a safepoint whilst in those states. Of these 'bad' states +// only _thread_in_native is possible when executing this code (based on our two callers). +// A thread that is _thread_in_native is already safepoint-safe and so it doesn't matter +// whether the VMThread sees the _thread_blocked state, or the _thread_in_native state, +// and so we don't need the explicit safepoint check. + +void JavaThread::java_suspend_self_with_safepoint_check() { + assert(this == Thread::current(), "invariant"); + JavaThreadState state = thread_state(); + set_thread_state(_thread_blocked); + java_suspend_self(); + set_thread_state_fence(state); + // Since we are not using a regular thread-state transition helper here, + // we must manually emit the instruction barrier after leaving a safe state. + OrderAccess::cross_modify_fence(); + if (state != _thread_in_native) { + SafepointMechanism::block_if_requested(this); + } +} + #ifdef ASSERT // Verify the JavaThread has not yet been published in the Threads::list, and // hence doesn't need protection from concurrent access at this stage. @@ -2504,32 +2517,10 @@ // threads could call into the VM with another thread's JNIEnv so we // can be here operating on behalf of a suspended thread (4432884). if (do_self_suspend && (!AllowJNIEnvProxy || curJT == thread)) { - JavaThreadState state = thread->thread_state(); - - // We mark this thread_blocked state as a suspend-equivalent so - // that a caller to is_ext_suspend_completed() won't be confused. - // The suspend-equivalent state is cleared by java_suspend_self(). - thread->set_suspend_equivalent(); - - // If the safepoint code sees the _thread_in_native_trans state, it will - // wait until the thread changes to other thread state. There is no - // guarantee on how soon we can obtain the SR_lock and complete the - // self-suspend request. It would be a bad idea to let safepoint wait for - // too long. Temporarily change the state to _thread_blocked to - // let the VM thread know that this thread is ready for GC. The problem - // of changing thread state is that safepoint could happen just after - // java_suspend_self() returns after being resumed, and VM thread will - // see the _thread_blocked state. We must check for safepoint - // after restoring the state and make sure we won't leave while a safepoint - // is in progress. - thread->set_thread_state(_thread_blocked); - thread->java_suspend_self(); - thread->set_thread_state(state); - - InterfaceSupport::serialize_thread_state_with_handler(thread); - } - - SafepointMechanism::block_if_requested(curJT); + thread->java_suspend_self_with_safepoint_check(); + } else { + SafepointMechanism::block_if_requested(curJT); + } if (thread->is_deopt_suspend()) { thread->clear_deopt_suspend(); @@ -2950,9 +2941,21 @@ } } +#ifdef ASSERT +void JavaThread::verify_states_for_handshake() { + // This checks that the thread has a correct frame state during a handshake. + assert((!has_last_Java_frame() && java_call_counter() == 0) || + (has_last_Java_frame() && java_call_counter() > 0), + "unexpected frame info: has_last_frame=%d, java_call_counter=%d", + has_last_Java_frame(), java_call_counter()); +} +#endif + void JavaThread::nmethods_do(CodeBlobClosure* cf) { assert((!has_last_Java_frame() && java_call_counter() == 0) || - (has_last_Java_frame() && java_call_counter() > 0), "wrong java_sp info!"); + (has_last_Java_frame() && java_call_counter() > 0), + "unexpected frame info: has_last_frame=%d, java_call_counter=%d", + has_last_Java_frame(), java_call_counter()); if (has_last_Java_frame()) { // Traverse the execution stack @@ -2962,7 +2965,7 @@ } } -void JavaThread::metadata_do(void f(Metadata*)) { +void JavaThread::metadata_do(MetadataClosure* f) { if (has_last_Java_frame()) { // Traverse the execution stack to call f() on the methods in the stack for (StackFrameStream fst(this); !fst.is_done(); fst.next()) { @@ -3472,7 +3475,7 @@ int Threads::_number_of_threads = 0; int Threads::_number_of_non_daemon_threads = 0; int Threads::_return_code = 0; -int Threads::_thread_claim_parity = 0; +uintx Threads::_thread_claim_token = 1; // Never zero. size_t JavaThread::_stack_size_at_create = 0; #ifdef ASSERT @@ -3532,14 +3535,14 @@ } void Threads::possibly_parallel_threads_do(bool is_par, ThreadClosure* tc) { - int cp = Threads::thread_claim_parity(); + uintx claim_token = Threads::thread_claim_token(); ALL_JAVA_THREADS(p) { - if (p->claim_oops_do(is_par, cp)) { + if (p->claim_threads_do(is_par, claim_token)) { tc->do_thread(p); } } VMThread* vmt = VMThread::vm_thread(); - if (vmt->claim_oops_do(is_par, cp)) { + if (vmt->claim_threads_do(is_par, claim_token)) { tc->do_thread(vmt); } } @@ -3626,6 +3629,7 @@ initialize_class(vmSymbols::java_lang_Thread(), CHECK); oop thread_object = create_initial_thread(thread_group, main_thread, CHECK); main_thread->set_threadObj(thread_object); + // Set thread status to running since main thread has // been started and running. java_lang_Thread::set_thread_status(thread_object, @@ -3634,6 +3638,15 @@ // The VM creates objects of this class. initialize_class(vmSymbols::java_lang_Module(), CHECK); +#ifdef ASSERT + InstanceKlass *k = SystemDictionary::UnsafeConstants_klass(); + assert(k->is_not_initialized(), "UnsafeConstants should not already be initialized"); +#endif + + // initialize the hardware-specific constants needed by Unsafe + initialize_class(vmSymbols::jdk_internal_misc_UnsafeConstants(), CHECK); + jdk_internal_misc_UnsafeConstants::set_unsafe_constants(); + // The VM preresolves methods to these classes. Make sure that they get initialized initialize_class(vmSymbols::java_lang_reflect_Method(), CHECK); initialize_class(vmSymbols::java_lang_ref_Finalizer(), CHECK); @@ -4466,9 +4479,9 @@ Events::log(p, "Thread added: " INTPTR_FORMAT, p2i(p)); } -void Threads::remove(JavaThread* p) { - - // Reclaim the objectmonitors from the omInUseList and omFreeList of the moribund thread. +void Threads::remove(JavaThread* p, bool is_daemon) { + + // Reclaim the ObjectMonitors from the omInUseList and omFreeList of the moribund thread. ObjectSynchronizer::omFlush(p); // Extra scope needed for Thread_lock, so we can check @@ -4495,11 +4508,8 @@ } _number_of_threads--; - oop threadObj = p->threadObj(); - bool daemon = true; - if (!is_daemon(threadObj)) { + if (!is_daemon) { _number_of_non_daemon_threads--; - daemon = false; // Only one thread left, do a notify on the Threads_lock so a thread waiting // on destroy_vm will wake up. @@ -4507,7 +4517,7 @@ Threads_lock->notify_all(); } } - ThreadService::remove_thread(p, daemon); + ThreadService::remove_thread(p, is_daemon); // Make sure that safepoint code disregard this thread. This is needed since // the thread might mess around with locks after this point. This can cause it @@ -4534,27 +4544,39 @@ VMThread::vm_thread()->oops_do(f, cf); } -void Threads::change_thread_claim_parity() { - // Set the new claim parity. - assert(_thread_claim_parity >= 0 && _thread_claim_parity <= 2, - "Not in range."); - _thread_claim_parity++; - if (_thread_claim_parity == 3) _thread_claim_parity = 1; - assert(_thread_claim_parity >= 1 && _thread_claim_parity <= 2, - "Not in range."); +void Threads::change_thread_claim_token() { + if (++_thread_claim_token == 0) { + // On overflow of the token counter, there is a risk of future + // collisions between a new global token value and a stale token + // for a thread, because not all iterations visit all threads. + // (Though it's pretty much a theoretical concern for non-trivial + // token counter sizes.) To deal with the possibility, reset all + // the thread tokens to zero on global token overflow. + struct ResetClaims : public ThreadClosure { + virtual void do_thread(Thread* t) { + t->claim_threads_do(false, 0); + } + } reset_claims; + Threads::threads_do(&reset_claims); + // On overflow, update the global token to non-zero, to + // avoid the special "never claimed" initial thread value. + _thread_claim_token = 1; + } } #ifdef ASSERT +void assert_thread_claimed(const char* kind, Thread* t, uintx expected) { + const uintx token = t->threads_do_token(); + assert(token == expected, + "%s " PTR_FORMAT " has incorrect value " UINTX_FORMAT " != " + UINTX_FORMAT, kind, p2i(t), token, expected); +} + void Threads::assert_all_threads_claimed() { ALL_JAVA_THREADS(p) { - const int thread_parity = p->oops_do_parity(); - assert((thread_parity == _thread_claim_parity), - "Thread " PTR_FORMAT " has incorrect parity %d != %d", p2i(p), thread_parity, _thread_claim_parity); - } - VMThread* vmt = VMThread::vm_thread(); - const int thread_parity = vmt->oops_do_parity(); - assert((thread_parity == _thread_claim_parity), - "VMThread " PTR_FORMAT " has incorrect parity %d != %d", p2i(vmt), thread_parity, _thread_claim_parity); + assert_thread_claimed("Thread", p, _thread_claim_token); + } + assert_thread_claimed("VMThread", VMThread::vm_thread(), _thread_claim_token); } #endif // ASSERT @@ -4585,7 +4607,7 @@ } } -void Threads::metadata_do(void f(Metadata*)) { +void Threads::metadata_do(MetadataClosure* f) { ALL_JAVA_THREADS(p) { p->metadata_do(f); } @@ -4784,7 +4806,7 @@ print_threads_compiling(st, buf, buflen); } -void Threads::print_threads_compiling(outputStream* st, char* buf, int buflen) { +void Threads::print_threads_compiling(outputStream* st, char* buf, int buflen, bool short_form) { ALL_JAVA_THREADS(thread) { if (thread->is_Compiler_thread()) { CompilerThread* ct = (CompilerThread*) thread; @@ -4797,7 +4819,7 @@ if (task != NULL) { thread->print_name_on_error(st, buf, buflen); st->print(" "); - task->print(st, NULL, true, true); + task->print(st, NULL, short_form, true); } } }