int sigresend(int sig, siginfo_t *siginfo, sigset_t *mask) { kthread_t *t = curthread; klwp_t *lwp = ttolwp(t); sigqueue_t *sqp = kmem_zalloc(sizeof (*sqp), KM_SLEEP); sigset_t set; k_sigset_t kset; int error; if (sig <= 0 || sig >= NSIG || sigismember(&cantmask, sig)) { error = EINVAL; goto bad; } if (siginfo == NULL) { sqp->sq_info.si_signo = sig; sqp->sq_info.si_code = SI_NOINFO; } else { if (copyin_siginfo(get_udatamodel(), siginfo, &sqp->sq_info)) { error = EFAULT; goto bad; } if (sqp->sq_info.si_signo != sig) { error = EINVAL; goto bad; } } if (copyin(mask, &set, sizeof (set))) { error = EFAULT; goto bad; } sigutok(&set, &kset); /* * We don't need to acquire p->p_lock here; * we are manipulating thread-private data. */ if (lwp->lwp_cursig || lwp->lwp_curinfo) { t->t_sig_check = 1; error = EAGAIN; goto bad; } lwp->lwp_cursig = sig; lwp->lwp_curinfo = sqp; schedctl_finish_sigblock(t); t->t_hold = kset; t->t_sig_check = 1; return (0); bad: kmem_free(sqp, sizeof (*sqp)); return (set_errno(error)); }
int sigsuspend(sigset_t *setp) { sigset_t set; k_sigset_t kset; proc_t *p = curproc; if (copyin((caddr_t)setp, (caddr_t)&set, sizeof (sigset_t))) return (set_errno(EFAULT)); sigutok(&set, &kset); mutex_enter(&p->p_lock); schedctl_finish_sigblock(curthread); ttolwp(curthread)->lwp_sigoldmask = curthread->t_hold; curthread->t_hold = kset; curthread->t_sig_check = 1; /* so post-syscall will re-evaluate */ curthread->t_flag |= T_TOMASK; /* pause() */ while (cv_wait_sig_swap(&curthread->t_delay_cv, &p->p_lock)) ; mutex_exit(&p->p_lock); return (set_errno(EINTR)); }
/* * Handle a watchpoint that occurs while doing copyin() * or copyout() in a system call. * Return non-zero if the fault or signal is cleared * by a debugger while the lwp is stopped. */ static int sys_watchpoint(caddr_t addr, int watchcode, int ta) { extern greg_t getuserpc(void); /* XXX header file */ k_sigset_t smask; register proc_t *p = ttoproc(curthread); register klwp_t *lwp = ttolwp(curthread); register sigqueue_t *sqp; int rval; /* assert no locks are held */ /* ASSERT(curthread->t_nlocks == 0); */ sqp = kmem_zalloc(sizeof (sigqueue_t), KM_SLEEP); sqp->sq_info.si_signo = SIGTRAP; sqp->sq_info.si_code = watchcode; sqp->sq_info.si_addr = addr; sqp->sq_info.si_trapafter = ta; sqp->sq_info.si_pc = (caddr_t)getuserpc(); mutex_enter(&p->p_lock); /* this will be tested and cleared by the caller */ lwp->lwp_sysabort = 0; if (prismember(&p->p_fltmask, FLTWATCH)) { lwp->lwp_curflt = (uchar_t)FLTWATCH; lwp->lwp_siginfo = sqp->sq_info; stop(PR_FAULTED, FLTWATCH); if (lwp->lwp_curflt == 0) { mutex_exit(&p->p_lock); kmem_free(sqp, sizeof (sigqueue_t)); return (1); } lwp->lwp_curflt = 0; } /* * post the SIGTRAP signal. * Block all other signals so we only stop showing SIGTRAP. */ if (signal_is_blocked(curthread, SIGTRAP) || sigismember(&p->p_ignore, SIGTRAP)) { /* SIGTRAP is blocked or ignored, forget the rest. */ mutex_exit(&p->p_lock); kmem_free(sqp, sizeof (sigqueue_t)); return (0); } sigdelq(p, curthread, SIGTRAP); sigaddqa(p, curthread, sqp); schedctl_finish_sigblock(curthread); smask = curthread->t_hold; sigfillset(&curthread->t_hold); sigdiffset(&curthread->t_hold, &cantmask); sigdelset(&curthread->t_hold, SIGTRAP); mutex_exit(&p->p_lock); rval = ((ISSIG_FAST(curthread, lwp, p, FORREAL))? 0 : 1); /* restore the original signal mask */ mutex_enter(&p->p_lock); curthread->t_hold = smask; mutex_exit(&p->p_lock); return (rval); }