kernel - Add per-process token, adjust signal code to use it.
authorMatthew Dillon <dillon@apollo.backplane.com>
Fri, 11 Feb 2011 22:47:58 +0000 (14:47 -0800)
committerMatthew Dillon <dillon@apollo.backplane.com>
Fri, 11 Feb 2011 22:47:58 +0000 (14:47 -0800)
* Add proc->p_token and use it to interlock signal-related operations.

* Remove the use of proc_token in various signal paths.  Note that proc_token
  is still used in conjuction with pfind().

* Remove the use of proc_token in CURSIG*()/issignal() sequences, which
  also removes its use in the tsleep path and the syscall path.  p->p_token
  is use instead.

* Move the automatic interlock in the tsleep code to before the CURSIG code,
  fixing a rare race where a SIGCHLD could race against a parent process
  in sigsuspend().  Also acquire p->p_token here to interlock LWP_SINTR
  handling.

sys/kern/init_main.c
sys/kern/kern_checkpoint.c
sys/kern/kern_exit.c
sys/kern/kern_fork.c
sys/kern/kern_sig.c
sys/kern/kern_synch.c
sys/kern/sys_process.c
sys/sys/proc.h
sys/sys/signal2.h
sys/vfs/procfs/procfs_ctl.c
sys/vfs/procfs/procfs_subr.c

index a65de3f..90b398c 100644 (file)
@@ -170,6 +170,7 @@ mi_proc0init(struct globaldata *gd, struct user *proc0paddr)
        lwkt_set_comm(&thread0, "thread0");
        RB_INIT(&proc0.p_lwp_tree);
        spin_init(&proc0.p_spin);
+       lwkt_token_init(&proc0.p_token, "iproc");
        proc0.p_lasttid = 0;    /* +1 = next TID */
        lwp_rb_tree_RB_INSERT(&proc0.p_lwp_tree, &lwp0);
        lwp0.lwp_thread = &thread0;
index b515a9e..2f8fcfd 100644 (file)
@@ -692,7 +692,7 @@ ckpt_freeze_proc(struct lwp *lp, struct file *fp)
        rlim_t limit;
        int error;
 
-       lwkt_gettoken(&proc_token);     /* needed for proc_*() calls */
+       lwkt_gettoken(&p->p_token);     /* needed for proc_*() calls */
 
         PRINTF(("calling generic_elf_coredump\n"));
        limit = p->p_rlimit[RLIMIT_CORE].rlim_cur;
@@ -705,7 +705,7 @@ ckpt_freeze_proc(struct lwp *lp, struct file *fp)
        } else {
                error = ERANGE;
        }
-       lwkt_reltoken(&proc_token);
+       lwkt_reltoken(&p->p_token);
        return error;
 }
 
index 71697e4..b41f36f 100644 (file)
@@ -785,7 +785,8 @@ loop:
                    p->p_pid != pid && p->p_pgid != -pid)
                        continue;
 
-               /* This special case handles a kthread spawned by linux_clone 
+               /*
+                * This special case handles a kthread spawned by linux_clone
                 * (see linux_misc.c).  The linux_wait4 and linux_waitpid 
                 * functions need to be able to distinguish between waiting
                 * on a process and waiting on a thread.  It is a thread if
index 87a4077..8e99475 100644 (file)
@@ -368,6 +368,7 @@ fork1(struct lwp *lp1, int flags, struct proc **procp)
 
        RB_INIT(&p2->p_lwp_tree);
        spin_init(&p2->p_spin);
+       lwkt_token_init(&p2->p_token, "iproc");
        p2->p_lasttid = -1;     /* first tid will be 0 */
 
        /*
index 617e4cf..c275364 100644 (file)
@@ -240,7 +240,7 @@ kern_sigaction(int sig, struct sigaction *act, struct sigaction *oact)
        if (sig <= 0 || sig > _SIG_MAXSIG)
                return (EINVAL);
 
-       lwkt_gettoken(&proc_token);
+       lwkt_gettoken(&p->p_token);
 
        if (oact) {
                oact->sa_handler = ps->ps_sigact[_SIG_IDX(sig)];
@@ -270,13 +270,15 @@ kern_sigaction(int sig, struct sigaction *act, struct sigaction *oact)
                 */
                if (sig == SIGKILL || sig == SIGSTOP) {
                        if (act->sa_handler != SIG_DFL) {
-                               lwkt_reltoken(&proc_token);
+                               lwkt_reltoken(&p->p_token);
                                return (EINVAL);
                        }
 #if 0
                        /* (not needed, SIG_DFL forces action to occur) */
-                       if (act->sa_flags & SA_MAILBOX)
+                       if (act->sa_flags & SA_MAILBOX) {
+                               lwkt_reltoken(&p->p_token);
                                return (EINVAL);
+                       }
 #endif
                }
 
