kernel - Optimize lwp-specific signaling.
authorMatthew Dillon <dillon@apollo.backplane.com>
Wed, 25 Jan 2017 17:25:40 +0000 (09:25 -0800)
committerMatthew Dillon <dillon@apollo.backplane.com>
Wed, 25 Jan 2017 19:07:49 +0000 (11:07 -0800)
* Optimize the signal code to remove most instances of needing proc->p_token
  when lwp-specific signals are sent.

* Add a CURSIG_LCK_TRACE() macro which can now return with p_token held, and
  pass the status to postsig() which then consumes it.

* lwpsignal() now tries very hard to avoid acquiring proc->p_token.

* Significantly improves vkernel operation under heavy (vkernel) IPI loads.

12 files changed:
sys/kern/kern_sig.c
sys/kern/kern_synch.c
sys/kern/kern_time.c
sys/kern/lwkt_token.c
sys/platform/pc64/x86_64/trap.c
sys/platform/vkernel64/x86_64/trap.c
sys/sys/signal2.h
sys/sys/signalvar.h
sys/sys/systm.h
sys/sys/thread.h
sys/vfs/mfs/mfs_vfsops.c
sys/vfs/procfs/procfs_ctl.c

index 8f3018e..06f14e3 100644 (file)
@@ -333,7 +333,7 @@ kern_sigaction(int sig, struct sigaction *act, struct sigaction *oact)
                if (ps->ps_sigact[_SIG_IDX(sig)] == SIG_IGN ||
                    (sigprop(sig) & SA_IGNORE &&
                     ps->ps_sigact[_SIG_IDX(sig)] == SIG_DFL)) {
-                       SIGDELSET(p->p_siglist, sig);
+                       SIGDELSET_ATOMIC(p->p_siglist, sig);
                        FOREACH_LWP_IN_PROC(lp, p) {
                                spin_lock(&lp->lwp_spin);
                                SIGDELSET(lp->lwp_siglist, sig);
@@ -414,7 +414,7 @@ execsigs(struct proc *p)
                if (sigprop(sig) & SA_IGNORE) {
                        if (sig != SIGCONT)
                                SIGADDSET(p->p_sigignore, sig);
-                       SIGDELSET(p->p_siglist, sig);
+                       SIGDELSET_ATOMIC(p->p_siglist, sig);
                        /* don't need spinlock */
                        SIGDELSET(lp->lwp_siglist, sig);
                }
@@ -1102,12 +1102,13 @@ lwpsignal(struct proc *p, struct lwp *lp, int sig)
         * on.
         */
        PHOLD(p);
-       lwkt_gettoken(&p->p_token);
        if (lp) {
                LWPHOLD(lp);
                lwkt_gettoken(&lp->lwp_token);
-       } else if (p->p_flags & P_WEXIT) {
-               goto out;
+       } else {
+               lwkt_gettoken(&p->p_token);
+               if (p->p_flags & P_WEXIT)
+                       goto out;
        }
 
        prop = sigprop(sig);
@@ -1126,11 +1127,8 @@ lwpsignal(struct proc *p, struct lwp *lp, int sig)
                 * if P_WEXIT is set in the process flags.
                 */
                if (lp && (lp->lwp_mpflags & LWP_MP_WEXIT) && sig != SIGKILL) {
-                       if (lp) {
-                               lwkt_reltoken(&lp->lwp_token);
-                               LWPRELE(lp);
-                       }
-                       lwkt_reltoken(&p->p_token);
+                       lwkt_reltoken(&lp->lwp_token);
+                       LWPRELE(lp);
                        PRELE(p);
                        return;
                }
@@ -1149,8 +1147,9 @@ lwpsignal(struct proc *p, struct lwp *lp, int sig)
                        if (lp) {
                                lwkt_reltoken(&lp->lwp_token);
                                LWPRELE(lp);
+                       } else {
+                               lwkt_reltoken(&p->p_token);
                        }
-                       lwkt_reltoken(&p->p_token);
                        PRELE(p);
                        return;
                }
@@ -1161,10 +1160,14 @@ lwpsignal(struct proc *p, struct lwp *lp, int sig)
        }
 
        /*
-        * If continuing, clear any pending STOP signals.
+        * If continuing, clear any pending STOP signals for the whole
+        * process.
         */
