session: avoid proctree lock on proc exit when possible
We can get away with the common case with only proc lock held. Reviewed by: kib
This commit is contained in:
parent
4e1a382dbc
commit
eabf748a18
@ -189,7 +189,6 @@ exit1(struct thread *td, int rval, int signo)
|
||||
{
|
||||
struct proc *p, *nq, *q, *t;
|
||||
struct thread *tdt;
|
||||
struct vnode *ttyvp = NULL;
|
||||
|
||||
mtx_assert(&Giant, MA_NOTOWNED);
|
||||
KASSERT(rval == 0 || signo == 0, ("exit1 rv %d sig %d", rval, signo));
|
||||
@ -394,60 +393,9 @@ exit1(struct thread *td, int rval, int signo)
|
||||
}
|
||||
|
||||
vmspace_exit(td);
|
||||
|
||||
sx_xlock(&proctree_lock);
|
||||
if (SESS_LEADER(p)) {
|
||||
struct session *sp = p->p_session;
|
||||
struct tty *tp;
|
||||
|
||||
/*
|
||||
* s_ttyp is not zero'd; we use this to indicate that
|
||||
* the session once had a controlling terminal. (for
|
||||
* logging and informational purposes)
|
||||
*/
|
||||
SESS_LOCK(sp);
|
||||
ttyvp = sp->s_ttyvp;
|
||||
tp = sp->s_ttyp;
|
||||
sp->s_ttyvp = NULL;
|
||||
sp->s_ttydp = NULL;
|
||||
sp->s_leader = NULL;
|
||||
SESS_UNLOCK(sp);
|
||||
|
||||
/*
|
||||
* Signal foreground pgrp and revoke access to
|
||||
* controlling terminal if it has not been revoked
|
||||
* already.
|
||||
*
|
||||
* Because the TTY may have been revoked in the mean
|
||||
* time and could already have a new session associated
|
||||
* with it, make sure we don't send a SIGHUP to a
|
||||
* foreground process group that does not belong to this
|
||||
* session.
|
||||
*/
|
||||
|
||||
if (tp != NULL) {
|
||||
tty_lock(tp);
|
||||
if (tp->t_session == sp)
|
||||
tty_signal_pgrp(tp, SIGHUP);
|
||||
tty_unlock(tp);
|
||||
}
|
||||
|
||||
if (ttyvp != NULL) {
|
||||
sx_xunlock(&proctree_lock);
|
||||
if (vn_lock(ttyvp, LK_EXCLUSIVE) == 0) {
|
||||
VOP_REVOKE(ttyvp, REVOKEALL);
|
||||
VOP_UNLOCK(ttyvp, 0);
|
||||
}
|
||||
sx_xlock(&proctree_lock);
|
||||
}
|
||||
}
|
||||
fixjobc(p, p->p_pgrp, 0);
|
||||
sx_xunlock(&proctree_lock);
|
||||
killjobc();
|
||||
(void)acct_process(td);
|
||||
|
||||
/* Release the TTY now we've unlocked everything. */
|
||||
if (ttyvp != NULL)
|
||||
vrele(ttyvp);
|
||||
#ifdef KTRACE
|
||||
ktrprocexit(td);
|
||||
#endif
|
||||
|
@ -686,6 +686,79 @@ fixjobc(struct proc *p, struct pgrp *pgrp, int entering)
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
killjobc(void)
|
||||
{
|
||||
struct session *sp;
|
||||
struct tty *tp;
|
||||
struct proc *p;
|
||||
struct vnode *ttyvp;
|
||||
|
||||
p = curproc;
|
||||
MPASS(p->p_flag & P_WEXIT);
|
||||
/*
|
||||
* Do a quick check to see if there is anything to do with the
|
||||
* proctree_lock held. pgrp and LIST_EMPTY checks are for fixjobc().
|
||||
*/
|
||||
PROC_LOCK(p);
|
||||
if (!SESS_LEADER(p) &&
|
||||
(p->p_pgrp == p->p_pptr->p_pgrp) &&
|
||||
LIST_EMPTY(&p->p_children)) {
|
||||
PROC_UNLOCK(p);
|
||||
return;
|
||||
}
|
||||
PROC_UNLOCK(p);
|
||||
|
||||
sx_xlock(&proctree_lock);
|
||||
if (SESS_LEADER(p)) {
|
||||
sp = p->p_session;
|
||||
|
||||
/*
|
||||
* s_ttyp is not zero'd; we use this to indicate that
|
||||
* the session once had a controlling terminal. (for
|
||||
* logging and informational purposes)
|
||||
*/
|
||||
SESS_LOCK(sp);
|
||||
ttyvp = sp->s_ttyvp;
|
||||
tp = sp->s_ttyp;
|
||||
sp->s_ttyvp = NULL;
|
||||
sp->s_ttydp = NULL;
|
||||
sp->s_leader = NULL;
|
||||
SESS_UNLOCK(sp);
|
||||
|
||||
/*
|
||||
* Signal foreground pgrp and revoke access to
|
||||
* controlling terminal if it has not been revoked
|
||||
* already.
|
||||
*
|
||||
* Because the TTY may have been revoked in the mean
|
||||
* time and could already have a new session associated
|
||||
* with it, make sure we don't send a SIGHUP to a
|
||||
* foreground process group that does not belong to this
|
||||
* session.
|
||||
*/
|
||||
|
||||
if (tp != NULL) {
|
||||
tty_lock(tp);
|
||||
if (tp->t_session == sp)
|
||||
tty_signal_pgrp(tp, SIGHUP);
|
||||
tty_unlock(tp);
|
||||
}
|
||||
|
||||
if (ttyvp != NULL) {
|
||||
sx_xunlock(&proctree_lock);
|
||||
if (vn_lock(ttyvp, LK_EXCLUSIVE) == 0) {
|
||||
VOP_REVOKE(ttyvp, REVOKEALL);
|
||||
VOP_UNLOCK(ttyvp, 0);
|
||||
}
|
||||
vrele(ttyvp);
|
||||
sx_xlock(&proctree_lock);
|
||||
}
|
||||
}
|
||||
fixjobc(p, p->p_pgrp, 0);
|
||||
sx_xunlock(&proctree_lock);
|
||||
}
|
||||
|
||||
/*
|
||||
* A process group has become orphaned;
|
||||
* if there are any stopped processes in the group,
|
||||
|
@ -938,6 +938,7 @@ void fork_return(struct thread *, struct trapframe *);
|
||||
int inferior(struct proc *p);
|
||||
void kern_yield(int);
|
||||
void kick_proc0(void);
|
||||
void killjobc(void);
|
||||
int leavepgrp(struct proc *p);
|
||||
int maybe_preempt(struct thread *td);
|
||||
void maybe_yield(void);
|
||||
|
Loading…
x
Reference in New Issue
Block a user