summaryrefslogtreecommitdiff
path: root/usr/src/uts/common/os/session.c
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src/uts/common/os/session.c')
-rw-r--r--usr/src/uts/common/os/session.c651
1 files changed, 584 insertions, 67 deletions
diff --git a/usr/src/uts/common/os/session.c b/usr/src/uts/common/os/session.c
index 972677f7dc..7790a09094 100644
--- a/usr/src/uts/common/os/session.c
+++ b/usr/src/uts/common/os/session.c
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -20,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -47,102 +46,614 @@
#include <sys/kmem.h>
#include <sys/cmn_err.h>
#include <sys/strsubr.h>
+#include <sys/fs/snode.h>
sess_t session0 = {
- 1, /* s_ref */
- NODEV, /* s_dev */
- NULL, /* s_vp */
- &pid0, /* s_sidp */
- NULL /* s_cred */
+ &pid0, /* s_sidp */
+ {0}, /* s_lock */
+ 1, /* s_ref */
+ B_FALSE, /* s_sighuped */
+ B_FALSE, /* s_exit */
+ 0, /* s_exit_cv */
+ 0, /* s_cnt */
+ 0, /* s_cnt_cv */
+ NODEV, /* s_dev */
+ NULL, /* s_vp */
+ NULL /* s_cred */
};
void
-sess_rele(sess_t *sp)
+sess_hold(proc_t *p)
{
- ASSERT(MUTEX_HELD(&pidlock));
+ ASSERT(MUTEX_HELD(&pidlock) || MUTEX_HELD(&p->p_splock));
+ mutex_enter(&p->p_sessp->s_lock);
+ p->p_sessp->s_ref++;
+ mutex_exit(&p->p_sessp->s_lock);
+}
+
+void
+sess_rele(sess_t *sp, boolean_t pidlock_held)
+{
+ ASSERT(MUTEX_HELD(&pidlock) || !pidlock_held);
+
+ mutex_enter(&sp->s_lock);
ASSERT(sp->s_ref != 0);
- if (--sp->s_ref == 0) {
- if (sp == &session0)
- panic("sp == &session0");
- PID_RELE(sp->s_sidp);
- mutex_destroy(&sp->s_lock);
- cv_destroy(&sp->s_wait_cv);
- kmem_free(sp, sizeof (sess_t));
+ if (--sp->s_ref > 0) {
+ mutex_exit(&sp->s_lock);
+ return;
}
+ ASSERT(sp->s_ref == 0);
+
+ /*
+ * It's ok to free this session structure now because we know
+ * that no one else can have a pointer to it. We know this
+ * to be true because the only time that s_ref can possibly
+ * be incremented is when pidlock or p_splock is held AND there
+ * is a proc_t that points to that session structure. In that
+ * case we are guaranteed that the s_ref is at least 1 since there
+ * is a proc_t that points to it. So when s_ref finally drops to
+ * zero then no one else has a reference (and hence pointer) to
+ * this session structure and there is no valid proc_t pointing
+ * to this session structure anymore so, no one can acquire a
+ * reference (and pointer) to this session structure so it's
+ * ok to free it here.
+ */
+
+ if (sp == &session0)
+ panic("sp == &session0");
+
+ /* make sure there are no outstanding holds */
+ ASSERT(sp->s_cnt == 0);
+
+ /* make sure there is no exit in progress */
+ ASSERT(!sp->s_exit);
+
+ /* make sure someone already freed any ctty */
+ ASSERT(sp->s_vp == NULL);
+ ASSERT(sp->s_dev == NODEV);
+
+ if (!pidlock_held)
+ mutex_enter(&pidlock);
+ PID_RELE(sp->s_sidp);
+ if (!pidlock_held)
+ mutex_exit(&pidlock);
+
+ mutex_destroy(&sp->s_lock);
+ cv_destroy(&sp->s_cnt_cv);
+ kmem_free(sp, sizeof (sess_t));
+}
+
+sess_t *
+tty_hold(void)
+{
+ proc_t *p = curproc;
+ sess_t *sp;
+ boolean_t got_sig = B_FALSE;
+
+ /* make sure the caller isn't holding locks they shouldn't */
+ ASSERT(MUTEX_NOT_HELD(&pidlock));
+
+ for (;;) {
+ mutex_enter(&p->p_splock); /* protect p->p_sessp */
+ sp = p->p_sessp;
+ mutex_enter(&sp->s_lock); /* protect sp->* */
+
+ /* make sure the caller isn't holding locks they shouldn't */
+ ASSERT((sp->s_vp == NULL) ||
+ MUTEX_NOT_HELD(&sp->s_vp->v_stream->sd_lock));
+
+ /*
+ * If the session leader process is not exiting (and hence
+ * not trying to release the session's ctty) then we can
+ * safely grab a hold on the current session structure
+ * and return it. If on the other hand the session leader
+ * process is exiting and clearing the ctty then we'll
+ * wait till it's done before we loop around and grab a
+ * hold on the session structure.
+ */
+ if (!sp->s_exit)
+ break;
+
+ /* need to hold the session so it can't be freed */
+ sp->s_ref++;
+ mutex_exit(&p->p_splock);
+
+ /* Wait till the session leader is done */
+ if (!cv_wait_sig(&sp->s_exit_cv, &sp->s_lock))
+ got_sig = B_TRUE;
+
+ /*
+ * Now we need to drop our hold on the session structure,
+ * but we can't hold any locks when we do this because
+ * sess_rele() may need to aquire pidlock.
+ */
+ mutex_exit(&sp->s_lock);
+ sess_rele(sp, B_FALSE);
+
+ if (got_sig)
+ return (NULL);
+ }
+
+ /* whew, we finally got a hold */
+ sp->s_cnt++;
+ sp->s_ref++;
+ mutex_exit(&sp->s_lock);
+ mutex_exit(&p->p_splock);
+ return (sp);
}
void
-sess_create(void)
+tty_rele(sess_t *sp)
{
- proc_t *pp;
- sess_t *sp;
+ /* make sure the caller isn't holding locks they shouldn't */
+ ASSERT(MUTEX_NOT_HELD(&pidlock));
- pp = ttoproc(curthread);
+ mutex_enter(&sp->s_lock);
+ if ((--sp->s_cnt) == 0)
+ cv_broadcast(&sp->s_cnt_cv);
+ mutex_exit(&sp->s_lock);
+
+ sess_rele(sp, B_FALSE);
+}
+
+void
+sess_create(void)
+{
+ proc_t *p = curproc;
+ sess_t *sp, *old_sp;
sp = kmem_zalloc(sizeof (sess_t), KM_SLEEP);
mutex_init(&sp->s_lock, NULL, MUTEX_DEFAULT, NULL);
- cv_init(&sp->s_wait_cv, NULL, CV_DEFAULT, NULL);
+ cv_init(&sp->s_cnt_cv, NULL, CV_DEFAULT, NULL);
+ /*
+ * we need to grap p_lock to protect p_pgidp because
+ * /proc looks at p_pgidp while holding only p_lock.
+ *
+ * we don't need to hold p->p_sessp->s_lock or get a hold on the
+ * session structure since we're not actually updating any of
+ * the contents of the old session structure.
+ */
mutex_enter(&pidlock);
+ mutex_enter(&p->p_lock);
+ mutex_enter(&p->p_splock);
+
+ pgexit(p);
+
+ sp->s_sidp = p->p_pidp;
+ sp->s_ref = 1;
+ sp->s_dev = NODEV;
+
+ old_sp = p->p_sessp;
+ p->p_sessp = sp;
+
+ pgjoin(p, p->p_pidp);
+ PID_HOLD(p->p_pidp);
+
+ mutex_exit(&p->p_splock);
+ mutex_exit(&p->p_lock);
+ mutex_exit(&pidlock);
+ sess_rele(old_sp, B_FALSE);
+}
+
+/*
+ * Note that sess_ctty_clear() resets all the fields in the session
+ * structure but doesn't release any holds or free any objects
+ * that the session structure might currently point to. it is the
+ * callers responsibility to do this.
+ */
+static void
+sess_ctty_clear(sess_t *sp, stdata_t *stp)
+{
/*
- * We need to protect p_pgidp with p_lock because
- * /proc looks at it while holding only p_lock.
+ * Assert that we hold all the necessary locks. We also need
+ * to be holding proc_t->p_splock for the process associated
+ * with this session, but since we don't have a proc pointer
+ * passed in we can't assert this here.
*/
- mutex_enter(&pp->p_lock);
- pgexit(pp);
- SESS_RELE(pp->p_sessp);
+ ASSERT(MUTEX_HELD(&stp->sd_lock) && MUTEX_HELD(&pidlock) &&
+ MUTEX_HELD(&sp->s_lock));
- sp->s_sidp = pp->p_pidp;
- sp->s_ref = 1;
+ /* reset the session structure members to defaults */
+ sp->s_sighuped = B_FALSE;
sp->s_dev = NODEV;
+ sp->s_vp = NULL;
+ sp->s_cred = NULL;
+
+ /* reset the stream session and group pointers */
+ stp->sd_pgidp = NULL;
+ stp->sd_sidp = NULL;
+}
+
+static void
+sess_ctty_set(proc_t *p, sess_t *sp, stdata_t *stp)
+{
+ cred_t *crp;
+
+ /* Assert that we hold all the necessary locks. */
+ ASSERT(MUTEX_HELD(&stp->sd_lock) && MUTEX_HELD(&pidlock) &&
+ MUTEX_HELD(&p->p_splock) && MUTEX_HELD(&sp->s_lock));
+
+ /* get holds on structures */
+ mutex_enter(&p->p_crlock);
+ crhold(crp = p->p_cred);
+ mutex_exit(&p->p_crlock);
+ PID_HOLD(sp->s_sidp); /* requires pidlock */
+ PID_HOLD(sp->s_sidp); /* requires pidlock */
+
+ /* update the session structure members */
+ sp->s_vp = makectty(stp->sd_vnode);
+ sp->s_dev = sp->s_vp->v_rdev;
+ sp->s_cred = crp;
+
+ /* update the stream emebers */
+ stp->sd_flag |= STRISTTY; /* just to be sure */
+ stp->sd_sidp = sp->s_sidp;
+ stp->sd_pgidp = sp->s_sidp;
+}
+
+int
+strctty(stdata_t *stp)
+{
+ sess_t *sp;
+ proc_t *p = curproc;
+ boolean_t got_sig = B_FALSE;
+
+ /*
+ * We are going to try to make stp the default ctty for the session
+ * associated with curproc. Not only does this require holding a
+ * bunch of locks but it also requires waiting for any outstanding
+ * holds on the session structure (aquired via tty_hold()) to be
+ * released. Hence, we have the following for(;;) loop that will
+ * aquire our locks, do some sanity checks, and wait for the hold
+ * count on the session structure to hit zero. If we get a signal
+ * while waiting for outstanding holds to be released then we abort
+ * the operation and return.
+ */
+ for (;;) {
+ mutex_enter(&stp->sd_lock); /* protects sd_pgidp/sd_sidp */
+ mutex_enter(&pidlock); /* protects p_pidp */
+ mutex_enter(&p->p_splock); /* protects p_sessp */
+ sp = p->p_sessp;
+ mutex_enter(&sp->s_lock); /* protects sp->* */
+
+ if (((stp->sd_flag & (STRHUP|STRDERR|STWRERR|STPLEX)) != 0) ||
+ (stp->sd_sidp != NULL) || /* stp already ctty? */
+ (p->p_pidp != sp->s_sidp) || /* we're not leader? */
+ (sp->s_vp != NULL)) { /* session has ctty? */
+ mutex_exit(&sp->s_lock);
+ mutex_exit(&p->p_splock);
+ mutex_exit(&pidlock);
+ mutex_exit(&stp->sd_lock);
+ return (ENOTTY);
+ }
+
+ /* sanity check. we can't be exiting right now */
+ ASSERT(!sp->s_exit);
+
+ /*
+ * If no one else has a hold on this session structure
+ * then we now have exclusive access to it, so break out
+ * of this loop and update the session structure.
+ */
+ if (sp->s_cnt == 0)
+ break;
+
+ /* need to hold the session so it can't be freed */
+ sp->s_ref++;
- pp->p_sessp = sp;
+ /* ain't locking order fun? */
+ mutex_exit(&p->p_splock);
+ mutex_exit(&pidlock);
+ mutex_exit(&stp->sd_lock);
- pgjoin(pp, pp->p_pidp);
- mutex_exit(&pp->p_lock);
+ if (!cv_wait_sig(&sp->s_cnt_cv, &sp->s_lock))
+ got_sig = B_TRUE;
+ mutex_exit(&sp->s_lock);
+ sess_rele(sp, B_FALSE);
- PID_HOLD(sp->s_sidp);
+ if (got_sig)
+ return (EINTR);
+ }
+
+ /* set the session ctty bindings */
+ sess_ctty_set(p, sp, stp);
+
+ mutex_exit(&sp->s_lock);
+ mutex_exit(&p->p_splock);
mutex_exit(&pidlock);
+ mutex_exit(&stp->sd_lock);
+ return (0);
}
-void
-freectty(sess_t *sp)
+/*
+ * freectty_lock() attempts to aquire the army of locks required to free
+ * the ctty associated with a given session leader process. If it returns
+ * successfully the following locks will be held:
+ * sd_lock, pidlock, p_splock, s_lock
+ *
+ * as a secondary bit of convience, freectty_lock() will also return
+ * pointers to the session, ctty, and ctty stream associated with the
+ * specified session leader process.
+ */
+static boolean_t
+freectty_lock(proc_t *p, sess_t **spp, vnode_t **vpp, stdata_t **stpp,
+ boolean_t at_exit)
{
- vnode_t *vp = sp->s_vp;
- cred_t *cred = sp->s_cred;
+ sess_t *sp;
+ vnode_t *vp;
+ stdata_t *stp;
- strfreectty(vp->v_stream);
+ mutex_enter(&pidlock); /* protect p_pidp */
+ mutex_enter(&p->p_splock); /* protect p->p_sessp */
+ sp = p->p_sessp;
+ mutex_enter(&sp->s_lock); /* protect sp->* */
- mutex_enter(&sp->s_lock);
- while (sp->s_cnt > 0) {
- cv_wait(&sp->s_wait_cv, &sp->s_lock);
+ if ((sp->s_sidp != p->p_pidp) || /* we're not leader? */
+ (sp->s_vp == NULL)) { /* no ctty? */
+ mutex_exit(&sp->s_lock);
+ mutex_exit(&p->p_splock);
+ mutex_exit(&pidlock);
+ return (B_FALSE);
+ }
+
+ vp = sp->s_vp;
+ stp = sp->s_vp->v_stream;
+
+ if (at_exit) {
+ /* stop anyone else calling tty_hold() */
+ sp->s_exit = B_TRUE;
+ } else {
+ /*
+ * due to locking order we have to grab stp->sd_lock before
+ * grabbing all the other proc/session locks. but after we
+ * drop all our current locks it's possible that someone
+ * could come in and change our current session or close
+ * the current ctty (vp) there by making sp or stp invalid.
+ * (a VN_HOLD on vp won't protect stp because that only
+ * prevents the vnode from being freed not closed.) so
+ * to prevent this we bump s_ref and s_cnt here.
+ *
+ * course this doesn't matter if we're the last thread in
+ * an exiting process that is the session leader, since no
+ * one else can change our session or free our ctty.
+ */
+ sp->s_ref++; /* hold the session structure */
+ sp->s_cnt++; /* protect vp and stp */
+ }
+
+ /* drop our session locks */
+ mutex_exit(&sp->s_lock);
+ mutex_exit(&p->p_splock);
+ mutex_exit(&pidlock);
+
+ /* grab locks in the right order */
+ mutex_enter(&stp->sd_lock); /* protects sd_pgidp/sd_sidp */
+ mutex_enter(&pidlock); /* protect p_pidp */
+ mutex_enter(&p->p_splock); /* protects p->p_sessp */
+ mutex_enter(&sp->s_lock); /* protects sp->* */
+
+ /* if the session has changed, abort mission */
+ if (sp != p->p_sessp) {
+ /*
+ * this can't happen during process exit since we're the
+ * only thread in the process and we sure didn't change
+ * our own session at this point.
+ */
+ ASSERT(!at_exit);
+
+ /* release our locks and holds */
+ mutex_exit(&sp->s_lock);
+ mutex_exit(&p->p_splock);
+ mutex_exit(&pidlock);
+ mutex_exit(&stp->sd_lock);
+ tty_rele(sp);
+ return (B_FALSE);
}
- ASSERT(sp->s_cnt == 0);
- ASSERT(vp->v_count >= 1);
- sp->s_vp = NULL;
- sp->s_cred = NULL;
/*
- * It is possible for the VOP_CLOSE below to call stralloctty()
- * and reallocate a new tty vnode. To prevent that the
- * session is marked as closing here.
+ * sanity checks. none of this should have changed since we had
+ * holds on the current ctty.
*/
+ ASSERT(sp->s_sidp == p->p_pidp); /* we're the leader */
+ ASSERT(sp->s_vp != NULL); /* a ctty exists */
+ ASSERT(vp == sp->s_vp);
+ ASSERT(stp == sp->s_vp->v_stream);
+
+ /* release our holds */
+ if (!at_exit) {
+ if ((--(sp)->s_cnt) == 0)
+ cv_broadcast(&sp->s_cnt_cv);
+ sp->s_ref--;
+ ASSERT(sp->s_ref > 0);
+ }
+
+ /* return our pointers */
+ *spp = sp;
+ *vpp = vp;
+ *stpp = stp;
- sp->s_flag = SESS_CLOSE;
+ return (B_TRUE);
+}
+
+/*
+ * Returns B_FALSE if no signal is sent to the process group associated with
+ * this ctty. Returns B_TRUE if a signal is sent to the process group.
+ * If it return B_TRUE it also means that all the locks we were holding
+ * were dropped so that we could send the signal.
+ */
+static boolean_t
+freectty_signal(proc_t *p, sess_t *sp, stdata_t *stp, boolean_t at_exit)
+{
+ /* Assert that we hold all the necessary locks. */
+ ASSERT(MUTEX_HELD(&stp->sd_lock) && MUTEX_HELD(&pidlock) &&
+ MUTEX_HELD(&p->p_splock) && MUTEX_HELD(&sp->s_lock));
+
+ /* check if we already signaled this group */
+ if (sp->s_sighuped)
+ return (B_FALSE);
+
+ sp->s_sighuped = B_TRUE;
+
+ if (!at_exit) {
+ /*
+ * once again, we're about to drop our army of locks and we
+ * don't want sp or stp to be freed. (see the comment in
+ * freectty_lock())
+ */
+ sp->s_ref++; /* hold the session structure */
+ sp->s_cnt++; /* protect vp and stp */
+ }
+
+ /* can't hold these locks while calling pgsignal() */
mutex_exit(&sp->s_lock);
+ mutex_exit(&p->p_splock);
+ mutex_exit(&pidlock);
+
+ /* signal anyone in the foreground process group */
+ pgsignal(stp->sd_pgidp, SIGHUP);
+
+ /* signal anyone blocked in poll on this stream */
+ if (!(stp->sd_flag & STRHUP))
+ strhup(stp);
+
+ mutex_exit(&stp->sd_lock);
+
+ /* release our holds */
+ if (!at_exit)
+ tty_rele(sp);
+
+ return (B_TRUE);
+}
+
+int
+freectty(boolean_t at_exit)
+{
+ proc_t *p = curproc;
+ stdata_t *stp;
+ vnode_t *vp;
+ cred_t *cred;
+ sess_t *sp;
+ struct pid *pgidp, *sidp;
+ boolean_t got_sig = B_FALSE;
/*
- * This will be the only thread with access to
- * this vnode, from this point on.
+ * If the current process is a session leader we are going to
+ * try to release the ctty associated our current session. To
+ * do this we need to aquire a bunch of locks, signal any
+ * processes in the forground that are associated with the ctty,
+ * and make sure no one has any outstanding holds on the current
+ * session * structure (aquired via tty_hold()). Hence, we have
+ * the following for(;;) loop that will do all this work for
+ * us and break out when the hold count on the session structure
+ * hits zero.
*/
+ for (;;) {
+ if (!freectty_lock(p, &sp, &vp, &stp, at_exit))
+ return (EIO);
+
+ if (freectty_signal(p, sp, stp, at_exit)) {
+ /* loop around to re-aquire locks */
+ continue;
+ }
+
+ /*
+ * Only a session leader process can free a ctty. So if
+ * we've made it here we know we're a session leader and
+ * if we're not actively exiting it impossible for another
+ * thread in this process to be exiting. (Because that
+ * thread would have already stopped all other threads
+ * in the current process.)
+ */
+ ASSERT(at_exit || !sp->s_exit);
+
+ /*
+ * If no one else has a hold on this session structure
+ * then we now have exclusive access to it, so break out
+ * of this loop and update the session structure.
+ */
+ if (sp->s_cnt == 0)
+ break;
+
+ if (!at_exit) {
+ /* need to hold the session so it can't be freed */
+ sp->s_ref++;
+ }
+
+ /* ain't locking order fun? */
+ mutex_exit(&p->p_splock);
+ mutex_exit(&pidlock);
+ mutex_exit(&stp->sd_lock);
+
+ if (at_exit) {
+ /*
+ * if we're exiting then we can't allow this operation
+ * to fail so we do a cw_wait() instead of a
+ * cv_wait_sig(). if there are threads with active
+ * holds on this ctty that are blocked, then
+ * they should only be blocked in a cv_wait_sig()
+ * and hopefully they were in the foreground process
+ * group and recieved the SIGHUP we sent above. of
+ * course it's possible that they weren't in the
+ * foreground process group and didn't get our
+ * signal (or they could be stopped by job control
+ * in which case our signal wouldn't matter until
+ * they are restarted). in this case we won't
+ * exit until someone else sends them a signal.
+ */
+ cv_wait(&sp->s_cnt_cv, &sp->s_lock);
+ mutex_exit(&sp->s_lock);
+ continue;
+ }
+
+ if (!cv_wait_sig(&sp->s_cnt_cv, &sp->s_lock)) {
+ got_sig = B_TRUE;
+ }
+
+ mutex_exit(&sp->s_lock);
+ sess_rele(sp, B_FALSE);
+
+ if (got_sig)
+ return (EINTR);
+ }
+ ASSERT(sp->s_cnt == 0);
+ /* save some pointers for later */
+ cred = sp->s_cred;
+ pgidp = stp->sd_pgidp;
+ sidp = stp->sd_sidp;
+
+ /* clear the session ctty bindings */
+ sess_ctty_clear(sp, stp);
+
+ /* wake up anyone blocked in tty_hold() */
+ if (at_exit) {
+ ASSERT(sp->s_exit);
+ sp->s_exit = B_FALSE;
+ cv_broadcast(&sp->s_exit_cv);
+ }
+
+ /* we can drop these locks now */
+ mutex_exit(&sp->s_lock);
+ mutex_exit(&p->p_splock);
+ mutex_exit(&pidlock);
+ mutex_exit(&stp->sd_lock);
+
+ /* This is the only remaining thread with access to this vnode */
(void) VOP_CLOSE(vp, 0, 1, (offset_t)0, cred);
VN_RELE(vp);
-
crfree(cred);
+
+ /* release our holds on assorted structures and return */
+ mutex_enter(&pidlock);
+ PID_RELE(pgidp);
+ PID_RELE(sidp);
+ mutex_exit(&pidlock);
+
+ return (1);
}
/*
@@ -169,23 +680,29 @@ vhangup(void)
dev_t
cttydev(proc_t *pp)
{
- sess_t *sp = pp->p_sessp;
+ sess_t *sp;
+ dev_t dev;
+
+ mutex_enter(&pp->p_splock); /* protects p->p_sessp */
+ sp = pp->p_sessp;
+
+#ifdef DEBUG
+ mutex_enter(&sp->s_lock); /* protects sp->* */
if (sp->s_vp == NULL)
- return (NODEV);
- return (sp->s_dev);
+ ASSERT(sp->s_dev == NODEV);
+ else
+ ASSERT(sp->s_dev != NODEV);
+ mutex_exit(&sp->s_lock);
+#endif /* DEBUG */
+
+ dev = sp->s_dev;
+ mutex_exit(&pp->p_splock);
+ return (dev);
}
void
-alloctty(proc_t *pp, vnode_t *vp)
+ctty_clear_sighuped(void)
{
- sess_t *sp = pp->p_sessp;
- cred_t *crp;
-
- sp->s_vp = vp;
- sp->s_dev = vp->v_rdev;
-
- mutex_enter(&pp->p_crlock);
- crhold(crp = pp->p_cred);
- mutex_exit(&pp->p_crlock);
- sp->s_cred = crp;
+ ASSERT(MUTEX_HELD(&pidlock) || MUTEX_HELD(&curproc->p_splock));
+ curproc->p_sessp->s_sighuped = B_FALSE;
}