TTY Internals

Kopen

These functions serve for opening a TTY from the kernelspace:

voidtty_kclose(structtty_struct*tty)

closes tty opened by tty_kopen

Parameters

structtty_struct*tty

tty device

Description

Performs the final steps to release and free a tty device. It is the same astty_release_struct() except that it also resetsTTY_PORT_KOPENED flag ontty->port.

structtty_struct*tty_kopen_exclusive(dev_tdevice)

open a tty device for kernel

Parameters

dev_tdevice

dev_t of device to open

Description

Opens tty exclusively for kernel. Performs the driver lookup, makes sureit’s not already opened and performs the first-time tty initialization.

Claims the globaltty_mutex to serialize:
  • concurrent first-time tty initialization

  • concurrent tty driver removal w/ lookup

  • concurrent tty removal from driver table

Return

the locked initializedtty_struct

structtty_struct*tty_kopen_shared(dev_tdevice)

open a tty device for shared in-kernel use

Parameters

dev_tdevice

dev_t of device to open

Description

Opens an already existing tty for in-kernel use. Compared totty_kopen_exclusive() above it doesn’t ensure to be the only user.

Locking: identical totty_kopen() above.


Exported Internal Functions

inttty_dev_name_to_number(constchar*name,dev_t*number)

return dev_t for device name

Parameters

constchar*name

user space name of device under /dev

dev_t*number

pointer to dev_t that this function will populate

Description

This function converts device names like ttyS0 or ttyUSB1 into dev_t like(4, 64) or (188, 1). If no corresponding driver is registered then thefunction returns -ENODEV.

Locking: this acquires tty_mutex to protect the tty_drivers list from

being modified while we are traversing it, and makes sure torelease it before exiting.

voidtty_release_struct(structtty_struct*tty,intidx)

release a tty struct

Parameters

structtty_struct*tty

tty device

intidx

index of the tty

Description

Performs the final steps to release and free a tty device. It is roughly thereverse oftty_init_dev().

inttty_get_icount(structtty_struct*tty,structserial_icounter_struct*icount)

get tty statistics

Parameters

structtty_struct*tty

tty device

structserial_icounter_struct*icount

output parameter

Description

Gets a copy of thetty’s icount statistics.

Locking: none (up to the driver)


Internal Functions

voidfree_tty_struct(structtty_struct*tty)

free a disused tty

Parameters

structtty_struct*tty

ttystructto free

Description

Free the write buffers, tty queue and tty memory itself.

Locking: none. Must be called after tty is definitely unused

voidtty_free_file(structfile*file)

free file->private_data

Parameters

structfile*file

to free private_data of

Description

This shall be used only for fail path handling when tty_add_file was notcalled yet.

structtty_driver*get_tty_driver(dev_tdevice,int*index)

find device of a tty

Parameters

dev_tdevice

device identifier

int*index

returns the index of the tty

Description

This routine returns a tty driver structure, given a device number and alsopasses back the index number.

Locking: caller must hold tty_mutex

structfile*tty_release_redirect(structtty_struct*tty)

Release a redirect on a pty if present

Parameters

structtty_struct*tty

tty device

Description

This is available to the pty code so if the master closes, if the slave is aredirect it can release the redirect.

void__tty_hangup(structtty_struct*tty,intexit_session)

actual handler for hangup events

Parameters

structtty_struct*tty

tty device

intexit_session

if non-zero, signal all foreground group processes

Description

This can be called by a “kworker” kernel thread. That is process synchronousbut doesn’t hold any locks, so we need to make sure we have the appropriatelocks for what we’re doing.

The hangup event clears any pending redirections onto the hung up device. Itensures future writes will error and it does the needed line disciplinehangup and signal delivery. The tty object itself remains intact.

Locking:
  • BTM

  • redirect lock for undoing redirection

  • file list lock for manipulating list of ttys

  • tty_ldiscs_lock from called functions

  • termios_rwsem resetting termios data

  • tasklist_lock to walk task list for hangup event

  • ->siglock to protect ->signal/->sighand

voidtty_vhangup_self(void)

process vhangup for own ctty

Parameters