@@ -367,7 +369,7 @@ kern_sigaction(int sig, struct sigaction *act, struct sigaction *oact)
 
                crit_exit();
        }
-       lwkt_reltoken(&proc_token);
+       lwkt_reltoken(&p->p_token);
        return (0);
 }
 
@@ -460,9 +462,10 @@ kern_sigprocmask(int how, sigset_t *set, sigset_t *oset)
 {
        struct thread *td = curthread;
        struct lwp *lp = td->td_lwp;
+       struct proc *p = td->td_proc;
        int error;
 
-       lwkt_gettoken(&proc_token);
+       lwkt_gettoken(&p->p_token);
 
        if (oset != NULL)
                *oset = lp->lwp_sigmask;
@@ -487,7 +490,7 @@ kern_sigprocmask(int how, sigset_t *set, sigset_t *oset)
                }
        }
 
-       lwkt_reltoken(&proc_token);
+       lwkt_reltoken(&p->p_token);
 
        return (error);
 }
@@ -751,7 +754,11 @@ kern_kill(int sig, pid_t pid, lwpid_t tid)
                        lwkt_reltoken(&proc_token);
                        return (ESRCH);
                }
+               PHOLD(p);
+               lwkt_gettoken(&p->p_token);
                if (!CANSIGNAL(p, sig)) {
+                       lwkt_reltoken(&p->p_token);
+                       PRELE(p);
                        lwkt_reltoken(&proc_token);
                        return (EPERM);
                }
@@ -762,21 +769,28 @@ kern_kill(int sig, pid_t pid, lwpid_t tid)
                 * during exit, which is allowed.
                 */
                if (p->p_flag & P_WEXIT) {
+                       lwkt_reltoken(&p->p_token);
+                       PRELE(p);
                        lwkt_reltoken(&proc_token);
                        return (0);
                }
                if (tid != -1) {
                        lp = lwp_rb_tree_RB_LOOKUP(&p->p_lwp_tree, tid);
                        if (lp == NULL) {
+                               lwkt_reltoken(&p->p_token);
+                               PRELE(p);
                                lwkt_reltoken(&proc_token);
                                return (ESRCH);
                        }
                }
                if (sig)
                        lwpsignal(p, lp, sig);
+               lwkt_reltoken(&p->p_token);
+               PRELE(p);
                lwkt_reltoken(&proc_token);
                return (0);
        }
+
        /*
         * If we come here, pid is a special broadcast pid.
         * This doesn't mix with a tid.
@@ -1017,7 +1031,7 @@ lwpsignal(struct proc *p, struct lwp *lp, int sig)
 
        KKASSERT(lp == NULL || lp->lwp_proc == p);
 
-       lwkt_gettoken(&proc_token);
+       lwkt_gettoken(&p->p_token);
 
        prop = sigprop(sig);
 
@@ -1035,7 +1049,7 @@ lwpsignal(struct proc *p, struct lwp *lp, int sig)
                 * in the process flags.
                 */
                if (lp && (lp->lwp_flag & LWP_WEXIT)) {
-                       lwkt_reltoken(&proc_token);
+                       lwkt_reltoken(&p->p_token);
                        return;
                }
 
