TTY Struct

struct tty_struct is allocated by the TTY layer upon the first open of the TTY device and released after the last close. The TTY layer passes this structure to most of struct tty_operation’s hooks. Members of tty_struct are documented in TTY Struct Reference at the bottom.

Initialization

void tty_init_termios(struct tty_struct *tty)

helper for termios setup

Parameters

struct tty_struct *tty

the tty to set up

Description

Initialise the termios structure for this tty. This runs under the tty_mutex currently so we can be relaxed about ordering.

Name

const char *tty_name(const struct tty_struct *tty)

return tty naming

Parameters

const struct tty_struct *tty

tty structure

Description

Convert a tty structure into a name. The name reflects the kernel naming policy and if udev is in use may not reflect user space

Locking: none

Reference counting

struct tty_struct *tty_kref_get(struct tty_struct *tty)

get a tty reference

Parameters

struct tty_struct *tty

tty device

Return a new reference to a tty object. The caller must hold sufficient locks/counts to ensure that their existing reference cannot go away

void tty_kref_put(struct tty_struct *tty)

release a tty kref

Parameters

struct tty_struct *tty

tty device

Description

Release a reference to the tty device and if need be let the kref layer destruct the object for us.

Install

int tty_standard_install(struct tty_driver *driver, struct tty_struct *tty)

usual tty->ops->install

Parameters

struct tty_driver *driver

the driver for the tty

struct tty_struct *tty

the tty

Description

If the driver overrides tty->ops->install, it still can call this function to perform the standard install operations.

Read & Write

int tty_put_char(struct tty_struct *tty, unsigned char ch)

write one character to a tty

Parameters

struct tty_struct *tty

tty

unsigned char ch

character to write

Description

Write one byte to the tty using the provided tty->ops->put_char() method if present.

Note

the specific put_char operation in the driver layer may go away soon. Don’t call it directly, use this method

Return

the number of characters successfully output.

Start & Stop

void stop_tty(struct tty_struct *tty)

propagate flow control

Parameters

struct tty_struct *tty

tty to stop

Description

Perform flow control to the driver. May be called on an already stopped device and will not re-call the tty_driver->stop() method.

This functionality is used by both the line disciplines for halting incoming flow and by the driver. It may therefore be called from any context, may be under the tty atomic_write_lock but not always.

Locking:

flow.lock

void start_tty(struct tty_struct *tty)

propagate flow control

Parameters

struct tty_struct *tty

tty to start

Description

Start a tty that has been stopped if at all possible. If tty was previously stopped and is now being started, the tty_driver->start() method is invoked and the line discipline woken.

Locking:

flow.lock

Wakeup

void tty_wakeup(struct tty_struct *tty)

request more data

Parameters

struct tty_struct *tty

terminal

Description

Internal and external helper for wakeups of tty. This function informs the line discipline if present that the driver is ready to receive more output data.

Hangup

void tty_hangup(struct tty_struct *tty)

trigger a hangup event

Parameters

struct tty_struct *tty

tty to hangup

Description

A carrier loss (virtual or otherwise) has occurred on tty. Schedule a hangup sequence to run after this event.

void tty_vhangup(struct tty_struct *tty)

process vhangup

Parameters

struct tty_struct *tty

tty to hangup

Description

The user has asked via system call for the terminal to be hung up. We do this synchronously so that when the syscall returns the process is complete. That guarantee is necessary for security reasons.

int tty_hung_up_p(struct file *filp)

was tty hung up

Parameters

struct file *filp

file pointer of tty

Return

true if the tty has been subject to a vhangup or a carrier loss

Misc

int tty_do_resize(struct tty_struct *tty, struct winsize *ws)

resize event

Parameters

struct tty_struct *tty

tty being resized

struct winsize *ws

new dimensions

Description

Update the termios variables and send the necessary signals to peform a terminal resize correctly.

TTY Struct Flags

These bits are used in the tty_struct.flags field.

So that interrupts won’t be able to mess up the queues, copy_to_cooked must be atomic with respect to itself, as must tty->write. Thus, you must use the inline functions set_bit() and clear_bit() to make things atomic.

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 (at threshold min).

TTY_IO_ERROR

If set, causes all subsequent userspace read/write calls on the tty to fail, returning -EIO. (May be no ldisc too.)

TTY_OTHER_CLOSED

Device is a pty and the other side has closed.

TTY_EXCLUSIVE

Exclusive open mode (a single opener).

TTY_DO_WRITE_WAKEUP

If set, causes the driver to call the tty_ldisc_ops.write_wakeup() method in order to resume transmission when it can accept more data to transmit.

TTY_LDISC_OPEN

Indicates that a line discipline is open. For debugging purposes only.

TTY_PTY_LOCK

A flag private to pty code to implement TIOCSPTLCK/TIOCGPTLCK logic.

TTY_NO_WRITE_SPLIT

Prevent driver from splitting up writes into smaller chunks (preserve write boundaries to driver).

TTY_HUPPED

The TTY was hung up. This is set post tty_driver.hangup().

TTY_HUPPING

The TTY is in the process of hanging up to abort potential readers.

TTY_LDISC_CHANGING

Line discipline for this TTY is being changed. I/O should not block when this is set. Use tty_io_nonblock() to check.

TTY_LDISC_HALTED

