Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 364218
b: refs/heads/master
c: 70bc126
h: refs/heads/master
v: v3
  • Loading branch information
Peter Hurley authored and Greg Kroah-Hartman committed Mar 18, 2013
1 parent 0897ebf commit 33c628f
Show file tree
Hide file tree
Showing 3 changed files with 83 additions and 1 deletion.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: c828f679eed393d6925a2b44a4c3fb80a8d657cb
refs/heads/master: 70bc126471af30bb115e635512dcf6d86fe6e29a
64 changes: 64 additions & 0 deletions trunk/drivers/tty/tty_ioctl.c
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,7 @@ void tty_throttle(struct tty_struct *tty)
if (!test_and_set_bit(TTY_THROTTLED, &tty->flags) &&
tty->ops->throttle)
tty->ops->throttle(tty);
tty->flow_change = 0;
mutex_unlock(&tty->termios_mutex);
}
EXPORT_SYMBOL(tty_throttle);
Expand All @@ -129,10 +130,73 @@ void tty_unthrottle(struct tty_struct *tty)
if (test_and_clear_bit(TTY_THROTTLED, &tty->flags) &&
tty->ops->unthrottle)
tty->ops->unthrottle(tty);
tty->flow_change = 0;
mutex_unlock(&tty->termios_mutex);
}
EXPORT_SYMBOL(tty_unthrottle);

/**
* tty_throttle_safe - flow control
* @tty: terminal
*
* Similar to tty_throttle() but will only attempt throttle
* if tty->flow_change is TTY_THROTTLE_SAFE. Prevents an accidental
* throttle due to race conditions when throttling is conditional
* on factors evaluated prior to throttling.
*
* Returns 0 if tty is throttled (or was already throttled)
*/

int tty_throttle_safe(struct tty_struct *tty)
{
int ret = 0;

mutex_lock(&tty->termios_mutex);
if (!test_bit(TTY_THROTTLED, &tty->flags)) {
if (tty->flow_change != TTY_THROTTLE_SAFE)
ret = 1;
else {
__set_bit(TTY_THROTTLED, &tty->flags);
if (tty->ops->throttle)
tty->ops->throttle(tty);
}
}
mutex_unlock(&tty->termios_mutex);

return ret;
}

/**
* tty_unthrottle_safe - flow control
* @tty: terminal
*
* Similar to tty_unthrottle() but will only attempt unthrottle
* if tty->flow_change is TTY_UNTHROTTLE_SAFE. Prevents an accidental
* unthrottle due to race conditions when unthrottling is conditional
* on factors evaluated prior to unthrottling.
*
* Returns 0 if tty is unthrottled (or was already unthrottled)
*/

int tty_unthrottle_safe(struct tty_struct *tty)
{
int ret = 0;

mutex_lock(&tty->termios_mutex);
if (test_bit(TTY_THROTTLED, &tty->flags)) {
if (tty->flow_change != TTY_UNTHROTTLE_SAFE)
ret = 1;
else {
__clear_bit(TTY_THROTTLED, &tty->flags);
if (tty->ops->unthrottle)
tty->ops->unthrottle(tty);
}
}
mutex_unlock(&tty->termios_mutex);

return ret;
}

/**
* tty_wait_until_sent - wait for I/O to finish
* @tty: tty we are waiting for
Expand Down
18 changes: 18 additions & 0 deletions trunk/include/linux/tty.h
Original file line number Diff line number Diff line change
Expand Up @@ -258,6 +258,7 @@ struct tty_struct {
unsigned char warned:1;
unsigned char ctrl_status; /* ctrl_lock */
unsigned int receive_room; /* Bytes free for queue */
int flow_change;

struct tty_struct *link;
struct fasync_struct *fasync;
Expand Down Expand Up @@ -318,6 +319,21 @@ struct tty_file_private {

#define TTY_WRITE_FLUSH(tty) tty_write_flush((tty))

/* Values for tty->flow_change */
#define TTY_THROTTLE_SAFE 1
#define TTY_UNTHROTTLE_SAFE 2

static inline void __tty_set_flow_change(struct tty_struct *tty, int val)
{
tty->flow_change = val;
}

static inline void tty_set_flow_change(struct tty_struct *tty, int val)
{
tty->flow_change = val;
smp_mb();
}

#ifdef CONFIG_TTY
extern void console_init(void);
extern void tty_kref_put(struct tty_struct *tty);
Expand Down Expand Up @@ -400,6 +416,8 @@ extern int tty_write_room(struct tty_struct *tty);
extern void tty_driver_flush_buffer(struct tty_struct *tty);
extern void tty_throttle(struct tty_struct *tty);
extern void tty_unthrottle(struct tty_struct *tty);
extern int tty_throttle_safe(struct tty_struct *tty);
extern int tty_unthrottle_safe(struct tty_struct *tty);
extern int tty_do_resize(struct tty_struct *tty, struct winsize *ws);
extern void tty_driver_remove_tty(struct tty_driver *driver,
struct tty_struct *tty);
Expand Down

0 comments on commit 33c628f

Please sign in to comment.