@@ -1045,7 +1059,7 @@ lwpsignal(struct proc *p, struct lwp *lp, int sig)
                 * and if it is set to SIG_IGN, action will be SIG_DFL here.
                 */
                if (SIGISMEMBER(p->p_sigignore, sig)) {
-                       lwkt_reltoken(&proc_token);
+                       lwkt_reltoken(&p->p_token);
                        return;
                }
                if (SIGISMEMBER(p->p_sigcatch, sig))
@@ -1069,7 +1083,7 @@ lwpsignal(struct proc *p, struct lwp *lp, int sig)
                 */
                if (prop & SA_TTYSTOP && p->p_pgrp->pg_jobc == 0 &&
                    action == SIG_DFL) {
-                       lwkt_reltoken(&proc_token);
+                       lwkt_reltoken(&p->p_token);
                        return;
                }
                SIG_CONTSIGMASK(p->p_siglist);
@@ -1231,17 +1245,17 @@ active_process:
        lwp_signotify(lp);
 
 out:
-       lwkt_reltoken(&proc_token);
+       lwkt_reltoken(&p->p_token);
        crit_exit();
 }
 
 /*
- * proc_token must be held
+ * p->p_token must be held
  */
 static void
 lwp_signotify(struct lwp *lp)
 {
-       ASSERT_LWKT_TOKEN_HELD(&proc_token);
+       ASSERT_LWKT_TOKEN_HELD(&lp->lwp_proc->p_token);
        crit_enter();
 
        if (lp->lwp_stat == LSSLEEP || lp->lwp_stat == LSSTOP) {
@@ -1356,14 +1370,14 @@ signotify_remote(void *arg)
 #endif
 
 /*
- * Caller must hold proc_token
+ * Caller must hold p->p_token
  */
 void
 proc_stop(struct proc *p)
 {
        struct lwp *lp;
 
-       ASSERT_LWKT_TOKEN_HELD(&proc_token);
+       ASSERT_LWKT_TOKEN_HELD(&p->p_token);
        crit_enter();
 
        /* If somebody raced us, be happy with it */
@@ -1423,7 +1437,7 @@ proc_unstop(struct proc *p)
 {
        struct lwp *lp;
 
-       ASSERT_LWKT_TOKEN_HELD(&proc_token);
+       ASSERT_LWKT_TOKEN_HELD(&p->p_token);
        crit_enter();
 
        if (p->p_stat != SSTOP) {
@@ -1486,8 +1500,6 @@ kern_sigtimedwait(sigset_t waitset, siginfo_t *info, struct timespec *timeout)
        struct timespec rts, ets, ts;
        struct timeval tv;
 
-       lwkt_gettoken(&proc_token);
-
        error = 0;
        sig = 0;
        ets.tv_sec = 0;         /* silence compiler warning */
@@ -1550,8 +1562,9 @@ kern_sigtimedwait(sigset_t waitset, siginfo_t *info, struct timespec *timeout)
                        timespecsub(&ts, &rts);
                        TIMESPEC_TO_TIMEVAL(&tv, &ts);
                        hz = tvtohz_high(&tv);
-               } else
+               } else {
                        hz = 0;
+               }
 
                lp->lwp_sigmask = savedmask;
                SIGSETNAND(lp->lwp_sigmask, waitset);
@@ -1580,14 +1593,11 @@ kern_sigtimedwait(sigset_t waitset, siginfo_t *info, struct timespec *timeout)
                lwp_delsig(lp, sig);    /* take the signal! */
 
                if (sig == SIGKILL) {
-                       lwkt_reltoken(&proc_token);
                        sigexit(lp, sig);
                        /* NOT REACHED */
                }
        }
 
-       lwkt_reltoken(&proc_token);
-
        return (error);
 }
 
@@ -1693,14 +1703,16 @@ iscaught(struct lwp *lp)
  * Stop signals with default action are processed immediately, then cleared;
  * they aren't returned.  This is checked after each entry to the system for
  * a syscall or trap (though this can usually be done without calling issignal
- * by checking the pending signal masks in the CURSIG macro.) The normal call
- * sequence is
+ * by checking the pending signal masks in the CURSIG macro).
  *
