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. Needed for fetch_frame_from_ucontext(), which is used by: 3505 // - Forte Analyzer: AsyncGetCallTrace() 3506 // - StackBanging: get_frame_at_stack_banging_point() 3507 // - JFR: get_topframe()-->....-->get_valid_uc_in_signal_handler() 3508 // 3509 // The remaining code is greatly simplified from the more general suspension 3510 // code that used to be used. 3511 // 3512 // The protocol is quite simple: 3513 // - suspend: 3514 // - sends a signal to the target thread 3515 // - polls the suspend state of the osthread using a yield loop 3516 // - target thread signal handler (SR_handler) sets suspend state 3517 // and blocks in sigsuspend until continued 3518 // - resume: 3519 // - sets target osthread state to continue 3520 // - sends signal to end the sigsuspend loop in the SR_handler 3521 // 3522 // Note that the SR_lock plays no role in this suspend/resume protocol, 3523 // but is checked for NULL in SR_handler as a thread termination indicator. 3524 // 3525 3526 static void resume_clear_context(OSThread *osthread) { 3527 osthread->set_ucontext(NULL); 3528 } 3529 3530 static void suspend_save_context(OSThread *osthread, ucontext_t* context) { 3531 osthread->set_ucontext(context); 3532 } 3533 3534 static PosixSemaphore sr_semaphore; 3535 3536 void os::Solaris::SR_handler(Thread* thread, ucontext_t* context) { 3537 // Save and restore errno to avoid confusing native code with EINTR 3538 // after sigsuspend. 3539 int old_errno = errno; 3540 3541 OSThread* osthread = thread->osthread(); 3542 assert(thread->is_VM_thread() || thread->is_Java_thread(), "Must be VMThread or JavaThread"); 3543 3544 os::SuspendResume::State current = osthread->sr.state(); 3545 if (current == os::SuspendResume::SR_SUSPEND_REQUEST) { 3546 suspend_save_context(osthread, context); 3547 3548 // attempt to switch the state, we assume we had a SUSPEND_REQUEST 3549 os::SuspendResume::State state = osthread->sr.suspended(); 3550 if (state == os::SuspendResume::SR_SUSPENDED) { 3551 sigset_t suspend_set; // signals for sigsuspend() 3552 3553 // get current set of blocked signals and unblock resume signal 3554 pthread_sigmask(SIG_BLOCK, NULL, &suspend_set); 3555 sigdelset(&suspend_set, ASYNC_SIGNAL); 3556 3557 sr_semaphore.signal(); 3558 // wait here until we are resumed 3559 while (1) { 3560 sigsuspend(&suspend_set); 3561 3562 os::SuspendResume::State result = osthread->sr.running(); 3563 if (result == os::SuspendResume::SR_RUNNING) { 3564 sr_semaphore.signal(); 3565 break; 3566 } 3673 if (osthread->sr.is_running()) { 3674 return; 3675 } 3676 } 3677 } else { 3678 ShouldNotReachHere(); 3679 } 3680 } 3681 3682 guarantee(osthread->sr.is_running(), "Must be running!"); 3683 } 3684 3685 void os::SuspendedThreadTask::internal_do_task() { 3686 if (do_suspend(_thread->osthread())) { 3687 SuspendedThreadTaskContext context(_thread, _thread->osthread()->ucontext()); 3688 do_task(context); 3689 do_resume(_thread->osthread()); 3690 } 3691 } 3692 3693 // This does not do anything on Solaris. This is basically a hook for being 3694 // able to use structured exception handling (thread-local exception filters) on, e.g., Win32. 3695 void os::os_exception_wrapper(java_call_t f, JavaValue* value, 3696 const methodHandle& method, JavaCallArguments* args, 3697 Thread* thread) { 3698 f(value, method, args, thread); 3699 } 3700 3701 // This routine may be used by user applications as a "hook" to catch signals. 3702 // The user-defined signal handler must pass unrecognized signals to this 3703 // routine, and if it returns true (non-zero), then the signal handler must 3704 // return immediately. If the flag "abort_if_unrecognized" is true, then this 3705 // routine will never retun false (zero), but instead will execute a VM panic 3706 // routine kill the process. 3707 // 3708 // If this routine returns false, it is OK to call it again. This allows 3709 // the user-defined signal handler to perform checks either before or after 3710 // the VM performs its own checks. Naturally, the user code would be making 3711 // a serious error if it tried to handle an exception (such as a null check 3712 // or breakpoint) that the VM was generating for its own correct operation. |