void

no arguments

Description

Perform a vhangup on the current controlling tty

voidtty_vhangup_session(structtty_struct*tty)

hangup session leader exit

Parameters

structtty_struct*tty

tty to hangup

Description

The session leader is exiting and hanging up its controlling terminal.Every process in the foreground process group is signalledSIGHUP.

We do this synchronously so that when the syscall returns the process iscomplete. That guarantee is necessary for security reasons.

ssize_ttty_read(structkiocb*iocb,structiov_iter*to)

read method for tty device files

Parameters

structkiocb*iocb

kernel I/O control block

structiov_iter*to

destination for the data read

Description

Perform the read system call function on this terminal device. Checksfor hung up devices before calling the line discipline method.

Locking:

Locks the line discipline internally while needed. Multiple read callsmay be outstanding in parallel.

voidtty_write_message(structtty_struct*tty,char*msg)

write a message to a certain tty, not just the console.

Parameters

structtty_struct*tty

the destination tty_struct

char*msg

the message to write

Description

This is used for messages that need to be redirected to a specific tty. Wedon’t put it into the syslog queue right now maybe in the future if reallyneeded.

We must still hold the BTM and test the CLOSING flag for the moment.

This function is DEPRECATED, do not use in new code.

ssize_ttty_write(structkiocb*iocb,structiov_iter*from)

write method for tty device file

Parameters

structkiocb*iocb

kernel I/O control block

structiov_iter*from

iov_iter with data to write

Description

Write data to a tty device via the line discipline.

Locking:

Locks the line discipline as requiredWrites to the tty driver are serialized by the atomic_write_lockand are then processed in chunks to the device. The linediscipline write method will not be invoked in parallel foreach device.

inttty_send_xchar(structtty_struct*tty,u8ch)

send priority character

Parameters

structtty_struct*tty

the tty to send to

u8ch

xchar to send

Description

Send a high priority character to the tty even if stopped.

Locking: none for xchar method, write ordering for write method.

voidpty_line_name(structtty_driver*driver,intindex,char*p)

generate name for a pty

Parameters

structtty_driver*driver

the tty driver in use

intindex

the minor number

char*p

output buffer of at least 6 bytes

Description

Generate a name from adriver reference and write it to the output bufferp.

Locking: None

ssize_ttty_line_name(structtty_driver*driver,intindex,char*p)

generate name for a tty

Parameters

structtty_driver*driver

the tty driver in use

intindex

the minor number

char*p

output buffer of at least 7 bytes

Description

Generate a name from adriver reference and write it to the output bufferp.

Locking: None

structtty_struct*tty_driver_lookup_tty(structtty_driver*driver,structfile*file,intidx)

find an existing tty, if any

Parameters

structtty_driver*driver

the driver for the tty

structfile*file

file object

intidx

the minor number

Return

the tty, if found. If not found, returnNULL orERR_PTR() if thedriverlookup() method returns an error.

Description

Locking: tty_mutex must be held. If the tty is found, bump the tty kref.

inttty_driver_install_tty(structtty_driver*driver,structtty_struct*tty)

install a tty entry in the driver

Parameters

structtty_driver*driver

the driver for the tty

structtty_struct*tty

the tty

Description

Install a tty object into the driver tables. Thetty->index field will beset by the time this is called. This method is responsible for ensuring anyneed additional structures are allocated and configured.

Locking: tty_mutex for now

voidtty_driver_remove_tty(structtty_driver*driver,structtty_struct*tty)

remove a tty from the driver tables

Parameters

structtty_driver*driver

the driver for the tty

structtty_struct*tty

tty to remove

Description

Remove a tty object from the driver tables. The tty->index field will be setby the time this is called.

Locking: tty_mutex for now

inttty_reopen(structtty_struct*tty)

fast re-open of an open tty

Parameters

structtty_struct*tty

the tty to open

Description

Re-opens on master ptys are not allowed and return -EIO.

Locking: Caller must hold tty_lock

Return

0 on success, -errno on error.

structtty_struct*tty_init_dev(structtty_driver*driver,intidx)

initialise a tty device

Parameters

