This commit was manufactured by cvs2svn to create branch 'vserver'.
[linux-2.6.git] / Documentation / tty.txt
diff --git a/Documentation/tty.txt b/Documentation/tty.txt
new file mode 100644 (file)
index 0000000..a496056
--- /dev/null
@@ -0,0 +1,194 @@
+
+                       The Lockronomicon
+
+Your guide to the ancient and twisted locking policies of the tty layer and
+the warped logic behind them. Beware all ye who read on.
+
+FIXME: still need to work out the full set of BKL assumptions and document
+them so they can eventually be killed off.
+
+
+Line Discipline
+---------------
+
+Line disciplines are registered with tty_register_ldisc() passing the
+discipline number and the ldisc structure. At the point of registration the 
+discipline must be ready to use and it is possible it will get used before
+the call returns success. If the call returns an error then it won't get
+called. Do not re-use ldisc numbers as they are part of the userspace ABI
+and writing over an existing ldisc will cause demons to eat your computer.
+After the return the ldisc data has been copied so you may free your own 
+copy of the structure. You must not re-register over the top of the line
+discipline even with the same data or your computer again will be eaten by
+demons.
+
+In order to remove a line discipline call tty_register_ldisc passing NULL.
+In ancient times this always worked. In modern times the function will
+return -EBUSY if the ldisc is currently in use. Since the ldisc referencing
+code manages the module counts this should not usually be a concern.
+
+Heed this warning: the reference count field of the registered copies of the
+tty_ldisc structure in the ldisc table counts the number of lines using this
+discipline. The reference count of the tty_ldisc structure within a tty 
+counts the number of active users of the ldisc at this instant. In effect it
+counts the number of threads of execution within an ldisc method (plus those
+about to enter and exit although this detail matters not).
+
+Line Discipline Methods
+-----------------------
+
+TTY side interfaces:
+
+close()                -       This is called on a terminal when the line
+                       discipline is being unplugged. At the point of
+                       execution no further users will enter the
+                       ldisc code for this tty. Can sleep.
+
+open()         -       Called when the line discipline is attached to
+                       the terminal. No other call into the line
+                       discipline for this tty will occur until it
+                       completes successfully. Can sleep.
+
+write()                -       A process is writing data from user space
+                       through the line discipline. Multiple write calls
+                       are serialized by the tty layer for the ldisc. May
+                       sleep.
+
+flush_buffer() -       May be called at any point between open and close.
+
+chars_in_buffer() -    Report the number of bytes in the buffer.
+
+set_termios()  -       Called on termios structure changes. The caller
+                       passes the old termios data and the current data
+                       is in the tty. Called under the termios semaphore so
+                       allowed to sleep. Serialized against itself only.
+
+read()         -       Move data from the line discipline to the user.
+                       Multiple read calls may occur in parallel and the
+                       ldisc must deal with serialization issues. May 
+                       sleep.
+
+poll()         -       Check the status for the poll/select calls. Multiple
+                       poll calls may occur in parallel. May sleep.
+
+ioctl()                -       Called when an ioctl is handed to the tty layer
+                       that might be for the ldisc. Multiple ioctl calls
+                       may occur in parallel. May sleep. 
+
+Driver Side Interfaces:
+
+receive_buf()  -       Hand buffers of bytes from the driver to the ldisc
+                       for processing. Semantics currently rather
+                       mysterious 8(
+
+receive_room() -       Can be called by the driver layer at any time when
+                       the ldisc is opened. The ldisc must be able to
+                       handle the reported amount of data at that instant.
+                       Synchronization between active receive_buf and
+                       receive_room calls is down to the driver not the
+                       ldisc. Must not sleep.
+
+write_wakeup() -       May be called at any point between open and close.
+                       The TTY_DO_WRITE_WAKEUP flag indicates if a call
+                       is needed but always races versus calls. Thus the
+                       ldisc must be careful about setting order and to
+                       handle unexpected calls. Must not sleep.
+
+
+Locking
+
+Callers to the line discipline functions from the tty layer are required to
+take line discipline locks. The same is true of calls from the driver side
+but not yet enforced.
+
+Three calls are now provided
+
+       ldisc = tty_ldisc_ref(tty);
+
+takes a handle to the line discipline in the tty and returns it. If no ldisc
+is currently attached or the ldisc is being closed and re-opened at this
+point then NULL is returned. While this handle is held the ldisc will not
+change or go away.
+
+       tty_ldisc_deref(ldisc)
+
+Returns the ldisc reference and allows the ldisc to be closed. Returning the
+reference takes away your right to call the ldisc functions until you take
+a new reference.
+
+       ldisc = tty_ldisc_ref_wait(tty);
+
+Performs the same function as tty_ldisc_ref except that it will wait for an
+ldisc change to complete and then return a reference to the new ldisc. 
+
+While these functions are slightly slower than the old code they should have
+minimal impact as most receive logic uses the flip buffers and they only
+need to take a reference when they push bits up through the driver.
+
+A caution: The ldisc->open(), ldisc->close() and driver->set_ldisc 
+functions are called with the ldisc unavailable. Thus tty_ldisc_ref will
+fail in this situation if used within these functions. Ldisc and driver
+code calling its own functions must be careful in this case. 
+
+
+Driver Interface
+----------------
+
+open()         -       Called when a device is opened. May sleep
+
+close()                -       Called when a device is closed. At the point of
+                       return from this call the driver must make no 
+                       further ldisc calls of any kind. May sleep
+
+write()                -       Called to write bytes to the device. May not
+                       sleep. May occur in parallel in special cases. 
+                       Because this includes panic paths drivers generally
+                       shouldn't try and do clever locking here.
+
+put_char()     -       Stuff a single character onto the queue. The
+                       driver is guaranteed following up calls to
+                       flush_chars.
+
+flush_chars()  -       Ask the kernel to write put_char queue
+
+write_room()   -       Return the number of characters tht can be stuffed
+                       into the port buffers without overflow (or less).
+                       The ldisc is responsible for being intelligent
+                       about multi-threading of write_room/write calls
+
+ioctl()                -       Called when an ioctl may be for the driver
+
+set_termios()  -       Called on termios change, serialized against
+                       itself by a semaphore. May sleep.
+
+set_ldisc()    -       Notifier for discipline change. At the point this 
+                       is done the discipline is not yet usable. Can now
+                       sleep (I think)
+
+throttle()     -       Called by the ldisc to ask the driver to do flow
+                       control.  Serialization including with unthrottle
+                       is the job of the ldisc layer.
+
+unthrottle()   -       Called by the ldisc to ask the driver to stop flow
+                       control.
+
+stop()         -       Ldisc notifier to the driver to stop output. As with
+                       throttle the serializations with start() are down
+                       to the ldisc layer.
+
+start()                -       Ldisc notifier to the driver to start output.
+
+hangup()       -       Ask the tty driver to cause a hangup initiated
+                       from the host side. [Can sleep ??]
+
+break_ctl()    -       Send RS232 break. Can sleep. Can get called in
+                       parallel, driver must serialize (for now), and
+                       with write calls.
+
+wait_until_sent() -    Wait for characters to exit the hardware queue
+                       of the driver. Can sleep
+
+send_xchar()     -     Send XON/XOFF and if possible jump the queue with
+                       it in order to get fast flow control responses.
+                       Cannot sleep ??
+