| |
| 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: |
| |
| 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 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. |
| |
| 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. |
| |
| |
| 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 ?? |
| |