In preparation for threaded execution, make 8250 code thread safe by
introducing a per-device mutex.

Cc: Asias He <[email protected]>
Cc: Cyrill Gorcunov <[email protected]>
Cc: Ingo Molnar <[email protected]>
Signed-off-by: Pekka Enberg <[email protected]>
---
 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 [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to