aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKeir Fraser <keir.fraser@citrix.com>2007-12-08 15:46:04 +0000
committerKeir Fraser <keir.fraser@citrix.com>2007-12-08 15:46:04 +0000
commit0d6aee7d684194be380fe1646f971dd87c432501 (patch)
treee1d89efd224f8bf2d9471ae7f84ef15766bea42e
parente028ead54447be95f5de9680a85f38fef3d70d79 (diff)
downloadxen-0d6aee7d684194be380fe1646f971dd87c432501.tar.gz
xen-0d6aee7d684194be380fe1646f971dd87c432501.tar.bz2
xen-0d6aee7d684194be380fe1646f971dd87c432501.zip
qemu 16550 uart: Fast-drop bursts of transmitted characters to avoid
stalling due to a disconnected pipe or pty. Signed-off-by: Trolle Selander <trolle.selander@gmail.com>
-rw-r--r--tools/ioemu/hw/serial.c18
1 files changed, 12 insertions, 6 deletions
diff --git a/tools/ioemu/hw/serial.c b/tools/ioemu/hw/serial.c
index 952f5b955c..af6aa64ee3 100644
--- a/tools/ioemu/hw/serial.c
+++ b/tools/ioemu/hw/serial.c
@@ -359,7 +359,7 @@ static void serial_xmit(void *opaque) {
SerialState *s = opaque;
uint64_t new_xmit_ts = qemu_get_clock(vm_clock);
- if ( s->tsr_retry == 0 ) {
+ if ( s->tsr_retry <= 0 ) {
if (s->fcr & UART_FCR_FE) {
s->tsr = fifo_get(s,XMIT_FIFO);
if ( !s->xmit_fifo.count )
@@ -371,16 +371,22 @@ static void serial_xmit(void *opaque) {
}
if ( qemu_chr_write(s->chr, &s->tsr, 1) != 1 ) {
- s->tsr_retry++;
- if ( s->tsr_retry <= MAX_XMIT_RETRY ) {
+ if ( ( s->tsr_retry > 0 ) && ( s->tsr_retry <= MAX_XMIT_RETRY ) ) {
+ s->tsr_retry++;
qemu_mod_timer(s->transmit_timer, new_xmit_ts + s->char_transmit_time );
return;
+ } else if ( s->poll_msl < 0 ) {
+ /* If we exceed MAX_XMIT_RETRY and the backend is not a real serial port, then
+ drop any further failed writes instantly, until we get one that goes through.
+ This is to prevent guests that log to unconnected pipes or pty's from stalling. */
+ s->tsr_retry = -1;
}
}
-
- s->tsr_retry = 0;
- s->last_xmit_ts = qemu_get_clock(vm_clock);
+ else {
+ s->tsr_retry = 0;
+ }
+ s->last_xmit_ts = qemu_get_clock(vm_clock);
if ( !(s->lsr & UART_LSR_THRE) )
qemu_mod_timer(s->transmit_timer, s->last_xmit_ts + s->char_transmit_time );