--- old/src/os/solaris/vm/os_solaris.cpp 2017-08-18 12:12:44.000000000 -0500 +++ new/src/os/solaris/vm/os_solaris.cpp 2017-08-18 12:12:44.000000000 -0500 @@ -3496,6 +3496,37 @@ schedctl_start(schedctl_init()); } +//////////////////////////////////////////////////////////////////////////////// +// suspend/resume support + +// The low-level signal-based suspend/resume support is a remnant from the +// old VM-suspension that used to be for java-suspension, safepoints etc, +// within hotspot. Currently used by JFR's OSThreadSampler +// +// The remaining code is greatly simplified from the more general suspension +// code that used to be used. +// +// The protocol is quite simple: +// - suspend: +// - sends a signal to the target thread +// - polls the suspend state of the osthread using a yield loop +// - target thread signal handler (SR_handler) sets suspend state +// and blocks in sigsuspend until continued +// - resume: +// - sets target osthread state to continue +// - sends signal to end the sigsuspend loop in the SR_handler +// +// Note that the SR_lock plays no role in this suspend/resume protocol, +// but is checked for NULL in SR_handler as a thread termination indicator. +// The SR_lock is, however, used by JavaThread::java_suspend()/java_resume() APIs. +// +// Note that resume_clear_context() and suspend_save_context() are needed +// by SR_handler(), so that fetch_frame_from_ucontext() works, +// which in part is used by: +// - Forte Analyzer: AsyncGetCallTrace() +// - StackBanging: get_frame_at_stack_banging_point() +// - JFR: get_topframe()-->....-->get_valid_uc_in_signal_handler() + static void resume_clear_context(OSThread *osthread) { osthread->set_ucontext(NULL); } @@ -3506,7 +3537,7 @@ static PosixSemaphore sr_semaphore; -void os::Solaris::SR_handler(Thread* thread, ucontext_t* uc) { +void os::Solaris::SR_handler(Thread* thread, ucontext_t* context) { // Save and restore errno to avoid confusing native code with EINTR // after sigsuspend. int old_errno = errno; @@ -3516,7 +3547,7 @@ os::SuspendResume::State current = osthread->sr.state(); if (current == os::SuspendResume::SR_SUSPEND_REQUEST) { - suspend_save_context(osthread, uc); + suspend_save_context(osthread, context); // attempt to switch the state, we assume we had a SUSPEND_REQUEST os::SuspendResume::State state = osthread->sr.suspended(); @@ -3538,7 +3569,7 @@ break; } } - + } else if (state == os::SuspendResume::SR_RUNNING) { // request was cancelled, continue } else { @@ -3663,45 +3694,6 @@ } } -class PcFetcher : public os::SuspendedThreadTask { - public: - PcFetcher(Thread* thread) : os::SuspendedThreadTask(thread) {} - ExtendedPC result(); - protected: - void do_task(const os::SuspendedThreadTaskContext& context); - private: - ExtendedPC _epc; -}; - -ExtendedPC PcFetcher::result() { - guarantee(is_done(), "task is not done yet."); - return _epc; -} - -void PcFetcher::do_task(const os::SuspendedThreadTaskContext& context) { - Thread* thread = context.thread(); - OSThread* osthread = thread->osthread(); - if (osthread->ucontext() != NULL) { - _epc = os::Solaris::ucontext_get_pc((const ucontext_t *) context.ucontext()); - } else { - // NULL context is unexpected, double-check this is the VMThread - guarantee(thread->is_VM_thread(), "can only be called for VMThread"); - } -} - -// A lightweight implementation that does not suspend the target thread and -// thus returns only a hint. Used for profiling only! -ExtendedPC os::get_thread_pc(Thread* thread) { - // Make sure that it is called by the watcher and the Threads lock is owned. - assert(Thread::current()->is_Watcher_thread(), "Must be watcher and own Threads_lock"); - // For now, is only used to profile the VM Thread - assert(thread->is_VM_thread(), "Can only be called for VMThread"); - PcFetcher fetcher(thread); - fetcher.run(); - return fetcher.result(); -} - - // This does not do anything on Solaris. This is basically a hook for being // able to use structured exception handling (thread-local exception filters) on, e.g., Win32. void os::os_exception_wrapper(java_call_t f, JavaValue* value,