diff options
Diffstat (limited to 'sys/kern/kern_sig.c')
-rw-r--r-- | sys/kern/kern_sig.c | 244 |
1 files changed, 166 insertions, 78 deletions
diff --git a/sys/kern/kern_sig.c b/sys/kern/kern_sig.c index 607c78c..233bdbe 100644 --- a/sys/kern/kern_sig.c +++ b/sys/kern/kern_sig.c @@ -74,7 +74,7 @@ #define ONSIG 32 /* NSIG for osig* syscalls. XXX. */ -static int coredump __P((struct proc *)); +static int coredump __P((struct thread *)); static int do_sigaction __P((struct proc *p, int sig, struct sigaction *act, struct sigaction *oact, int old)); static int do_sigprocmask __P((struct proc *p, int how, sigset_t *set, @@ -351,10 +351,11 @@ struct sigaction_args { */ /* ARGSUSED */ int -sigaction(p, uap) - struct proc *p; +sigaction(td, uap) + struct thread *td; register struct sigaction_args *uap; { + struct proc *p = td->td_proc; struct sigaction act, oact; register struct sigaction *actp, *oactp; int error; @@ -390,10 +391,11 @@ struct osigaction_args { */ /* ARGSUSED */ int -osigaction(p, uap) - struct proc *p; +osigaction(td, uap) + struct thread *td; register struct osigaction_args *uap; { + struct proc *p = td->td_proc; struct osigaction sa; struct sigaction nsa, osa; register struct sigaction *nsap, *osap; @@ -534,7 +536,7 @@ do_sigprocmask(p, how, set, oset, old) } /* - * sigprocmask() - MP SAFE + * sigprocmask() - MP SAFE (XXXKSE not under KSE it isn't) */ #ifndef _SYS_SYSPROTO_H_ @@ -545,10 +547,11 @@ struct sigprocmask_args { }; #endif int -sigprocmask(p, uap) - register struct proc *p; +sigprocmask(td, uap) + register struct thread *td; struct sigprocmask_args *uap; { + struct proc *p = td->td_proc; sigset_t set, oset; sigset_t *setp, *osetp; int error; @@ -578,16 +581,17 @@ struct osigprocmask_args { }; #endif int -osigprocmask(p, uap) - register struct proc *p; +osigprocmask(td, uap) + register struct thread *td; struct osigprocmask_args *uap; { + struct proc *p = td->td_proc; sigset_t set, oset; int error; OSIG2SIG(uap->mask, set); error = do_sigprocmask(p, uap->how, &set, &oset, 1); - SIG2OSIG(oset, p->p_retval[0]); + SIG2OSIG(oset, td->td_retval[0]); return (error); } #endif /* COMPAT_43 */ @@ -602,10 +606,11 @@ struct sigpending_args { */ /* ARGSUSED */ int -sigpending(p, uap) - struct proc *p; +sigpending(td, uap) + struct thread *td; struct sigpending_args *uap; { + struct proc *p = td->td_proc; sigset_t siglist; int error; @@ -629,13 +634,15 @@ struct osigpending_args { */ /* ARGSUSED */ int -osigpending(p, uap) - struct proc *p; +osigpending(td, uap) + struct thread *td; struct osigpending_args *uap; { + struct proc *p = td->td_proc; + mtx_lock(&Giant); PROC_LOCK(p); - SIG2OSIG(p->p_siglist, p->p_retval[0]); + SIG2OSIG(p->p_siglist, td->td_retval[0]); PROC_UNLOCK(p); mtx_unlock(&Giant); return (0); @@ -658,10 +665,11 @@ struct osigvec_args { */ /* ARGSUSED */ int -osigvec(p, uap) - struct proc *p; +osigvec(td, uap) + struct thread *td; register struct osigvec_args *uap; { + struct proc *p = td->td_proc; struct sigvec vec; struct sigaction nsa, osa; register struct sigaction *nsap, *osap; @@ -709,17 +717,18 @@ struct osigblock_args { * MPSAFE */ int -osigblock(p, uap) - register struct proc *p; +osigblock(td, uap) + register struct thread *td; struct osigblock_args *uap; { + struct proc *p = td->td_proc; sigset_t set; OSIG2SIG(uap->mask, set); SIG_CANTMASK(set); mtx_lock(&Giant); PROC_LOCK(p); - SIG2OSIG(p->p_sigmask, p->p_retval[0]); + SIG2OSIG(p->p_sigmask, td->td_retval[0]); SIGSETOR(p->p_sigmask, set); PROC_UNLOCK(p); mtx_unlock(&Giant); @@ -735,17 +744,18 @@ struct osigsetmask_args { * MPSAFE */ int -osigsetmask(p, uap) - struct proc *p; +osigsetmask(td, uap) + struct thread *td; struct osigsetmask_args *uap; { + struct proc *p = td->td_proc; sigset_t set; OSIG2SIG(uap->mask, set); SIG_CANTMASK(set); mtx_lock(&Giant); PROC_LOCK(p); - SIG2OSIG(p->p_sigmask, p->p_retval[0]); + SIG2OSIG(p->p_sigmask, td->td_retval[0]); SIGSETLO(p->p_sigmask, set); PROC_UNLOCK(p); mtx_unlock(&Giant); @@ -757,6 +767,9 @@ osigsetmask(p, uap) * Suspend process until signal, providing mask to be set * in the meantime. Note nonstandard calling convention: * libc stub passes mask, not pointer, to save a copyin. + ***** XXXKSE this doesn't make sense under KSE. + ***** Do we suspend the thread or all threads in the process? + ***** How do we suspend threads running NOW on another processor? */ #ifndef _SYS_SYSPROTO_H_ struct sigsuspend_args { @@ -768,10 +781,11 @@ struct sigsuspend_args { */ /* ARGSUSED */ int -sigsuspend(p, uap) - register struct proc *p; +sigsuspend(td, uap) + struct thread *td; struct sigsuspend_args *uap; { + struct proc *p = td->td_proc; sigset_t mask; register struct sigacts *ps; int error; @@ -814,10 +828,11 @@ struct osigsuspend_args { */ /* ARGSUSED */ int -osigsuspend(p, uap) - register struct proc *p; +osigsuspend(td, uap) + struct thread *td; struct osigsuspend_args *uap; { + struct proc *p = td->td_proc; sigset_t mask; register struct sigacts *ps; @@ -850,10 +865,11 @@ struct osigstack_args { */ /* ARGSUSED */ int -osigstack(p, uap) - struct proc *p; +osigstack(td, uap) + struct thread *td; register struct osigstack_args *uap; { + struct proc *p = td->td_proc; struct sigstack ss; int error = 0; @@ -862,7 +878,7 @@ osigstack(p, uap) if (uap->oss != NULL) { PROC_LOCK(p); ss.ss_sp = p->p_sigstk.ss_sp; - ss.ss_onstack = sigonstack(cpu_getstack(p)); + ss.ss_onstack = sigonstack(cpu_getstack(td)); PROC_UNLOCK(p); error = copyout(&ss, uap->oss, sizeof(struct sigstack)); if (error) @@ -896,17 +912,18 @@ struct sigaltstack_args { */ /* ARGSUSED */ int -sigaltstack(p, uap) - struct proc *p; +sigaltstack(td, uap) + struct thread *td; register struct sigaltstack_args *uap; { + struct proc *p = td->td_proc; stack_t ss; int oonstack; int error = 0; mtx_lock(&Giant); - oonstack = sigonstack(cpu_getstack(p)); + oonstack = sigonstack(cpu_getstack(td)); if (uap->oss != NULL) { PROC_LOCK(p); @@ -1027,10 +1044,11 @@ struct kill_args { */ /* ARGSUSED */ int -kill(cp, uap) - register struct proc *cp; +kill(td, uap) + register struct thread *td; register struct kill_args *uap; { + register struct proc *cp = td->td_proc; register struct proc *p; int error = 0; @@ -1080,8 +1098,8 @@ struct okillpg_args { */ /* ARGSUSED */ int -okillpg(p, uap) - struct proc *p; +okillpg(td, uap) + struct thread *td; register struct okillpg_args *uap; { int error; @@ -1089,7 +1107,7 @@ okillpg(p, uap) if ((u_int)uap->signum > _SIG_MAXSIG) return (EINVAL); mtx_lock(&Giant); - error = killpg1(p, uap->signum, uap->pgid, 0); + error = killpg1(td->td_proc, uap->signum, uap->pgid, 0); mtx_unlock(&Giant); return (error); } @@ -1198,6 +1216,8 @@ psignal(p, sig) { register int prop; register sig_t action; + struct thread *td; + struct ksegrp *kg; if (sig > _SIG_MAXSIG || sig <= 0) { printf("psignal: signal %d\n", sig); @@ -1214,9 +1234,9 @@ psignal(p, sig) * if signal event is tracked by procfs, give *that* * a chance, as well. */ - if ((p->p_flag & P_TRACED) || (p->p_stops & S_SIG)) + if ((p->p_flag & P_TRACED) || (p->p_stops & S_SIG)) { action = SIG_DFL; - else { + } else { /* * If the signal is being ignored, * then we forget about it immediately. @@ -1234,10 +1254,27 @@ psignal(p, sig) action = SIG_DFL; } + /* + * bring the priority of a process up if we want it to get + * killed in this lifetime. + * XXXKSE think if a better way to do this. + * + * What we need to do is see if there is a thread that will + * be able to accept the signal. e.g. + * FOREACH_THREAD_IN_PROC() { + * if runnable, we're done + * else pick one at random. + * } + */ + /* XXXKSE + * For now there is one thread per proc. + * Effectively select one sucker thread.. + */ + td = &p->p_thread; mtx_lock_spin(&sched_lock); - if (p->p_nice > NZERO && action == SIG_DFL && (prop & SA_KILL) && - (p->p_flag & P_TRACED) == 0) - p->p_nice = NZERO; + if ((p->p_ksegrp.kg_nice > NZERO) && (action == SIG_DFL) && + (prop & SA_KILL) && ((p->p_flag & P_TRACED) == 0)) + p->p_ksegrp.kg_nice = NZERO; /* XXXKSE */ mtx_unlock_spin(&sched_lock); if (prop & SA_CONT) @@ -1266,6 +1303,7 @@ psignal(p, sig) mtx_unlock_spin(&sched_lock); return; } + switch (p->p_stat) { case SSLEEP: @@ -1275,7 +1313,7 @@ psignal(p, sig) * be noticed when the process returns through * trap() or syscall(). */ - if ((p->p_sflag & PS_SINTR) == 0) { + if ((td->td_flags & TDF_SINTR) == 0) { mtx_unlock_spin(&sched_lock); goto out; } @@ -1357,11 +1395,28 @@ psignal(p, sig) if (action == SIG_CATCH) goto runfast; mtx_lock_spin(&sched_lock); - if (p->p_wchan == NULL) - goto run; - p->p_stat = SSLEEP; - mtx_unlock_spin(&sched_lock); - goto out; + /* + * XXXKSE + * do this for each thread. + */ + if (p->p_flag & P_KSES) { + mtx_assert(&sched_lock, + MA_OWNED | MA_NOTRECURSED); + FOREACH_THREAD_IN_PROC(p, td) { + if (td->td_wchan == NULL) { + setrunnable(td); /* XXXKSE */ + } else { + /* mark it as sleeping */ + } + } + mtx_unlock_spin(&sched_lock); + goto out; + } else { + if (p->p_thread.td_wchan == NULL) + goto run; + p->p_stat = SSLEEP; + mtx_unlock_spin(&sched_lock); + } } if (prop & SA_STOP) { @@ -1378,13 +1433,25 @@ psignal(p, sig) * wakeup so that when it is continued, it will be made * runnable and can look at the signal. But don't make * the process runnable, leave it stopped. + * XXXKSE should we wake ALL blocked threads? */ mtx_lock_spin(&sched_lock); - if (p->p_wchan && p->p_sflag & PS_SINTR) { - if (p->p_sflag & PS_CVWAITQ) - cv_waitq_remove(p); - else - unsleep(p); + if (p->p_flag & P_KSES) { + FOREACH_THREAD_IN_PROC(p, td) { + if (td->td_wchan && (td->td_flags & TDF_SINTR)){ + if (td->td_flags & TDF_CVWAITQ) + cv_waitq_remove(td); + else + unsleep(td); /* XXXKSE */ + } + } + } else { + if (td->td_wchan && td->td_flags & TDF_SINTR) { + if (td->td_flags & TDF_CVWAITQ) + cv_waitq_remove(td); + else + unsleep(td); /* XXXKSE */ + } } mtx_unlock_spin(&sched_lock); goto out; @@ -1396,9 +1463,21 @@ psignal(p, sig) * It will either never be noticed, or noticed very soon. */ if (p->p_stat == SRUN) { - signotify(p); #ifdef SMP - forward_signal(p); + struct kse *ke; + struct thread *td = curthread; + signotify(&p->p_kse); /* XXXKSE */ +/* we should only deliver to one thread.. but which one? */ + FOREACH_KSEGRP_IN_PROC(p, kg) { + FOREACH_KSE_IN_GROUP(kg, ke) { + if (ke->ke_thread == td) { + continue; + } + forward_signal(ke->ke_thread); + } + } +#else + signotify(&p->p_kse); /* XXXKSE */ #endif } mtx_unlock_spin(&sched_lock); @@ -1409,14 +1488,19 @@ psignal(p, sig) runfast: /* * Raise priority to at least PUSER. + * XXXKSE Should we make them all run fast? + * Maybe just one would be enough? */ mtx_lock_spin(&sched_lock); - if (p->p_pri.pri_level > PUSER) - p->p_pri.pri_level = PUSER; + FOREACH_KSEGRP_IN_PROC(p, kg) { + if (kg->kg_pri.pri_level > PUSER) { + kg->kg_pri.pri_level = PUSER; + } + } run: /* If we jump here, sched_lock has to be owned. */ mtx_assert(&sched_lock, MA_OWNED | MA_NOTRECURSED); - setrunnable(p); + setrunnable(td); /* XXXKSE */ mtx_unlock_spin(&sched_lock); out: /* If we jump here, sched_lock should not be owned. */ @@ -1623,7 +1707,8 @@ void postsig(sig) register int sig; { - register struct proc *p = curproc; + struct thread *td = curthread; + register struct proc *p = td->td_proc; struct sigacts *ps; sig_t action; sigset_t returnmask; @@ -1647,7 +1732,7 @@ postsig(sig) * Default action, where the default is to kill * the process. (Other cases were ignored above.) */ - sigexit(p, sig); + sigexit(td, sig); /* NOTREACHED */ } else { /* @@ -1722,10 +1807,11 @@ killproc(p, why) * does not return. */ void -sigexit(p, sig) - register struct proc *p; +sigexit(td, sig) + struct thread *td; int sig; { + struct proc *p = td->td_proc; PROC_LOCK_ASSERT(p, MA_OWNED); p->p_acflag |= AXSIG; @@ -1740,7 +1826,7 @@ sigexit(p, sig) PROC_UNLOCK(p); if (!mtx_owned(&Giant)) mtx_lock(&Giant); - if (coredump(p) == 0) + if (coredump(td) == 0) sig |= WCOREFLAG; if (kern_logsigexit) log(LOG_INFO, @@ -1754,7 +1840,7 @@ sigexit(p, sig) if (!mtx_owned(&Giant)) mtx_lock(&Giant); } - exit1(p, W_EXITCODE(0, sig)); + exit1(td, W_EXITCODE(0, sig)); /* NOTREACHED */ } @@ -1849,9 +1935,9 @@ const char *name; uid_t uid; pid_t pid; { */ static int -coredump(p) - register struct proc *p; +coredump(struct thread *td) { + struct proc *p = td->td_proc; register struct vnode *vp; register struct ucred *cred = p->p_ucred; struct flock lf; @@ -1889,7 +1975,7 @@ restart: name = expand_name(p->p_comm, p->p_ucred->cr_uid, p->p_pid); if (name == NULL) return (EINVAL); - NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_SYSSPACE, name, p); + NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_SYSSPACE, name, td); /* XXXKSE */ flags = O_CREAT | FWRITE | O_NOFOLLOW; error = vn_open(&nd, &flags, S_IRUSR | S_IWUSR); free(name, M_TEMP); @@ -1898,7 +1984,7 @@ restart: NDFREE(&nd, NDF_ONLY_PNBUF); vp = nd.ni_vp; - VOP_UNLOCK(vp, 0, p); + VOP_UNLOCK(vp, 0, td); lf.l_whence = SEEK_SET; lf.l_start = 0; lf.l_len = 0; @@ -1910,7 +1996,7 @@ restart: if (vn_start_write(vp, &mp, V_NOWAIT) != 0) { lf.l_type = F_UNLCK; VOP_ADVLOCK(vp, (caddr_t)p, F_UNLCK, &lf, F_FLOCK); - if ((error = vn_close(vp, FWRITE, cred, p)) != 0) + if ((error = vn_close(vp, FWRITE, cred, td)) != 0) return (error); if ((error = vn_start_write(NULL, &mp, V_XSLEEP | PCATCH)) != 0) return (error); @@ -1919,20 +2005,20 @@ restart: /* Don't dump to non-regular files or files with links. */ if (vp->v_type != VREG || - VOP_GETATTR(vp, &vattr, cred, p) || vattr.va_nlink != 1) { + VOP_GETATTR(vp, &vattr, cred, td) || vattr.va_nlink != 1) { error = EFAULT; goto out1; } VATTR_NULL(&vattr); vattr.va_size = 0; - VOP_LEASE(vp, p, cred, LEASE_WRITE); - VOP_SETATTR(vp, &vattr, cred, p); + VOP_LEASE(vp, td, cred, LEASE_WRITE); + VOP_SETATTR(vp, &vattr, cred, td); PROC_LOCK(p); p->p_acflag |= ACORE; PROC_UNLOCK(p); error = p->p_sysent->sv_coredump ? - p->p_sysent->sv_coredump(p, vp, limit) : + p->p_sysent->sv_coredump(td, vp, limit) : ENOSYS; out1: @@ -1940,7 +2026,7 @@ out1: VOP_ADVLOCK(vp, (caddr_t)p, F_UNLCK, &lf, F_FLOCK); vn_finished_write(mp); out2: - error1 = vn_close(vp, FWRITE, cred, p); + error1 = vn_close(vp, FWRITE, cred, td); if (error == 0) error = error1; return (error); @@ -1960,10 +2046,12 @@ struct nosys_args { */ /* ARGSUSED */ int -nosys(p, args) - struct proc *p; +nosys(td, args) + struct thread *td; struct nosys_args *args; { + struct proc *p = td->td_proc; + mtx_lock(&Giant); PROC_LOCK(p); psignal(p, SIGSYS); |