diff options
author | Paul Fulghum <paulkf@microgate.com> | 2006-08-27 03:36:58 +0200 |
---|---|---|
committer | Adrian Bunk <bunk@stusta.de> | 2006-08-27 03:36:58 +0200 |
commit | 9d0d1f832451c283fb93d3300531ae7b8f7b3c37 (patch) | |
tree | ed6f1611e91125f4b14bb50f95945024dee061ba | |
parent | 189abe08c84ab16197c29683d40df3c4917bd475 (diff) |
tty serialize flush_to_ldisc
Serialize processing of tty buffers in flush_to_ldisc
to fix (very rare) corruption of tty buffer free list
on SMP systems.
Signed-off-by: Paul Fulghum <paulkf@microgate.com>
Acked-by: Alan Cox <alan@redhat.com>
Signed-off-by: Adrian Bunk <bunk@stusta.de>
-rw-r--r-- | drivers/char/tty_io.c | 14 |
1 files changed, 9 insertions, 5 deletions
diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c index edaee70b2e6..34d31263d33 100644 --- a/drivers/char/tty_io.c +++ b/drivers/char/tty_io.c @@ -2759,7 +2759,7 @@ static void flush_to_ldisc(void *private_) struct tty_struct *tty = (struct tty_struct *) private_; unsigned long flags; struct tty_ldisc *disc; - struct tty_buffer *tbuf; + struct tty_buffer *tbuf, *head; int count; char *char_buf; unsigned char *flag_buf; @@ -2776,7 +2776,9 @@ static void flush_to_ldisc(void *private_) goto out; } spin_lock_irqsave(&tty->buf.lock, flags); - while((tbuf = tty->buf.head) != NULL) { + head = tty->buf.head; + tty->buf.head = NULL; + while((tbuf = head) != NULL) { while ((count = tbuf->commit - tbuf->read) != 0) { char_buf = tbuf->char_buf_ptr + tbuf->read; flag_buf = tbuf->flag_buf_ptr + tbuf->read; @@ -2785,10 +2787,12 @@ static void flush_to_ldisc(void *private_) disc->receive_buf(tty, char_buf, flag_buf, count); spin_lock_irqsave(&tty->buf.lock, flags); } - if (tbuf->active) + if (tbuf->active) { + tty->buf.head = head; break; - tty->buf.head = tbuf->next; - if (tty->buf.head == NULL) + } + head = tbuf->next; + if (head == NULL) tty->buf.tail = NULL; tty_buffer_free(tty, tbuf); } |