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));
}
示例#3
0
/*
 * 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);
}