Updated diff below with the following changes:
- p_sigmask is now volatile, per kettenis's request
- kern_fork.c's memcpy() for p_startcopy needs to cast away the
volatile now
- kettenis pointed out atomic_swap_uint() isn't safe to use in MI code
yet, so for now proc_sigsetmask() just relies on volatile assignment
being atomic
ok?
Index: sys/proc.h
===================================================================
RCS file: /home/matthew/cvs-mirror/cvs/src/sys/sys/proc.h,v
retrieving revision 1.186
diff -u -p -r1.186 proc.h
--- sys/proc.h 15 May 2014 03:52:25 -0000 1.186
+++ sys/proc.h 8 Jul 2014 19:19:17 -0000
@@ -310,7 +310,7 @@ struct proc {
/* The following fields are all copied upon creation in fork. */
#define p_startcopy p_sigmask
- sigset_t p_sigmask; /* Current signal mask. */
+ volatile sigset_t p_sigmask; /* Current signal mask. */
u_char p_priority; /* Process priority. */
u_char p_usrpri; /* User-priority based on p_cpu and ps_nice. */
@@ -520,6 +520,8 @@ int proc_cansugid(struct proc *);
void proc_finish_wait(struct proc *, struct proc *);
void process_zap(struct process *);
void proc_free(struct proc *);
+void proc_sigsetmask(struct proc *, sigset_t);
+void proc_sigsuspend(struct proc *, sigset_t);
struct sleep_state {
int sls_s;
@@ -559,4 +561,3 @@ struct cpu_info *cpuset_first(struct cpu
#endif /* _KERNEL */
#endif /* !_SYS_PROC_H_ */
-
Index: kern/kern_sig.c
===================================================================
RCS file: /home/matthew/cvs-mirror/cvs/src/sys/kern/kern_sig.c,v
retrieving revision 1.166
diff -u -p -r1.166 kern_sig.c
--- kern/kern_sig.c 4 May 2014 05:03:26 -0000 1.166
+++ kern/kern_sig.c 8 Jul 2014 20:29:50 -0000
@@ -62,6 +62,7 @@
#include <sys/ptrace.h>
#include <sys/sched.h>
#include <sys/user.h>
+#include <sys/atomic.h>
#include <sys/mount.h>
#include <sys/syscallargs.h>
@@ -439,37 +440,55 @@ sys_sigprocmask(struct proc *p, void *v,
syscallarg(int) how;
syscallarg(sigset_t) mask;
} */ *uap = v;
- int error = 0;
- int s;
- sigset_t mask;
+ sigset_t mask = SCARG(uap, mask);
*retval = p->p_sigmask;
- mask = SCARG(uap, mask);
- s = splhigh();
switch (SCARG(uap, how)) {
case SIG_BLOCK:
- p->p_sigmask |= mask &~ sigcantmask;
+ atomic_setbits_int(&p->p_sigmask, mask &~ sigcantmask);
break;
case SIG_UNBLOCK:
- p->p_sigmask &= ~mask;
+ atomic_clearbits_int(&p->p_sigmask, mask);
break;
case SIG_SETMASK:
- p->p_sigmask = mask &~ sigcantmask;
+ proc_sigsetmask(p, mask &~ sigcantmask);
break;
default:
- error = EINVAL;
- break;
+ return (EINVAL);
}
- splx(s);
- return (error);
+
+ return (0);
+}
+
+void
+proc_sigsetmask(struct proc *p, sigset_t mask)
+{
+ KASSERT(p == curproc);
+
+ /* XXX: Abusing volatile assignment as atomic store operation. */
+ p->p_sigmask = mask;
+}
+
+/*
+ * Temporarily replace calling proc's signal mask for the duration of a
+ * system call. Original signal mask will be restored by userret().
+ */
+void
+proc_sigsuspend(struct proc *p, sigset_t mask)
+{
+ KASSERT(p == curproc);
+ KASSERT(!(p->p_flag & P_SIGSUSPEND));
+
+ p->p_oldmask = p->p_sigmask;
+ atomic_setbits_int(&p->p_flag, P_SIGSUSPEND);
+ proc_sigsetmask(p, mask);
}
/* ARGSUSED */
int
sys_sigpending(struct proc *p, void *v, register_t *retval)
{
-
*retval = p->p_siglist;
return (0);
}
@@ -489,16 +508,7 @@ sys_sigsuspend(struct proc *p, void *v,
struct process *pr = p->p_p;
struct sigacts *ps = pr->ps_sigacts;
- /*
- * When returning from sigpause, we want
- * the old mask to be restored after the
- * signal handler has finished. Thus, we
- * save it here and mark the sigacts structure
- * to indicate this.
- */
- p->p_oldmask = p->p_sigmask;
- atomic_setbits_int(&p->p_flag, P_SIGSUSPEND);
- p->p_sigmask = SCARG(uap, mask) &~ sigcantmask;
+ proc_sigsuspend(p, SCARG(uap, mask) &~ sigcantmask);
while (tsleep(ps, PPAUSE|PCATCH, "pause", 0) == 0)
/* void */;
/* always return EINTR rather than ERESTART... */
@@ -749,7 +759,7 @@ trapsignal(struct proc *p, int signum, u
p->p_ru.ru_nsignals++;
(*pr->ps_emul->e_sendsig)(ps->ps_sigact[signum], signum,
p->p_sigmask, trapno, code, sigval);
- p->p_sigmask |= ps->ps_catchmask[signum];
+ atomic_setbits_int(&p->p_sigmask, ps->ps_catchmask[signum]);
if ((ps->ps_sigreset & mask) != 0) {
ps->ps_sigcatch &= ~mask;
if (signum != SIGCONT && sigprop[signum] & SA_IGNORE)
@@ -1365,7 +1375,7 @@ postsig(int signum)
} else {
returnmask = p->p_sigmask;
}
- p->p_sigmask |= ps->ps_catchmask[signum];
+ atomic_setbits_int(&p->p_sigmask, ps->ps_catchmask[signum]);
if ((ps->ps_sigreset & mask) != 0) {
ps->ps_sigcatch &= ~mask;
if (signum != SIGCONT && sigprop[signum] & SA_IGNORE)
@@ -1818,7 +1828,7 @@ userret(struct proc *p)
*/
if (p->p_flag & P_SIGSUSPEND) {
atomic_clearbits_int(&p->p_flag, P_SIGSUSPEND);
- p->p_sigmask = p->p_oldmask;
+ proc_sigsetmask(p, p->p_oldmask);
while ((sig = CURSIG(p)) != 0)
postsig(sig);
Index: kern/sys_generic.c
===================================================================
RCS file: /home/matthew/cvs-mirror/cvs/src/sys/kern/sys_generic.c,v
retrieving revision 1.86
diff -u -p -r1.86 sys_generic.c
--- kern/sys_generic.c 30 Mar 2014 21:54:48 -0000 1.86
+++ kern/sys_generic.c 8 Jul 2014 19:20:05 -0000
@@ -657,11 +657,8 @@ dopselect(struct proc *p, int nd, fd_set
}
timo = 0;
- if (sigmask) {
- p->p_oldmask = p->p_sigmask;
- atomic_setbits_int(&p->p_flag, P_SIGSUSPEND);
- p->p_sigmask = *sigmask &~ sigcantmask;
- }
+ if (sigmask)
+ proc_sigsuspend(p, *sigmask &~ sigcantmask);
retry:
ncoll = nselcoll;
@@ -965,11 +962,8 @@ doppoll(struct proc *p, struct pollfd *f
}
timo = 0;
- if (sigmask) {
- p->p_oldmask = p->p_sigmask;
- atomic_setbits_int(&p->p_flag, P_SIGSUSPEND);
- p->p_sigmask = *sigmask &~ sigcantmask;
- }
+ if (sigmask)
+ proc_sigsuspend(p, *sigmask &~ sigcantmask);
retry:
ncoll = nselcoll;
Index: kern/kern_fork.c
===================================================================
RCS file: /home/matthew/cvs-mirror/cvs/src/sys/kern/kern_fork.c,v
retrieving revision 1.167
diff -u -p -r1.167 kern_fork.c
--- kern/kern_fork.c 15 May 2014 03:52:25 -0000 1.167
+++ kern/kern_fork.c 8 Jul 2014 20:08:25 -0000
@@ -326,7 +326,7 @@ fork1(struct proc *curp, int flags, void
*/
memset(&p->p_startzero, 0,
(caddr_t)&p->p_endzero - (caddr_t)&p->p_startzero);
- memcpy(&p->p_startcopy, &curp->p_startcopy,
+ memcpy((void *)&p->p_startcopy, (void *)&curp->p_startcopy,
(caddr_t)&p->p_endcopy - (caddr_t)&p->p_startcopy);
crhold(p->p_ucred);
Index: compat/linux/linux_signal.c
===================================================================
RCS file: /home/matthew/cvs-mirror/cvs/src/sys/compat/linux/linux_signal.c,v
retrieving revision 1.17
diff -u -p -r1.17 linux_signal.c
--- compat/linux/linux_signal.c 26 Mar 2014 05:23:42 -0000 1.17
+++ compat/linux/linux_signal.c 7 Jul 2014 19:24:07 -0000
@@ -584,7 +584,6 @@ linux_sys_sigprocmask(p, v, retval)
linux_old_sigset_t ss;
sigset_t bs;
int error = 0;
- int s;
*retval = 0;
@@ -604,19 +603,17 @@ linux_sys_sigprocmask(p, v, retval)
linux_old_to_bsd_sigset(&ss, &bs);
- s = splhigh();
-
switch (SCARG(uap, how)) {
case LINUX_SIG_BLOCK:
- p->p_sigmask |= bs & ~sigcantmask;
+ atomic_setbits_int(&p->p_sigmask, bs &~ sigcantmask);
break;
case LINUX_SIG_UNBLOCK:
- p->p_sigmask &= ~bs;
+ atomic_clearbits_int(&p->p_sigmask, bs);
break;
case LINUX_SIG_SETMASK:
- p->p_sigmask = bs & ~sigcantmask;
+ proc_sigsetmask(p, bs &~ sigcantmask);
break;
default:
@@ -624,8 +621,6 @@ linux_sys_sigprocmask(p, v, retval)
break;
}
- splx(s);
-
return (error);
}
@@ -644,7 +639,6 @@ linux_sys_rt_sigprocmask(p, v, retval)
linux_sigset_t ls;
sigset_t bs;
int error = 0;
- int s;
if (SCARG(uap, sigsetsize) != sizeof(linux_sigset_t))
return (EINVAL);
@@ -667,19 +661,17 @@ linux_sys_rt_sigprocmask(p, v, retval)
linux_to_bsd_sigset(&ls, &bs);
- s = splhigh();
-
switch (SCARG(uap, how)) {
case LINUX_SIG_BLOCK:
- p->p_sigmask |= bs & ~sigcantmask;
+ atomic_setbits_int(&p->p_sigmask, bs &~ sigcantmask);
break;
case LINUX_SIG_UNBLOCK:
- p->p_sigmask &= ~bs;
+ atomic_clearbits_int(&p->p_sigmask, bs);
break;
case LINUX_SIG_SETMASK:
- p->p_sigmask = bs & ~sigcantmask;
+ proc_sigsetmask(p, bs &~ sigcantmask);
break;
default:
@@ -687,8 +679,6 @@ linux_sys_rt_sigprocmask(p, v, retval)
break;
}
- splx(s);
-
return (error);
}
@@ -727,16 +717,13 @@ linux_sys_sigsetmask(p, v, retval)
} */ *uap = v;
linux_old_sigset_t mask;
sigset_t bsdsig;
- int s;
bsd_to_linux_old_sigset(&p->p_sigmask, (linux_old_sigset_t *)retval);
mask = SCARG(uap, mask);
bsd_to_linux_old_sigset(&bsdsig, &mask);
- s = splhigh();
- p->p_sigmask = bsdsig & ~sigcantmask;
- splx(s);
+ proc_sigsetmask(p, bsdsig &~ sigcantmask);
return (0);
}
Index: arch/amd64/amd64/machdep.c
===================================================================
RCS file: /home/matthew/cvs-mirror/cvs/src/sys/arch/amd64/amd64/machdep.c,v
retrieving revision 1.180
diff -u -p -r1.180 machdep.c
--- arch/amd64/amd64/machdep.c 15 Jun 2014 11:43:24 -0000 1.180
+++ arch/amd64/amd64/machdep.c 7 Jul 2014 19:24:07 -0000
@@ -670,7 +670,7 @@ sys_sigreturn(struct proc *p, void *v, r
bcopy(&ksc, tf, sizeof(*tf));
/* Restore signal mask. */
- p->p_sigmask = ksc.sc_mask & ~sigcantmask;
+ proc_sigsetmask(p, ksc.sc_mask & ~sigcantmask);
/*
* sigreturn() needs to return to userspace via the 'iretq'
Index: arch/i386/i386/machdep.c
===================================================================
RCS file: /home/matthew/cvs-mirror/cvs/src/sys/arch/i386/i386/machdep.c,v
retrieving revision 1.539
diff -u -p -r1.539 machdep.c
--- arch/i386/i386/machdep.c 15 Jun 2014 11:43:24 -0000 1.539
+++ arch/i386/i386/machdep.c 7 Jul 2014 19:24:07 -0000
@@ -2491,7 +2491,7 @@ sys_sigreturn(struct proc *p, void *v, r
p->p_md.md_flags |= MDP_USEDFPU;
}
- p->p_sigmask = context.sc_mask & ~sigcantmask;
+ proc_sigsetmask(p, context.sc_mask & ~sigcantmask);
return (EJUSTRETURN);
}
@@ -3990,4 +3990,3 @@ intr_handler(struct intrframe *frame, st
#endif
return rc;
}
-