In preparation for threaded execution, make 8250 code thread safe by introducing a per-device mutex. Cc: Asias He <asias.hejun@xxxxxxxxx> Cc: Cyrill Gorcunov <gorcunov@xxxxxxxxx> Cc: Ingo Molnar <mingo@xxxxxxx> Signed-off-by: Pekka Enberg <penberg@xxxxxxxxxx> --- tools/kvm/8250-serial.c | 57 +++++++++++++++++++++++++++++++++++++++------- tools/kvm/Makefile | 1 + 2 files changed, 49 insertions(+), 9 deletions(-) diff --git a/tools/kvm/8250-serial.c b/tools/kvm/8250-serial.c index 9f047ca..3395f85 100644 --- a/tools/kvm/8250-serial.c +++ b/tools/kvm/8250-serial.c @@ -8,8 +8,11 @@ #include <linux/serial_reg.h> +#include <pthread.h> struct serial8250_device { + pthread_mutex_t mutex; + uint16_t iobase; uint8_t irq; @@ -29,6 +32,8 @@ struct serial8250_device { static struct serial8250_device devices[] = { /* ttyS0 */ [0] = { + .mutex = PTHREAD_MUTEX_INITIALIZER, + .iobase = 0x3f8, .irq = 4, @@ -39,6 +44,8 @@ static struct serial8250_device devices[] = { }, /* ttyS1 */ [1] = { + .mutex = PTHREAD_MUTEX_INITIALIZER, + .iobase = 0x2f8, .irq = 3, @@ -46,6 +53,8 @@ static struct serial8250_device devices[] = { }, /* ttyS2 */ [2] = { + .mutex = PTHREAD_MUTEX_INITIALIZER, + .iobase = 0x3e8, .irq = 4, @@ -107,6 +116,9 @@ void serial8250__inject_interrupt(struct kvm *self) { struct serial8250_device *dev = &devices[0]; + if (pthread_mutex_lock(&dev->mutex) < 0) + die("pthread_mutex_lock"); + serial8250__receive(self, dev); if (dev->ier & UART_IER_RDI && dev->lsr & UART_LSR_DR) @@ -120,6 +132,9 @@ void serial8250__inject_interrupt(struct kvm *self) kvm__irq_line(self, dev->irq, 0); kvm__irq_line(self, dev->irq, 1); } + + if (pthread_mutex_unlock(&dev->mutex) < 0) + die("pthread_mutex_unlock"); } void serial8250__inject_sysrq(struct kvm *self) @@ -144,11 +159,15 @@ static bool serial8250_out(struct kvm *self, uint16_t port, void *data, int size { struct serial8250_device *dev; uint16_t offset; + bool ret = true; dev = find_device(port); if (!dev) return false; + if (pthread_mutex_lock(&dev->mutex) < 0) + die("pthread_mutex_lock"); + offset = port - dev->iobase; if (dev->lcr & UART_LCR_DLAB) { @@ -178,7 +197,8 @@ static bool serial8250_out(struct kvm *self, uint16_t port, void *data, int size dev->scr = ioport__read8(data); break; default: - return false; + ret = false; + goto out_unlock; } } else { switch (offset) { @@ -213,31 +233,43 @@ static bool serial8250_out(struct kvm *self, uint16_t port, void *data, int size dev->scr = ioport__read8(data); break; default: - return false; + ret = false; + goto out_unlock; } } - return true; + +out_unlock: + if (pthread_mutex_unlock(&dev->mutex) < 0) + die("pthread_mutex_unlock"); + + return ret; } static bool serial8250_in(struct kvm *self, uint16_t port, void *data, int size, uint32_t count) { struct serial8250_device *dev; uint16_t offset; + bool ret = true; dev = find_device(port); if (!dev) return false; + if (pthread_mutex_lock(&dev->mutex) < 0) + die("pthread_mutex_lock"); + offset = port - dev->iobase; if (dev->lcr & UART_LCR_DLAB) { switch (offset) { case UART_DLL: ioport__write8(data, dev->dll); - return true; + goto out_unlock; + case UART_DLM: ioport__write8(data, dev->dlm); - return true; + goto out_unlock; + default: break; } @@ -247,10 +279,12 @@ static bool serial8250_in(struct kvm *self, uint16_t port, void *data, int size, ioport__write8(data, dev->rbr); dev->lsr &= ~UART_LSR_DR; dev->iir = UART_IIR_NO_INT; - return true; + goto out_unlock; + case UART_IER: ioport__write8(data, dev->ier); - return true; + goto out_unlock; + default: break; } @@ -283,9 +317,14 @@ static bool serial8250_in(struct kvm *self, uint16_t port, void *data, int size, ioport__write8(data, dev->scr); break; default: - return false; + ret = false; + goto out_unlock; } - return true; +out_unlock: + if (pthread_mutex_unlock(&dev->mutex) < 0) + die("pthread_mutex_unlock"); + + return ret; } static struct ioport_operations serial8250_ops = { diff --git a/tools/kvm/Makefile b/tools/kvm/Makefile index 141cdec..7a2863d 100644 --- a/tools/kvm/Makefile +++ b/tools/kvm/Makefile @@ -41,6 +41,7 @@ OBJS += bios.o OBJS += bios/bios.o LIBS += -lrt +LIBS += -lpthread # Additional ARCH settings for x86 ARCH ?= $(shell echo $(uname_M) | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ \ -- 1.7.0.4 -- To unsubscribe from this list: send the line "unsubscribe kvm" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html