msc@qubix.UUCP (Mark Callow) (09/17/84)
> 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@qubix.UUCP, qubix!msc@decwrl.ARPA ...{decvax,ucbvax}!decwrl!qubix!msc, ...{amd,ihnp4,ittvax}!qubix!msc "Nothing shocks me. I'm an Engineer."