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;
 }
-

Reply via email to