structtty_driver*driver

tty driver we are opening a device on

intidx

device index

Description

Prepare a tty device. This may not be a “new” clean device but could also bean active device. The pty drivers require special handling because of this.

Locking:

The function is called under the tty_mutex, which protects us from thettystructor driver itself going away.

On exit the tty device has the line discipline attached and a referencecount of 1. If a pair was created for pty/tty use and the other was a ptymaster then it too has a reference count of 1.

WSH 06/09/97: Rewritten to remove races and properly clean up after a failedopen. The new code protects the open with a mutex, so it’s really quitestraightforward. The mutex locking can probably be relaxed for the (mostcommon) case of reopening a tty.

Return

new tty structure

voidtty_flush_works(structtty_struct*tty)

flush all works of a tty/pty pair

Parameters

structtty_struct*tty

tty device to flush works for (or either end of a pty pair)

Description

Sync flush all works belonging totty (and the ‘other’ tty).

voidrelease_one_tty(structwork_struct*work)

release tty structure memory

Parameters

structwork_struct*work

work of tty we are obliterating

Description

Releases memory associated with a tty structure, and clears out thedriver table slots. This function is called when a device is no longerin use. It also gets called when setup of a device fails.

Locking:

takes the file list lock internally when working on the list of ttysthat the driver keeps.

This method gets called from a work queue so that the driver privatecleanup ops can sleep (needed for USB at least)

voidrelease_tty(structtty_struct*tty,intidx)

release tty structure memory

Parameters

structtty_struct*tty

tty device release

intidx

index of the tty device release

Description

Release bothtty and a possible linked partner (think pty pair),and decrement the refcount of the backing module.

Locking:

tty_mutextakes the file list lock internally when working on the list of ttysthat the driver keeps.

inttty_release_checks(structtty_struct*tty,intidx)

check a tty before real release

Parameters

structtty_struct*tty

tty to check

intidx

index of the tty

Description

Performs some paranoid checking before true release of thetty. This is ano-op unlessTTY_PARANOIA_CHECK is defined.

inttty_release(structinode*inode,structfile*filp)

vfs callback for close

Parameters

structinode*inode

inode of tty

structfile*filp

file pointer for handle to tty

Description

Called the last time each file handle is closed that references this tty.There may however be several such references.

Locking:

Takes BKL. Seetty_release_dev().

Even releasing the tty structures is a tricky business. We have to be verycareful that the structures are all released at the same time, as interruptsmight otherwise get the wrong pointers.

WSH 09/09/97: rewritten to avoid some nasty race conditions that couldlead to double frees or releasing memory still in use.

structtty_struct*tty_open_current_tty(dev_tdevice,structfile*filp)

get locked tty of current task

Parameters

dev_tdevice

device number

structfile*filp

file pointer to tty

Return

locked tty of the current task iffdevice is /dev/tty

Description

Performs a re-open of the current task’s controlling tty.

We cannot return driver and index like for the other nodes because devptswill not work then. It expects inodes to be from devpts FS.

structtty_driver*tty_lookup_driver(dev_tdevice,structfile*filp,int*index)

lookup a tty driver for a given device file

Parameters

dev_tdevice

device number

structfile*filp

file pointer to tty

int*index

index for the device in thereturn driver

Description

If returned value is not erroneous, the caller is responsible to decrementthe refcount bytty_driver_kref_put().

Locking:tty_mutex protectsget_tty_driver()

Return

driver for this inode (with increased refcount)

structtty_struct*tty_open_by_driver(dev_tdevice,structfile*filp)

open a tty device

Parameters

dev_tdevice

dev_t of device to open

structfile*filp

file pointer to tty

Description

Performs the driver lookup, checks for a reopen, or otherwise performs thefirst-time tty initialization.

Claims the global tty_mutex to serialize:
  • concurrent first-time tty initialization

  • concurrent tty driver removal w/ lookup

  • concurrent tty removal from driver table

Return

the locked initialized or re-openedtty_struct

inttty_open(structinode*inode,structfile*filp)

open a tty device

Parameters

structinode*inode

inode of device file

structfile*filp

file pointer to tty