- * This routine is called via CURSIG/__cursig and the MP lock might not be
- * held.  Obtain the MP lock for the duration of the operation.
+ * This routine is called via CURSIG/__cursig.  We will acquire and release
+ * p->p_token but if the caller needs to interlock the test the caller must
+ * also hold p->p_token.
  *
  *     while (sig = CURSIG(curproc))
  *             postsig(sig);
+ *
+ * MPSAFE
  */
 int
 issignal(struct lwp *lp, int maytrace)
@@ -1709,7 +1721,7 @@ issignal(struct lwp *lp, int maytrace)
        sigset_t mask;
        int sig, prop;
 
-       lwkt_gettoken(&proc_token);
+       lwkt_gettoken(&p->p_token);
 
        for (;;) {
                int traced = (p->p_flag & P_TRACED) || (p->p_stops & S_SIG);
@@ -1725,7 +1737,7 @@ issignal(struct lwp *lp, int maytrace)
                if (p->p_flag & P_PPWAIT)
                        SIG_STOPSIGMASK(mask);
                if (SIGISEMPTY(mask)) {         /* no signal to send */
-                       lwkt_reltoken(&proc_token);
+                       lwkt_reltoken(&p->p_token);
                        return (0);
                }
                sig = sig_ffs(&mask);
@@ -1842,7 +1854,7 @@ issignal(struct lwp *lp, int maytrace)
                                 */
                                break;          /* == ignore */
                        } else {
-                               lwkt_reltoken(&proc_token);
+                               lwkt_reltoken(&p->p_token);
                                return (sig);
                        }
 
@@ -1864,7 +1876,7 @@ issignal(struct lwp *lp, int maytrace)
                         * This signal has an action, let
                         * postsig() process it.
                         */
-                       lwkt_reltoken(&proc_token);
+                       lwkt_reltoken(&p->p_token);
                        return (sig);
                }
                lwp_delsig(lp, sig);            /* take the signal! */
index 8f812d6..8180140 100644 (file)
@@ -526,7 +526,20 @@ tsleep(const volatile void *ident, int flags, const char *wmesg, int timo)
                        ident, wmesg, lp->lwp_stat));
 
        /*
+        * We interlock the sleep queue if the caller has not already done
+        * it for us.  This must be done before we potentially acquire any
+        * tokens or we can loose the wakeup.
+        */
+       if ((flags & PINTERLOCKED) == 0) {
+               id = LOOKUP(ident);
+               _tsleep_interlock(gd, ident, flags);
+       }
+
+       /*
         * Setup for the current process (if this is a process). 
+        *
+        * We hold the process token if lp && catch.  The resume
+        * code will release it.
         */
        if (lp) {
                if (catch) {
@@ -538,6 +551,7 @@ tsleep(const volatile void *ident, int flags, const char *wmesg, int timo)
                         * Early termination only occurs when tsleep() is
                         * entered while in a normal LSRUN state.
                         */
+                       lwkt_gettoken(&p->p_token);
                        if ((sig = CURSIG(lp)) != 0)
                                goto resume;
 
@@ -552,29 +566,19 @@ tsleep(const volatile void *ident, int flags, const char *wmesg, int timo)
                                goto resume;
 
                        /*
-                        * Causes ksignal to wake us up when.
+                        * Causes ksignal to wake us up if a signal is
+                        * received (interlocked with p->p_token).
                         */
                        lp->lwp_flag |= LWP_SINTR;
                }
+       } else {
+               KKASSERT(p == NULL);
        }
 
        /*
-        * We interlock the sleep queue if the caller has not already done
-        * it for us.
-        */
-       if ((flags & PINTERLOCKED) == 0) {
-               id = LOOKUP(ident);
-               _tsleep_interlock(gd, ident, flags);
-       }
-
-       /*
-        *
-        * If no interlock was set we do an integrated interlock here.
         * Make sure the current process has been untangled from
         * the userland scheduler and initialize slptime to start
-        * counting.  We must interlock the sleep queue before doing
-        * this to avoid wakeup/process-ipi races which can occur under
-        * heavy loads.
+        * counting.
         */
        if (lp) {
                p->p_usched->release_curproc(lp);
@@ -683,6 +687,8 @@ tsleep(const volatile void *ident, int flags, const char *wmesg, int timo)
         * interlock, the user must poll it prior to any system call
         * that it wishes to interlock a mailbox signal against since
         * the flag is cleared on *any* system call that sleeps.
+        *
+        * p->p_token is held in the p && catch case.
         */
 resume:
        if (p) {
@@ -696,6 +702,8 @@ resume:
                                        error = ERESTART;
                        }
                }