-       if (prop & SA_CONT)
-               SIG_STOPSIGMASK(p->p_siglist);
+       if (prop & SA_CONT) {
+               lwkt_gettoken(&p->p_token);
+               SIG_STOPSIGMASK_ATOMIC(p->p_siglist);
+               lwkt_reltoken(&p->p_token);
+       }
        
        if (prop & SA_STOP) {
                /*
@@ -1173,18 +1176,21 @@ lwpsignal(struct proc *p, struct lwp *lp, int sig)
                 * is default; don't stop the process below if sleeping,
                 * and don't clear any pending SIGCONT.
                 */
-               if (prop & SA_TTYSTOP && p->p_pgrp->pg_jobc == 0 &&
+               if ((prop & SA_TTYSTOP) && p->p_pgrp->pg_jobc == 0 &&
                    action == SIG_DFL) {
                        if (lp) {
                                lwkt_reltoken(&lp->lwp_token);
                                LWPRELE(lp);
+                       } else {
+                               lwkt_reltoken(&p->p_token);
                        }
-                       lwkt_reltoken(&p->p_token);
                        PRELE(p);
                        return;
                }
-               SIG_CONTSIGMASK(p->p_siglist);
+               lwkt_gettoken(&p->p_token);
+               SIG_CONTSIGMASK_ATOMIC(p->p_siglist);
                p->p_flags &= ~P_CONTINUED;
+               lwkt_reltoken(&p->p_token);
        }
 
        if (p->p_stat == SSTOP) {
@@ -1192,20 +1198,27 @@ lwpsignal(struct proc *p, struct lwp *lp, int sig)
                 * Nobody can handle this signal, add it to the lwp or
                 * process pending list 
                 */
+               lwkt_gettoken(&p->p_token);
+               if (p->p_stat != SSTOP) {
+                       lwkt_reltoken(&p->p_token);
+                       goto not_stopped;
+               }
                if (lp) {
                        spin_lock(&lp->lwp_spin);
                        SIGADDSET(lp->lwp_siglist, sig);
                        spin_unlock(&lp->lwp_spin);
                } else {
-                       SIGADDSET(p->p_siglist, sig);
+                       SIGADDSET_ATOMIC(p->p_siglist, sig);
                }
 
                /*
                 * If the process is stopped and is being traced, then no
                 * further action is necessary.
                 */
-               if (p->p_flags & P_TRACED)
+               if (p->p_flags & P_TRACED) {
+                       lwkt_reltoken(&p->p_token);
                        goto out;
+               }
 
                /*
                 * If the process is stopped and receives a KILL signal,
@@ -1213,6 +1226,7 @@ lwpsignal(struct proc *p, struct lwp *lp, int sig)
                 */
                if (sig == SIGKILL) {
                        proc_unstop(p, SSTOP);
+                       lwkt_reltoken(&p->p_token);
                        goto active_process;
                }
 
@@ -1241,10 +1255,11 @@ lwpsignal(struct proc *p, struct lwp *lp, int sig)
                        p->p_flags |= P_CONTINUED;
                        wakeup(q);
                        if (action == SIG_DFL)
-                               SIGDELSET(p->p_siglist, sig);
+                               SIGDELSET_ATOMIC(p->p_siglist, sig);
                        proc_unstop(p, SSTOP);
                        lwkt_reltoken(&q->p_token);
                        PRELE(q);
+                       lwkt_reltoken(&p->p_token);
                        if (action == SIG_CATCH)
                                goto active_process;
                        goto out;
@@ -1261,9 +1276,12 @@ lwpsignal(struct proc *p, struct lwp *lp, int sig)
                 * we don't want to wait until it reaches userret!
                 */
                if (prop & SA_STOP) {
+                       lwkt_gettoken(&p->p_token);
                        if (lwkt_preempted_proc() == NULL ||
-                           lwkt_preempted_proc()->lwp_proc != p)
-                               SIGDELSET(p->p_siglist, sig);
+                           lwkt_preempted_proc()->lwp_proc != p) {
+                               SIGDELSET_ATOMIC(p->p_siglist, sig);
+                       }
+                       lwkt_reltoken(&p->p_token);
                }
 
                /*
@@ -1272,14 +1290,11 @@ lwpsignal(struct proc *p, struct lwp *lp, int sig)
                 * the process is continued a wakeup(p) will be issued which
                 * will wakeup any threads sleeping in tstop().
                 */
-               if (lp == NULL) {
-                       /* NOTE: returns lp w/ token held */
-                       lp = find_lwp_for_signal(p, sig);
-               }
                goto out;
-
                /* NOTREACHED */
        }