Description

tty_open() andtty_release() keep up the tty count that contains the numberof opens done on a tty. We cannot use the inode-count, as different inodesmight point to the same tty.

Open-counting is needed for pty masters, as well as for keeping track ofserial lines: DTR is dropped when the last close happens.(This is not done solely through tty->count, now. - Ted 1/27/92)

The termios state of a pty is reset on the first open so that settings don’tpersist across reuse.

Locking:

Note

the tty_unlock/lock cases without a ref are only safe due totty_mutex

__poll_ttty_poll(structfile*filp,poll_table*wait)

check tty status

Parameters

structfile*filp

file being polled

poll_table*wait

poll wait structures to update

Description

Call the line discipline polling method to obtain the poll status of thedevice.

Locking: locks called line discipline but ldisc poll method may bere-entered freely by other callers.

inttiocsti(structtty_struct*tty,u8__user*p)

fake input character

Parameters

structtty_struct*tty

tty to fake input into

u8__user*p

pointer to character

Description

Fake input to a tty device. Does the necessary locking and input management.

FIXME: does not honour flow control ??

Locking:
  • Called functions take tty_ldiscs_lock

  • current->signal->tty check is safe without locks

inttiocgwinsz(structtty_struct*tty,structwinsize__user*arg)

implement window query ioctl

Parameters

structtty_struct*tty

tty

structwinsize__user*arg

user buffer for result

Description

Copies the kernel idea of the window size into the user buffer.

Locking:tty->winsize_mutex is taken to ensure the winsize data isconsistent.

inttiocswinsz(structtty_struct*tty,structwinsize__user*arg)

implement window size set ioctl

Parameters

structtty_struct*tty

tty side of tty

structwinsize__user*arg

user buffer for result

Description

Copies the user idea of the window size to the kernel. Traditionally this isjust advisory information but for the Linux console it actually has driverlevel meaning and triggers a VC resize.

Locking:

Driver dependent. The default do_resize method takes the tty termiosmutex and ctrl.lock. The console takes its own lock then calls into thedefault method.

inttioccons(structfile*file)

allow admin to move logical console

Parameters

structfile*file

the file to become console

Description

Allow the administrator to move the redirected console device.

Locking: uses redirect_lock to guard the redirect information

inttiocsetd(structtty_struct*tty,int__user*p)

set line discipline

Parameters

structtty_struct*tty

tty device

int__user*p

pointer to user data

Description

Set the line discipline according to user request.

Locking: seetty_set_ldisc(), this function is just a helper

inttiocgetd(structtty_struct*tty,int__user*p)

get line discipline

Parameters

structtty_struct*tty

tty device

int__user*p

pointer to user data

Description

Retrieves the line discipline id directly from the ldisc.

Locking: waits for ldisc reference (in case the line discipline is changingor thetty is being hungup)

intsend_break(structtty_struct*tty,unsignedintduration)

performed time break

Parameters

structtty_struct*tty

device to break on

unsignedintduration

timeout in mS

Description

Perform a timed break on hardware that lacks its own driver level timedbreak functionality.

Locking:

tty->atomic_write_lock serializes

inttty_tiocmget(structtty_struct*tty,int__user*p)

get modem status

Parameters

structtty_struct*tty

tty device

int__user*p

pointer to result

Description

Obtain the modem status bits from the tty driver if the feature issupported. Return -ENOTTY if it is not available.

Locking: none (up to the driver)

inttty_tiocmset(structtty_struct*tty,unsignedintcmd,unsigned__user*p)

set modem status

Parameters

structtty_struct*tty

tty device

unsignedintcmd

command - clear bits, set bits or set all

unsigned__user*p

pointer to desired bits

Description

Set the modem status bits from the tty driver if the featureis supported. Return -ENOTTY if it is not available.

Locking: none (up to the driver)

structtty_struct*alloc_tty_struct(structtty_driver*driver,intidx)

allocate a new tty

Parameters

structtty_driver*driver

driver which will handle the returned tty

intidx

minor of the tty

Description

This subroutine allocates and initializes a tty structure.

Locking: none -tty in question is not exposed at this point