summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sys/alpha/alpha/machdep.c20
-rw-r--r--sys/alpha/osf1/osf1_signal.c3
-rw-r--r--sys/amd64/amd64/machdep.c7
-rw-r--r--sys/compat/linprocfs/linprocfs.c8
-rw-r--r--sys/compat/svr4/svr4_filio.c15
-rw-r--r--sys/compat/svr4/svr4_misc.c8
-rw-r--r--sys/i386/i386/machdep.c21
-rw-r--r--sys/i386/linux/linux_sysvec.c16
-rw-r--r--sys/i386/svr4/svr4_machdep.c3
-rw-r--r--sys/ia64/ia64/machdep.c5
-rw-r--r--sys/kern/init_main.c11
-rw-r--r--sys/kern/kern_condvar.c6
-rw-r--r--sys/kern/kern_exec.c25
-rw-r--r--sys/kern/kern_exit.c24
-rw-r--r--sys/kern/kern_fork.c38
-rw-r--r--sys/kern/kern_kthread.c4
-rw-r--r--sys/kern/kern_proc.c10
-rw-r--r--sys/kern/kern_sig.c242
-rw-r--r--sys/kern/kern_synch.c4
-rw-r--r--sys/kern/subr_trap.c2
-rw-r--r--sys/kern/tty.c4
-rw-r--r--sys/kern/tty_pty.c2
-rw-r--r--sys/netncp/ncp_ncp.c4
-rw-r--r--sys/netsmb/smb_subr.c4
-rw-r--r--sys/nfsclient/nfs_socket.c4
-rw-r--r--sys/pc98/i386/machdep.c21
-rw-r--r--sys/pc98/pc98/machdep.c21
-rw-r--r--sys/powerpc/aim/machdep.c9
-rw-r--r--sys/powerpc/powerpc/machdep.c9
-rw-r--r--sys/sparc64/sparc64/machdep.c4
-rw-r--r--sys/sys/proc.h18
-rw-r--r--sys/sys/signalvar.h27
-rw-r--r--sys/sys/user.h1
-rw-r--r--sys/vm/vm_glue.c12
34 files changed, 364 insertions, 248 deletions
diff --git a/sys/alpha/alpha/machdep.c b/sys/alpha/alpha/machdep.c
index 1efc6b9..c9b2caf 100644
--- a/sys/alpha/alpha/machdep.c
+++ b/sys/alpha/alpha/machdep.c
@@ -1133,11 +1133,13 @@ osendsig(sig_t catcher, int sig, sigset_t *mask, u_long code)
td = curthread;
p = td->td_proc;
PROC_LOCK_ASSERT(p, MA_OWNED);
+ psp = p->p_sigacts;
+ mtx_assert(&psp->ps_mtx, MA_OWNED);
+
frame = td->td_frame;
- oonstack = sigonstack(alpha_pal_rdusp());
fsize = sizeof ksi;
rndfsize = ((fsize + 15) / 16) * 16;
- psp = p->p_sigacts;
+ oonstack = sigonstack(alpha_pal_rdusp());
/*
* Allocate and validate space for the signal handler
@@ -1155,6 +1157,7 @@ osendsig(sig_t catcher, int sig, sigset_t *mask, u_long code)
#endif
} else
sip = (osiginfo_t *)(alpha_pal_rdusp() - rndfsize);
+ mtx_unlock(&psp->ps_mtx);
PROC_UNLOCK(p);
/*
@@ -1210,7 +1213,8 @@ osendsig(sig_t catcher, int sig, sigset_t *mask, u_long code)
frame->tf_regs[FRAME_A0] = sig;
frame->tf_regs[FRAME_FLAGS] = 0; /* full restore */
PROC_LOCK(p);
- if (SIGISMEMBER(p->p_sigacts->ps_siginfo, sig))
+ mtx_lock(&psp->ps_mtx);
+ if (SIGISMEMBER(psp->ps_siginfo, sig))
frame->tf_regs[FRAME_A1] = (u_int64_t)sip;
else
frame->tf_regs[FRAME_A1] = code;
@@ -1235,6 +1239,7 @@ freebsd4_sendsig(sig_t catcher, int sig, sigset_t *mask, u_long code)
p = td->td_proc;
PROC_LOCK_ASSERT(p, MA_OWNED);
psp = p->p_sigacts;
+ mtx_assert(&psp->ps_mtx, MA_OWNED);
frame = td->td_frame;
oonstack = sigonstack(alpha_pal_rdusp());
@@ -1276,6 +1281,7 @@ freebsd4_sendsig(sig_t catcher, int sig, sigset_t *mask, u_long code)
#endif
} else
sfp = (struct sigframe4 *)(alpha_pal_rdusp() - rndfsize);
+ mtx_unlock(&psp->ps_mtx);
PROC_UNLOCK(p);
/* save the floating-point state, if necessary, then copy it. */
@@ -1311,7 +1317,8 @@ freebsd4_sendsig(sig_t catcher, int sig, sigset_t *mask, u_long code)
frame->tf_regs[FRAME_PC] = PS_STRINGS - szfreebsd4_sigcode;
frame->tf_regs[FRAME_A0] = sig;
PROC_LOCK(p);
- if (SIGISMEMBER(p->p_sigacts->ps_siginfo, sig)) {
+ mtx_lock(&psp->ps_mtx);
+ if (SIGISMEMBER(psp->ps_siginfo, sig)) {
frame->tf_regs[FRAME_A1] = (u_int64_t)&(sfp->sf_si);
/* Fill in POSIX parts */
@@ -1343,6 +1350,7 @@ sendsig(sig_t catcher, int sig, sigset_t *mask, u_long code)
p = td->td_proc;
PROC_LOCK_ASSERT(p, MA_OWNED);
psp = p->p_sigacts;
+ mtx_assert(&psp->ps_mtx, MA_OWNED);
#ifdef COMPAT_FREEBSD4
if (SIGISMEMBER(psp->ps_freebsd4, sig)) {
freebsd4_sendsig(catcher, sig, mask, code);
@@ -1397,6 +1405,7 @@ sendsig(sig_t catcher, int sig, sigset_t *mask, u_long code)
#endif
} else
sfp = (struct sigframe *)(alpha_pal_rdusp() - rndfsize);
+ mtx_unlock(&psp->ps_mtx);
PROC_UNLOCK(p);
/* save the floating-point state, if necessary, then copy it. */
@@ -1432,7 +1441,8 @@ sendsig(sig_t catcher, int sig, sigset_t *mask, u_long code)
frame->tf_regs[FRAME_PC] = PS_STRINGS - szsigcode;
frame->tf_regs[FRAME_A0] = sig;
PROC_LOCK(p);
- if (SIGISMEMBER(p->p_sigacts->ps_siginfo, sig)) {
+ mtx_lock(&psp->ps_mtx);
+ if (SIGISMEMBER(psp->ps_siginfo, sig)) {
frame->tf_regs[FRAME_A1] = (u_int64_t)&(sfp->sf_si);
/* Fill in POSIX parts */
diff --git a/sys/alpha/osf1/osf1_signal.c b/sys/alpha/osf1/osf1_signal.c
index bc3e06c..4ba7e86 100644
--- a/sys/alpha/osf1/osf1_signal.c
+++ b/sys/alpha/osf1/osf1_signal.c
@@ -471,6 +471,7 @@ osf1_sendsig(sig_t catcher, int sig, sigset_t *mask, u_long code)
p = td->td_proc;
PROC_LOCK_ASSERT(p, MA_OWNED);
psp = p->p_sigacts;
+ mtx_assert(&psp->ps_mtx, MA_OWNED);
frame = td->td_frame;
oonstack = sigonstack(alpha_pal_rdusp());
@@ -490,6 +491,7 @@ osf1_sendsig(sig_t catcher, int sig, sigset_t *mask, u_long code)
p->p_sigstk.ss_flags |= SS_ONSTACK;
} else
sip = (osiginfo_t *)(alpha_pal_rdusp() - rndfsize);
+ mtx_unlock(&psp->ps_mtx);
PROC_UNLOCK(p);
/*
@@ -551,6 +553,7 @@ osf1_sendsig(sig_t catcher, int sig, sigset_t *mask, u_long code)
frame->tf_regs[FRAME_FLAGS] = 0; /* full restore */
alpha_pal_wrusp((unsigned long)sip);
PROC_LOCK(p);
+ mtx_lock(&psp->ps_mtx);
}
diff --git a/sys/amd64/amd64/machdep.c b/sys/amd64/amd64/machdep.c
index cafc80b..b727256 100644
--- a/sys/amd64/amd64/machdep.c
+++ b/sys/amd64/amd64/machdep.c
@@ -235,6 +235,7 @@ sendsig(catcher, sig, mask, code)
p = td->td_proc;
PROC_LOCK_ASSERT(p, MA_OWNED);
psp = p->p_sigacts;
+ mtx_assert(&psp->ps_mtx, MA_OWNED);
regs = td->td_frame;
oonstack = sigonstack(regs->tf_rsp);
@@ -262,7 +263,6 @@ sendsig(catcher, sig, mask, code)
sp = (char *)regs->tf_rsp - sizeof(struct sigframe) - 128;
/* Align to 16 bytes. */
sfp = (struct sigframe *)((unsigned long)sp & ~0xF);
- PROC_UNLOCK(p);
/* Translate the signal if appropriate. */
if (p->p_sysent->sv_sigtbl && sig <= p->p_sysent->sv_sigsize)
@@ -271,8 +271,7 @@ sendsig(catcher, sig, mask, code)
/* Build the argument list for the signal handler. */
regs->tf_rdi = sig; /* arg 1 in %rdi */
regs->tf_rdx = (register_t)&sfp->sf_uc; /* arg 3 in %rdx */
- PROC_LOCK(p);
- if (SIGISMEMBER(p->p_sigacts->ps_siginfo, sig)) {
+ if (SIGISMEMBER(psp->ps_siginfo, sig)) {
/* Signal handler installed with SA_SIGINFO. */
regs->tf_rsi = (register_t)&sfp->sf_si; /* arg 2 in %rsi */
sf.sf_ahu.sf_action = (__siginfohandler_t *)catcher;
@@ -287,6 +286,7 @@ sendsig(catcher, sig, mask, code)
regs->tf_rcx = regs->tf_addr; /* arg 4 in %rcx */
sf.sf_ahu.sf_handler = catcher;
}
+ mtx_unlock(&psp->ps_mtx);
PROC_UNLOCK(p);
/*
@@ -305,6 +305,7 @@ sendsig(catcher, sig, mask, code)
regs->tf_rflags &= ~PSL_T;
regs->tf_cs = _ucodesel;
PROC_LOCK(p);
+ mtx_lock(&psp->ps_mtx);
}
/*
diff --git a/sys/compat/linprocfs/linprocfs.c b/sys/compat/linprocfs/linprocfs.c
index 033346b..14f9aeb 100644
--- a/sys/compat/linprocfs/linprocfs.c
+++ b/sys/compat/linprocfs/linprocfs.c
@@ -547,6 +547,7 @@ linprocfs_doprocstatus(PFS_FILL_ARGS)
char *state;
segsz_t lsize;
struct thread *td2;
+ struct sigacts *ps;
int i;
PROC_LOCK(p);
@@ -653,8 +654,11 @@ linprocfs_doprocstatus(PFS_FILL_ARGS)
* relation to struct proc, so SigBlk is left unimplemented.
*/
sbuf_printf(sb, "SigBlk:\t%08x\n", 0); /* XXX */
- sbuf_printf(sb, "SigIgn:\t%08x\n", p->p_sigignore.__bits[0]);
- sbuf_printf(sb, "SigCgt:\t%08x\n", p->p_sigcatch.__bits[0]);
+ ps = p->p_sigacts;
+ mtx_lock(&ps->ps_mtx);
+ sbuf_printf(sb, "SigIgn:\t%08x\n", ps->ps_sigignore.__bits[0]);
+ sbuf_printf(sb, "SigCgt:\t%08x\n", ps->ps_sigcatch.__bits[0]);
+ mtx_unlock(&ps->ps_mtx);
PROC_UNLOCK(p);
/*
diff --git a/sys/compat/svr4/svr4_filio.c b/sys/compat/svr4/svr4_filio.c
index 870da5d..374338f 100644
--- a/sys/compat/svr4/svr4_filio.c
+++ b/sys/compat/svr4/svr4_filio.c
@@ -132,10 +132,21 @@ svr4_sys_read(td, uap)
DPRINTF(("svr4_read(%d, 0x%0x, %d) = %d\n",
uap->fd, uap->buf, uap->nbyte, rv));
if (rv == EAGAIN) {
+#ifdef DEBUG_SVR4
+ struct sigacts *ps;
+
+ PROC_LOCK(td->td_proc);
+ ps = td->td_proc->p_sigacts;
+ mtx_lock(&ps->ps_mtx);
+#endif
DPRINTF(("sigmask = 0x%x\n", td->td_sigmask));
- DPRINTF(("sigignore = 0x%x\n", td->td_proc->p_sigignore));
- DPRINTF(("sigcaught = 0x%x\n", td->td_proc->p_sigcatch));
+ DPRINTF(("sigignore = 0x%x\n", ps->ps_sigignore));
+ DPRINTF(("sigcaught = 0x%x\n", ps->ps_sigcatch));
DPRINTF(("siglist = 0x%x\n", td->td_siglist));
+#ifdef DEBUG_SVR4
+ mtx_unlock(&ps->ps_mtx);
+ PROC_UNLOCK(td->td_proc);
+#endif
}
#if defined(GROTTY_READ_HACK)
diff --git a/sys/compat/svr4/svr4_misc.c b/sys/compat/svr4/svr4_misc.c
index 81eef66..22fdc66 100644
--- a/sys/compat/svr4/svr4_misc.c
+++ b/sys/compat/svr4/svr4_misc.c
@@ -1363,12 +1363,8 @@ loop:
sx_xunlock(&proctree_lock);
PROC_LOCK(q);
- if (--q->p_procsig->ps_refcnt == 0) {
- if (q->p_sigacts != &q->p_uarea->u_sigacts)
- FREE(q->p_sigacts, M_SUBPROC);
- FREE(q->p_procsig, M_SUBPROC);
- q->p_procsig = NULL;
- }
+ sigacts_free(q->p_sigacts);
+ q->p_sigacts = NULL;
PROC_UNLOCK(q);
/*
diff --git a/sys/i386/i386/machdep.c b/sys/i386/i386/machdep.c
index e5377d4..912035d 100644
--- a/sys/i386/i386/machdep.c
+++ b/sys/i386/i386/machdep.c
@@ -295,6 +295,7 @@ osendsig(catcher, sig, mask, code)
p = td->td_proc;
PROC_LOCK_ASSERT(p, MA_OWNED);
psp = p->p_sigacts;
+ mtx_assert(&psp->ps_mtx, MA_OWNED);
regs = td->td_frame;
oonstack = sigonstack(regs->tf_esp);
@@ -308,7 +309,6 @@ osendsig(catcher, sig, mask, code)
#endif
} else
fp = (struct osigframe *)regs->tf_esp - 1;
- PROC_UNLOCK(p);
/* Translate the signal if appropriate. */
if (p->p_sysent->sv_sigtbl && sig <= p->p_sysent->sv_sigsize)
@@ -317,8 +317,7 @@ osendsig(catcher, sig, mask, code)
/* Build the argument list for the signal handler. */
sf.sf_signum = sig;
sf.sf_scp = (register_t)&fp->sf_siginfo.si_sc;
- PROC_LOCK(p);
- if (SIGISMEMBER(p->p_sigacts->ps_siginfo, sig)) {
+ if (SIGISMEMBER(psp->ps_siginfo, sig)) {
/* Signal handler installed with SA_SIGINFO. */
sf.sf_arg2 = (register_t)&fp->sf_siginfo;
sf.sf_siginfo.si_signo = sig;
@@ -330,6 +329,7 @@ osendsig(catcher, sig, mask, code)
sf.sf_addr = regs->tf_err;
sf.sf_ahu.sf_handler = catcher;
}
+ mtx_unlock(&psp->ps_mtx);
PROC_UNLOCK(p);
/* Save most if not all of trap frame. */
@@ -402,6 +402,7 @@ osendsig(catcher, sig, mask, code)
load_gs(_udatasel);
regs->tf_ss = _udatasel;
PROC_LOCK(p);
+ mtx_lock(&psp->ps_mtx);
}
#endif /* COMPAT_43 */
@@ -424,6 +425,7 @@ freebsd4_sendsig(catcher, sig, mask, code)
p = td->td_proc;
PROC_LOCK_ASSERT(p, MA_OWNED);
psp = p->p_sigacts;
+ mtx_assert(&psp->ps_mtx, MA_OWNED);
regs = td->td_frame;
oonstack = sigonstack(regs->tf_esp);
@@ -447,7 +449,6 @@ freebsd4_sendsig(catcher, sig, mask, code)
#endif
} else
sfp = (struct sigframe4 *)regs->tf_esp - 1;
- PROC_UNLOCK(p);
/* Translate the signal if appropriate. */
if (p->p_sysent->sv_sigtbl && sig <= p->p_sysent->sv_sigsize)
@@ -456,8 +457,7 @@ freebsd4_sendsig(catcher, sig, mask, code)
/* Build the argument list for the signal handler. */
sf.sf_signum = sig;
sf.sf_ucontext = (register_t)&sfp->sf_uc;
- PROC_LOCK(p);
- if (SIGISMEMBER(p->p_sigacts->ps_siginfo, sig)) {
+ if (SIGISMEMBER(psp->ps_siginfo, sig)) {
/* Signal handler installed with SA_SIGINFO. */
sf.sf_siginfo = (register_t)&sfp->sf_si;
sf.sf_ahu.sf_action = (__siginfohandler_t *)catcher;
@@ -472,6 +472,7 @@ freebsd4_sendsig(catcher, sig, mask, code)
sf.sf_addr = regs->tf_err;
sf.sf_ahu.sf_handler = catcher;
}
+ mtx_unlock(&psp->ps_mtx);
PROC_UNLOCK(p);
/*
@@ -523,6 +524,7 @@ freebsd4_sendsig(catcher, sig, mask, code)
regs->tf_fs = _udatasel;
regs->tf_ss = _udatasel;
PROC_LOCK(p);
+ mtx_lock(&psp->ps_mtx);
}
#endif /* COMPAT_FREEBSD4 */
@@ -545,6 +547,7 @@ sendsig(catcher, sig, mask, code)
p = td->td_proc;
PROC_LOCK_ASSERT(p, MA_OWNED);
psp = p->p_sigacts;
+ mtx_assert(&psp->ps_mtx, MA_OWNED);
#ifdef COMPAT_FREEBSD4
if (SIGISMEMBER(psp->ps_freebsd4, sig)) {
freebsd4_sendsig(catcher, sig, mask, code);
@@ -585,7 +588,6 @@ sendsig(catcher, sig, mask, code)
sp = (char *)regs->tf_esp - sizeof(struct sigframe);
/* Align to 16 bytes. */
sfp = (struct sigframe *)((unsigned int)sp & ~0xF);
- PROC_UNLOCK(p);
/* Translate the signal if appropriate. */
if (p->p_sysent->sv_sigtbl && sig <= p->p_sysent->sv_sigsize)
@@ -594,8 +596,7 @@ sendsig(catcher, sig, mask, code)
/* Build the argument list for the signal handler. */
sf.sf_signum = sig;
sf.sf_ucontext = (register_t)&sfp->sf_uc;
- PROC_LOCK(p);
- if (SIGISMEMBER(p->p_sigacts->ps_siginfo, sig)) {
+ if (SIGISMEMBER(psp->ps_siginfo, sig)) {
/* Signal handler installed with SA_SIGINFO. */
sf.sf_siginfo = (register_t)&sfp->sf_si;
sf.sf_ahu.sf_action = (__siginfohandler_t *)catcher;
@@ -610,6 +611,7 @@ sendsig(catcher, sig, mask, code)
sf.sf_addr = regs->tf_err;
sf.sf_ahu.sf_handler = catcher;
}
+ mtx_unlock(&psp->ps_mtx);
PROC_UNLOCK(p);
/*
@@ -661,6 +663,7 @@ sendsig(catcher, sig, mask, code)
regs->tf_fs = _udatasel;
regs->tf_ss = _udatasel;
PROC_LOCK(p);
+ mtx_lock(&psp->ps_mtx);
}
/*
diff --git a/sys/i386/linux/linux_sysvec.c b/sys/i386/linux/linux_sysvec.c
index 27105bc..706c944 100644
--- a/sys/i386/linux/linux_sysvec.c
+++ b/sys/i386/linux/linux_sysvec.c
@@ -273,11 +273,14 @@ linux_rt_sendsig(sig_t catcher, int sig, sigset_t *mask, u_long code)
{
struct thread *td = curthread;
struct proc *p = td->td_proc;
+ struct sigacts *psp;
struct trapframe *regs;
struct l_rt_sigframe *fp, frame;
int oonstack;
PROC_LOCK_ASSERT(p, MA_OWNED);
+ psp = p->p_sigacts;
+ mtx_assert(&psp->ps_mtx, MA_OWNED);
regs = td->td_frame;
oonstack = sigonstack(regs->tf_esp);
@@ -290,11 +293,12 @@ linux_rt_sendsig(sig_t catcher, int sig, sigset_t *mask, u_long code)
* Allocate space for the signal handler context.
*/
if ((p->p_flag & P_ALTSTACK) && !oonstack &&
- SIGISMEMBER(p->p_sigacts->ps_sigonstack, sig)) {
+ SIGISMEMBER(psp->ps_sigonstack, sig)) {
fp = (struct l_rt_sigframe *)(p->p_sigstk.ss_sp +
p->p_sigstk.ss_size - sizeof(struct l_rt_sigframe));
} else
fp = (struct l_rt_sigframe *)regs->tf_esp - 1;
+ mtx_unlock(&psp->ps_mtx);
/*
* Build the argument list for the signal handler.
@@ -383,6 +387,7 @@ linux_rt_sendsig(sig_t catcher, int sig, sigset_t *mask, u_long code)
regs->tf_fs = _udatasel;
regs->tf_ss = _udatasel;
PROC_LOCK(p);
+ mtx_lock(&psp->ps_mtx);
}
@@ -401,13 +406,16 @@ linux_sendsig(sig_t catcher, int sig, sigset_t *mask, u_long code)
{
struct thread *td = curthread;
struct proc *p = td->td_proc;
+ struct sigacts *psp;
struct trapframe *regs;
struct l_sigframe *fp, frame;
l_sigset_t lmask;
int oonstack, i;
PROC_LOCK_ASSERT(p, MA_OWNED);
- if (SIGISMEMBER(p->p_sigacts->ps_siginfo, sig)) {
+ psp = p->p_sigacts;
+ mtx_assert(&psp->ps_mtx, MA_OWNED);
+ if (SIGISMEMBER(psp->ps_siginfo, sig)) {
/* Signal handler installed with SA_SIGINFO. */
linux_rt_sendsig(catcher, sig, mask, code);
return;
@@ -426,11 +434,12 @@ linux_sendsig(sig_t catcher, int sig, sigset_t *mask, u_long code)
* Allocate space for the signal handler context.
*/
if ((p->p_flag & P_ALTSTACK) && !oonstack &&
- SIGISMEMBER(p->p_sigacts->ps_sigonstack, sig)) {
+ SIGISMEMBER(psp->ps_sigonstack, sig)) {
fp = (struct l_sigframe *)(p->p_sigstk.ss_sp +
p->p_sigstk.ss_size - sizeof(struct l_sigframe));
} else
fp = (struct l_sigframe *)regs->tf_esp - 1;
+ mtx_unlock(&psp->ps_mtx);
PROC_UNLOCK(p);
/*
@@ -494,6 +503,7 @@ linux_sendsig(sig_t catcher, int sig, sigset_t *mask, u_long code)
regs->tf_fs = _udatasel;
regs->tf_ss = _udatasel;
PROC_LOCK(p);
+ mtx_lock(&psp->ps_mtx);
}
/*
diff --git a/sys/i386/svr4/svr4_machdep.c b/sys/i386/svr4/svr4_machdep.c
index d29e37b..e477629 100644
--- a/sys/i386/svr4/svr4_machdep.c
+++ b/sys/i386/svr4/svr4_machdep.c
@@ -428,6 +428,7 @@ svr4_sendsig(catcher, sig, mask, code)
#endif
PROC_LOCK_ASSERT(p, MA_OWNED);
psp = p->p_sigacts;
+ mtx_assert(&psp->ps_mtx, MA_OWNED);
tf = td->td_frame;
oonstack = sigonstack(tf->tf_esp);
@@ -443,6 +444,7 @@ svr4_sendsig(catcher, sig, mask, code)
} else {
fp = (struct svr4_sigframe *)tf->tf_esp - 1;
}
+ mtx_unlock(&psp->ps_mtx);
PROC_UNLOCK(p);
/*
@@ -505,6 +507,7 @@ svr4_sendsig(catcher, sig, mask, code)
load_gs(_udatasel);
tf->tf_ss = _udatasel;
PROC_LOCK(p);
+ mtx_lock(&psp->ps_mtx);
#endif
}
diff --git a/sys/ia64/ia64/machdep.c b/sys/ia64/ia64/machdep.c
index fafe287..dd3fc59 100644
--- a/sys/ia64/ia64/machdep.c
+++ b/sys/ia64/ia64/machdep.c
@@ -756,6 +756,7 @@ sendsig(sig_t catcher, int sig, sigset_t *mask, u_long code)
p = td->td_proc;
PROC_LOCK_ASSERT(p, MA_OWNED);
psp = p->p_sigacts;
+ mtx_assert(&psp->ps_mtx, MA_OWNED);
frame = td->td_frame;
oonstack = sigonstack(frame->tf_r[FRAME_SP]);
rndfsize = ((sizeof(sf) + 15) / 16) * 16;
@@ -822,6 +823,7 @@ sendsig(sig_t catcher, int sig, sigset_t *mask, u_long code)
#endif
} else
sfp = (struct sigframe *)(frame->tf_r[FRAME_SP] - rndfsize);
+ mtx_unlock(&psp->ps_mtx);
PROC_UNLOCK(p);
#ifdef DEBUG
@@ -870,7 +872,8 @@ sendsig(sig_t catcher, int sig, sigset_t *mask, u_long code)
frame->tf_cr_iip = PS_STRINGS - (esigcode - sigcode);
frame->tf_r[FRAME_R1] = sig;
PROC_LOCK(p);
- if (SIGISMEMBER(p->p_sigacts->ps_siginfo, sig)) {
+ mtx_lock(&psp->ps_mtx);
+ if (SIGISMEMBER(psp->ps_siginfo, sig)) {
frame->tf_r[FRAME_R15] = (u_int64_t)&(sfp->sf_si);
/* Fill in POSIX parts */
diff --git a/sys/kern/init_main.c b/sys/kern/init_main.c
index 83fca78..6caec77 100644
--- a/sys/kern/init_main.c
+++ b/sys/kern/init_main.c
@@ -90,7 +90,6 @@ struct proc proc0;
struct thread thread0;
struct kse kse0;
struct ksegrp ksegrp0;
-static struct procsig procsig0;
static struct filedesc0 filedesc0;
static struct plimit limit0;
struct vmspace vmspace0;
@@ -399,9 +398,8 @@ proc0_init(void *dummy __unused)
#endif
td->td_ucred = crhold(p->p_ucred);
- /* Create procsig. */
- p->p_procsig = &procsig0;
- p->p_procsig->ps_refcnt = 1;
+ /* Create sigacts. */
+ p->p_sigacts = sigacts_alloc();
/* Initialize signal state for process 0. */
siginit(&proc0);
@@ -441,11 +439,10 @@ proc0_init(void *dummy __unused)
vmspace0.vm_map.pmap = vmspace_pmap(&vmspace0);
/*
- * We continue to place resource usage info and signal
- * actions in the user struct so they're pageable.
+ * We continue to place resource usage info
+ * in the user struct so that it's pageable.
*/
p->p_stats = &p->p_uarea->u_stats;
- p->p_sigacts = &p->p_uarea->u_sigacts;
/*
* Charge root for one process.
diff --git a/sys/kern/kern_condvar.c b/sys/kern/kern_condvar.c
index 160434b..7852234 100644
--- a/sys/kern/kern_condvar.c
+++ b/sys/kern/kern_condvar.c
@@ -146,7 +146,9 @@ cv_switch_catch(struct thread *td)
mtx_unlock_spin(&sched_lock);
p = td->td_proc;
PROC_LOCK(p);
+ mtx_lock(&p->p_sigacts->ps_mtx);
sig = cursig(td);
+ mtx_unlock(&p->p_sigacts->ps_mtx);
if (thread_suspend_check(1))
sig = SIGSTOP;
mtx_lock_spin(&sched_lock);
@@ -283,6 +285,7 @@ cv_wait_sig(struct cv *cvp, struct mtx *mp)
mtx_unlock_spin(&sched_lock);
PROC_LOCK(p);
+ mtx_lock(&p->p_sigacts->ps_mtx);
if (sig == 0)
sig = cursig(td); /* XXXKSE */
if (sig != 0) {
@@ -291,6 +294,7 @@ cv_wait_sig(struct cv *cvp, struct mtx *mp)
else
rval = ERESTART;
}
+ mtx_unlock(&p->p_sigacts->ps_mtx);
if (p->p_flag & P_WEXIT)
rval = EINTR;
PROC_UNLOCK(p);
@@ -446,6 +450,7 @@ cv_timedwait_sig(struct cv *cvp, struct mtx *mp, int timo)
mtx_unlock_spin(&sched_lock);
PROC_LOCK(p);
+ mtx_lock(&p->p_sigacts->ps_mtx);
if (sig == 0)
sig = cursig(td);
if (sig != 0) {
@@ -454,6 +459,7 @@ cv_timedwait_sig(struct cv *cvp, struct mtx *mp, int timo)
else
rval = ERESTART;
}
+ mtx_unlock(&p->p_sigacts->ps_mtx);
if (p->p_flag & P_WEXIT)
rval = EINTR;
PROC_UNLOCK(p);
diff --git a/sys/kern/kern_exec.c b/sys/kern/kern_exec.c
index 7f5c819..a453152 100644
--- a/sys/kern/kern_exec.c
+++ b/sys/kern/kern_exec.c
@@ -163,7 +163,7 @@ kern_execve(td, fname, argv, envv, mac_p)
struct vattr attr;
int (*img_first)(struct image_params *);
struct pargs *oldargs = NULL, *newargs = NULL;
- struct procsig *oldprocsig, *newprocsig;
+ struct sigacts *oldsigacts, *newsigacts;
#ifdef KTRACE
struct vnode *tracevp = NULL;
struct ucred *tracecred = NULL;
@@ -409,23 +409,16 @@ interpret:
* reset.
*/
PROC_LOCK(p);
- mp_fixme("procsig needs a lock");
- if (p->p_procsig->ps_refcnt > 1) {
- oldprocsig = p->p_procsig;
+ if (sigacts_shared(p->p_sigacts)) {
+ oldsigacts = p->p_sigacts;
PROC_UNLOCK(p);
- MALLOC(newprocsig, struct procsig *, sizeof(struct procsig),
- M_SUBPROC, M_WAITOK);
- bcopy(oldprocsig, newprocsig, sizeof(*newprocsig));
- newprocsig->ps_refcnt = 1;
- oldprocsig->ps_refcnt--;
+ newsigacts = sigacts_alloc();
+ sigacts_copy(newsigacts, oldsigacts);
PROC_LOCK(p);
- p->p_procsig = newprocsig;
- if (p->p_sigacts == &p->p_uarea->u_sigacts)
- panic("shared procsig but private sigacts?");
+ p->p_sigacts = newsigacts;
+ } else
+ oldsigacts = NULL;
- p->p_uarea->u_sigacts = *p->p_sigacts;
- p->p_sigacts = &p->p_uarea->u_sigacts;
- }
/* Stop profiling */
stopprofclock(p);
@@ -624,6 +617,8 @@ done1:
pargs_drop(oldargs);
if (newargs != NULL)
pargs_drop(newargs);
+ if (oldsigacts != NULL)
+ sigacts_free(oldsigacts);
exec_fail_dealloc:
diff --git a/sys/kern/kern_exit.c b/sys/kern/kern_exit.c
index b77c1d9..2adfa9c 100644
--- a/sys/kern/kern_exit.c
+++ b/sys/kern/kern_exit.c
@@ -431,9 +431,11 @@ exit1(struct thread *td, int rv)
* 1 instead (and hope it will handle this situation).
*/
PROC_LOCK(p->p_pptr);
- if (p->p_pptr->p_procsig->ps_flag & (PS_NOCLDWAIT | PS_CLDSIGIGN)) {
+ mtx_lock(&p->p_pptr->p_sigacts->ps_mtx);
+ if (p->p_pptr->p_sigacts->ps_flag & (PS_NOCLDWAIT | PS_CLDSIGIGN)) {
struct proc *pp;
+ mtx_unlock(&p->p_pptr->p_sigacts->ps_mtx);
pp = p->p_pptr;
PROC_UNLOCK(pp);
proc_reparent(p, initproc);
@@ -445,7 +447,8 @@ exit1(struct thread *td, int rv)
*/
if (LIST_EMPTY(&pp->p_children))
wakeup(pp);
- }
+ } else
+ mtx_unlock(&p->p_pptr->p_sigacts->ps_mtx);
if (p->p_sigparent && p->p_pptr != initproc)
psignal(p->p_pptr, p->p_sigparent);
@@ -656,23 +659,14 @@ loop:
(void)chgproccnt(p->p_ucred->cr_ruidinfo, -1, 0);
/*
- * Free up credentials.
+ * Free credentials, arguments, and sigacts
*/
crfree(p->p_ucred);
- p->p_ucred = NULL; /* XXX: why? */
-
- /*
- * Remove unused arguments
- */
+ p->p_ucred = NULL;
pargs_drop(p->p_args);
p->p_args = NULL;
-
- if (--p->p_procsig->ps_refcnt == 0) {
- if (p->p_sigacts != &p->p_uarea->u_sigacts)
- FREE(p->p_sigacts, M_SUBPROC);
- FREE(p->p_procsig, M_SUBPROC);
- p->p_procsig = NULL;
- }
+ sigacts_free(p->p_sigacts);
+ p->p_sigacts = NULL;
/*
* do any thread-system specific cleanups
diff --git a/sys/kern/kern_fork.c b/sys/kern/kern_fork.c
index 17387f8..0ba17ce 100644
--- a/sys/kern/kern_fork.c
+++ b/sys/kern/kern_fork.c
@@ -214,7 +214,6 @@ fork1(td, flags, pages, procp)
struct kse *ke2;
struct ksegrp *kg2;
struct sigacts *newsigacts;
- struct procsig *newprocsig;
int error;
/* Can't copy and clear */
@@ -412,15 +411,10 @@ again:
/*
* Malloc things while we don't hold any locks.
*/
- if (flags & RFSIGSHARE) {
- MALLOC(newsigacts, struct sigacts *,
- sizeof(struct sigacts), M_SUBPROC, M_WAITOK);
- newprocsig = NULL;
- } else {
+ if (flags & RFSIGSHARE)
newsigacts = NULL;
- MALLOC(newprocsig, struct procsig *, sizeof(struct procsig),
- M_SUBPROC, M_WAITOK);
- }
+ else
+ newsigacts = sigacts_alloc();
/*
* Copy filedesc.
@@ -477,7 +471,7 @@ again:
/*
* Duplicate sub-structures as needed.
* Increase reference counts on shared objects.
- * The p_stats and p_sigacts substructs are set in vm_forkproc.
+ * The p_stats substruct is set in vm_forkproc.
*/
p2->p_flag = 0;
if (p1->p_flag & P_PROFIL)
@@ -497,25 +491,10 @@ again:
pargs_hold(p2->p_args);
if (flags & RFSIGSHARE) {
- p2->p_procsig = p1->p_procsig;
- p2->p_procsig->ps_refcnt++;
- if (p1->p_sigacts == &p1->p_uarea->u_sigacts) {
- /*
- * Set p_sigacts to the new shared structure.
- * Note that this is updating p1->p_sigacts at the
- * same time, since p_sigacts is just a pointer to
- * the shared p_procsig->ps_sigacts.
- */
- p2->p_sigacts = newsigacts;
- newsigacts = NULL;
- *p2->p_sigacts = p1->p_uarea->u_sigacts;
- }
+ p2->p_sigacts = sigacts_hold(p1->p_sigacts);
} else {
- p2->p_procsig = newprocsig;
- newprocsig = NULL;
- bcopy(p1->p_procsig, p2->p_procsig, sizeof(*p2->p_procsig));
- p2->p_procsig->ps_refcnt = 1;
- p2->p_sigacts = NULL; /* finished in vm_forkproc() */
+ sigacts_copy(newsigacts, p1->p_sigacts);
+ p2->p_sigacts = newsigacts;
}
if (flags & RFLINUXTHPN)
p2->p_sigparent = SIGUSR1;
@@ -647,9 +626,6 @@ again:
p2->p_acflag = AFORK;
PROC_UNLOCK(p2);
- KASSERT(newprocsig == NULL, ("unused newprocsig"));
- if (newsigacts != NULL)
- FREE(newsigacts, M_SUBPROC);
/*
* Finish creating the child process. It will return via a different
* execution path later. (ie: directly into user mode)
diff --git a/sys/kern/kern_kthread.c b/sys/kern/kern_kthread.c
index d4846dd..7d38520 100644
--- a/sys/kern/kern_kthread.c
+++ b/sys/kern/kern_kthread.c
@@ -94,7 +94,9 @@ kthread_create(void (*func)(void *), void *arg,
/* this is a non-swapped system process */
PROC_LOCK(p2);
p2->p_flag |= P_SYSTEM | P_KTHREAD;
- p2->p_procsig->ps_flag |= PS_NOCLDWAIT;
+ mtx_lock(&p2->p_sigacts->ps_mtx);
+ p2->p_sigacts->ps_flag |= PS_NOCLDWAIT;
+ mtx_unlock(&p2->p_sigacts->ps_mtx);
_PHOLD(p2);
PROC_UNLOCK(p2);
diff --git a/sys/kern/kern_proc.c b/sys/kern/kern_proc.c
index 6810537..7665674 100644
--- a/sys/kern/kern_proc.c
+++ b/sys/kern/kern_proc.c
@@ -623,6 +623,7 @@ fill_kinfo_proc(p, kp)
struct tty *tp;
struct session *sp;
struct timeval tv;
+ struct sigacts *ps;
td = FIRST_THREAD_IN_PROC(p);
@@ -653,9 +654,12 @@ fill_kinfo_proc(p, kp)
kp->ki_rgid = p->p_ucred->cr_rgid;
kp->ki_svgid = p->p_ucred->cr_svgid;
}
- if (p->p_procsig) {
- kp->ki_sigignore = p->p_procsig->ps_sigignore;
- kp->ki_sigcatch = p->p_procsig->ps_sigcatch;
+ if (p->p_sigacts) {
+ ps = p->p_sigacts;
+ mtx_lock(&ps->ps_mtx);
+ kp->ki_sigignore = ps->ps_sigignore;
+ kp->ki_sigcatch = ps->ps_sigcatch;
+ mtx_unlock(&ps->ps_mtx);
}
mtx_lock_spin(&sched_lock);
if (p->p_state != PRS_NEW &&
diff --git a/sys/kern/kern_sig.c b/sys/kern/kern_sig.c
index dd2fb3e..abe10df 100644
--- a/sys/kern/kern_sig.c
+++ b/sys/kern/kern_sig.c
@@ -181,6 +181,7 @@ int
cursig(struct thread *td)
{
PROC_LOCK_ASSERT(td->td_proc, MA_OWNED);
+ mtx_assert(&td->td_proc->p_sigacts->ps_mtx, MA_OWNED);
mtx_assert(&sched_lock, MA_NOTOWNED);
return (SIGPENDING(td) ? issignal(td) : 0);
}
@@ -267,16 +268,16 @@ kern_sigaction(td, sig, act, oact, flags)
struct sigaction *act, *oact;
int flags;
{
- register struct sigacts *ps;
+ struct sigacts *ps;
struct thread *td0;
struct proc *p = td->td_proc;
if (!_SIG_VALID(sig))
return (EINVAL);
- mtx_lock(&Giant);
PROC_LOCK(p);
ps = p->p_sigacts;
+ mtx_lock(&ps->ps_mtx);
if (oact) {
oact->sa_handler = ps->ps_sigact[_SIG_IDX(sig)];
oact->sa_mask = ps->ps_catchmask[_SIG_IDX(sig)];
@@ -291,16 +292,16 @@ kern_sigaction(td, sig, act, oact, flags)
oact->sa_flags |= SA_NODEFER;
if (SIGISMEMBER(ps->ps_siginfo, sig))
oact->sa_flags |= SA_SIGINFO;
- if (sig == SIGCHLD && p->p_procsig->ps_flag & PS_NOCLDSTOP)
+ if (sig == SIGCHLD && ps->ps_flag & PS_NOCLDSTOP)
oact->sa_flags |= SA_NOCLDSTOP;
- if (sig == SIGCHLD && p->p_procsig->ps_flag & PS_NOCLDWAIT)
+ if (sig == SIGCHLD && ps->ps_flag & PS_NOCLDWAIT)
oact->sa_flags |= SA_NOCLDWAIT;
}
if (act) {
if ((sig == SIGKILL || sig == SIGSTOP) &&
act->sa_handler != SIG_DFL) {
+ mtx_unlock(&ps->ps_mtx);
PROC_UNLOCK(p);
- mtx_unlock(&Giant);
return (EINVAL);
}
@@ -342,9 +343,9 @@ kern_sigaction(td, sig, act, oact, flags)
#endif
if (sig == SIGCHLD) {
if (act->sa_flags & SA_NOCLDSTOP)
- p->p_procsig->ps_flag |= PS_NOCLDSTOP;
+ ps->ps_flag |= PS_NOCLDSTOP;
else
- p->p_procsig->ps_flag &= ~PS_NOCLDSTOP;
+ ps->ps_flag &= ~PS_NOCLDSTOP;
if (act->sa_flags & SA_NOCLDWAIT) {
/*
* Paranoia: since SA_NOCLDWAIT is implemented
@@ -353,20 +354,20 @@ kern_sigaction(td, sig, act, oact, flags)
* is forbidden to set SA_NOCLDWAIT.
*/
if (p->p_pid == 1)
- p->p_procsig->ps_flag &= ~PS_NOCLDWAIT;
+ ps->ps_flag &= ~PS_NOCLDWAIT;
else
- p->p_procsig->ps_flag |= PS_NOCLDWAIT;
+ ps->ps_flag |= PS_NOCLDWAIT;
} else
- p->p_procsig->ps_flag &= ~PS_NOCLDWAIT;
+ ps->ps_flag &= ~PS_NOCLDWAIT;
if (ps->ps_sigact[_SIG_IDX(SIGCHLD)] == SIG_IGN)
- p->p_procsig->ps_flag |= PS_CLDSIGIGN;
+ ps->ps_flag |= PS_CLDSIGIGN;
else
- p->p_procsig->ps_flag &= ~PS_CLDSIGIGN;
+ ps->ps_flag &= ~PS_CLDSIGIGN;
}
/*
- * Set bit in p_sigignore for signals that are set to SIG_IGN,
+ * Set bit in ps_sigignore for signals that are set to SIG_IGN,
* and for signals set to SIG_DFL where the default is to
- * ignore. However, don't put SIGCONT in p_sigignore, as we
+ * ignore. However, don't put SIGCONT in ps_sigignore, as we
* have to restart the process.
*/
if (ps->ps_sigact[_SIG_IDX(sig)] == SIG_IGN ||
@@ -378,14 +379,14 @@ kern_sigaction(td, sig, act, oact, flags)
SIGDELSET(td0->td_siglist, sig);
if (sig != SIGCONT)
/* easier in psignal */
- SIGADDSET(p->p_sigignore, sig);
- SIGDELSET(p->p_sigcatch, sig);
+ SIGADDSET(ps->ps_sigignore, sig);
+ SIGDELSET(ps->ps_sigcatch, sig);
} else {
- SIGDELSET(p->p_sigignore, sig);
+ SIGDELSET(ps->ps_sigignore, sig);
if (ps->ps_sigact[_SIG_IDX(sig)] == SIG_DFL)
- SIGDELSET(p->p_sigcatch, sig);
+ SIGDELSET(ps->ps_sigcatch, sig);
else
- SIGADDSET(p->p_sigcatch, sig);
+ SIGADDSET(ps->ps_sigcatch, sig);
}
#ifdef COMPAT_FREEBSD4
if (ps->ps_sigact[_SIG_IDX(sig)] == SIG_IGN ||
@@ -404,8 +405,8 @@ kern_sigaction(td, sig, act, oact, flags)
SIGADDSET(ps->ps_osigset, sig);
#endif
}
+ mtx_unlock(&ps->ps_mtx);
PROC_UNLOCK(p);
- mtx_unlock(&Giant);
return (0);
}
@@ -543,11 +544,15 @@ siginit(p)
struct proc *p;
{
register int i;
+ struct sigacts *ps;
PROC_LOCK(p);
+ ps = p->p_sigacts;
+ mtx_lock(&ps->ps_mtx);
for (i = 1; i <= NSIG; i++)
if (sigprop(i) & SA_IGNORE && i != SIGCONT)
- SIGADDSET(p->p_sigignore, i);
+ SIGADDSET(ps->ps_sigignore, i);
+ mtx_unlock(&ps->ps_mtx);
PROC_UNLOCK(p);
}
@@ -568,12 +573,13 @@ execsigs(p)
*/
PROC_LOCK_ASSERT(p, MA_OWNED);
ps = p->p_sigacts;
- while (SIGNOTEMPTY(p->p_sigcatch)) {
- sig = sig_ffs(&p->p_sigcatch);
- SIGDELSET(p->p_sigcatch, sig);
+ mtx_lock(&ps->ps_mtx);
+ while (SIGNOTEMPTY(ps->ps_sigcatch)) {
+ sig = sig_ffs(&ps->ps_sigcatch);
+ SIGDELSET(ps->ps_sigcatch, sig);
if (sigprop(sig) & SA_IGNORE) {
if (sig != SIGCONT)
- SIGADDSET(p->p_sigignore, sig);
+ SIGADDSET(ps->ps_sigignore, sig);
SIGDELSET(p->p_siglist, sig);
/*
* There is only one thread at this point.
@@ -597,9 +603,10 @@ execsigs(p)
/*
* Reset no zombies if child dies flag as Solaris does.
*/
- p->p_procsig->ps_flag &= ~(PS_NOCLDWAIT | PS_CLDSIGIGN);
+ ps->ps_flag &= ~(PS_NOCLDWAIT | PS_CLDSIGIGN);
if (ps->ps_sigact[_SIG_IDX(SIGCHLD)] == SIG_IGN)
ps->ps_sigact[_SIG_IDX(SIGCHLD)] = SIG_DFL;
+ mtx_unlock(&ps->ps_mtx);
}
/*
@@ -822,14 +829,13 @@ kern_sigtimedwait(struct thread *td, sigset_t set, siginfo_t *info,
sig = 0;
SIG_CANTMASK(set);
- mtx_lock(&Giant);
PROC_LOCK(p);
-
ps = p->p_sigacts;
oldmask = td->td_sigmask;
td->td_sigmask = set;
signotify(td);
+ mtx_lock(&ps->ps_mtx);
sig = cursig(td);
if (sig)
goto out;
@@ -850,7 +856,9 @@ kern_sigtimedwait(struct thread *td, sigset_t set, siginfo_t *info,
} else
hz = 0;
+ mtx_unlock(&ps->ps_mtx);
error = msleep(ps, &p->p_mtx, PPAUSE|PCATCH, "pause", hz);
+ mtx_lock(&ps->ps_mtx);
if (error == EINTR)
error = 0;
else if (error)
@@ -863,6 +871,7 @@ out:
sig_t action;
action = ps->ps_sigact[_SIG_IDX(sig)];
+ mtx_unlock(&ps->ps_mtx);
#ifdef KTRACE
if (KTRPOINT(td, KTR_PSIG))
ktrpsig(sig, action, td->td_flags & TDF_OLDMASK ?
@@ -877,11 +886,9 @@ out:
SIGDELSET(td->td_siglist, sig);
info->si_signo = sig;
info->si_code = 0;
- }
-
+ } else
+ mtx_unlock(&ps->ps_mtx);
PROC_UNLOCK(p);
- mtx_unlock(&Giant);
-
return (error);
}
@@ -1330,39 +1337,30 @@ kill(td, uap)
register struct kill_args *uap;
{
register struct proc *p;
- int error = 0;
+ int error;
if ((u_int)uap->signum > _SIG_MAXSIG)
return (EINVAL);
- mtx_lock(&Giant);
if (uap->pid > 0) {
/* kill single process */
- if ((p = pfind(uap->pid)) == NULL) {
- error = ESRCH;
- } else if ((error = p_cansignal(td, p, uap->signum)) != 0) {
- PROC_UNLOCK(p);
- } else {
- if (uap->signum)
- psignal(p, uap->signum);
- PROC_UNLOCK(p);
- error = 0;
- }
- } else {
- switch (uap->pid) {
- case -1: /* broadcast signal */
- error = killpg1(td, uap->signum, 0, 1);
- break;
- case 0: /* signal own process group */
- error = killpg1(td, uap->signum, 0, 0);
- break;
- default: /* negative explicit process group */
- error = killpg1(td, uap->signum, -uap->pid, 0);
- break;
- }
+ if ((p = pfind(uap->pid)) == NULL)
+ return (ESRCH);
+ error = p_cansignal(td, p, uap->signum);
+ if (error == 0 && uap->signum)
+ psignal(p, uap->signum);
+ PROC_UNLOCK(p);
+ return (error);
+ }
+ switch (uap->pid) {
+ case -1: /* broadcast signal */
+ return (killpg1(td, uap->signum, 0, 1));
+ case 0: /* signal own process group */
+ return (killpg1(td, uap->signum, 0, 0));
+ default: /* negative explicit process group */
+ return (killpg1(td, uap->signum, -uap->pid, 0));
}
- mtx_unlock(&Giant);
- return(error);
+ /* NOTREACHED */
}
#if defined(COMPAT_43) || defined(COMPAT_SUNOS)
@@ -1381,14 +1379,10 @@ okillpg(td, uap)
struct thread *td;
register struct okillpg_args *uap;
{
- int error;
if ((u_int)uap->signum > _SIG_MAXSIG)
return (EINVAL);
- mtx_lock(&Giant);
- error = killpg1(td, uap->signum, uap->pgid, 0);
- mtx_unlock(&Giant);
- return (error);
+ return (killpg1(td, uap->signum, uap->pgid, 0));
}
#endif /* COMPAT_43 || COMPAT_SUNOS */
@@ -1451,7 +1445,8 @@ trapsignal(struct thread *td, int sig, u_long code)
PROC_LOCK(p);
ps = p->p_sigacts;
- if ((p->p_flag & P_TRACED) == 0 && SIGISMEMBER(p->p_sigcatch, sig) &&
+ mtx_lock(&ps->ps_mtx);
+ if ((p->p_flag & P_TRACED) == 0 && SIGISMEMBER(ps->ps_sigcatch, sig) &&
!SIGISMEMBER(td->td_sigmask, sig)) {
p->p_stats->p_ru.ru_nsignals++;
#ifdef KTRACE
@@ -1468,13 +1463,15 @@ trapsignal(struct thread *td, int sig, u_long code)
/*
* See kern_sigaction() for origin of this code.
*/
- SIGDELSET(p->p_sigcatch, sig);
+ SIGDELSET(ps->ps_sigcatch, sig);
if (sig != SIGCONT &&
sigprop(sig) & SA_IGNORE)
- SIGADDSET(p->p_sigignore, sig);
+ SIGADDSET(ps->ps_sigignore, sig);
ps->ps_sigact[_SIG_IDX(sig)] = SIG_DFL;
}
+ mtx_unlock(&ps->ps_mtx);
} else {
+ mtx_unlock(&ps->ps_mtx);
p->p_code = code; /* XXX for core dump/debugger */
p->p_sig = sig; /* XXX to verify code */
tdsignal(td, sig);
@@ -1528,6 +1525,8 @@ sigtd(struct proc *p, int sig, int prop)
* regardless of the signal action (eg, blocked or ignored).
*
* Other ignored signals are discarded immediately.
+ *
+ * MPSAFE
*/
void
psignal(struct proc *p, int sig)
@@ -1546,6 +1545,9 @@ psignal(struct proc *p, int sig)
tdsignal(td, sig);
}
+/*
+ * MPSAFE
+ */
void
tdsignal(struct thread *td, int sig)
{
@@ -1554,12 +1556,13 @@ tdsignal(struct thread *td, int sig)
sigset_t *siglist;
struct thread *td0;
register int prop;
-
+ struct sigacts *ps;
KASSERT(_SIG_VALID(sig),
("tdsignal(): invalid signal %d\n", sig));
p = td->td_proc;
+ ps = p->p_sigacts;
PROC_LOCK_ASSERT(p, MA_OWNED);
KNOTE(&p->p_klist, NOTE_SIGNAL | sig);
@@ -1586,18 +1589,23 @@ tdsignal(struct thread *td, int sig)
/*
* If the signal is being ignored,
* then we forget about it immediately.
- * (Note: we don't set SIGCONT in p_sigignore,
+ * (Note: we don't set SIGCONT in ps_sigignore,
* and if it is set to SIG_IGN,
* action will be SIG_DFL here.)
*/
- if (SIGISMEMBER(p->p_sigignore, sig) || (p->p_flag & P_WEXIT))
+ mtx_lock(&ps->ps_mtx);
+ if (SIGISMEMBER(ps->ps_sigignore, sig) ||
+ (p->p_flag & P_WEXIT)) {
+ mtx_unlock(&ps->ps_mtx);
return;
+ }
if (SIGISMEMBER(td->td_sigmask, sig))
action = SIG_HOLD;
- else if (SIGISMEMBER(p->p_sigcatch, sig))
+ else if (SIGISMEMBER(ps->ps_sigcatch, sig))
action = SIG_CATCH;
else
action = SIG_DFL;
+ mtx_unlock(&ps->ps_mtx);
}
if (prop & SA_CONT) {
@@ -1890,13 +1898,14 @@ issignal(td)
struct thread *td;
{
struct proc *p;
+ struct sigacts *ps;
sigset_t sigpending;
register int sig, prop;
p = td->td_proc;
+ ps = p->p_sigacts;
+ mtx_assert(&ps->ps_mtx, MA_OWNED);
PROC_LOCK_ASSERT(p, MA_OWNED);
- WITNESS_WARN(WARN_GIANTOK | WARN_SLEEPOK, &p->p_mtx.mtx_object,
- "Checking for signals");
for (;;) {
int traced = (p->p_flag & P_TRACED) || (p->p_stops & S_SIG);
@@ -1916,7 +1925,7 @@ issignal(td)
* We should see pending but ignored signals
* only if P_TRACED was on when they were posted.
*/
- if (SIGISMEMBER(p->p_sigignore, sig) && (traced == 0)) {
+ if (SIGISMEMBER(ps->ps_sigignore, sig) && (traced == 0)) {
SIGDELSET(td->td_siglist, sig);
continue;
}
@@ -1924,6 +1933,9 @@ issignal(td)
/*
* If traced, always stop.
*/
+ mtx_unlock(&ps->ps_mtx);
+ WITNESS_WARN(WARN_GIANTOK | WARN_SLEEPOK,
+ &p->p_mtx.mtx_object, "Stopping for traced signal");
p->p_xstat = sig;
PROC_LOCK(p->p_pptr);
psignal(p->p_pptr, SIGCHLD);
@@ -1938,11 +1950,12 @@ issignal(td)
mtx_unlock_spin(&sched_lock);
PICKUP_GIANT();
PROC_LOCK(p);
+ mtx_lock(&ps->ps_mtx);
/*
* If the traced bit got turned off, go back up
* to the top to rescan signals. This ensures
- * that p_sig* and ps_sigact are consistent.
+ * that p_sig* and p_sigacts are consistent.
*/
if ((p->p_flag & P_TRACED) == 0)
continue;
@@ -2001,6 +2014,9 @@ issignal(td)
(p->p_pgrp->pg_jobc == 0 &&
prop & SA_TTYSTOP))
break; /* == ignore */
+ mtx_unlock(&ps->ps_mtx);
+ WITNESS_WARN(WARN_GIANTOK | WARN_SLEEPOK,
+ &p->p_mtx.mtx_object, "Catching SIGSTOP");
p->p_flag |= P_STOPPED_SIG;
p->p_xstat = sig;
mtx_lock_spin(&sched_lock);
@@ -2013,6 +2029,7 @@ issignal(td)
mtx_unlock_spin(&sched_lock);
PICKUP_GIANT();
PROC_LOCK(p);
+ mtx_lock(&ps->ps_mtx);
break;
} else if (prop & SA_IGNORE) {
/*
@@ -2063,10 +2080,14 @@ stop(struct proc *p)
wakeup(p->p_pptr);
}
+/*
+ * MPSAFE
+ */
void
thread_stopped(struct proc *p)
{
struct proc *p1 = curthread->td_proc;
+ struct sigacts *ps;
int n;
PROC_LOCK_ASSERT(p, MA_OWNED);
@@ -2078,10 +2099,13 @@ thread_stopped(struct proc *p)
mtx_unlock_spin(&sched_lock);
stop(p);
PROC_LOCK(p->p_pptr);
- if ((p->p_pptr->p_procsig->ps_flag &
- PS_NOCLDSTOP) == 0) {
+ ps = p->p_pptr->p_sigacts;
+ mtx_lock(&ps->ps_mtx);
+ if ((ps->ps_flag & PS_NOCLDSTOP) == 0) {
+ mtx_unlock(&ps->ps_mtx);
psignal(p->p_pptr, SIGCHLD);
- }
+ } else
+ mtx_unlock(&ps->ps_mtx);
PROC_UNLOCK(p->p_pptr);
mtx_lock_spin(&sched_lock);
}
@@ -2106,6 +2130,7 @@ postsig(sig)
PROC_LOCK_ASSERT(p, MA_OWNED);
ps = p->p_sigacts;
+ mtx_assert(&ps->ps_mtx, MA_OWNED);
SIGDELSET(td->td_siglist, sig);
action = ps->ps_sigact[_SIG_IDX(sig)];
#ifdef KTRACE
@@ -2120,6 +2145,7 @@ postsig(sig)
* Default action, where the default is to kill
* the process. (Other cases were ignored above.)
*/
+ mtx_unlock(&ps->ps_mtx);
sigexit(td, sig);
/* NOTREACHED */
} else {
@@ -2153,10 +2179,10 @@ postsig(sig)
/*
* See kern_sigaction() for origin of this code.
*/
- SIGDELSET(p->p_sigcatch, sig);
+ SIGDELSET(ps->ps_sigcatch, sig);
if (sig != SIGCONT &&
sigprop(sig) & SA_IGNORE)
- SIGADDSET(p->p_sigignore, sig);
+ SIGADDSET(ps->ps_sigignore, sig);
ps->ps_sigact[_SIG_IDX(sig)] = SIG_DFL;
}
p->p_stats->p_ru.ru_nsignals++;
@@ -2199,6 +2225,8 @@ killproc(p, why)
* signal state. Mark the accounting record with the signal termination.
* If dumping core, save the signal number for the debugger. Calls exit and
* does not return.
+ *
+ * MPSAFE
*/
void
sigexit(td, sig)
@@ -2443,11 +2471,9 @@ nosys(td, args)
{
struct proc *p = td->td_proc;
- mtx_lock(&Giant);
PROC_LOCK(p);
psignal(p, SIGSYS);
PROC_UNLOCK(p);
- mtx_unlock(&Giant);
return (ENOSYS);
}
@@ -2532,3 +2558,57 @@ filt_signal(struct knote *kn, long hint)
}
return (kn->kn_data != 0);
}
+
+struct sigacts *
+sigacts_alloc(void)
+{
+ struct sigacts *ps;
+
+ ps = malloc(sizeof(struct sigacts), M_SUBPROC, M_WAITOK | M_ZERO);
+ ps->ps_refcnt = 1;
+ mtx_init(&ps->ps_mtx, "sigacts", NULL, MTX_DEF);
+ return (ps);
+}
+
+void
+sigacts_free(struct sigacts *ps)
+{
+
+ mtx_lock(&ps->ps_mtx);
+ ps->ps_refcnt--;
+ if (ps->ps_refcnt == 0) {
+ mtx_destroy(&ps->ps_mtx);
+ free(ps, M_SUBPROC);
+ } else
+ mtx_unlock(&ps->ps_mtx);
+}
+
+struct sigacts *
+sigacts_hold(struct sigacts *ps)
+{
+ mtx_lock(&ps->ps_mtx);
+ ps->ps_refcnt++;
+ mtx_unlock(&ps->ps_mtx);
+ return (ps);
+}
+
+void
+sigacts_copy(struct sigacts *dest, struct sigacts *src)
+{
+
+ KASSERT(dest->ps_refcnt == 1, ("sigacts_copy to shared dest"));
+ mtx_lock(&src->ps_mtx);
+ bcopy(src, dest, offsetof(struct sigacts, ps_refcnt));
+ mtx_unlock(&src->ps_mtx);
+}
+
+int
+sigacts_shared(struct sigacts *ps)
+{
+ int shared;
+
+ mtx_lock(&ps->ps_mtx);
+ shared = ps->ps_refcnt > 1;
+ mtx_unlock(&ps->ps_mtx);
+ return (shared);
+}
diff --git a/sys/kern/kern_synch.c b/sys/kern/kern_synch.c
index d648e9e..fbf6ed3 100644
--- a/sys/kern/kern_synch.c
+++ b/sys/kern/kern_synch.c
@@ -230,7 +230,9 @@ msleep(ident, mtx, priority, wmesg, timo)
td->td_flags |= TDF_SINTR;
mtx_unlock_spin(&sched_lock);
PROC_LOCK(p);
+ mtx_lock(&p->p_sigacts->ps_mtx);
sig = cursig(td);
+ mtx_unlock(&p->p_sigacts->ps_mtx);
if (sig == 0 && thread_suspend_check(1))
sig = SIGSTOP;
mtx_lock_spin(&sched_lock);
@@ -291,12 +293,14 @@ msleep(ident, mtx, priority, wmesg, timo)
if (rval == 0 && catch) {
PROC_LOCK(p);
/* XXX: shouldn't we always be calling cursig() */
+ mtx_lock(&p->p_sigacts->ps_mtx);
if (sig != 0 || (sig = cursig(td))) {
if (SIGISMEMBER(p->p_sigacts->ps_sigintr, sig))
rval = EINTR;
else
rval = ERESTART;
}
+ mtx_unlock(&p->p_sigacts->ps_mtx);
PROC_UNLOCK(p);
}
#ifdef KTRACE
diff --git a/sys/kern/subr_trap.c b/sys/kern/subr_trap.c
index b2fc0fc..9eaa5b8 100644
--- a/sys/kern/subr_trap.c
+++ b/sys/kern/subr_trap.c
@@ -245,10 +245,12 @@ ast(struct trapframe *framep)
sigs = 0;
PROC_LOCK(p);
+ mtx_lock(&p->p_sigacts->ps_mtx);
while ((sig = cursig(td)) != 0) {
postsig(sig);
sigs++;
}
+ mtx_unlock(&p->p_sigacts->ps_mtx);
PROC_UNLOCK(p);
if (p->p_flag & P_THREADED && sigs) {
struct kse_upcall *ku = td->td_upcall;
diff --git a/sys/kern/tty.c b/sys/kern/tty.c
index 33ecd6e..0b543f1 100644
--- a/sys/kern/tty.c
+++ b/sys/kern/tty.c
@@ -776,7 +776,7 @@ ttioctl(struct tty *tp, u_long cmd, void *data, int flag)
sx_slock(&proctree_lock);
PROC_LOCK(p);
while (isbackground(p, tp) && !(p->p_flag & P_PPWAIT) &&
- !SIGISMEMBER(p->p_sigignore, SIGTTOU) &&
+ !SIGISMEMBER(p->p_sigacts->ps_sigignore, SIGTTOU) &&
!SIGISMEMBER(td->td_sigmask, SIGTTOU)) {
pgrp = p->p_pgrp;
PROC_UNLOCK(p);
@@ -1934,7 +1934,7 @@ loop:
PROC_LOCK(p);
if (isbackground(p, tp) &&
ISSET(tp->t_lflag, TOSTOP) && !(p->p_flag & P_PPWAIT) &&
- !SIGISMEMBER(p->p_sigignore, SIGTTOU) &&
+ !SIGISMEMBER(p->p_sigacts->ps_sigignore, SIGTTOU) &&
!SIGISMEMBER(td->td_sigmask, SIGTTOU)) {
if (p->p_pgrp->pg_jobc == 0) {
PROC_UNLOCK(p);
diff --git a/sys/kern/tty_pty.c b/sys/kern/tty_pty.c
index b104e6b..eadcf08 100644
--- a/sys/kern/tty_pty.c
+++ b/sys/kern/tty_pty.c
@@ -235,7 +235,7 @@ again:
while (isbackground(p, tp)) {
sx_slock(&proctree_lock);
PROC_LOCK(p);
- if (SIGISMEMBER(p->p_sigignore, SIGTTIN) ||
+ if (SIGISMEMBER(p->p_sigacts->ps_sigignore, SIGTTIN) ||
SIGISMEMBER(td->td_sigmask, SIGTTIN) ||
p->p_pgrp->pg_jobc == 0 || p->p_flag & P_PPWAIT) {
PROC_UNLOCK(p);
diff --git a/sys/netncp/ncp_ncp.c b/sys/netncp/ncp_ncp.c
index 0541793..1d29afe 100644
--- a/sys/netncp/ncp_ncp.c
+++ b/sys/netncp/ncp_ncp.c
@@ -88,7 +88,9 @@ ncp_chkintr(struct ncp_conn *conn, struct thread *td)
tmpset = p->p_siglist;
SIGSETOR(tmpset, td->td_siglist);
SIGSETNAND(tmpset, td->td_sigmask);
- SIGSETNAND(tmpset, p->p_sigignore);
+ mtx_lock(&p->p_sigacts->ps_mtx);
+ SIGSETNAND(tmpset, p->p_sigacts->ps_sigignore);
+ mtx_unlock(&p->p_sigacts->ps_mtx);
if (SIGNOTEMPTY(td->td_siglist) && NCP_SIGMASK(tmpset)) {
PROC_UNLOCK(p);
return EINTR;
diff --git a/sys/netsmb/smb_subr.c b/sys/netsmb/smb_subr.c
index 0e03560..1650ece 100644
--- a/sys/netsmb/smb_subr.c
+++ b/sys/netsmb/smb_subr.c
@@ -82,7 +82,9 @@ smb_td_intr(struct thread *td)
tmpset = p->p_siglist;
SIGSETOR(tmpset, td->td_siglist);
SIGSETNAND(tmpset, td->td_sigmask);
- SIGSETNAND(tmpset, p->p_sigignore);
+ mtx_lock(&p->p_sigacts->ps_mtx);
+ SIGSETNAND(tmpset, p->p_sigacts->ps_sigignore);
+ mtx_unlock(&p->p_sigacts->ps_mtx);
if (SIGNOTEMPTY(td->td_siglist) && SMB_SIGMASK(tmpset)) {
PROC_UNLOCK(p);
return EINTR;
diff --git a/sys/nfsclient/nfs_socket.c b/sys/nfsclient/nfs_socket.c
index 3949b74..aaa2f7a 100644
--- a/sys/nfsclient/nfs_socket.c
+++ b/sys/nfsclient/nfs_socket.c
@@ -1239,7 +1239,9 @@ nfs_sigintr(struct nfsmount *nmp, struct nfsreq *rep, struct thread *td)
PROC_LOCK(p);
tmpset = p->p_siglist;
SIGSETNAND(tmpset, td->td_sigmask);
- SIGSETNAND(tmpset, p->p_sigignore);
+ mtx_lock(&p->p_sigacts->ps_mtx);
+ SIGSETNAND(tmpset, p->p_sigacts->ps_sigignore);
+ mtx_unlock(&p->p_sigacts->ps_mtx);
if (SIGNOTEMPTY(p->p_siglist) && NFSINT_SIGMASK(tmpset)) {
PROC_UNLOCK(p);
return (EINTR);
diff --git a/sys/pc98/i386/machdep.c b/sys/pc98/i386/machdep.c
index b9013a2..4797ae1 100644
--- a/sys/pc98/i386/machdep.c
+++ b/sys/pc98/i386/machdep.c
@@ -315,6 +315,7 @@ osendsig(catcher, sig, mask, code)
p = td->td_proc;
PROC_LOCK_ASSERT(p, MA_OWNED);
psp = p->p_sigacts;
+ mtx_assert(&psp->ps_mtx, MA_OWNED);
regs = td->td_frame;
oonstack = sigonstack(regs->tf_esp);
@@ -328,7 +329,6 @@ osendsig(catcher, sig, mask, code)
#endif
} else
fp = (struct osigframe *)regs->tf_esp - 1;
- PROC_UNLOCK(p);
/* Translate the signal if appropriate. */
if (p->p_sysent->sv_sigtbl && sig <= p->p_sysent->sv_sigsize)
@@ -337,8 +337,7 @@ osendsig(catcher, sig, mask, code)
/* Build the argument list for the signal handler. */
sf.sf_signum = sig;
sf.sf_scp = (register_t)&fp->sf_siginfo.si_sc;
- PROC_LOCK(p);
- if (SIGISMEMBER(p->p_sigacts->ps_siginfo, sig)) {
+ if (SIGISMEMBER(psp->ps_siginfo, sig)) {
/* Signal handler installed with SA_SIGINFO. */
sf.sf_arg2 = (register_t)&fp->sf_siginfo;
sf.sf_siginfo.si_signo = sig;
@@ -350,6 +349,7 @@ osendsig(catcher, sig, mask, code)
sf.sf_addr = regs->tf_err;
sf.sf_ahu.sf_handler = catcher;
}
+ mtx_unlock(&psp->ps_mtx);
PROC_UNLOCK(p);
/* Save most if not all of trap frame. */
@@ -422,6 +422,7 @@ osendsig(catcher, sig, mask, code)
load_gs(_udatasel);
regs->tf_ss = _udatasel;
PROC_LOCK(p);
+ mtx_lock(&psp->ps_mtx);
}
#endif /* COMPAT_43 */
@@ -444,6 +445,7 @@ freebsd4_sendsig(catcher, sig, mask, code)
p = td->td_proc;
PROC_LOCK_ASSERT(p, MA_OWNED);
psp = p->p_sigacts;
+ mtx_assert(&psp->ps_mtx, MA_OWNED);
regs = td->td_frame;
oonstack = sigonstack(regs->tf_esp);
@@ -467,7 +469,6 @@ freebsd4_sendsig(catcher, sig, mask, code)
#endif
} else
sfp = (struct sigframe4 *)regs->tf_esp - 1;
- PROC_UNLOCK(p);
/* Translate the signal if appropriate. */
if (p->p_sysent->sv_sigtbl && sig <= p->p_sysent->sv_sigsize)
@@ -476,8 +477,7 @@ freebsd4_sendsig(catcher, sig, mask, code)
/* Build the argument list for the signal handler. */
sf.sf_signum = sig;
sf.sf_ucontext = (register_t)&sfp->sf_uc;
- PROC_LOCK(p);
- if (SIGISMEMBER(p->p_sigacts->ps_siginfo, sig)) {
+ if (SIGISMEMBER(psp->ps_siginfo, sig)) {
/* Signal handler installed with SA_SIGINFO. */
sf.sf_siginfo = (register_t)&sfp->sf_si;
sf.sf_ahu.sf_action = (__siginfohandler_t *)catcher;
@@ -492,6 +492,7 @@ freebsd4_sendsig(catcher, sig, mask, code)
sf.sf_addr = regs->tf_err;
sf.sf_ahu.sf_handler = catcher;
}
+ mtx_unlock(&psp->ps_mtx);
PROC_UNLOCK(p);
/*
@@ -543,6 +544,7 @@ freebsd4_sendsig(catcher, sig, mask, code)
regs->tf_fs = _udatasel;
regs->tf_ss = _udatasel;
PROC_LOCK(p);
+ mtx_lock(&psp->ps_mtx);
}
#endif /* COMPAT_FREEBSD4 */
@@ -565,6 +567,7 @@ sendsig(catcher, sig, mask, code)
p = td->td_proc;
PROC_LOCK_ASSERT(p, MA_OWNED);
psp = p->p_sigacts;
+ mtx_assert(&psp->ps_mtx,.MA_OWNED);
#ifdef COMPAT_FREEBSD4
if (SIGISMEMBER(psp->ps_freebsd4, sig)) {
freebsd4_sendsig(catcher, sig, mask, code);
@@ -605,7 +608,6 @@ sendsig(catcher, sig, mask, code)
sp = (char *)regs->tf_esp - sizeof(struct sigframe);
/* Align to 16 bytes. */
sfp = (struct sigframe *)((unsigned int)sp & ~0xF);
- PROC_UNLOCK(p);
/* Translate the signal if appropriate. */
if (p->p_sysent->sv_sigtbl && sig <= p->p_sysent->sv_sigsize)
@@ -614,8 +616,7 @@ sendsig(catcher, sig, mask, code)
/* Build the argument list for the signal handler. */
sf.sf_signum = sig;
sf.sf_ucontext = (register_t)&sfp->sf_uc;
- PROC_LOCK(p);
- if (SIGISMEMBER(p->p_sigacts->ps_siginfo, sig)) {
+ if (SIGISMEMBER(psp->ps_siginfo, sig)) {
/* Signal handler installed with SA_SIGINFO. */
sf.sf_siginfo = (register_t)&sfp->sf_si;
sf.sf_ahu.sf_action = (__siginfohandler_t *)catcher;
@@ -630,6 +631,7 @@ sendsig(catcher, sig, mask, code)
sf.sf_addr = regs->tf_err;
sf.sf_ahu.sf_handler = catcher;
}
+ mtx_unlock(&psp->ps_mtx);
PROC_UNLOCK(p);
/*
@@ -681,6 +683,7 @@ sendsig(catcher, sig, mask, code)
regs->tf_fs = _udatasel;
regs->tf_ss = _udatasel;
PROC_LOCK(p);
+ mtx_lock(&psp->ps_mtx);
}
/*
diff --git a/sys/pc98/pc98/machdep.c b/sys/pc98/pc98/machdep.c
index b9013a2..4797ae1 100644
--- a/sys/pc98/pc98/machdep.c
+++ b/sys/pc98/pc98/machdep.c
@@ -315,6 +315,7 @@ osendsig(catcher, sig, mask, code)
p = td->td_proc;
PROC_LOCK_ASSERT(p, MA_OWNED);
psp = p->p_sigacts;
+ mtx_assert(&psp->ps_mtx, MA_OWNED);
regs = td->td_frame;
oonstack = sigonstack(regs->tf_esp);
@@ -328,7 +329,6 @@ osendsig(catcher, sig, mask, code)
#endif
} else
fp = (struct osigframe *)regs->tf_esp - 1;
- PROC_UNLOCK(p);
/* Translate the signal if appropriate. */
if (p->p_sysent->sv_sigtbl && sig <= p->p_sysent->sv_sigsize)
@@ -337,8 +337,7 @@ osendsig(catcher, sig, mask, code)
/* Build the argument list for the signal handler. */
sf.sf_signum = sig;
sf.sf_scp = (register_t)&fp->sf_siginfo.si_sc;
- PROC_LOCK(p);
- if (SIGISMEMBER(p->p_sigacts->ps_siginfo, sig)) {
+ if (SIGISMEMBER(psp->ps_siginfo, sig)) {
/* Signal handler installed with SA_SIGINFO. */
sf.sf_arg2 = (register_t)&fp->sf_siginfo;
sf.sf_siginfo.si_signo = sig;
@@ -350,6 +349,7 @@ osendsig(catcher, sig, mask, code)
sf.sf_addr = regs->tf_err;
sf.sf_ahu.sf_handler = catcher;
}
+ mtx_unlock(&psp->ps_mtx);
PROC_UNLOCK(p);
/* Save most if not all of trap frame. */
@@ -422,6 +422,7 @@ osendsig(catcher, sig, mask, code)
load_gs(_udatasel);
regs->tf_ss = _udatasel;
PROC_LOCK(p);
+ mtx_lock(&psp->ps_mtx);
}
#endif /* COMPAT_43 */
@@ -444,6 +445,7 @@ freebsd4_sendsig(catcher, sig, mask, code)
p = td->td_proc;
PROC_LOCK_ASSERT(p, MA_OWNED);
psp = p->p_sigacts;
+ mtx_assert(&psp->ps_mtx, MA_OWNED);
regs = td->td_frame;
oonstack = sigonstack(regs->tf_esp);
@@ -467,7 +469,6 @@ freebsd4_sendsig(catcher, sig, mask, code)
#endif
} else
sfp = (struct sigframe4 *)regs->tf_esp - 1;
- PROC_UNLOCK(p);
/* Translate the signal if appropriate. */
if (p->p_sysent->sv_sigtbl && sig <= p->p_sysent->sv_sigsize)
@@ -476,8 +477,7 @@ freebsd4_sendsig(catcher, sig, mask, code)
/* Build the argument list for the signal handler. */
sf.sf_signum = sig;
sf.sf_ucontext = (register_t)&sfp->sf_uc;
- PROC_LOCK(p);
- if (SIGISMEMBER(p->p_sigacts->ps_siginfo, sig)) {
+ if (SIGISMEMBER(psp->ps_siginfo, sig)) {
/* Signal handler installed with SA_SIGINFO. */
sf.sf_siginfo = (register_t)&sfp->sf_si;
sf.sf_ahu.sf_action = (__siginfohandler_t *)catcher;
@@ -492,6 +492,7 @@ freebsd4_sendsig(catcher, sig, mask, code)
sf.sf_addr = regs->tf_err;
sf.sf_ahu.sf_handler = catcher;
}
+ mtx_unlock(&psp->ps_mtx);
PROC_UNLOCK(p);
/*
@@ -543,6 +544,7 @@ freebsd4_sendsig(catcher, sig, mask, code)
regs->tf_fs = _udatasel;
regs->tf_ss = _udatasel;
PROC_LOCK(p);
+ mtx_lock(&psp->ps_mtx);
}
#endif /* COMPAT_FREEBSD4 */
@@ -565,6 +567,7 @@ sendsig(catcher, sig, mask, code)
p = td->td_proc;
PROC_LOCK_ASSERT(p, MA_OWNED);
psp = p->p_sigacts;
+ mtx_assert(&psp->ps_mtx,.MA_OWNED);
#ifdef COMPAT_FREEBSD4
if (SIGISMEMBER(psp->ps_freebsd4, sig)) {
freebsd4_sendsig(catcher, sig, mask, code);
@@ -605,7 +608,6 @@ sendsig(catcher, sig, mask, code)
sp = (char *)regs->tf_esp - sizeof(struct sigframe);
/* Align to 16 bytes. */
sfp = (struct sigframe *)((unsigned int)sp & ~0xF);
- PROC_UNLOCK(p);
/* Translate the signal if appropriate. */
if (p->p_sysent->sv_sigtbl && sig <= p->p_sysent->sv_sigsize)
@@ -614,8 +616,7 @@ sendsig(catcher, sig, mask, code)
/* Build the argument list for the signal handler. */
sf.sf_signum = sig;
sf.sf_ucontext = (register_t)&sfp->sf_uc;
- PROC_LOCK(p);
- if (SIGISMEMBER(p->p_sigacts->ps_siginfo, sig)) {
+ if (SIGISMEMBER(psp->ps_siginfo, sig)) {
/* Signal handler installed with SA_SIGINFO. */
sf.sf_siginfo = (register_t)&sfp->sf_si;
sf.sf_ahu.sf_action = (__siginfohandler_t *)catcher;
@@ -630,6 +631,7 @@ sendsig(catcher, sig, mask, code)
sf.sf_addr = regs->tf_err;
sf.sf_ahu.sf_handler = catcher;
}
+ mtx_unlock(&psp->ps_mtx);
PROC_UNLOCK(p);
/*
@@ -681,6 +683,7 @@ sendsig(catcher, sig, mask, code)
regs->tf_fs = _udatasel;
regs->tf_ss = _udatasel;
PROC_LOCK(p);
+ mtx_lock(&psp->ps_mtx);
}
/*
diff --git a/sys/powerpc/aim/machdep.c b/sys/powerpc/aim/machdep.c
index 81fb604..62e46e9 100644
--- a/sys/powerpc/aim/machdep.c
+++ b/sys/powerpc/aim/machdep.c
@@ -408,7 +408,9 @@ sendsig(sig_t catcher, int sig, sigset_t *mask, u_long code)
td = curthread;
p = td->td_proc;
+ PROC_LOCK_ASSERT(p, MA_OWNED);
psp = p->p_sigacts;
+ mtx_assert(&psp->ps_mtx, MA_OWNED);
tf = td->td_frame;
oonstack = sigonstack(tf->fixreg[1]);
@@ -439,7 +441,6 @@ sendsig(sig_t catcher, int sig, sigset_t *mask, u_long code)
} else {
sfp = (struct sigframe *)(tf->fixreg[1] - rndfsize);
}
- PROC_UNLOCK(p);
/*
* Translate the signal if appropriate (Linux emu ?)
@@ -466,9 +467,7 @@ sendsig(sig_t catcher, int sig, sigset_t *mask, u_long code)
tf->fixreg[1] = (register_t)sfp;
tf->fixreg[FIRSTARG] = sig;
tf->fixreg[FIRSTARG+2] = (register_t)&sfp->sf_uc;
-
- PROC_LOCK(p);
- if (SIGISMEMBER(p->p_sigacts->ps_siginfo, sig)) {
+ if (SIGISMEMBER(psp->ps_siginfo, sig)) {
/*
* Signal handler installed with SA_SIGINFO.
*/
@@ -484,6 +483,7 @@ sendsig(sig_t catcher, int sig, sigset_t *mask, u_long code)
/* Old FreeBSD-style arguments. */
tf->fixreg[FIRSTARG+1] = code;
}
+ mtx_unlock(&psp->ps_mtx);
PROC_UNLOCK(p);
tf->srr0 = (register_t)(PS_STRINGS - *(p->p_sysent->sv_szsigcode));
@@ -504,6 +504,7 @@ sendsig(sig_t catcher, int sig, sigset_t *mask, u_long code)
tf->srr0, tf->fixreg[1]);
PROC_LOCK(p);
+ mtx_lock(&psp->ps_mtx);
}
int
diff --git a/sys/powerpc/powerpc/machdep.c b/sys/powerpc/powerpc/machdep.c
index 81fb604..62e46e9 100644
--- a/sys/powerpc/powerpc/machdep.c
+++ b/sys/powerpc/powerpc/machdep.c
@@ -408,7 +408,9 @@ sendsig(sig_t catcher, int sig, sigset_t *mask, u_long code)
td = curthread;
p = td->td_proc;
+ PROC_LOCK_ASSERT(p, MA_OWNED);
psp = p->p_sigacts;
+ mtx_assert(&psp->ps_mtx, MA_OWNED);
tf = td->td_frame;
oonstack = sigonstack(tf->fixreg[1]);
@@ -439,7 +441,6 @@ sendsig(sig_t catcher, int sig, sigset_t *mask, u_long code)
} else {
sfp = (struct sigframe *)(tf->fixreg[1] - rndfsize);
}
- PROC_UNLOCK(p);
/*
* Translate the signal if appropriate (Linux emu ?)
@@ -466,9 +467,7 @@ sendsig(sig_t catcher, int sig, sigset_t *mask, u_long code)
tf->fixreg[1] = (register_t)sfp;
tf->fixreg[FIRSTARG] = sig;
tf->fixreg[FIRSTARG+2] = (register_t)&sfp->sf_uc;
-
- PROC_LOCK(p);
- if (SIGISMEMBER(p->p_sigacts->ps_siginfo, sig)) {
+ if (SIGISMEMBER(psp->ps_siginfo, sig)) {
/*
* Signal handler installed with SA_SIGINFO.
*/
@@ -484,6 +483,7 @@ sendsig(sig_t catcher, int sig, sigset_t *mask, u_long code)
/* Old FreeBSD-style arguments. */
tf->fixreg[FIRSTARG+1] = code;
}
+ mtx_unlock(&psp->ps_mtx);
PROC_UNLOCK(p);
tf->srr0 = (register_t)(PS_STRINGS - *(p->p_sysent->sv_szsigcode));
@@ -504,6 +504,7 @@ sendsig(sig_t catcher, int sig, sigset_t *mask, u_long code)
tf->srr0, tf->fixreg[1]);
PROC_LOCK(p);
+ mtx_lock(&psp->ps_mtx);
}
int
diff --git a/sys/sparc64/sparc64/machdep.c b/sys/sparc64/sparc64/machdep.c
index 6cf0f6a..669f4c7 100644
--- a/sys/sparc64/sparc64/machdep.c
+++ b/sys/sparc64/sparc64/machdep.c
@@ -403,7 +403,9 @@ sendsig(sig_t catcher, int sig, sigset_t *mask, u_long code)
oonstack = 0;
td = curthread;
p = td->td_proc;
+ PROC_LOCK_ASSERT(p, MA_OWNED);
psp = p->p_sigacts;
+ mtx_assert(&psp->ps_mtx, MA_OWNED);
tf = td->td_frame;
sp = tf->tf_sp + SPOFF;
oonstack = sigonstack(sp);
@@ -437,6 +439,7 @@ sendsig(sig_t catcher, int sig, sigset_t *mask, u_long code)
p->p_sigstk.ss_size - sizeof(struct sigframe));
} else
sfp = (struct sigframe *)sp - 1;
+ mtx_unlock(&psp->ps_mtx);
PROC_UNLOCK(p);
fp = (struct frame *)sfp - 1;
@@ -476,6 +479,7 @@ sendsig(sig_t catcher, int sig, sigset_t *mask, u_long code)
tf->tf_sp);
PROC_LOCK(p);
+ mtx_lock(&psp->ps_mtx);
}
#ifndef _SYS_SYSPROTO_H_
diff --git a/sys/sys/proc.h b/sys/sys/proc.h
index 92f9739..1b7982c 100644
--- a/sys/sys/proc.h
+++ b/sys/sys/proc.h
@@ -102,18 +102,6 @@ struct pgrp {
struct mtx pg_mtx; /* Mutex to protect members */
};
-struct procsig {
- sigset_t ps_sigignore; /* Signals being ignored. */
- sigset_t ps_sigcatch; /* Signals being caught by user. */
- int ps_flag;
- struct sigacts *ps_sigacts; /* Signal actions, state. */
- int ps_refcnt;
-};
-
-#define PS_NOCLDWAIT 0x0001 /* No zombies if child dies */
-#define PS_NOCLDSTOP 0x0002 /* No SIGCHLD when children stop. */
-#define PS_CLDSIGIGN 0x0004 /* The SIGCHLD handler is SIG_IGN. */
-
/*
* pargs, used to hold a copy of the command line, if it had a sane length.
*/
@@ -157,6 +145,7 @@ struct pargs {
* o - ktrace lock
* p - select lock (sellock)
* r - p_peers lock
+ * x - created at fork, only changes during single threading in exec
* z - zombie threads/kse/ksegroup lock
*
* If the locking key specifies two identifiers (for example, p_pptr) then
@@ -525,7 +514,7 @@ struct proc {
struct pstats *p_stats; /* (b) Accounting/statistics (CPU). */
struct plimit *p_limit; /* (c*) Process limits. */
struct vm_object *p_upages_obj; /* (a) Upages object. */
- struct procsig *p_procsig; /* (c) Signal actions, state (CPU). */
+ struct sigacts *p_sigacts; /* (x) Signal actions, state (CPU). */
/*struct ksegrp p_ksegrp;
struct kse p_kse; */
@@ -614,9 +603,6 @@ struct proc {
};
#define p_rlimit p_limit->pl_rlimit
-#define p_sigacts p_procsig->ps_sigacts
-#define p_sigignore p_procsig->ps_sigignore
-#define p_sigcatch p_procsig->ps_sigcatch
#define p_session p_pgrp->pg_session
#define p_pgid p_pgrp->pg_id
diff --git a/sys/sys/signalvar.h b/sys/sys/signalvar.h
index 1173d78..5635ab2 100644
--- a/sys/sys/signalvar.h
+++ b/sys/sys/signalvar.h
@@ -37,6 +37,8 @@
#ifndef _SYS_SIGNALVAR_H_
#define _SYS_SIGNALVAR_H_
+#include <sys/_lock.h>
+#include <sys/_mutex.h>
#include <sys/signal.h>
/*
@@ -45,8 +47,11 @@
*/
/*
- * Process signal actions and state, needed only within the process
- * (not necessarily resident).
+ * Logical process signal actions and state, needed only within the process
+ * The mapping between sigacts and proc structures is 1:1 except for rfork()
+ * processes masquerading as threads which use one structure for the whole
+ * group. All members are locked by the included mutex. The reference count
+ * and mutex must be last for the bcopy in sigacts_copy() to work.
*/
struct sigacts {
sig_t ps_sigact[_SIG_MAXSIG]; /* Disposition of signals. */
@@ -56,11 +61,20 @@ struct sigacts {
sigset_t ps_sigreset; /* Signals that reset when caught. */
sigset_t ps_signodefer; /* Signals not masked while handled. */
sigset_t ps_siginfo; /* Signals that want SA_SIGINFO args. */
- sigset_t ps_freebsd4; /* Signals using freebsd4 ucontext. */
+ sigset_t ps_sigignore; /* Signals being ignored. */
+ sigset_t ps_sigcatch; /* Signals being caught by user. */
+ sigset_t ps_freebsd4; /* signals using freebsd4 ucontext. */
sigset_t ps_osigset; /* Signals using <= 3.x osigset_t. */
- sigset_t ps_usertramp; /* SunOS compat; libc sigtramp XXX. */
+ sigset_t ps_usertramp; /* SunOS compat; libc sigtramp. XXX */
+ int ps_flag;
+ int ps_refcnt;
+ struct mtx ps_mtx;
};
+#define PS_NOCLDWAIT 0x0001 /* No zombies if child dies */
+#define PS_NOCLDSTOP 0x0002 /* No SIGCHLD when children stop. */
+#define PS_CLDSIGIGN 0x0004 /* The SIGCHLD handler is SIG_IGN. */
+
#if defined(_KERNEL) && defined(COMPAT_43)
/*
* Compatibility.
@@ -243,6 +257,11 @@ void pgsigio(struct sigio **, int signum, int checkctty);
void pgsignal(struct pgrp *pgrp, int sig, int checkctty);
void postsig(int sig);
void psignal(struct proc *p, int sig);
+struct sigacts *sigacts_alloc(void);
+void sigacts_copy(struct sigacts *dest, struct sigacts *src);
+void sigacts_free(struct sigacts *ps);
+struct sigacts *sigacts_hold(struct sigacts *ps);
+int sigacts_shared(struct sigacts *ps);
void sigexit(struct thread *td, int signum) __dead2;
int sig_ffs(sigset_t *set);
void siginit(struct proc *p);
diff --git a/sys/sys/user.h b/sys/sys/user.h
index 473480a..a52610f 100644
--- a/sys/sys/user.h
+++ b/sys/sys/user.h
@@ -174,7 +174,6 @@ void fill_kinfo_proc(struct proc *, struct kinfo_proc *);
* when the process isn't running (esp. when swapped out).
*/
struct user {
- struct sigacts u_sigacts; /* *p_sigacts */
struct pstats u_stats; /* *p_stats */
/*
* Remaining field for a.out core dumps - not valid at other times!
diff --git a/sys/vm/vm_glue.c b/sys/vm/vm_glue.c
index cd00c33..3c42cca 100644
--- a/sys/vm/vm_glue.c
+++ b/sys/vm/vm_glue.c
@@ -441,23 +441,14 @@ vm_forkproc(td, p2, td2, flags)
/* XXXKSE this is unsatisfactory but should be adequate */
up = p2->p_uarea;
+ MPASS(p2->p_sigacts != NULL);
/*
* p_stats currently points at fields in the user struct
* but not at &u, instead at p_addr. Copy parts of
* p_stats; zero the rest of p_stats (statistics).
- *
- * If procsig->ps_refcnt is 1 and p2->p_sigacts is NULL we dont' need
- * to share sigacts, so we use the up->u_sigacts.
*/
p2->p_stats = &up->u_stats;
- if (p2->p_sigacts == NULL) {
- if (p2->p_procsig->ps_refcnt != 1)
- printf ("PID:%d NULL sigacts with refcnt not 1!\n",p2->p_pid);
- p2->p_sigacts = &up->u_sigacts;
- up->u_sigacts = *p1->p_sigacts;
- }
-
bzero(&up->u_stats.pstat_startzero,
(unsigned) ((caddr_t) &up->u_stats.pstat_endzero -
(caddr_t) &up->u_stats.pstat_startzero));
@@ -465,7 +456,6 @@ vm_forkproc(td, p2, td2, flags)
((caddr_t) &up->u_stats.pstat_endcopy -
(caddr_t) &up->u_stats.pstat_startcopy));
-
/*
* cpu_fork will copy and update the pcb, set up the kernel stack,
* and make the child ready to run.
OpenPOWER on IntegriCloud