+not_stopped:
+       ;
        /* else not stopped */
 active_process:
 
@@ -1294,6 +1309,9 @@ active_process:
                                lwkt_reltoken(&lp->lwp_token);
                                LWPRELE(lp);
                                lp = NULL;
+                       } else {
+                               lwkt_token_swap();
+                               lwkt_reltoken(&p->p_token);
                        }
                }
        }
@@ -1305,7 +1323,7 @@ active_process:
         */
        if (lp == NULL) {
                KNOTE(&p->p_klist, NOTE_SIGNAL | sig);
-               SIGADDSET(p->p_siglist, sig);
+               SIGADDSET_ATOMIC(p->p_siglist, sig);
                goto out;
        }
 
@@ -1315,7 +1333,9 @@ active_process:
         */
        if (p->p_nice > NZERO && action == SIG_DFL && (prop & SA_KILL) &&
            (p->p_flags & P_TRACED) == 0) {
+               lwkt_gettoken(&p->p_token);
                p->p_nice = NZERO;
+               lwkt_reltoken(&p->p_token);
        }
 
        /*
@@ -1329,8 +1349,10 @@ active_process:
                 * could cause deadlock.  Take no action at this
                 * time.
                 */
+               lwkt_gettoken(&p->p_token);
                if (p->p_flags & P_PPWAIT) {
-                       SIGADDSET(p->p_siglist, sig);
+                       SIGADDSET_ATOMIC(p->p_siglist, sig);
+                       lwkt_reltoken(&p->p_token);
                        goto out;
                }
 
@@ -1344,6 +1366,7 @@ active_process:
                        p->p_xstat = sig;
                        proc_stop(p, SSTOP);
                }
+               lwkt_reltoken(&p->p_token);
                goto out;
        }
 
@@ -1366,8 +1389,9 @@ out:
        if (lp) {
                lwkt_reltoken(&lp->lwp_token);
                LWPRELE(lp);
+       } else {
+               lwkt_reltoken(&p->p_token);
        }
-       lwkt_reltoken(&p->p_token);
        PRELE(p);
 }
 
