Oddities in 4.2BSD tty routines

Mark Callow msc at qubix.UUCP
Tue Sep 18 06:54:40 AEST 1984


> Chris Torek
> In the 4.2 file /usr/sys/sys/tty.c, we find this odd bit of code:
> 	/*
> 	 * clean tp on last close
> 	 */
> 	ttyclose(tp)
> 		register struct tty *tp;
> 	{
> 
> 		if (tp->t_line) {
> other->			ttywflush(tp);
> 			tp->t_line = 0;
> 			return;
> 		}
> old tty->	tp->t_pgrp = 0;
> 		ttywflush(tp);
> 		tp->t_state = 0;
> 	}
> 
> Now, why should the action on the last close depend on the current
> line discipline?  If it's ``old tty'', it zeros out tp->t_pgrp and
> tp->t_state, which makes a certain amount of sense....  Otherwise,
> it's ``new tty'' or Berknet or what have you, and it merely does a
> wait-and-flush, then sets the line discipline back to OTTYDISC (0).

All tty device driver close routines call the line discipline close
routine then ttyclose().  Therefore the first call resets the line
discipline (assuming the line discipline close ends up calling
ttyclose()), and the second cleans everything up.  I guess this was
a way of providing a single close routine that could be used by all
line disciplines to clean everything up.

> Looking further through the code we see this here other oddity:
> ttioctl calls the line open and close routines when changing line
> disciplines.
> 
> 	/* set line discipline */
> 	case TIOCSETD: {
> 		register int t = *(int *)data;
> 		int error = 0;
> 
> 		if ((unsigned) t >= nldisp)
> 			return (ENXIO);
> 		s = spl5();
> other->		if (tp->t_line)
> 			(*linesw[tp->t_line].l_close)(tp);
> other->		if (t)
> 			error = (*linesw[t].l_open)(dev, tp);
> 		splx(s);
START WINDOW
> 		if (error) {
> 			s = spl5();
> restore other->		if (tp->t_line)
> 				(void) (*linesw[tp->t_line].l_open)(dev, tp);
> 			splx(s);
> 			return (error);
> 		}
END WINDOW
> made it!->	tp->t_line = t;
> 		break;
> 	}
> 
> All this seems OK, though a bit weird.  I suppose it's mainly for the
> graphics tablet support I see floating around in there.  If so, it
> seems to me that a better way to do that would be to have two more
> linesw entries, ``l_shutdown'' and ``l_startup'', to shut down or start
> up a particular line discipline.
> 
Having written a couple of other line disciplines I can report that
closing the old line discipline and opening the new one is necessary.
There is a bug in this code though.  There is a window, indicated above,
through which an interrupt can come in from the device and be serviced by
the old line discipline even though the new one has been opened.  This
can be a disaster the two disciplines are using the bits in tp->t_state
differently.  It can also result in loss or mutation of perfectly good
characters depending upon the disciplines involved.

The splx(s) should be moved to just after the statement "tp->t_line = t;";
the spl5() inside the "if (error) " is then superflous and can be removed.
-- 
>From the TARDIS of Mark Callow
msc at qubix.UUCP,  qubix!msc at decwrl.ARPA
...{decvax,ucbvax}!decwrl!qubix!msc, ...{amd,ihnp4,ittvax}!qubix!msc

"Nothing shocks me.  I'm an Engineer."



More information about the Comp.unix.wizards mailing list