diff options
| author | James Morris <jmorris@namei.org> | 2010-11-29 08:27:07 +1100 |
|---|---|---|
| committer | James Morris <jmorris@namei.org> | 2010-11-29 08:27:07 +1100 |
| commit | 1d6d75684d869406e5bb2ac5d3ed9454f52d0cab (patch) | |
| tree | afb229254bed6415407b7b7d4641f9f792109966 /drivers/tty/tty_buffer.c | |
| parent | 074e61ec3751da9ab88ee66d3818574556c03489 (diff) | |
| parent | 0f639a3c5ca63dd76ee07de9b02ebf0178ce9a17 (diff) | |
| download | olio-linux-3.10-1d6d75684d869406e5bb2ac5d3ed9454f52d0cab.tar.xz olio-linux-3.10-1d6d75684d869406e5bb2ac5d3ed9454f52d0cab.zip | |
Merge branch 'master' into next
Diffstat (limited to 'drivers/tty/tty_buffer.c')
| -rw-r--r-- | drivers/tty/tty_buffer.c | 14 |
1 files changed, 12 insertions, 2 deletions
diff --git a/drivers/tty/tty_buffer.c b/drivers/tty/tty_buffer.c index cc1e9850d65..d8210ca0072 100644 --- a/drivers/tty/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; } |