summaryrefslogtreecommitdiffstats
path: root/sys/kern/tty.c
diff options
context:
space:
mode:
authortanimura <tanimura@FreeBSD.org>2002-02-23 11:12:57 +0000
committertanimura <tanimura@FreeBSD.org>2002-02-23 11:12:57 +0000
commita09da298590e8c11ebafa37f79e0046814665237 (patch)
tree2289c653c0f7aa23498f82b603c33107952652ec /sys/kern/tty.c
parent33e8ee5265ca2838260ab581a9cebdedb1e1e29b (diff)
downloadFreeBSD-src-a09da298590e8c11ebafa37f79e0046814665237.zip
FreeBSD-src-a09da298590e8c11ebafa37f79e0046814665237.tar.gz
Lock struct pgrp, session and sigio.
New locks are: - pgrpsess_lock which locks the whole pgrps and sessions, - pg_mtx which protects the pgrp members, and - s_mtx which protects the session members. Please refer to sys/proc.h for the coverage of these locks. Changes on the pgrp/session interface: - pgfind() needs the pgrpsess_lock held. - The caller of enterpgrp() is responsible to allocate a new pgrp and session. - Call enterthispgrp() in order to enter an existing pgrp. - pgsignal() requires a pgrp lock held. Reviewed by: jhb, alfred Tested on: cvsup.jp.FreeBSD.org (which is a quad-CPU machine running -current)
Diffstat (limited to 'sys/kern/tty.c')
-rw-r--r--sys/kern/tty.c195
1 files changed, 142 insertions, 53 deletions
diff --git a/sys/kern/tty.c b/sys/kern/tty.c
index 5c778b7..2ca162a 100644
--- a/sys/kern/tty.c
+++ b/sys/kern/tty.c
@@ -75,6 +75,7 @@
#include <sys/filio.h>
#include <sys/lock.h>
#include <sys/mutex.h>
+#include <sys/sx.h>
#if defined(COMPAT_43) || defined(COMPAT_SUNOS)
#include <sys/ioctl_compat.h>
#endif
@@ -328,7 +329,11 @@ ttyinput(c, tp)
return (0);
if (ISSET(iflag, BRKINT)) {
ttyflush(tp, FREAD | FWRITE);
- pgsignal(tp->t_pgrp, SIGINT, 1);
+ if (tp->t_pgrp != NULL) {
+ PGRP_LOCK(tp->t_pgrp);
+ pgsignal(tp->t_pgrp, SIGINT, 1);
+ PGRP_UNLOCK(tp->t_pgrp);
+ }
goto endcase;
}
if (ISSET(iflag, PARMRK))
@@ -406,15 +411,23 @@ parmrk:
if (!ISSET(lflag, NOFLSH))
ttyflush(tp, FREAD | FWRITE);
ttyecho(c, tp);
- pgsignal(tp->t_pgrp,
- CCEQ(cc[VINTR], c) ? SIGINT : SIGQUIT, 1);
+ if (tp->t_pgrp != NULL) {
+ PGRP_LOCK(tp->t_pgrp);
+ pgsignal(tp->t_pgrp,
+ CCEQ(cc[VINTR], c) ? SIGINT : SIGQUIT, 1);
+ PGRP_UNLOCK(tp->t_pgrp);
+ }
goto endcase;
}
if (CCEQ(cc[VSUSP], c)) {
if (!ISSET(lflag, NOFLSH))
ttyflush(tp, FREAD);
ttyecho(c, tp);
- pgsignal(tp->t_pgrp, SIGTSTP, 1);
+ if (tp->t_pgrp != NULL) {
+ PGRP_LOCK(tp->t_pgrp);
+ pgsignal(tp->t_pgrp, SIGTSTP, 1);
+ PGRP_UNLOCK(tp->t_pgrp);
+ }
goto endcase;
}
}
@@ -532,8 +545,11 @@ parmrk:
* ^T - kernel info and generate SIGINFO
*/
if (CCEQ(cc[VSTATUS], c) && ISSET(lflag, IEXTEN)) {
- if (ISSET(lflag, ISIG))
+ if (ISSET(lflag, ISIG) && tp->t_pgrp != NULL) {
+ PGRP_LOCK(tp->t_pgrp);
pgsignal(tp->t_pgrp, SIGINFO, 1);
+ PGRP_UNLOCK(tp->t_pgrp);
+ }
if (!ISSET(lflag, NOKERNINFO))
ttyinfo(tp);
goto endcase;
@@ -752,17 +768,30 @@ ttioctl(tp, cmd, data, flag)
case TIOCSETP:
case TIOCSLTC:
#endif
+ PGRPSESS_SLOCK();
+ PROC_LOCK(p);
while (isbackground(p, tp) && !(p->p_flag & P_PPWAIT) &&
!SIGISMEMBER(p->p_sigignore, SIGTTOU) &&
!SIGISMEMBER(p->p_sigmask, SIGTTOU)) {
- if (p->p_pgrp->pg_jobc == 0)
+ if (p->p_pgrp->pg_jobc == 0) {
+ PROC_UNLOCK(p);
+ PGRPSESS_SUNLOCK();
return (EIO);
+ }
+ PROC_UNLOCK(p);
+ PGRP_LOCK(p->p_pgrp);
pgsignal(p->p_pgrp, SIGTTOU, 1);
+ PGRP_UNLOCK(p->p_pgrp);
error = ttysleep(tp, &lbolt, TTOPRI | PCATCH, "ttybg1",
0);
- if (error)
+ if (error) {
+ PGRPSESS_SUNLOCK();
return (error);
+ }
+ PROC_LOCK(p);
}
+ PROC_UNLOCK(p);
+ PGRPSESS_SUNLOCK();
break;
}
@@ -1012,22 +1041,44 @@ ttioctl(tp, cmd, data, flag)
break;
case TIOCSCTTY: /* become controlling tty */
/* Session ctty vnode pointer set in vnode layer. */
+ PGRPSESS_XLOCK();
if (!SESS_LEADER(p) ||
((p->p_session->s_ttyvp || tp->t_session) &&
- (tp->t_session != p->p_session)))
+ (tp->t_session != p->p_session))) {
+ PGRPSESS_XUNLOCK();
return (EPERM);
+ }
tp->t_session = p->p_session;
tp->t_pgrp = p->p_pgrp;
+ SESS_LOCK(p->p_session);
p->p_session->s_ttyp = tp;
+ SESS_UNLOCK(p->p_session);
+ PROC_LOCK(p);
p->p_flag |= P_CONTROLT;
+ PROC_UNLOCK(p);
+ PGRPSESS_XUNLOCK();
break;
case TIOCSPGRP: { /* set pgrp of tty */
- register struct pgrp *pgrp = pgfind(*(int *)data);
-
- if (!isctty(p, tp))
+ register struct pgrp *pgrp;
+
+ PGRPSESS_SLOCK();
+ pgrp = pgfind(*(int *)data);
+ if (!isctty(p, tp)) {
+ if (pgrp != NULL)
+ PGRP_UNLOCK(pgrp);
+ PGRPSESS_SUNLOCK();
return (ENOTTY);
- else if (pgrp == NULL || pgrp->pg_session != p->p_session)
+ }
+ if (pgrp == NULL) {
+ PGRPSESS_SUNLOCK();
return (EPERM);
+ }
+ PGRP_UNLOCK(pgrp);
+ if (pgrp->pg_session != p->p_session) {
+ PGRPSESS_SUNLOCK();
+ return (EPERM);
+ }
+ PGRPSESS_SUNLOCK();
tp->t_pgrp = pgrp;
break;
}
@@ -1040,7 +1091,11 @@ ttioctl(tp, cmd, data, flag)
if (bcmp((caddr_t)&tp->t_winsize, data,
sizeof (struct winsize))) {
tp->t_winsize = *(struct winsize *)data;
- pgsignal(tp->t_pgrp, SIGWINCH, 1);
+ if (tp->t_pgrp != NULL) {
+ PGRP_LOCK(tp->t_pgrp);
+ pgsignal(tp->t_pgrp, SIGWINCH, 1);
+ PGRP_UNLOCK(tp->t_pgrp);
+ }
}
break;
case TIOCSDRAINWAIT:
@@ -1459,13 +1514,17 @@ ttymodem(tp, flag)
!ISSET(tp->t_cflag, CLOCAL)) {
SET(tp->t_state, TS_ZOMBIE);
CLR(tp->t_state, TS_CONNECTED);
- if (tp->t_session && tp->t_session->s_leader) {
- struct proc *p;
-
- p = tp->t_session->s_leader;
- PROC_LOCK(p);
- psignal(p, SIGHUP);
- PROC_UNLOCK(p);
+ if (tp->t_session) {
+ PGRPSESS_SLOCK();
+ if (tp->t_session->s_leader) {
+ struct proc *p;
+
+ p = tp->t_session->s_leader;
+ PROC_LOCK(p);
+ psignal(p, SIGHUP);
+ PROC_UNLOCK(p);
+ }
+ PGRPSESS_SUNLOCK();
}
ttyflush(tp, FREAD | FWRITE);
return (0);
@@ -1549,11 +1608,20 @@ loop:
*/
if (isbackground(p, tp)) {
splx(s);
+ PGRPSESS_SLOCK();
+ PROC_LOCK(p);
if (SIGISMEMBER(p->p_sigignore, SIGTTIN) ||
SIGISMEMBER(p->p_sigmask, SIGTTIN) ||
- (p->p_flag & P_PPWAIT) || p->p_pgrp->pg_jobc == 0)
+ (p->p_flag & P_PPWAIT) || p->p_pgrp->pg_jobc == 0) {
+ PROC_UNLOCK(p);
+ PGRPSESS_SUNLOCK();
return (EIO);
+ }
+ PROC_UNLOCK(p);
+ PGRP_LOCK(p->p_pgrp);
+ PGRPSESS_SUNLOCK();
pgsignal(p->p_pgrp, SIGTTIN, 1);
+ PGRP_UNLOCK(p->p_pgrp);
error = ttysleep(tp, &lbolt, TTIPRI | PCATCH, "ttybg2", 0);
if (error)
return (error);
@@ -1727,7 +1795,11 @@ slowcase:
*/
if (CCEQ(cc[VDSUSP], c) &&
ISSET(lflag, IEXTEN | ISIG) == (IEXTEN | ISIG)) {
- pgsignal(tp->t_pgrp, SIGTSTP, 1);
+ if (tp->t_pgrp != NULL) {
+ PGRP_LOCK(tp->t_pgrp);
+ pgsignal(tp->t_pgrp, SIGTSTP, 1);
+ PGRP_UNLOCK(tp->t_pgrp);
+ }
if (first) {
error = ttysleep(tp, &lbolt, TTIPRI | PCATCH,
"ttybg3", 0);
@@ -1855,19 +1927,30 @@ loop:
* Hang the process if it's in the background.
*/
p = curproc;
+ PGRPSESS_SLOCK();
+ PROC_LOCK(p);
if (isbackground(p, tp) &&
ISSET(tp->t_lflag, TOSTOP) && !(p->p_flag & P_PPWAIT) &&
!SIGISMEMBER(p->p_sigignore, SIGTTOU) &&
!SIGISMEMBER(p->p_sigmask, SIGTTOU)) {
if (p->p_pgrp->pg_jobc == 0) {
+ PROC_UNLOCK(p);
+ PGRPSESS_SUNLOCK();
error = EIO;
goto out;
}
+ PROC_UNLOCK(p);
+ PGRP_LOCK(p->p_pgrp);
+ PGRPSESS_SUNLOCK();
pgsignal(p->p_pgrp, SIGTTOU, 1);
+ PGRP_UNLOCK(p->p_pgrp);
error = ttysleep(tp, &lbolt, TTIPRI | PCATCH, "ttybg4", 0);
if (error)
goto out;
goto loop;
+ } else {
+ PROC_UNLOCK(p);
+ PGRPSESS_SUNLOCK();
}
/*
* Process the user's data in at most OBUFSIZ chunks. Perform any
@@ -2328,38 +2411,44 @@ ttyinfo(tp)
ttyprintf(tp, "not a controlling terminal\n");
else if (tp->t_pgrp == NULL)
ttyprintf(tp, "no foreground process group\n");
- else if ((p = LIST_FIRST(&tp->t_pgrp->pg_members)) == 0)
- ttyprintf(tp, "empty foreground process group\n");
else {
- mtx_lock_spin(&sched_lock);
-
- /* Pick interesting process. */
- for (pick = NULL; p != 0; p = LIST_NEXT(p, p_pglist))
- if (proc_compare(pick, p))
- pick = p;
-
- td = FIRST_THREAD_IN_PROC(pick);
- stmp = pick->p_stat == SRUN ? "running" : /* XXXKSE */
- td->td_wmesg ? td->td_wmesg : "iowait";
- calcru(pick, &utime, &stime, NULL);
- ltmp = pick->p_stat == SIDL || pick->p_stat == SWAIT ||
- pick->p_stat == SZOMB ? 0 :
- pgtok(vmspace_resident_count(pick->p_vmspace));
- mtx_unlock_spin(&sched_lock);
-
- ttyprintf(tp, " cmd: %s %d [%s] ", pick->p_comm, pick->p_pid,
- stmp);
-
- /* Print user time. */
- ttyprintf(tp, "%ld.%02ldu ",
- (long)utime.tv_sec, utime.tv_usec / 10000);
-
- /* Print system time. */
- ttyprintf(tp, "%ld.%02lds ",
- (long)stime.tv_sec, stime.tv_usec / 10000);
-
- /* Print percentage cpu, resident set size. */
- ttyprintf(tp, "%d%% %ldk\n", tmp / 100, ltmp);
+ PGRP_LOCK(tp->t_pgrp);
+ if ((p = LIST_FIRST(&tp->t_pgrp->pg_members)) == 0) {
+ PGRP_UNLOCK(tp->t_pgrp);
+ ttyprintf(tp, "empty foreground process group\n");
+ } else {
+ PGRP_UNLOCK(tp->t_pgrp);
+ mtx_lock_spin(&sched_lock);
+
+ /* Pick interesting process. */
+ for (pick = NULL; p != 0; p = LIST_NEXT(p, p_pglist))
+ if (proc_compare(pick, p))
+ pick = p;
+
+ td = FIRST_THREAD_IN_PROC(pick);
+ stmp = pick->p_stat == SRUN ? "running" : /* XXXKSE */
+ td->td_wmesg ? td->td_wmesg : "iowait";
+ calcru(pick, &utime, &stime, NULL);
+ ltmp = pick->p_stat == SIDL || pick->p_stat == SWAIT ||
+ pick->p_stat == SZOMB ? 0 :
+ pgtok(vmspace_resident_count(pick->p_vmspace));
+ mtx_unlock_spin(&sched_lock);
+
+ ttyprintf(tp, " cmd: %s %d [%s] ", pick->p_comm, pick->p_pid,
+ stmp);
+
+ /* Print user time. */
+ ttyprintf(tp, "%lld.%02ldu ",
+ utime.tv_sec, utime.tv_usec / 10000);
+
+ /* Print system time. */
+ ttyprintf(tp, "%ld.%02lds ",
+ (long)stime.tv_sec, stime.tv_usec / 10000);
+
+ /* Print percentage cpu, resident set size. */
+ ttyprintf(tp, "%d%% %ldk\n", tmp / 100, ltmp);
+
+ }
}
tp->t_rocount = 0; /* so pending input will be retyped if BS */
}
OpenPOWER on IntegriCloud