+               if (catch)
+                       lwkt_reltoken(&p->p_token);
                lp->lwp_flag &= ~(LWP_BREAKTSLEEP | LWP_SINTR);
                p->p_flag &= ~P_MAILBOX;
        }
@@ -842,17 +850,20 @@ endtsleep(void *arg)
        struct lwp *lp;
 
        crit_enter();
-       lwkt_gettoken(&proc_token);
+       lp = td->td_lwp;
+
+       if (lp)
+               lwkt_gettoken(&lp->lwp_proc->p_token);
 
        /*
         * cpu interlock.  Thread flags are only manipulated on
         * the cpu owning the thread.  proc flags are only manipulated
-        * by the older of the MP lock.  We have both.
+        * by the holder of p->p_token.  We have both.
         */
        if (td->td_flags & TDF_TSLEEP_DESCHEDULED) {
                td->td_flags |= TDF_TIMEOUT;
 
-               if ((lp = td->td_lwp) != NULL) {
+               if (lp) {
                        lp->lwp_flag |= LWP_BREAKTSLEEP;
                        if (lp->lwp_proc->p_stat != SSTOP)
                                setrunnable(lp);
@@ -860,7 +871,8 @@ endtsleep(void *arg)
                        _tsleep_wakeup(td);
                }
        }
-       lwkt_reltoken(&proc_token);
+       if (lp)
+               lwkt_reltoken(&lp->lwp_proc->p_token);
        crit_exit();
 }
 
@@ -1044,17 +1056,17 @@ wakeup_domain_one(const volatile void *ident, int domain)
 /*
  * setrunnable()
  *
- * Make a process runnable.  The proc_token must be held on call.  This only
- * has an effect if we are in SSLEEP.  We only break out of the
+ * Make a process runnable.  lp->lwp_proc->p_token must be held on call.
+ * This only has an effect if we are in SSLEEP.  We only break out of the
  * tsleep if LWP_BREAKTSLEEP is set, otherwise we just fix-up the state.
  *
- * NOTE: With proc_token held we can only safely manipulate the process
+ * NOTE: With p_token held we can only safely manipulate the process
  * structure and the lp's lwp_stat.
  */
 void
 setrunnable(struct lwp *lp)
 {
-       ASSERT_LWKT_TOKEN_HELD(&proc_token);
+       ASSERT_LWKT_TOKEN_HELD(&lp->lwp_proc->p_token);
        crit_enter();
        if (lp->lwp_stat == LSSTOP)
                lp->lwp_stat = LSSLEEP;
index 104c0e5..9673903 100644 (file)
@@ -275,7 +275,8 @@ sys_ptrace(struct ptrace_args *uap)
 }
 
 int
