[PATCH] kvm tools: Make 8250 code thread-safe

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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


[Index of Archives]     [KVM ARM]     [KVM ia64]     [KVM ppc]     [Virtualization Tools]     [Spice Development]     [Libvirt]     [Libvirt Users]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite Questions]     [Linux Kernel]     [Linux SCSI]     [XFree86]
  Powered by Linux