mirror of
https://github.com/FEX-Emu/linux.git
synced 2025-01-17 23:15:52 +00:00
n_tty: Encapsulate minimum_to_wake within N_TTY
minimum_to_wake is unique to N_TTY processing, and belongs in per-ldisc data. Add the ldisc method, ldisc_ops::fasync(), to notify line disciplines when signal-driven I/O is enabled or disabled. When enabled for N_TTY (by fcntl(F_SETFL, O_ASYNC)), blocking reader/polls will be woken for any readable input. When disabled, blocking reader/polls are not woken until the read buffer is full. Canonical mode (L_ICANON(tty), n_tty_data::icanon) is not affected by the minimum_to_wake setting. Signed-off-by: Peter Hurley <peter@hurleysoftware.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
parent
a630fbfbb1
commit
f6c8dbe6e5
@ -89,6 +89,7 @@ struct n_tty_data {
|
||||
int read_head;
|
||||
int read_tail;
|
||||
int read_cnt;
|
||||
int minimum_to_wake;
|
||||
|
||||
unsigned char *echo_buf;
|
||||
unsigned int echo_pos;
|
||||
@ -1455,7 +1456,7 @@ static void n_tty_receive_buf(struct tty_struct *tty, const unsigned char *cp,
|
||||
|
||||
n_tty_set_room(tty);
|
||||
|
||||
if ((!ldata->icanon && (ldata->read_cnt >= tty->minimum_to_wake)) ||
|
||||
if ((!ldata->icanon && (ldata->read_cnt >= ldata->minimum_to_wake)) ||
|
||||
L_EXTPROC(tty)) {
|
||||
kill_fasync(&tty->fasync, SIGIO, POLL_IN);
|
||||
if (waitqueue_active(&tty->read_wait))
|
||||
@ -1636,7 +1637,7 @@ static int n_tty_open(struct tty_struct *tty)
|
||||
tty->disc_data = ldata;
|
||||
reset_buffer_flags(tty->disc_data);
|
||||
ldata->column = 0;
|
||||
tty->minimum_to_wake = 1;
|
||||
ldata->minimum_to_wake = 1;
|
||||
tty->closing = 0;
|
||||
/* indicate buffer work may resume */
|
||||
clear_bit(TTY_LDISC_HALTED, &tty->flags);
|
||||
@ -1804,17 +1805,17 @@ do_it_again:
|
||||
minimum = MIN_CHAR(tty);
|
||||
if (minimum) {
|
||||
if (time)
|
||||
tty->minimum_to_wake = 1;
|
||||
ldata->minimum_to_wake = 1;
|
||||
else if (!waitqueue_active(&tty->read_wait) ||
|
||||
(tty->minimum_to_wake > minimum))
|
||||
tty->minimum_to_wake = minimum;
|
||||
(ldata->minimum_to_wake > minimum))
|
||||
ldata->minimum_to_wake = minimum;
|
||||
} else {
|
||||
timeout = 0;
|
||||
if (time) {
|
||||
timeout = time;
|
||||
time = 0;
|
||||
}
|
||||
tty->minimum_to_wake = minimum = 1;
|
||||
ldata->minimum_to_wake = minimum = 1;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1854,9 +1855,9 @@ do_it_again:
|
||||
TASK_RUNNING. */
|
||||
set_current_state(TASK_INTERRUPTIBLE);
|
||||
|
||||
if (((minimum - (b - buf)) < tty->minimum_to_wake) &&
|
||||
if (((minimum - (b - buf)) < ldata->minimum_to_wake) &&
|
||||
((minimum - (b - buf)) >= 1))
|
||||
tty->minimum_to_wake = (minimum - (b - buf));
|
||||
ldata->minimum_to_wake = (minimum - (b - buf));
|
||||
|
||||
if (!input_available_p(tty, 0)) {
|
||||
if (test_bit(TTY_OTHER_CLOSED, &tty->flags)) {
|
||||
@ -1973,7 +1974,7 @@ do_it_again:
|
||||
remove_wait_queue(&tty->read_wait, &wait);
|
||||
|
||||
if (!waitqueue_active(&tty->read_wait))
|
||||
tty->minimum_to_wake = minimum;
|
||||
ldata->minimum_to_wake = minimum;
|
||||
|
||||
__set_current_state(TASK_RUNNING);
|
||||
size = b - buf;
|
||||
@ -2105,6 +2106,7 @@ break_out:
|
||||
static unsigned int n_tty_poll(struct tty_struct *tty, struct file *file,
|
||||
poll_table *wait)
|
||||
{
|
||||
struct n_tty_data *ldata = tty->disc_data;
|
||||
unsigned int mask = 0;
|
||||
|
||||
poll_wait(file, &tty->read_wait, wait);
|
||||
@ -2119,9 +2121,9 @@ static unsigned int n_tty_poll(struct tty_struct *tty, struct file *file,
|
||||
mask |= POLLHUP;
|
||||
if (!(mask & (POLLHUP | POLLIN | POLLRDNORM))) {
|
||||
if (MIN_CHAR(tty) && !TIME_CHAR(tty))
|
||||
tty->minimum_to_wake = MIN_CHAR(tty);
|
||||
ldata->minimum_to_wake = MIN_CHAR(tty);
|
||||
else
|
||||
tty->minimum_to_wake = 1;
|
||||
ldata->minimum_to_wake = 1;
|
||||
}
|
||||
if (tty->ops->write && !tty_is_writelocked(tty) &&
|
||||
tty_chars_in_buffer(tty) < WAKEUP_CHARS &&
|
||||
@ -2169,6 +2171,18 @@ static int n_tty_ioctl(struct tty_struct *tty, struct file *file,
|
||||
}
|
||||
}
|
||||
|
||||
static void n_tty_fasync(struct tty_struct *tty, int on)
|
||||
{
|
||||
struct n_tty_data *ldata = tty->disc_data;
|
||||
|
||||
if (!waitqueue_active(&tty->read_wait)) {
|
||||
if (on)
|
||||
ldata->minimum_to_wake = 1;
|
||||
else if (!tty->fasync)
|
||||
ldata->minimum_to_wake = N_TTY_BUF_SIZE;
|
||||
}
|
||||
}
|
||||
|
||||
struct tty_ldisc_ops tty_ldisc_N_TTY = {
|
||||
.magic = TTY_LDISC_MAGIC,
|
||||
.name = "n_tty",
|
||||
@ -2182,7 +2196,8 @@ struct tty_ldisc_ops tty_ldisc_N_TTY = {
|
||||
.set_termios = n_tty_set_termios,
|
||||
.poll = n_tty_poll,
|
||||
.receive_buf = n_tty_receive_buf,
|
||||
.write_wakeup = n_tty_write_wakeup
|
||||
.write_wakeup = n_tty_write_wakeup,
|
||||
.fasync = n_tty_fasync,
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -2138,6 +2138,7 @@ static unsigned int tty_poll(struct file *filp, poll_table *wait)
|
||||
static int __tty_fasync(int fd, struct file *filp, int on)
|
||||
{
|
||||
struct tty_struct *tty = file_tty(filp);
|
||||
struct tty_ldisc *ldisc;
|
||||
unsigned long flags;
|
||||
int retval = 0;
|
||||
|
||||
@ -2148,11 +2149,17 @@ static int __tty_fasync(int fd, struct file *filp, int on)
|
||||
if (retval <= 0)
|
||||
goto out;
|
||||
|
||||
ldisc = tty_ldisc_ref(tty);
|
||||
if (ldisc) {
|
||||
if (ldisc->ops->fasync)
|
||||
ldisc->ops->fasync(tty, on);
|
||||
tty_ldisc_deref(ldisc);
|
||||
}
|
||||
|
||||
if (on) {
|
||||
enum pid_type type;
|
||||
struct pid *pid;
|
||||
if (!waitqueue_active(&tty->read_wait))
|
||||
tty->minimum_to_wake = 1;
|
||||
|
||||
spin_lock_irqsave(&tty->ctrl_lock, flags);
|
||||
if (tty->pgrp) {
|
||||
pid = tty->pgrp;
|
||||
@ -2165,13 +2172,7 @@ static int __tty_fasync(int fd, struct file *filp, int on)
|
||||
spin_unlock_irqrestore(&tty->ctrl_lock, flags);
|
||||
retval = __f_setown(filp, pid, type, 0);
|
||||
put_pid(pid);
|
||||
if (retval)
|
||||
goto out;
|
||||
} else {
|
||||
if (!tty->fasync && !waitqueue_active(&tty->read_wait))
|
||||
tty->minimum_to_wake = N_TTY_BUF_SIZE;
|
||||
}
|
||||
retval = 0;
|
||||
out:
|
||||
return retval;
|
||||
}
|
||||
|
@ -272,7 +272,6 @@ struct tty_struct {
|
||||
#define N_TTY_BUF_SIZE 4096
|
||||
|
||||
unsigned char closing:1;
|
||||
unsigned short minimum_to_wake;
|
||||
unsigned char *write_buf;
|
||||
int write_cnt;
|
||||
/* If the tty has a pending do_SAK, queue it here - akpm */
|
||||
|
@ -100,6 +100,11 @@
|
||||
* seek to perform this action quickly but should wait until
|
||||
* any pending driver I/O is completed.
|
||||
*
|
||||
* void (*fasync)(struct tty_struct *, int on)
|
||||
*
|
||||
* Notify line discipline when signal-driven I/O is enabled or
|
||||
* disabled.
|
||||
*
|
||||
* void (*dcd_change)(struct tty_struct *tty, unsigned int status)
|
||||
*
|
||||
* Tells the discipline that the DCD pin has changed its status.
|
||||
@ -189,6 +194,7 @@ struct tty_ldisc_ops {
|
||||
char *fp, int count);
|
||||
void (*write_wakeup)(struct tty_struct *);
|
||||
void (*dcd_change)(struct tty_struct *, unsigned int);
|
||||
void (*fasync)(struct tty_struct *tty, int on);
|
||||
|
||||
struct module *owner;
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user