-kern_ptrace(struct proc *curp, int req, pid_t pid, void *addr, int data, int *res)
+kern_ptrace(struct proc *curp, int req, pid_t pid, void *addr,
+           int data, int *res)
 {
        struct proc *p, *pp;
        struct lwp *lp;
@@ -302,8 +303,10 @@ kern_ptrace(struct proc *curp, int req, pid_t pid, void *addr, int data, int *re
                return (ESRCH);
        }
 
+       lwkt_gettoken(&p->p_token);
        /* Can't trace a process that's currently exec'ing. */
        if ((p->p_flag & P_INEXEC) != 0) {
+               lwkt_reltoken(&p->p_token);
                lwkt_reltoken(&proc_token);
                return EAGAIN;
        }
@@ -319,12 +322,14 @@ kern_ptrace(struct proc *curp, int req, pid_t pid, void *addr, int data, int *re
        case PT_ATTACH:
                /* Self */
                if (p->p_pid == curp->p_pid) {
+                       lwkt_reltoken(&p->p_token);
                        lwkt_reltoken(&proc_token);
                        return EINVAL;
                }
 
                /* Already traced */
                if (p->p_flag & P_TRACED) {
+                       lwkt_reltoken(&p->p_token);
                        lwkt_reltoken(&proc_token);
                        return EBUSY;
                }
@@ -332,6 +337,7 @@ kern_ptrace(struct proc *curp, int req, pid_t pid, void *addr, int data, int *re
                if (curp->p_flag & P_TRACED)
                        for (pp = curp->p_pptr; pp != NULL; pp = pp->p_pptr)
                                if (pp == p) {
+                                       lwkt_reltoken(&p->p_token);
                                        lwkt_reltoken(&proc_token);
                                        return (EINVAL);
                                }
@@ -340,6 +346,7 @@ kern_ptrace(struct proc *curp, int req, pid_t pid, void *addr, int data, int *re
                if ((p->p_ucred->cr_ruid != curp->p_ucred->cr_ruid) ||
                     (p->p_flag & P_SUGID)) {
                        if ((error = priv_check_cred(curp->p_ucred, PRIV_ROOT, 0)) != 0) {
+                               lwkt_reltoken(&p->p_token);
                                lwkt_reltoken(&proc_token);
                                return error;
                        }
@@ -347,6 +354,7 @@ kern_ptrace(struct proc *curp, int req, pid_t pid, void *addr, int data, int *re
 
                /* can't trace init when securelevel > 0 */
                if (securelevel > 0 && p->p_pid == 1) {
+                       lwkt_reltoken(&p->p_token);
                        lwkt_reltoken(&proc_token);
                        return EPERM;
                }
@@ -383,12 +391,14 @@ kern_ptrace(struct proc *curp, int req, pid_t pid, void *addr, int data, int *re
 #endif
                /* not being traced... */
                if ((p->p_flag & P_TRACED) == 0) {
+                       lwkt_reltoken(&p->p_token);
                        lwkt_reltoken(&proc_token);
                        return EPERM;
                }
 
                /* not being traced by YOU */
                if (p->p_pptr != curp) {
+                       lwkt_reltoken(&p->p_token);
                        lwkt_reltoken(&proc_token);
                        return EBUSY;
                }
@@ -396,6 +406,7 @@ kern_ptrace(struct proc *curp, int req, pid_t pid, void *addr, int data, int *re
                /* not currently stopped */
                if (p->p_stat != SSTOP ||
                    (p->p_flag & P_WAITED) == 0) {
+                       lwkt_reltoken(&p->p_token);
                        lwkt_reltoken(&proc_token);
                        return EBUSY;
                }
@@ -404,6 +415,7 @@ kern_ptrace(struct proc *curp, int req, pid_t pid, void *addr, int data, int *re
                break;
 
        default:
+               lwkt_reltoken(&p->p_token);
                lwkt_reltoken(&proc_token);
                return EINVAL;
        }
@@ -428,6 +440,7 @@ kern_ptrace(struct proc *curp, int req, pid_t pid, void *addr, int data, int *re
                /* set my trace flag and "owner" so it can read/write me */
                p->p_flag |= P_TRACED;
                p->p_oppid = p->p_pptr->p_pid;
+               lwkt_reltoken(&p->p_token);
                lwkt_reltoken(&proc_token);
                return 0;
 
@@ -445,6 +458,7 @@ kern_ptrace(struct proc *curp, int req, pid_t pid, void *addr, int data, int *re
        case PT_DETACH:
                /* Zero means do not send any signal */
                if (data < 0 || data > _SIG_MAXSIG) {
+                       lwkt_reltoken(&p->p_token);
                        lwkt_reltoken(&proc_token);
                        return EINVAL;
                }
@@ -454,6 +468,7 @@ kern_ptrace(struct proc *curp, int req, pid_t pid, void *addr, int data, int *re
                if (req == PT_STEP) {
                        if ((error = ptrace_single_step (lp))) {
                                LWPRELE(lp);
+                               lwkt_reltoken(&p->p_token);
                                lwkt_reltoken(&proc_token);
                                return error;
                        }
@@ -463,6 +478,7 @@ kern_ptrace(struct proc *curp, int req, pid_t pid, void *addr, int data, int *re
                        if ((error = ptrace_set_pc (lp,
                            (u_long)(uintfptr_t)addr))) {
                                LWPRELE(lp);
+                               lwkt_reltoken(&p->p_token);
                                lwkt_reltoken(&proc_token);
                                return error;
                        }
@@ -498,6 +514,7 @@ kern_ptrace(struct proc *curp, int req, pid_t pid, void *addr, int data, int *re
                        ksignal(p, data);
                }
                crit_exit();
+               lwkt_reltoken(&p->p_token);
                lwkt_reltoken(&proc_token);
                return 0;
 
@@ -541,6 +558,7 @@ kern_ptrace(struct proc *curp, int req, pid_t pid, void *addr, int data, int *re
                }
                if (!write)
                        *res = tmp;
+               lwkt_reltoken(&p->p_token);
                lwkt_reltoken(&proc_token);
                return (error);
 
@@ -570,11 +588,13 @@ kern_ptrace(struct proc *curp, int req, pid_t pid, void *addr, int data, int *re
                        uio.uio_rw = UIO_WRITE;
                        break;
                default:
+                       lwkt_reltoken(&p->p_token);
                        lwkt_reltoken(&proc_token);
                        return (EINVAL);
                }
                error = procfs_domem(curp, lp, NULL, &uio);
                piod->piod_len -= uio.uio_resid;
+               lwkt_reltoken(&p->p_token);
                lwkt_reltoken(&proc_token);
                return (error);
 
@@ -593,6 +613,7 @@ kern_ptrace(struct proc *curp, int req, pid_t pid, void *addr, int data, int *re
 #endif /* PT_SETREGS */
 #if defined(PT_SETREGS) || defined(PT_GETREGS)
                if (!procfs_validregs(lp)) {    /* no P_SYSTEM procs please */
+                       lwkt_reltoken(&p->p_token);
                        lwkt_reltoken(&proc_token);
                        return EINVAL;
                } else {
@@ -606,6 +627,7 @@ kern_ptrace(struct proc *curp, int req, pid_t pid, void *addr, int data, int *re
                        uio.uio_rw = write ? UIO_WRITE : UIO_READ;
                        uio.uio_td = curthread;
                        t = procfs_doregs(curp, lp, NULL, &uio);
+                       lwkt_reltoken(&p->p_token);
                        lwkt_reltoken(&proc_token);
                        return t;
                }
@@ -622,6 +644,7 @@ kern_ptrace(struct proc *curp, int req, pid_t pid, void *addr, int data, int *re
 #endif /* PT_SETFPREGS */
 #if defined(PT_SETFPREGS) || defined(PT_GETFPREGS)
                if (!procfs_validfpregs(lp)) {  /* no P_SYSTEM procs please */
+                       lwkt_reltoken(&p->p_token);
                        lwkt_reltoken(&proc_token);
                        return EINVAL;
                } else {
@@ -635,6 +658,7 @@ kern_ptrace(struct proc *curp, int req, pid_t pid, void *addr, int data, int *re
                        uio.uio_rw = write ? UIO_WRITE : UIO_READ;
                        uio.uio_td = curthread;
                        t = procfs_dofpregs(curp, lp, NULL, &uio);
+                       lwkt_reltoken(&p->p_token);
                        lwkt_reltoken(&proc_token);
                        return t;
                }
@@ -651,6 +675,7 @@ kern_ptrace(struct proc *curp, int req, pid_t pid, void *addr, int data, int *re
 #endif /* PT_SETDBREGS */
 #if defined(PT_SETDBREGS) || defined(PT_GETDBREGS)
                if (!procfs_validdbregs(lp)) {  /* no P_SYSTEM procs please */
+                       lwkt_reltoken(&p->p_token);
                        lwkt_reltoken(&proc_token);
                        return EINVAL;
                } else {
@@ -664,6 +689,7 @@ kern_ptrace(struct proc *curp, int req, pid_t pid, void *addr, int data, int *re
                        uio.uio_rw = write ? UIO_WRITE : UIO_READ;
                        uio.uio_td = curthread;
                        t = procfs_dodbregs(curp, lp, NULL, &uio);
+                       lwkt_reltoken(&p->p_token);
                        lwkt_reltoken(&proc_token);
                        return t;
                }
@@ -673,6 +699,7 @@ kern_ptrace(struct proc *curp, int req, pid_t pid, void *addr, int data, int *re
                break;
        }
 
+       lwkt_reltoken(&p->p_token);
        lwkt_reltoken(&proc_token);
        return 0;
 }
index 19d8f13..dc24a4e 100644 (file)
@@ -322,6 +322,7 @@ struct      proc {
        void            (*p_userret)(void);/* p: return-to-user hook */
 
        struct spinlock p_spin;         /* Spinlock for LWP access to proc */
+       struct lwkt_token p_token;      /* Token for LWP access to proc */
 };
 
 #define lwp_wchan      lwp_thread->td_wchan
index 0266979..cebeaf9 100644 (file)
@@ -75,7 +75,10 @@ lwp_delsig(struct lwp *lp, int sig)
  * process, 0 if none.  If there is a pending stop signal with default
  * action, the process stops in issignal().
  *
- * MP SAFE
+ * This function does not interlock pending signals.  If the caller needs
+ * to interlock the caller must acquire the per-proc token.
+ *
+ * MPSAFE
  */
 static __inline
 int
index 4a34329..3fb9295 100644 (file)
@@ -114,6 +114,7 @@ procfs_control(struct proc *curp, struct lwp *lp, int op)
        struct proc *p = lp->lwp_proc;
        int error;
 
+       ASSERT_LWKT_TOKEN_HELD(&p->p_token);
        ASSERT_LWKT_TOKEN_HELD(&proc_token);
 
        /* Can't trace a process that's currently exec'ing. */ 
@@ -294,6 +295,7 @@ procfs_doctl(struct proc *curp, struct lwp *lp, struct pfsnode *pfs,
        char msg[PROCFS_CTLLEN+1];
        vfs_namemap_t *nm;
 
+       ASSERT_LWKT_TOKEN_HELD(&p->p_token);
        ASSERT_LWKT_TOKEN_HELD(&proc_token);
 
        if (uio->uio_rw != UIO_WRITE)
index 2186445..ce18058 100644 (file)
@@ -292,6 +292,8 @@ procfs_rw(struct vop_read_args *ap)
        }
        pfs->pfs_lockowner = curproc->p_pid;
 
+       lwkt_gettoken(&p->p_token);
+
        switch (pfs->pfs_type) {
        case Pnote:
        case Pnotepg:
@@ -342,7 +344,9 @@ procfs_rw(struct vop_read_args *ap)
                rtval = EOPNOTSUPP;
                break;
        }
+       lwkt_reltoken(&p->p_token);
        LWPRELE(lp);
+
        pfs->pfs_lockowner = 0;
        lwkt_reltoken(&proc_token);
        wakeup(&pfs->pfs_lockowner);