// osthread->sr->_state 变为 SR_SUSPEND_REQUEST if (osthread->sr.request_suspend() != os::SuspendResume::SR_SUSPEND_REQUEST) { // failed to switch, state wasn't running? ShouldNotReachHere(); returnfalse; } // 向线程传入 signal 信号(信号与对应的信号处理后续补充) // pthread_kill(osthread->pthread_id(), SR_signum) if (sr_notify(osthread) != 0) { ShouldNotReachHere(); }
// managed to send the signal and switch to SUSPEND_REQUEST, now wait for SUSPENDED while (true) { // 尝试将全局对象 sr_semaphore 的信号量 _semaphore -1 if (sr_semaphore.timedwait(create_semaphore_timespec(0, 2 * NANOSECS_PER_MILLISEC))) { // 完成 -1,跳出循环 break; } else { // 没完成即超过 2 ms的时间限制 // timeout os::SuspendResume::State cancelled = osthread->sr.cancel_suspend(); if (cancelled == os::SuspendResume::SR_RUNNING) { returnfalse; } elseif (cancelled == os::SuspendResume::SR_SUSPENDED) { // make sure that we consume the signal on the semaphore as well sr_semaphore.wait(); break; } else { ShouldNotReachHere(); returnfalse; } } }
guarantee(osthread->sr.is_suspended(), "Must be suspended"); returntrue; }
// pthread_kill 传递信号后,被采样的线程会进入异常处理函数,context 中会保留 CPU 上下文 staticvoidSR_handler(int sig, siginfo_t* siginfo, ucontext_t* context){ // Save and restore errno to avoid confusing native code with EINTR // after sigsuspend. int old_errno = errno; Thread* thread = Thread::current_or_null_safe();
OSThread* osthread = thread->osthread();
os::SuspendResume::State current = osthread->sr.state(); // 状态会在do_suspend 函数内被设置为 SR_SUSPEND_REQUEST if (current == os::SuspendResume::SR_SUSPEND_REQUEST) { // 将上下文信息保存到被采样的线程对象中去 suspend_save_context(osthread, siginfo, context);
// attempt to switch the state, we assume we had a SUSPEND_REQUEST // 准备将当前被采样线程暂停,需要将 state 变为 SR_SUSPENDED os::SuspendResume::State state = osthread->sr.suspended(); if (state == os::SuspendResume::SR_SUSPENDED) { sigset_t suspend_set; // signals for sigsuspend() sigemptyset(&suspend_set); // get current set of blocked signals and unblock resume signal pthread_sigmask(SIG_BLOCK, NULL, &suspend_set); sigdelset(&suspend_set, SR_signum);
sr_semaphore.signal(); // wait here until we are resumed while (1) { // 暂停线程,等待 UNBLOCK 信号唤醒 sigsuspend(&suspend_set);
os::SuspendResume::State result = osthread->sr.running(); if (result == os::SuspendResume::SR_RUNNING) { sr_semaphore.signal(); break; } }
//src/hotspot/os/posix/os_posix.cpp bool os::ThreadCrashProtection::call(os::CrashProtectionCallback& cb) { sigset_t saved_sig_mask; // 获取 _crash_mux 锁 Thread::muxAcquire(&_crash_mux, "CrashProtection"); // ... if (sigsetjmp(_jmpbuf, 0) == 0) { // make sure we can see in the signal handler that we have crash protection // installed _crash_protection = this; cb.call(); //... } //... } //src/hotspot/share/jfr/periodic/sampling/jfrThreadSampler.cpp // 最终方法采样调用的是 OSThreadSamplerCallback 类的 call 方法 classOSThreadSamplerCallback : public os::CrashProtectionCallback { //... virtualvoidcall(){ // 最终的反栈函数 _sampler.protected_task(_context); } //... };
voidOSThreadSampler::protected_task(const os::SuspendedThreadTaskContext& context){ // 被采样线程 JavaThread* jth = (JavaThread*)context.thread(); // Skip sample if we signaled a thread that moved to other state if (!thread_state_in_java(jth)) { return; } JfrGetCallTrace trace(true, jth); // 存储栈顶方法的栈信息 fp pc sp sender_sp frame topframe; // 获取被采样线程的函数调用栈的栈顶,放入 topframe,确保栈顶有方法 if (trace.get_topframe(context.ucontext(), topframe)) { // 根据栈顶函数状态和被采样线程指针将栈信息保存到线程私有的内存内 if (_stacktrace.record_thread(*jth, topframe)) { /* If we managed to get a topframe and a stacktrace, create an event * and put it into our array. We can't call Jfr::_stacktraces.add() * here since it would allocate memory using malloc. Doing so while * the stopped thread is inside malloc would deadlock. */ // jfr event 记录 _success = true; EventExecutionSample *ev = _closure.next_event(); ev->set_starttime(_suspend_time); ev->set_endtime(_suspend_time); // fake to not take an end time ev->set_sampledThread(JFR_THREAD_ID(jth)); ev->set_state(java_lang_Thread::get_thread_status(jth->threadObj())); } } }