3479 int p; 3480 if (!UseThreadPriorities) { 3481 *priority_ptr = NormalPriority; 3482 return OS_OK; 3483 } 3484 int status = thr_getprio(thread->osthread()->thread_id(), &p); 3485 if (status != 0) { 3486 return OS_ERR; 3487 } 3488 *priority_ptr = p; 3489 return OS_OK; 3490 } 3491 3492 3493 // Hint to the underlying OS that a task switch would not be good. 3494 // Void return because it's a hint and can fail. 3495 void os::hint_no_preempt() { 3496 schedctl_start(schedctl_init()); 3497 } 3498 3499 static void resume_clear_context(OSThread *osthread) { 3500 osthread->set_ucontext(NULL); 3501 } 3502 3503 static void suspend_save_context(OSThread *osthread, ucontext_t* context) { 3504 osthread->set_ucontext(context); 3505 } 3506 3507 static PosixSemaphore sr_semaphore; 3508 3509 void os::Solaris::SR_handler(Thread* thread, ucontext_t* uc) { 3510 // Save and restore errno to avoid confusing native code with EINTR 3511 // after sigsuspend. 3512 int old_errno = errno; 3513 3514 OSThread* osthread = thread->osthread(); 3515 assert(thread->is_VM_thread() || thread->is_Java_thread(), "Must be VMThread or JavaThread"); 3516 3517 os::SuspendResume::State current = osthread->sr.state(); 3518 if (current == os::SuspendResume::SR_SUSPEND_REQUEST) { 3519 suspend_save_context(osthread, uc); 3520 3521 // attempt to switch the state, we assume we had a SUSPEND_REQUEST 3522 os::SuspendResume::State state = osthread->sr.suspended(); 3523 if (state == os::SuspendResume::SR_SUSPENDED) { 3524 sigset_t suspend_set; // signals for sigsuspend() 3525 3526 // get current set of blocked signals and unblock resume signal 3527 pthread_sigmask(SIG_BLOCK, NULL, &suspend_set); 3528 sigdelset(&suspend_set, ASYNC_SIGNAL); 3529 3530 sr_semaphore.signal(); 3531 // wait here until we are resumed 3532 while (1) { 3533 sigsuspend(&suspend_set); 3534 3535 os::SuspendResume::State result = osthread->sr.running(); 3536 if (result == os::SuspendResume::SR_RUNNING) { 3537 sr_semaphore.signal(); 3538 break; 3539 } 3646 if (osthread->sr.is_running()) { 3647 return; 3648 } 3649 } 3650 } else { 3651 ShouldNotReachHere(); 3652 } 3653 } 3654 3655 guarantee(osthread->sr.is_running(), "Must be running!"); 3656 } 3657 3658 void os::SuspendedThreadTask::internal_do_task() { 3659 if (do_suspend(_thread->osthread())) { 3660 SuspendedThreadTaskContext context(_thread, _thread->osthread()->ucontext()); 3661 do_task(context); 3662 do_resume(_thread->osthread()); 3663 } 3664 } 3665 3666 class PcFetcher : public os::SuspendedThreadTask { 3667 public: 3668 PcFetcher(Thread* thread) : os::SuspendedThreadTask(thread) {} 3669 ExtendedPC result(); 3670 protected: 3671 void do_task(const os::SuspendedThreadTaskContext& context); 3672 private: 3673 ExtendedPC _epc; 3674 }; 3675 3676 ExtendedPC PcFetcher::result() { 3677 guarantee(is_done(), "task is not done yet."); 3678 return _epc; 3679 } 3680 3681 void PcFetcher::do_task(const os::SuspendedThreadTaskContext& context) { 3682 Thread* thread = context.thread(); 3683 OSThread* osthread = thread->osthread(); 3684 if (osthread->ucontext() != NULL) { 3685 _epc = os::Solaris::ucontext_get_pc((const ucontext_t *) context.ucontext()); 3686 } else { 3687 // NULL context is unexpected, double-check this is the VMThread 3688 guarantee(thread->is_VM_thread(), "can only be called for VMThread"); 3689 } 3690 } 3691 3692 // A lightweight implementation that does not suspend the target thread and 3693 // thus returns only a hint. Used for profiling only! 3694 ExtendedPC os::get_thread_pc(Thread* thread) { 3695 // Make sure that it is called by the watcher and the Threads lock is owned. 3696 assert(Thread::current()->is_Watcher_thread(), "Must be watcher and own Threads_lock"); 3697 // For now, is only used to profile the VM Thread 3698 assert(thread->is_VM_thread(), "Can only be called for VMThread"); 3699 PcFetcher fetcher(thread); 3700 fetcher.run(); 3701 return fetcher.result(); 3702 } 3703 3704 3705 // This does not do anything on Solaris. This is basically a hook for being 3706 // able to use structured exception handling (thread-local exception filters) on, e.g., Win32. 3707 void os::os_exception_wrapper(java_call_t f, JavaValue* value, 3708 const methodHandle& method, JavaCallArguments* args, 3709 Thread* thread) { 3710 f(value, method, args, thread); 3711 } 3712 3713 // This routine may be used by user applications as a "hook" to catch signals. 3714 // The user-defined signal handler must pass unrecognized signals to this 3715 // routine, and if it returns true (non-zero), then the signal handler must 3716 // return immediately. If the flag "abort_if_unrecognized" is true, then this 3717 // routine will never retun false (zero), but instead will execute a VM panic 3718 // routine kill the process. 3719 // 3720 // If this routine returns false, it is OK to call it again. This allows 3721 // the user-defined signal handler to perform checks either before or after 3722 // the VM performs its own checks. Naturally, the user code would be making 3723 // a serious error if it tried to handle an exception (such as a null check 3724 // or breakpoint) that the VM was generating for its own correct operation. | 3479 int p; 3480 if (!UseThreadPriorities) { 3481 *priority_ptr = NormalPriority; 3482 return OS_OK; 3483 } 3484 int status = thr_getprio(thread->osthread()->thread_id(), &p); 3485 if (status != 0) { 3486 return OS_ERR; 3487 } 3488 *priority_ptr = p; 3489 return OS_OK; 3490 } 3491 3492 3493 // Hint to the underlying OS that a task switch would not be good. 3494 // Void return because it's a hint and can fail. 3495 void os::hint_no_preempt() { 3496 schedctl_start(schedctl_init()); 3497 } 3498 3499 //////////////////////////////////////////////////////////////////////////////// 3500 // suspend/resume support 3501 3502 // The low-level signal-based suspend/resume support is a remnant from the 3503 // old VM-suspension that used to be for java-suspension, safepoints etc, 3504 // within hotspot. Currently used by JFR's OSThreadSampler 3505 // 3506 // The remaining code is greatly simplified from the more general suspension 3507 // code that used to be used. 3508 // 3509 // The protocol is quite simple: 3510 // - suspend: 3511 // - sends a signal to the target thread 3512 // - polls the suspend state of the osthread using a yield loop 3513 // - target thread signal handler (SR_handler) sets suspend state 3514 // and blocks in sigsuspend until continued 3515 // - resume: 3516 // - sets target osthread state to continue 3517 // - sends signal to end the sigsuspend loop in the SR_handler 3518 // 3519 // Note that the SR_lock plays no role in this suspend/resume protocol, 3520 // but is checked for NULL in SR_handler as a thread termination indicator. 3521 // The SR_lock is, however, used by JavaThread::java_suspend()/java_resume() APIs. 3522 // 3523 // Note that resume_clear_context() and suspend_save_context() are needed 3524 // by SR_handler(), so that fetch_frame_from_ucontext() works, 3525 // which in part is used by: 3526 // - Forte Analyzer: AsyncGetCallTrace() 3527 // - StackBanging: get_frame_at_stack_banging_point() 3528 // - JFR: get_topframe()-->....-->get_valid_uc_in_signal_handler() 3529 3530 static void resume_clear_context(OSThread *osthread) { 3531 osthread->set_ucontext(NULL); 3532 } 3533 3534 static void suspend_save_context(OSThread *osthread, ucontext_t* context) { 3535 osthread->set_ucontext(context); 3536 } 3537 3538 static PosixSemaphore sr_semaphore; 3539 3540 void os::Solaris::SR_handler(Thread* thread, ucontext_t* context) { 3541 // Save and restore errno to avoid confusing native code with EINTR 3542 // after sigsuspend. 3543 int old_errno = errno; 3544 3545 OSThread* osthread = thread->osthread(); 3546 assert(thread->is_VM_thread() || thread->is_Java_thread(), "Must be VMThread or JavaThread"); 3547 3548 os::SuspendResume::State current = osthread->sr.state(); 3549 if (current == os::SuspendResume::SR_SUSPEND_REQUEST) { 3550 suspend_save_context(osthread, context); 3551 3552 // attempt to switch the state, we assume we had a SUSPEND_REQUEST 3553 os::SuspendResume::State state = osthread->sr.suspended(); 3554 if (state == os::SuspendResume::SR_SUSPENDED) { 3555 sigset_t suspend_set; // signals for sigsuspend() 3556 3557 // get current set of blocked signals and unblock resume signal 3558 pthread_sigmask(SIG_BLOCK, NULL, &suspend_set); 3559 sigdelset(&suspend_set, ASYNC_SIGNAL); 3560 3561 sr_semaphore.signal(); 3562 // wait here until we are resumed 3563 while (1) { 3564 sigsuspend(&suspend_set); 3565 3566 os::SuspendResume::State result = osthread->sr.running(); 3567 if (result == os::SuspendResume::SR_RUNNING) { 3568 sr_semaphore.signal(); 3569 break; 3570 } 3677 if (osthread->sr.is_running()) { 3678 return; 3679 } 3680 } 3681 } else { 3682 ShouldNotReachHere(); 3683 } 3684 } 3685 3686 guarantee(osthread->sr.is_running(), "Must be running!"); 3687 } 3688 3689 void os::SuspendedThreadTask::internal_do_task() { 3690 if (do_suspend(_thread->osthread())) { 3691 SuspendedThreadTaskContext context(_thread, _thread->osthread()->ucontext()); 3692 do_task(context); 3693 do_resume(_thread->osthread()); 3694 } 3695 } 3696 3697 // This does not do anything on Solaris. This is basically a hook for being 3698 // able to use structured exception handling (thread-local exception filters) on, e.g., Win32. 3699 void os::os_exception_wrapper(java_call_t f, JavaValue* value, 3700 const methodHandle& method, JavaCallArguments* args, 3701 Thread* thread) { 3702 f(value, method, args, thread); 3703 } 3704 3705 // This routine may be used by user applications as a "hook" to catch signals. 3706 // The user-defined signal handler must pass unrecognized signals to this 3707 // routine, and if it returns true (non-zero), then the signal handler must 3708 // return immediately. If the flag "abort_if_unrecognized" is true, then this 3709 // routine will never retun false (zero), but instead will execute a VM panic 3710 // routine kill the process. 3711 // 3712 // If this routine returns false, it is OK to call it again. This allows 3713 // the user-defined signal handler to perform checks either before or after 3714 // the VM performs its own checks. Naturally, the user code would be making 3715 // a serious error if it tried to handle an exception (such as a null check 3716 // or breakpoint) that the VM was generating for its own correct operation. |