123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302 |
- 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_unregister_ldisc().
- 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:
- 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. Returning an error will
- prevent the ldisc from being attached. Can sleep.
- 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.
- hangup() - Called when the tty line is hung up.
- The line discipline should cease I/O to the tty.
- No further calls into the ldisc code will occur.
- The return value is ignored. Can sleep.
- write() - A process is writing data through the line
- discipline. Multiple write calls are serialized
- by the tty layer for the ldisc. May sleep.
- flush_buffer() - (optional) May be called at any point between
- open and close, and instructs the line discipline
- to empty its input buffer.
- chars_in_buffer() - (optional) Report the number of bytes in the input
- buffer.
- set_termios() - (optional) 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.
- compat_ioctl() - Called when a 32 bit 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(
- 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.
- The driver is forbidden from calling this directly
- from the ->write call from the ldisc as the ldisc
- is permitted to call the driver write method from
- this function. In such a situation defer it.
- dcd_change() - Report to the tty line the current DCD pin status
- changes and the relative timestamp. The timestamp
- cannot be NULL.
- Driver Access
- Line discipline methods can call the following methods of the underlying
- hardware driver through the function pointers within the tty->driver
- structure:
- write() Write a block of characters to the tty device.
- Returns the number of characters accepted. The
- character buffer passed to this method is already
- in kernel space.
- put_char() Queues a character for writing to the tty device.
- If there is no room in the queue, the character is
- ignored.
- flush_chars() (Optional) If defined, must be called after
- queueing characters with put_char() in order to
- start transmission.
- write_room() Returns the numbers of characters the tty driver
- will accept for queueing to be written.
- ioctl() Invoke device specific ioctl.
- Expects data pointers to refer to userspace.
- Returns ENOIOCTLCMD for unrecognized ioctl numbers.
- set_termios() Notify the tty driver that the device's termios
- settings have changed. New settings are in
- tty->termios. Previous settings should be passed in
- the "old" argument.
- The API is defined such that the driver should return
- the actual modes selected. This means that the
- driver function is responsible for modifying any
- bits in the request it cannot fulfill to indicate
- the actual modes being used. A device with no
- hardware capability for change (eg a USB dongle or
- virtual port) can provide NULL for this method.
- throttle() Notify the tty driver that input buffers for the
- line discipline are close to full, and it should
- somehow signal that no more characters should be
- sent to the tty.
- unthrottle() Notify the tty driver that characters can now be
- sent to the tty without fear of overrunning the
- input buffers of the line disciplines.
- stop() Ask the tty driver to stop outputting characters
- to the tty device.
- start() Ask the tty driver to resume sending characters
- to the tty device.
- hangup() Ask the tty driver to hang up the tty device.
- break_ctl() (Optional) Ask the tty driver to turn on or off
- BREAK status on the RS-232 port. If state is -1,
- then the BREAK status should be turned on; if
- state is 0, then BREAK should be turned off.
- If this routine is not implemented, use ioctls
- TIOCSBRK / TIOCCBRK instead.
- wait_until_sent() Waits until the device has written out all of the
- characters in its transmitter FIFO.
- send_xchar() Send a high-priority XON/XOFF character to the device.
- Flags
- Line discipline methods have access to tty->flags field containing the
- following interesting flags:
- TTY_THROTTLED Driver input is throttled. The ldisc should call
- tty->driver->unthrottle() in order to resume
- reception when it is ready to process more data.
- TTY_DO_WRITE_WAKEUP If set, causes the driver to call the ldisc's
- write_wakeup() method in order to resume
- transmission when it can accept more data
- to transmit.
- TTY_IO_ERROR If set, causes all subsequent userspace read/write
- calls on the tty to fail, returning -EIO.
- TTY_OTHER_CLOSED Device is a pty and the other side has closed.
- TTY_NO_WRITE_SPLIT Prevent driver from splitting up writes into
- smaller chunks.
- 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 ??
|