@@ -1397,7 +1421,7 @@ lwp_signotify(struct lwp *lp)
 {
        thread_t dtd;
 
-       ASSERT_LWKT_TOKEN_HELD(&lp->lwp_proc->p_token);
+       ASSERT_LWKT_TOKEN_HELD(&lp->lwp_token);
        dtd = lp->lwp_thread;
 
        crit_enter();
@@ -1697,7 +1721,7 @@ kern_sigtimedwait(sigset_t waitset, siginfo_t *info, struct timespec *timeout)
                        SIGFILLSET(lp->lwp_sigmask);
                        SIGDELSET(lp->lwp_sigmask, sig);
                        SIG_CANTMASK(lp->lwp_sigmask);
-                       sig = issignal(lp, 1);
+                       sig = issignal(lp, 1, 0);
                        /*
                         * It may be a STOP signal, in the case, issignal
                         * returns 0, because we may stop there, and new
@@ -1764,7 +1788,7 @@ kern_sigtimedwait(sigset_t waitset, siginfo_t *info, struct timespec *timeout)
                bzero(info, sizeof(*info));
                info->si_signo = sig;
                spin_lock(&lp->lwp_spin);
-               lwp_delsig(lp, sig);    /* take the signal! */
+               lwp_delsig(lp, sig, 1); /* take the signal! */
                spin_unlock(&lp->lwp_spin);
 
                if (sig == SIGKILL) {
@@ -1873,7 +1897,7 @@ iscaught(struct lwp *lp)
 }
 
 /*
- * If the current process has received a signal (should be caught or cause
+ * If the current lwp/proc has received a signal (should be caught or cause
  * termination, should interrupt current syscall), return the signal number.
  * Stop signals with default action are processed immediately, then cleared;
  * they aren't returned.  This is checked after each entry to the system for
@@ -1886,36 +1910,63 @@ iscaught(struct lwp *lp)
  *
  *     while (sig = CURSIG(curproc))
  *             postsig(sig);
- *
- * MPSAFE
  */
 int
-issignal(struct lwp *lp, int maytrace)
+issignal(struct lwp *lp, int maytrace, int *ptokp)
 {
        struct proc *p = lp->lwp_proc;
        sigset_t mask;
        int sig, prop;
-
-       lwkt_gettoken(&p->p_token);
+       int haveptok;
 
        for (;;) {
                int traced = (p->p_flags & P_TRACED) || (p->p_stops & S_SIG);
 
+               haveptok = 0;
+
                /*
                 * If this process is supposed to stop, stop this thread.
                 */
-               if (STOPLWP(p, lp))
+               if (STOPLWP(p, lp)) {
+                       lwkt_gettoken(&p->p_token);
                        tstop();
+                       lwkt_reltoken(&p->p_token);
+               }
 
+               /*
+                * Quick check without token
+                */
                mask = lwp_sigpend(lp);
                SIGSETNAND(mask, lp->lwp_sigmask);
                if (p->p_flags & P_PPWAIT)
                        SIG_STOPSIGMASK(mask);
-               if (SIGISEMPTY(mask)) {         /* no signal to send */
-                       lwkt_reltoken(&p->p_token);
+               if (SIGISEMPTY(mask))           /* no signal to send */
                        return (0);
-               }
+
+               /*
+                * If the signal is a member of the process signal set
+                * we need p_token (even if it is also a member of the
+                * lwp signal set).
+                */
                sig = sig_ffs(&mask);
+               if (SIGISMEMBER(p->p_siglist, sig)) {
+                       /*
+                        * Recheck with token
+                        */
+                       haveptok = 1;
+                       lwkt_gettoken(&p->p_token);
+
+                       mask = lwp_sigpend(lp);
+                       SIGSETNAND(mask, lp->lwp_sigmask);
+                       if (p->p_flags & P_PPWAIT)
+                               SIG_STOPSIGMASK(mask);
+                       if (SIGISEMPTY(mask)) {         /* no signal to send */
+                               /* haveptok is TRUE */
+                               lwkt_reltoken(&p->p_token);
+                               return (0);
+                       }
+                       sig = sig_ffs(&mask);
+               }
 
                STOPEVENT(p, S_SIG, sig);
 
@@ -1925,8 +1976,10 @@ issignal(struct lwp *lp, int maytrace)
                 */
                if (SIGISMEMBER(p->p_sigignore, sig) && (traced == 0)) {
                        spin_lock(&lp->lwp_spin);
-                       lwp_delsig(lp, sig);
+                       lwp_delsig(lp, sig, haveptok);
                        spin_unlock(&lp->lwp_spin);
+                       if (haveptok)
+                               lwkt_reltoken(&p->p_token);
                        continue;
                }
                if (maytrace &&
@@ -1943,6 +1996,10 @@ issignal(struct lwp *lp, int maytrace)
                         *
                         * XXX not sure if this is still true
                         */
+                       if (haveptok == 0) {
+                               lwkt_gettoken(&p->p_token);
+                               haveptok = 1;
+                       }
                        p->p_xstat = sig;
                        proc_stop(p, SSTOP);
                        do {
@@ -1955,11 +2012,14 @@ issignal(struct lwp *lp, int maytrace)
                         * otherwise we just look for signals again.
                         */
                        spin_lock(&lp->lwp_spin);
-                       lwp_delsig(lp, sig);    /* clear old signal */
+                       lwp_delsig(lp, sig, 1); /* clear old signal */
                        spin_unlock(&lp->lwp_spin);
                        sig = p->p_xstat;
-                       if (sig == 0)
+                       if (sig == 0) {
+                               /* haveptok is TRUE */
+                               lwkt_reltoken(&p->p_token);
                                continue;
+                       }
 
                        /*
                         * Put the new signal into p_siglist.  If the
@@ -1967,19 +2027,28 @@ issignal(struct lwp *lp, int maytrace)
                         *
                         * XXX lwp might need a call to ksignal()
                         */
-                       SIGADDSET(p->p_siglist, sig);
-                       if (SIGISMEMBER(lp->lwp_sigmask, sig))
+                       SIGADDSET_ATOMIC(p->p_siglist, sig);
+                       if (SIGISMEMBER(lp->lwp_sigmask, sig)) {
+                               /* haveptok is TRUE */
+                               lwkt_reltoken(&p->p_token);
                                continue;
+                       }
 
                        /*
                         * 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.
                         */
-                       if ((p->p_flags & P_TRACED) == 0)
+                       if ((p->p_flags & P_TRACED) == 0) {
+                               /* haveptok is TRUE */
+                               lwkt_reltoken(&p->p_token);
                                continue;
+                       }
                }
 
+               /*
+                * p_token may be held here
+                */
                prop = sigprop(sig);
 
                /*
@@ -2008,6 +2077,10 @@ issignal(struct lwp *lp, int maytrace)
                         * Handle the in-kernel checkpoint action
                         */
                        if (prop & SA_CKPT) {
+                               if (haveptok == 0) {
+                                       lwkt_gettoken(&p->p_token);
+                                       haveptok = 1;
+                               }
                                checkpoint_signal_handler(lp);
                                break;
                        }
@@ -2020,6 +2093,10 @@ issignal(struct lwp *lp, int maytrace)
                         * process group, ignore tty stop signals.
                         */
                        if (prop & SA_STOP) {
+                               if (haveptok == 0) {
+                                       lwkt_gettoken(&p->p_token);
+                                       haveptok = 1;
+                               }
                                if (p->p_flags & P_TRACED ||
                                    (p->p_pgrp->pg_jobc == 0 &&
                                    prop & SA_TTYSTOP))
@@ -2037,7 +2114,10 @@ issignal(struct lwp *lp, int maytrace)
                                 */
                                break;          /* == ignore */
                        } else {
-                               lwkt_reltoken(&p->p_token);
+                               if (ptokp)
+                                       *ptokp = haveptok;
+                               else if (haveptok)
+                                       lwkt_reltoken(&p->p_token);
                                return (sig);
                        }
 
@@ -2059,12 +2139,18 @@ issignal(struct lwp *lp, int maytrace)
                         * This signal has an action, let
                         * postsig() process it.
                         */
-                       lwkt_reltoken(&p->p_token);
+                       if (ptokp)
+                               *ptokp = haveptok;
+                       else if (haveptok)
+                               lwkt_reltoken(&p->p_token);
                        return (sig);
                }
                spin_lock(&lp->lwp_spin);
-               lwp_delsig(lp, sig);            /* take the signal! */
+               lwp_delsig(lp, sig, haveptok);          /* take the signal! */
                spin_unlock(&lp->lwp_spin);
+
+               if (haveptok)
+                       lwkt_reltoken(&p->p_token);
        }
        /* NOTREACHED */
 }
@@ -2073,10 +2159,12 @@ issignal(struct lwp *lp, int maytrace)
  * Take the action for the specified signal
  * from the current set of pending signals.
  *
- * Caller must hold p->p_token
+ * haveptok indicates whether the caller is holding
+ * p->p_token.  If the caller is, we are responsible
+ * for releasing it.
  */
 void
-postsig(int sig)
+postsig(int sig, int haveptok)
 {
        struct lwp *lp = curthread->td_lwp;
        struct proc *p = lp->lwp_proc;
@@ -2101,7 +2189,7 @@ postsig(int sig)
        }
 
        spin_lock(&lp->lwp_spin);
-       lwp_delsig(lp, sig);
+       lwp_delsig(lp, sig, haveptok);
        spin_unlock(&lp->lwp_spin);
        action = ps->ps_sigact[_SIG_IDX(sig)];
 #ifdef KTRACE
@@ -2109,6 +2197,12 @@ postsig(int sig)
                ktrpsig(lp, sig, action, lp->lwp_flags & LWP_OLDMASK ?
                        &lp->lwp_oldsigmask : &lp->lwp_sigmask, 0);
 #endif
+       /*
+        * We don't need p_token after this point.
+        */
+       if (haveptok)
+               lwkt_reltoken(&p->p_token);
+
        STOPEVENT(p, S_SIG, sig);
 
        if (action == SIG_DFL) {
index 788b8e3..b3379ed 100644 (file)
@@ -550,7 +550,7 @@ tsleep(const volatile void *ident, int flags, const char *wmesg, int timo)
 
                        /*
                         * Causes ksignal to wake us up if a signal is
-                        * received (interlocked with p->p_token).
+                        * received (interlocked with lp->lwp_token).
                         */
                        lp->lwp_flags |= LWP_SINTR;
                }
index 92418ee..883ca19 100644 (file)
@@ -68,6 +68,7 @@ struct timezone tz;
 
 static int     settime(struct timeval *);
 static void    timevalfix(struct timeval *);
+static void    realitexpire(void *arg);
 
 /*
  * Nanosleep tries very hard to sleep for a precisely requested time
@@ -856,6 +857,7 @@ sys_setitimer(struct setitimer_args *uap)
  * that here since we want to appear to be in sync with the clock
  * interrupt even when we're delayed.
  */
+static
 void
 realitexpire(void *arg)
 {
index 84cdd83..8e35887 100644 (file)
@@ -776,14 +776,6 @@ lwkt_trytoken(lwkt_token_t tok)
        return FALSE;
 }
 
-
-void
-lwkt_gettoken_hard(lwkt_token_t tok)
-{
-       lwkt_gettoken(tok);
-       crit_enter_hard();
-}
-
 lwkt_token_t
 lwkt_getpooltoken(void *ptr)
 {
@@ -817,13 +809,6 @@ lwkt_reltoken(lwkt_token_t tok)
        td->td_toks_stop = ref;
 }
 
-void
-lwkt_reltoken_hard(lwkt_token_t tok)
-{
-       lwkt_reltoken(tok);
-       crit_exit_hard();
-}
-
 /*
  * It is faster for users of lwkt_getpooltoken() to use the returned
  * token and just call lwkt_reltoken(), but for convenience we provide
index 5a3975b..fe5c42f 100644 (file)
@@ -218,6 +218,7 @@ userret(struct lwp *lp, struct trapframe *frame, int sticks)
 {
        struct proc *p = lp->lwp_proc;
        int sig;
+       int ptok;
 
        /*
         * Charge system time if profiling.  Note: times are in microseconds.
@@ -274,10 +275,8 @@ recheck:
         *
         * WARNING!  postsig() can exit and not return.
         */
-       if ((sig = CURSIG_TRACE(lp)) != 0) {
-               lwkt_gettoken(&p->p_token);
-               postsig(sig);
-               lwkt_reltoken(&p->p_token);
+       if ((sig = CURSIG_LCK_TRACE(lp, &ptok)) != 0) {
+               postsig(sig, ptok);
                goto recheck;
        }
 
index 9bcc7a4..352ade5 100644 (file)
@@ -195,6 +195,7 @@ userret(struct lwp *lp, struct trapframe *frame, int sticks)
 {
        struct proc *p = lp->lwp_proc;
        int sig;
+       int ptok;
 
        /*
         * Charge system time if profiling.  Note: times are in microseconds.
@@ -217,7 +218,7 @@ recheck:
        /*
         * Block here if we are in a stopped state.
         */
-       if (p->p_stat == SSTOP || p->p_stat == SCORE) {
+       if (STOPLWP(p, lp)) {
                lwkt_gettoken(&p->p_token);
                tstop();
                lwkt_reltoken(&p->p_token);
@@ -247,10 +248,8 @@ recheck:
         *
         * WARNING!  postsig() can exit and not return.
         */
-       if ((sig = CURSIG_TRACE(lp)) != 0) {
-               lwkt_gettoken(&p->p_token);
-               postsig(sig);
-               lwkt_reltoken(&p->p_token);
+       if ((sig = CURSIG_LCK_TRACE(lp, &ptok)) != 0) {
+               postsig(sig, ptok);
                goto recheck;
        }
 
@@ -300,8 +299,7 @@ userexit(struct lwp *lp)
         * Handle stop requests at kernel priority.  Any requests queued
         * after this loop will generate another AST.
         */
-       while (lp->lwp_proc->p_stat == SSTOP ||
-              lp->lwp_proc->p_stat == SCORE) {
+       while (STOPLWP(lp->lwp_proc, lp)) {
                lwkt_gettoken(&lp->lwp_proc->p_token);
                tstop();
                lwkt_reltoken(&lp->lwp_proc->p_token);
index a7bd504..949194c 100644 (file)
@@ -52,6 +52,7 @@ lwp_sigpend(struct lwp *lp)
 
        set = lp->lwp_proc->p_siglist;
        SIGSETOR(set, lp->lwp_siglist);
+
        return (set);
 }
 
@@ -61,15 +62,17 @@ lwp_sigpend(struct lwp *lp)
  * (p->p_token must be held, lp->lwp_spin must be held)
  */
 static __inline void
-lwp_delsig(struct lwp *lp, int sig)
+lwp_delsig(struct lwp *lp, int sig, int fromproc)
 {
        SIGDELSET(lp->lwp_siglist, sig);
-       SIGDELSET(lp->lwp_proc->p_siglist, sig);
+       if (fromproc)
+               SIGDELSET_ATOMIC(lp->lwp_proc->p_siglist, sig);
 }
 
-#define        CURSIG(lp)              __cursig(lp, 1, 0)
-#define        CURSIG_TRACE(lp)        __cursig(lp, 1, 1)
-#define CURSIG_NOBLOCK(lp)     __cursig(lp, 0, 0)
+#define        CURSIG(lp)                      __cursig(lp, 1, 0, NULL)
+#define        CURSIG_TRACE(lp)                __cursig(lp, 1, 1, NULL)
+#define        CURSIG_LCK_TRACE(lp, ptok)      __cursig(lp, 1, 1, ptok)
+#define CURSIG_NOBLOCK(lp)             __cursig(lp, 0, 0, NULL)
 
 /*
  * Determine signal that should be delivered to process p, the current
@@ -79,11 +82,14 @@ lwp_delsig(struct lwp *lp, int sig)
  * This function does not interlock pending signals.  If the caller needs
  * to interlock the caller must acquire the per-proc token.
  *
- * MPSAFE
+ * If ptok is non-NULL this function may return with proc->p_token held,
+ * indicating that the signal came from the process structure.  This is
+ * used by postsig to avoid holding p_token when possible.  Only applicable
+ * if mayblock is non-zero.
  */
 static __inline
 int
-__cursig(struct lwp *lp, int mayblock, int maytrace)
+__cursig(struct lwp *lp, int mayblock, int maytrace, int *ptok)
 {
        struct proc *p = lp->lwp_proc;
        sigset_t tmpset;
@@ -104,7 +110,7 @@ __cursig(struct lwp *lp, int mayblock, int maytrace)
        }
 
        if (mayblock)
-               r = issignal(lp, maytrace);
+               r = issignal(lp, maytrace, ptok);
        else
                r = TRUE;       /* simply state the fact */
 
index 7a61d8a..80d7fb7 100644 (file)
@@ -87,9 +87,15 @@ struct       sigacts {
 #define SIGADDSET(set, signo)                                          \
        (set).__bits[_SIG_WORD(signo)] |= _SIG_BIT(signo)
 
+#define SIGADDSET_ATOMIC(set, signo)                                   \
+       atomic_set_int(&(set).__bits[_SIG_WORD(signo)], _SIG_BIT(signo))
+
 #define SIGDELSET(set, signo)                                          \
        (set).__bits[_SIG_WORD(signo)] &= ~_SIG_BIT(signo)
 
+#define SIGDELSET_ATOMIC(set, signo)                                   \
+       atomic_clear_int(&(set).__bits[_SIG_WORD(signo)], _SIG_BIT(signo))
+
 #define SIGEMPTYSET(set)                                               \
        do {                                                            \
                int __i;                                                \
@@ -141,9 +147,16 @@ struct     sigacts {
        SIGDELSET(set, SIGSTOP), SIGDELSET(set, SIGTSTP),               \
        SIGDELSET(set, SIGTTIN), SIGDELSET(set, SIGTTOU)
 
+#define SIG_STOPSIGMASK_ATOMIC(set)                                    \
+       SIGDELSET_ATOMIC(set, SIGSTOP), SIGDELSET_ATOMIC(set, SIGTSTP), \
+       SIGDELSET_ATOMIC(set, SIGTTIN), SIGDELSET_ATOMIC(set, SIGTTOU)
+
 #define SIG_CONTSIGMASK(set)                                           \
        SIGDELSET(set, SIGCONT)
 
+#define SIG_CONTSIGMASK_ATOMIC(set)                                    \
+       SIGDELSET_ATOMIC(set, SIGCONT)
+
 #define sigcantmask    (sigmask(SIGKILL) | sigmask(SIGSTOP))
 
 static __inline int
@@ -185,12 +198,12 @@ extern int sugid_coredump;        /* Sysctl variable kern.sugid_coredump */
  */
 void   execsigs (struct proc *p);
 void   gsignal (int pgid, int sig);
-int    issignal (struct lwp *lp, int maytrace);
+int    issignal (struct lwp *lp, int maytrace, int *ptokp);
 int    iscaught (struct lwp *p);
 void   killproc (struct proc *p, char *why);
 void   pgsigio (struct sigio *, int signum, int checkctty);
 void   pgsignal (struct pgrp *pgrp, int sig, int checkctty);
-void   postsig (int sig);
+void   postsig (int sig, int ptok);
 void   ksignal (struct proc *p, int sig);
 void   lwpsignal (struct proc *p, struct lwp *lp, int sig);
 void   siginit (struct proc *p);
index 2fd95cf..eaba480 100644 (file)
@@ -274,7 +274,6 @@ int fusword (void *base);
 int    susword (void *base, int word);
 u_long casuword(volatile u_long *p, u_long oldval, u_long newval);
 
-void   realitexpire (void *);
 void   DELAY(int usec);
 void   DRIVERSLEEP(int usec);
 
index 9db9eea..0523731 100644 (file)
@@ -144,34 +144,6 @@ typedef struct lwkt_token {
 #define ASSERT_NO_TOKENS_HELD(td)      \
        KKASSERT((td)->td_toks_stop == &td->td_toks_array[0])
 
-/*
- * Assert that a particular token is held and we are in a hard
- * code execution section (interrupt, ipi, or hard code section).
- * Hard code sections are not allowed to block or potentially block.
- * e.g. lwkt_gettoken() would only be ok if the token were already
- * held.
- */
-#define ASSERT_LWKT_TOKEN_HARD(tok)                                    \
-       do {                                                            \
-               globaldata_t zgd __debugvar = mycpu;                    \
-               KKASSERT((tok)->t_ref &&                                \
-                        (tok)->t_ref->tr_owner == zgd->gd_curthread && \
-                        zgd->gd_intr_nesting_level > 0);               \
-       } while(0)
-
-/*
- * Assert that a particular token is held and we are in a normal
- * critical section.  Critical sections will not be preempted but
- * can explicitly block (tsleep, lwkt_gettoken, etc).
- */
-#define ASSERT_LWKT_TOKEN_CRIT(tok)                                    \
-       do {                                                            \
-               globaldata_t zgd __debugvar = mycpu;                    \
-               KKASSERT((tok)->t_ref &&                                \
-                        (tok)->t_ref->tr_owner == zgd->gd_curthread && \
-                        zgd->gd_curthread->td_critcount > 0);          \
-       } while(0)
-
 struct lwkt_tokref {
     lwkt_token_t       tr_tok;         /* token in question */
     long               tr_count;       /* TOK_EXCLUSIVE|TOK_EXCLREQ or 0 */
@@ -455,10 +427,8 @@ extern void lwkt_maybe_splz(thread_t);
 
 extern void lwkt_gettoken(lwkt_token_t);
 extern void lwkt_gettoken_shared(lwkt_token_t);
-extern void lwkt_gettoken_hard(lwkt_token_t);
 extern int  lwkt_trytoken(lwkt_token_t);
 extern void lwkt_reltoken(lwkt_token_t);
-extern void lwkt_reltoken_hard(lwkt_token_t);
 extern int  lwkt_cnttoken(lwkt_token_t, thread_t);
 extern int  lwkt_getalltokens(thread_t, int);
 extern void lwkt_relalltokens(thread_t);
index 5f7c3b3..1058c89 100644 (file)
@@ -475,12 +475,14 @@ mfs_start(struct mount *mp, int flags)
                        gotsig = 0;
                        if (dounmount(mp, 0) != 0) {
                                KKASSERT(td->td_proc);
+                               lwkt_gettoken(&td->td_proc->p_token);
                                sig = CURSIG(td->td_lwp);
                                if (sig) {
                                        spin_lock(&td->td_lwp->lwp_spin);
-                                       lwp_delsig(td->td_lwp, sig);
+                                       lwp_delsig(td->td_lwp, sig, 1);
                                        spin_unlock(&td->td_lwp->lwp_spin);
                                }
+                               lwkt_reltoken(&td->td_proc->p_token);
                        }
                }
                else if (tsleep((caddr_t)mfsp, PCATCH, "mfsidl", 0))
index 4a866ed..f406ae2 100644 (file)
@@ -208,7 +208,7 @@ procfs_control(struct proc *curp, struct lwp *lp, int op)
 
                /* remove pending SIGTRAP, else the process will die */
                spin_lock(&lp->lwp_spin);
-               lwp_delsig(lp, SIGTRAP);
+               lwp_delsig(lp, SIGTRAP, 1);
                spin_unlock(&lp->lwp_spin);
 
                /* give process back to original parent */