From: Matthew Dillon Date: Fri, 11 Feb 2011 22:47:58 +0000 (-0800) Subject: kernel - Add per-process token, adjust signal code to use it. X-Git-Tag: v2.10.0~267^2~102 X-Git-Url: http://gitweb.dragonflybsd.org/dragonfly.git/commitdiff_plain/5686ec5a3d0bf6c0ae72cf58ad9b957b4ea71c1a kernel - Add per-process token, adjust signal code to use it. * 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. --- diff --git a/sys/kern/init_main.c b/sys/kern/init_main.c index a65de3f..90b398c 100644 --- a/sys/kern/init_main.c +++ b/sys/kern/init_main.c @@ -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; diff --git a/sys/kern/kern_checkpoint.c b/sys/kern/kern_checkpoint.c index b515a9e..2f8fcfd 100644 --- a/sys/kern/kern_checkpoint.c +++ b/sys/kern/kern_checkpoint.c @@ -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; } diff --git a/sys/kern/kern_exit.c b/sys/kern/kern_exit.c index 71697e4..b41f36f 100644 --- a/sys/kern/kern_exit.c +++ b/sys/kern/kern_exit.c @@ -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 diff --git a/sys/kern/kern_fork.c b/sys/kern/kern_fork.c index 87a4077..8e99475 100644 --- a/sys/kern/kern_fork.c +++ b/sys/kern/kern_fork.c @@ -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 */ /* diff --git a/sys/kern/kern_sig.c b/sys/kern/kern_sig.c index 617e4cf..c275364 100644 --- a/sys/kern/kern_sig.c +++ b/sys/kern/kern_sig.c @@ -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! */ diff --git a/sys/kern/kern_synch.c b/sys/kern/kern_synch.c index 8f812d6..8180140 100644 --- a/sys/kern/kern_synch.c +++ b/sys/kern/kern_synch.c @@ -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; diff --git a/sys/kern/sys_process.c b/sys/kern/sys_process.c index 104c0e5..9673903 100644 --- a/sys/kern/sys_process.c +++ b/sys/kern/sys_process.c @@ -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; } diff --git a/sys/sys/proc.h b/sys/sys/proc.h index 19d8f13..dc24a4e 100644 --- a/sys/sys/proc.h +++ b/sys/sys/proc.h @@ -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 diff --git a/sys/sys/signal2.h b/sys/sys/signal2.h index 0266979..cebeaf9 100644 --- a/sys/sys/signal2.h +++ b/sys/sys/signal2.h @@ -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 diff --git a/sys/vfs/procfs/procfs_ctl.c b/sys/vfs/procfs/procfs_ctl.c index 4a34329..3fb9295 100644 --- a/sys/vfs/procfs/procfs_ctl.c +++ b/sys/vfs/procfs/procfs_ctl.c @@ -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) diff --git a/sys/vfs/procfs/procfs_subr.c b/sys/vfs/procfs/procfs_subr.c index 2186445..ce18058 100644 --- a/sys/vfs/procfs/procfs_subr.c +++ b/sys/vfs/procfs/procfs_subr.c @@ -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);