Line discipline for this TTY was stopped. No work should be queued to this ldisc.

TTY Struct Reference

struct tty_struct

state associated with a tty while open

Definition

struct tty_struct {
  int magic;
  struct kref kref;
  struct device *dev;
  struct tty_driver *driver;
  const struct tty_operations *ops;
  int index;
  struct ld_semaphore ldisc_sem;
  struct tty_ldisc *ldisc;
  struct mutex atomic_write_lock;
  struct mutex legacy_mutex;
  struct mutex throttle_mutex;
  struct rw_semaphore termios_rwsem;
  struct mutex winsize_mutex;
  struct ktermios termios, termios_locked;
  char name[64];
  unsigned long flags;
  int count;
  struct winsize winsize;
  struct {
    spinlock_t lock;
    bool stopped;
    bool tco_stopped;
    unsigned long unused[0];
  } flow;
  struct {
    spinlock_t lock;
    struct pid *pgrp;
    struct pid *session;
    unsigned char pktstatus;
    bool packet;
    unsigned long unused[0];
  } ctrl;
  int hw_stopped;
  unsigned int receive_room;
  int flow_change;
  struct tty_struct *link;
  struct fasync_struct *fasync;
  wait_queue_head_t write_wait;
  wait_queue_head_t read_wait;
  struct work_struct hangup_work;
  void *disc_data;
  void *driver_data;
  spinlock_t files_lock;
  struct list_head tty_files;
#define N_TTY_BUF_SIZE 4096;
  int closing;
  unsigned char *write_buf;
  int write_cnt;
  struct work_struct SAK_work;
  struct tty_port *port;
};

Members

magic

magic value set early in alloc_tty_struct to TTY_MAGIC, for debugging purposes

kref

reference counting by tty_kref_get() and tty_kref_put(), reaching zero frees the structure

dev

class device or NULL (e.g. ptys, serdev)

driver

struct tty_driver operating this tty

ops

struct tty_operations of driver for this tty (open, close, etc.)

index

index of this tty (e.g. to construct name like tty12)

ldisc_sem

protects line discipline changes (ldisc) – lock tty not pty

ldisc

the current line discipline for this tty (n_tty by default)

atomic_write_lock

protects against concurrent writers, i.e. locks write_cnt, write_buf and similar

legacy_mutex

leftover from history (BKL -> BTM -> legacy_mutex), protecting several operations on this tty

throttle_mutex

protects against concurrent tty_throttle_safe() and tty_unthrottle_safe() (but not tty_unthrottle())

termios_rwsem

protects termios and termios_locked

winsize_mutex

protects winsize

termios

termios for the current tty, copied from/to driver.termios

termios_locked

locked termios (by TIOCGLCKTRMIOS and TIOCSLCKTRMIOS ioctls)

name

name of the tty constructed by tty_line_name() (e.g. ttyS3)

flags

bitwise OR of TTY_THROTTLED, TTY_IO_ERROR, …

count

count of open processes, reaching zero cancels all the work for this tty and drops a kref too (but does not free this tty)

winsize

size of the terminal “window” (cf. winsize_mutex)

flow

flow settings grouped together, see also flow.unused

flow.lock

lock for flow members

flow.stopped

tty stopped/started by stop_tty()/start_tty()

flow.tco_stopped

tty stopped/started by TCOOFF/TCOON ioctls (it has precedence over flow.stopped)

flow.unused

alignment for Alpha, so that no members other than flow.* are modified by the same 64b word store. The flow’s __aligned is there for the very same reason.

ctrl

control settings grouped together, see also ctrl.unused

ctrl.lock

lock for ctrl members

ctrl.pgrp

process group of this tty (setpgrp(2))

ctrl.session

session of this tty (setsid(2)). Writes are protected by both ctrl.lock and legacy_mutex, readers must use at least one of them.

ctrl.pktstatus

packet mode status (bitwise OR of TIOCPKT_ constants)

ctrl.packet

packet mode enabled

ctrl.unused

alignment for Alpha, see flow.unused for explanation

hw_stopped

not controlled by the tty layer, under driver’s control for CTS handling

receive_room

bytes permitted to feed to ldisc without any being lost

flow_change

controls behavior of throttling, see tty_throttle_safe() and tty_unthrottle_safe()

link

link to another pty (master -> slave and vice versa)

fasync

state for O_ASYNC (for SIGIO); managed by fasync_helper()

write_wait

concurrent writers are waiting in this queue until they are allowed to write

read_wait

readers wait for data in this queue

hangup_work

normally a work to perform a hangup (do_tty_hangup()); while freeing the tty, (re)used to release_one_tty()

disc_data

pointer to ldisc’s private data (e.g. to struct n_tty_data)

driver_data

pointer to driver’s private data (e.g. struct uart_state)

files_lock

protects tty_files list

tty_files

list of (re)openers of this tty (i.e. linked struct tty_file_private)

closing

when set during close, n_tty processes only START & STOP chars

write_buf

temporary buffer used during tty_write() to copy user data to

write_cnt

count of bytes written in tty_write() to write_buf

SAK_work

if the tty has a pending do_SAK, it is queued here

port

persistent storage for this device (i.e. struct tty_port)

Description

All of the state associated with a tty while the tty is open. Persistent storage for tty devices is referenced here as port and is documented in struct tty_port.