diff mbox

kvm tools: Make 8250 code thread-safe

Message ID 1302344550-31118-1-git-send-email-penberg@kernel.org (mailing list archive)
State New, archived
Headers show

Commit Message

Pekka Enberg April 9, 2011, 10:22 a.m. UTC
In preparation for threaded execution, make 8250 code thread safe by
introducing a per-device mutex.

Cc: Asias He <asias.hejun@gmail.com>
Cc: Cyrill Gorcunov <gorcunov@gmail.com>
Cc: Ingo Molnar <mingo@elte.hu>
Signed-off-by: Pekka Enberg <penberg@kernel.org>
---
 tools/kvm/8250-serial.c |   57 +++++++++++++++++++++++++++++++++++++++-------
 tools/kvm/Makefile      |    1 +
 2 files changed, 49 insertions(+), 9 deletions(-)
diff mbox

Patch

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/ \