diff options
| author | 2011-03-18 23:38:50 -0700 | |
|---|---|---|
| committer | 2011-03-18 23:38:50 -0700 | |
| commit | 97eb3f24352ec6632c2127b35d8087d2a809a9b9 (patch) | |
| tree | 722948059bbd325bbca232269490124231df80d4 /drivers/tty/tty_buffer.c | |
| parent | Input: evdev - fix evdev_write return value on partial writes (diff) | |
| parent | Merge branch 'tsc2005' into next (diff) | |
| download | wireguard-linux-97eb3f24352ec6632c2127b35d8087d2a809a9b9.tar.xz wireguard-linux-97eb3f24352ec6632c2127b35d8087d2a809a9b9.zip | |
Merge branch 'next' into for-linus
Diffstat (limited to '')
| -rw-r--r-- | drivers/tty/tty_buffer.c (renamed from drivers/char/tty_buffer.c) | 14 |
1 files changed, 12 insertions, 2 deletions
diff --git a/drivers/char/tty_buffer.c b/drivers/tty/tty_buffer.c index cc1e9850d655..d8210ca00720 100644 --- a/drivers/char/tty_buffer.c +++ b/drivers/tty/tty_buffer.c @@ -413,7 +413,8 @@ static void flush_to_ldisc(struct work_struct *work) spin_lock_irqsave(&tty->buf.lock, flags); if (!test_and_set_bit(TTY_FLUSHING, &tty->flags)) { - struct tty_buffer *head; + struct tty_buffer *head, *tail = tty->buf.tail; + int seen_tail = 0; while ((head = tty->buf.head) != NULL) { int count; char *char_buf; @@ -423,6 +424,15 @@ static void flush_to_ldisc(struct work_struct *work) if (!count) { if (head->next == NULL) break; + /* + There's a possibility tty might get new buffer + added during the unlock window below. We could + end up spinning in here forever hogging the CPU + completely. To avoid this let's have a rest each + time we processed the tail buffer. + */ + if (tail == head) + seen_tail = 1; tty->buf.head = head->next; tty_buffer_free(tty, head); continue; @@ -432,7 +442,7 @@ static void flush_to_ldisc(struct work_struct *work) line discipline as we want to empty the queue */ if (test_bit(TTY_FLUSHPENDING, &tty->flags)) break; - if (!tty->receive_room) { + if (!tty->receive_room || seen_tail) { schedule_delayed_work(&tty->buf.work, 1); break; } |
