Alon Levy | 14 Mar 20:48 2011
Picon

[fedora-virt] qxl locking fixes round 2 (was: Re: spice and qemu 0.14)

On Mon, Mar 14, 2011 at 05:00:46PM +0100, Gianluca Cecchi wrote:
> On Mon, Mar 14, 2011 at 4:08 PM, Alon Levy <alevy <at> redhat.com> wrote:
> > On Mon, Mar 14, 2011 at 02:59:30PM +0100, Gianluca Cecchi wrote:
> >> On Mon, Mar 14, 2011 at 12:42 PM, Gianluca Cecchi
> >> <gianluca.cecchi <at> gmail.com> wrote:
> >> >
> >> > I'm going to test...
> >> > Gianluca
> >> >
> >>
> >> If I run the w2k3 vm with vga as video adapter I get normal behaviour.
> >> If I set qxl and spice, the vm enters the initial black screen with
> >> bars at bottom and then shutdowns:
> >
> > shutdowns? anyway, this patchset is not good enough for qemu-kvm, will
> > reply to thread when we have something working.
> >
> 
> Ok.
> shutdowns in log file.
> From a console point of view it powers off directly...

here is a new patchset, it's basically the old plus first patch of reverting gerd's
(cpu_single_env hackage) and last one removing all the locks, after being
convinced by hans (cc'ed) and uri that it should work. Tested with rhel
qemu-kvm, which should be identical (tm) to fedora qemu-kvm. On account of
being too lame to figure out how to add the patches to qemu.spec and doing a
scratch build right now..

Happy testing,
Alon

>From fb0b57bf9857ce22bcf805d7e23b82301563b76c Mon Sep 17 00:00:00 2001
From: Alon Levy <alevy <at> redhat.com>
Date: Mon, 14 Mar 2011 21:34:14 +0200
Subject: [PATCH 1/6] Revert "spice/qxl: locking fix for qemu-kvm"

This reverts commit 15ba0114aa3ddedbeb2519cb0a8755a05f0a1d38.
---
 hw/qxl.c           |   37 ++++++++-----------------------------
 ui/spice-display.c |   12 ++++++------
 ui/spice-display.h |    6 ------
 3 files changed, 14 insertions(+), 41 deletions(-)

diff --git a/hw/qxl.c b/hw/qxl.c
index 58d6222..61fd1fc 100644
--- a/hw/qxl.c
+++ b/hw/qxl.c
 <at>  <at>  -125,27 +125,6  <at>  <at>  static void qxl_reset_memslots(PCIQXLDevice *d);
 static void qxl_reset_surfaces(PCIQXLDevice *d);
 static void qxl_ring_set_dirty(PCIQXLDevice *qxl);

-/* qemu-kvm locking ... */
-void qxl_unlock_iothread(SimpleSpiceDisplay *ssd)
-{
-    if (cpu_single_env) {
-        assert(ssd->env == NULL);
-        ssd->env = cpu_single_env;
-        cpu_single_env = NULL;
-    }
-    qemu_mutex_unlock_iothread();
-}
-
-void qxl_lock_iothread(SimpleSpiceDisplay *ssd)
-{
-    qemu_mutex_lock_iothread();
-    if (ssd->env) {
-        assert(cpu_single_env == NULL);
-        cpu_single_env = ssd->env;
-        ssd->env = NULL;
-    }
-}
-
 static inline uint32_t msb_mask(uint32_t val)
 {
     uint32_t mask;
 <at>  <at>  -683,10 +662,10  <at>  <at>  static void qxl_hard_reset(PCIQXLDevice *d, int loadvm)
     dprint(d, 1, "%s: start%s\n", __FUNCTION__,
            loadvm ? " (loadvm)" : "");

-    qxl_unlock_iothread(&d->ssd);
+    qemu_mutex_unlock_iothread();
     d->ssd.worker->reset_cursor(d->ssd.worker);
     d->ssd.worker->reset_image_cache(d->ssd.worker);
-    qxl_lock_iothread(&d->ssd);
+    qemu_mutex_lock_iothread();
     qxl_reset_surfaces(d);
     qxl_reset_memslots(d);

 <at>  <at>  -816,9 +795,9  <at>  <at>  static void qxl_reset_surfaces(PCIQXLDevice *d)
 {
     dprint(d, 1, "%s:\n", __FUNCTION__);
     d->mode = QXL_MODE_UNDEFINED;
-    qxl_unlock_iothread(&d->ssd);
+    qemu_mutex_unlock_iothread();
     d->ssd.worker->destroy_surfaces(d->ssd.worker);
-    qxl_lock_iothread(&d->ssd);
+    qemu_mutex_lock_iothread();
     memset(&d->guest_surfaces.cmds, 0, sizeof(d->guest_surfaces.cmds));
 }

 <at>  <at>  -887,9 +866,9  <at>  <at>  static void qxl_destroy_primary(PCIQXLDevice *d)
     dprint(d, 1, "%s\n", __FUNCTION__);

     d->mode = QXL_MODE_UNDEFINED;
-    qxl_unlock_iothread(&d->ssd);
+    qemu_mutex_unlock_iothread();
     d->ssd.worker->destroy_primary_surface(d->ssd.worker, 0);
-    qxl_lock_iothread(&d->ssd);
+    qemu_mutex_lock_iothread();
 }

 static void qxl_set_mode(PCIQXLDevice *d, int modenr, int loadvm)
 <at>  <at>  -959,10 +938,10  <at>  <at>  static void ioport_write(void *opaque, uint32_t addr, uint32_t val)
     case QXL_IO_UPDATE_AREA:
     {
         QXLRect update = d->ram->update_area;
-        qxl_unlock_iothread(&d->ssd);
+        qemu_mutex_unlock_iothread();
         d->ssd.worker->update_area(d->ssd.worker, d->ram->update_surface,
                                    &update, NULL, 0, 0);
-        qxl_lock_iothread(&d->ssd);
+        qemu_mutex_lock_iothread();
         break;
     }
     case QXL_IO_NOTIFY_CMD:
diff --git a/ui/spice-display.c b/ui/spice-display.c
index 3f978e5..99d9fd6 100644
--- a/ui/spice-display.c
+++ b/ui/spice-display.c
 <at>  <at>  -187,18 +187,18  <at>  <at>  void qemu_spice_create_host_primary(SimpleSpiceDisplay *ssd)
     surface.mem        = (intptr_t)ssd->buf;
     surface.group_id   = MEMSLOT_GROUP_HOST;

-    qxl_unlock_iothread(ssd);
+    qemu_mutex_unlock_iothread();
     ssd->worker->create_primary_surface(ssd->worker, 0, &surface);
-    qxl_lock_iothread(ssd);
+    qemu_mutex_lock_iothread();
 }

 void qemu_spice_destroy_host_primary(SimpleSpiceDisplay *ssd)
 {
     dprint(1, "%s:\n", __FUNCTION__);

-    qxl_unlock_iothread(ssd);
+    qemu_mutex_unlock_iothread();
     ssd->worker->destroy_primary_surface(ssd->worker, 0);
-    qxl_lock_iothread(ssd);
+    qemu_mutex_lock_iothread();
 }

 void qemu_spice_vm_change_state_handler(void *opaque, int running, int reason)
 <at>  <at>  -208,9 +208,9  <at>  <at>  void qemu_spice_vm_change_state_handler(void *opaque, int running, int reason)
     if (running) {
         ssd->worker->start(ssd->worker);
     } else {
-        qxl_unlock_iothread(ssd);
+        qemu_mutex_unlock_iothread();
         ssd->worker->stop(ssd->worker);
-        qxl_lock_iothread(ssd);
+        qemu_mutex_lock_iothread();
     }
     ssd->running = running;
 }
diff --git a/ui/spice-display.h b/ui/spice-display.h
index df74828..aef0464 100644
--- a/ui/spice-display.h
+++ b/ui/spice-display.h
 <at>  <at>  -43,9 +43,6  <at>  <at>  typedef struct SimpleSpiceDisplay {
     QXLRect dirty;
     int notify;
     int running;
-
-    /* qemu-kvm locking ... */
-    void *env;
 } SimpleSpiceDisplay;

 typedef struct SimpleSpiceUpdate {
 <at>  <at>  -55,9 +52,6  <at>  <at>  typedef struct SimpleSpiceUpdate {
     uint8_t *bitmap;
 } SimpleSpiceUpdate;

-void qxl_unlock_iothread(SimpleSpiceDisplay *ssd);
-void qxl_lock_iothread(SimpleSpiceDisplay *ssd);
-
 int qemu_spice_rect_is_empty(const QXLRect* r);
 void qemu_spice_rect_union(QXLRect *dest, const QXLRect *r);

-- 
1.7.4.1

>From a844bf615a17b26e0a62856c4cabf72ffed705b1 Mon Sep 17 00:00:00 2001
From: Uri Lublin <uril <at> redhat.com>
Date: Sun, 13 Mar 2011 19:45:45 +0200
Subject: [PATCH 2/6] qxl: fix locking, do not lock from spice server thread

instead request iothread to do the operation, and wait for its response.
---
 hw/qxl.c           |   70 +++++++++++++++++++++++++++++++++++++++++++++------
 hw/qxl.h           |    3 +-
 ui/spice-display.c |    7 +++--
 ui/spice-display.h |    5 +++
 4 files changed, 72 insertions(+), 13 deletions(-)

diff --git a/hw/qxl.c b/hw/qxl.c
index 61fd1fc..d36c06c 100644
--- a/hw/qxl.c
+++ b/hw/qxl.c
 <at>  <at>  -28,6 +28,8  <at>  <at> 

 #include "qxl.h"

+#define ASSERT assert
+
 #undef SPICE_RING_PROD_ITEM
 #define SPICE_RING_PROD_ITEM(r, ret) {                                  \
         typeof(r) start = r;                                            \
 <at>  <at>  -117,6 +119,15  <at>  <at>  static QXLMode qxl_modes[] = {
 #endif
 };

+
+/*
+ * commands/requests from server thread to iothread.
+ */
+enum {
+	QXL_SERVER_SET_IRQ = 1,
+	QXL_SERVER_CREATE_UPDATE,
+};
+
 static PCIQXLDevice *qxl0;

 static void qxl_send_events(PCIQXLDevice *d, uint32_t events);
 <at>  <at>  -344,11 +355,24  <at>  <at>  static int interface_get_command(QXLInstance *sin, struct QXLCommandExt *ext)
     QXLCommandRing *ring;
     QXLCommand *cmd;
     int notify;
+    int r;
+    unsigned char req, ack;

     switch (qxl->mode) {
     case QXL_MODE_VGA:
         dprint(qxl, 2, "%s: vga\n", __FUNCTION__);
-        update = qemu_spice_create_update(&qxl->ssd);
+
+        /* TODO -- 1. check write+read return codes. retry upon e.g. EINTR */
+        /* TODO -- 2. change the imlpementation inside qemu_spice_create_update (option rename+add
functions) */
+        req = QXL_SERVER_CREATE_UPDATE;
+        r = write(qxl->pipe[1], &req , 1);
+        ASSERT(r == 1);
+        ack = 0;
+        r = read(qxl->pipe_out[0], &ack, 1);
+        ASSERT(r == 1);
+        ASSERT(ack == QXL_SERVER_CREATE_UPDATE); // ack==req
+        update = qxl->ssd.update;
+        //update = qemu_spice_create_update(&qxl->ssd);
         if (update == NULL) {
             return false;
         }
 <at>  <at>  -1058,16 +1082,27  <at>  <at>  static void qxl_map(PCIDevice *pci, int region_num,
 static void pipe_read(void *opaque)
 {
     PCIQXLDevice *d = opaque;
-    char dummy;
+    unsigned char cmd;
     int len;

     do {
-        len = read(d->pipe[0], &dummy, sizeof(dummy));
-    } while (len == sizeof(dummy));
-    qxl_set_irq(d);
+        len = read(d->pipe[0], &cmd, sizeof(cmd));
+    } while (len == sizeof(cmd));
+    switch (cmd) {
+    case QXL_SERVER_SET_IRQ:
+        qxl_set_irq(d);
+        break;
+    case QXL_SERVER_CREATE_UPDATE:
+        d->ssd.update = qemu_spice_create_update(&d->ssd);
+        len = write(d->pipe_out[1], &cmd, 1);
+        ASSERT(len == 1);
+        break;
+    default:
+        fprintf(stderr, "%s: unknown cmd %u\n", __FUNCTION__, cmd);
+        abort();
+    }
 }

-/* called from spice server thread context only */
 static void qxl_send_events(PCIQXLDevice *d, uint32_t events)
 {
     uint32_t old_pending;
 <at>  <at>  -1079,10 +1114,17  <at>  <at>  static void qxl_send_events(PCIQXLDevice *d, uint32_t events)
         return;
     }
     if (pthread_self() == d->main) {
+        /* running in io_thread thread */
         qxl_set_irq(d);
     } else {
-        if (write(d->pipe[1], d, 1) != 1) {
-            dprint(d, 1, "%s: write to pipe failed\n", __FUNCTION__);
+        /* called from spice-server thread */
+        int ret;
+        unsigned char ack = QXL_SERVER_SET_IRQ;
+        ret = write(d->pipe[1], &ack, 1);
+        if (ret != 1) {
+            fprintf(stderr, "%s: write to iothread pipe failed (%d) %m\n", 
+                    __FUNCTION__, ret);
+            perror("");
         }
     }
 }
 <at>  <at>  -1090,19 +1132,29  <at>  <at>  static void qxl_send_events(PCIQXLDevice *d, uint32_t events)
 static void init_pipe_signaling(PCIQXLDevice *d)
 {
    if (pipe(d->pipe) < 0) {
-       dprint(d, 1, "%s: pipe creation failed\n", __FUNCTION__);
+       fprintf(stderr, "%s: pipe creation failed\n", __FUNCTION__);
        return;
    }
+
+#if 0 // why non-blocking ? code does not check that case
 #ifdef CONFIG_IOTHREAD
    fcntl(d->pipe[0], F_SETFL, O_NONBLOCK);
 #else
    fcntl(d->pipe[0], F_SETFL, O_NONBLOCK /* | O_ASYNC */);
 #endif
    fcntl(d->pipe[1], F_SETFL, O_NONBLOCK);
+#endif //(if 0)
+
    fcntl(d->pipe[0], F_SETOWN, getpid());

    d->main = pthread_self();
    qemu_set_fd_handler(d->pipe[0], pipe_read, NULL, d);
+
+
+   if (pipe(d->pipe_out) < 0) {
+       fprintf(stderr, "%s: pipe creation failed\n", __FUNCTION__);
+       return;
+   }
 }

 /* graphics console */
diff --git a/hw/qxl.h b/hw/qxl.h
index f6c450d..b153e4b 100644
--- a/hw/qxl.h
+++ b/hw/qxl.h
 <at>  <at>  -57,7 +57,8  <at>  <at>  typedef struct PCIQXLDevice {

     /* thread signaling */
     pthread_t          main;
-    int                pipe[2];
+    int                pipe[2];     /* to iothread */
+    int                pipe_out[2]; /* from iothread */

     /* ram pci bar */
     QXLRam             *ram;
diff --git a/ui/spice-display.c b/ui/spice-display.c
index 99d9fd6..c7cf3b8 100644
--- a/ui/spice-display.c
+++ b/ui/spice-display.c
 <at>  <at>  -79,9 +79,9  <at>  <at>  SimpleSpiceUpdate *qemu_spice_create_update(SimpleSpiceDisplay *ssd)
     uint8_t *src, *dst;
     int by, bw, bh;

-    qemu_mutex_lock_iothread();
+    /* qemu_mutex_lock_iothread(); */
     if (qemu_spice_rect_is_empty(&ssd->dirty)) {
-        qemu_mutex_unlock_iothread();
+        /* qemu_mutex_unlock_iothread(); */
         return NULL;
     };

 <at>  <at>  -142,7 +142,7  <at>  <at>  SimpleSpiceUpdate *qemu_spice_create_update(SimpleSpiceDisplay *ssd)
     cmd->data = (intptr_t)drawable;

     memset(&ssd->dirty, 0, sizeof(ssd->dirty));
-    qemu_mutex_unlock_iothread();
+    /* qemu_mutex_unlock_iothread(); */
     return update;
 }

 <at>  <at>  -301,6 +301,7  <at>  <at>  static int interface_get_command(QXLInstance *sin, struct QXLCommandExt *ext)
     SimpleSpiceUpdate *update;

     dprint(3, "%s:\n", __FUNCTION__);
+    assert((const char *)"TODO -- fixme" == NULL);
     update = qemu_spice_create_update(ssd);
     if (update == NULL) {
         return false;
diff --git a/ui/spice-display.h b/ui/spice-display.h
index aef0464..e1fc398 100644
--- a/ui/spice-display.h
+++ b/ui/spice-display.h
 <at>  <at>  -31,6 +31,8  <at>  <at> 

 #define NUM_SURFACES 1024

+struct SimpleSpiceUpdate;
+
 typedef struct SimpleSpiceDisplay {
     DisplayState *ds;
     void *buf;
 <at>  <at>  -43,6 +45,9  <at>  <at>  typedef struct SimpleSpiceDisplay {
     QXLRect dirty;
     int notify;
     int running;
+
+    /* ssd updates (one request/command at a time) */
+    struct SimpleSpiceUpdate *update;
 } SimpleSpiceDisplay;

 typedef struct SimpleSpiceUpdate {
-- 
1.7.4.1

>From 9b18471b053b80a12f64bf65d5e12ba590edc208 Mon Sep 17 00:00:00 2001
From: Uri Lublin <uril <at> redhat.com>
Date: Sun, 13 Mar 2011 19:45:46 +0200
Subject: [PATCH 3/6] qxl: read_pipe: keep reading as long as there are things in the queue

---
 hw/qxl.c |   39 ++++++++++++++++++++++++---------------
 1 files changed, 24 insertions(+), 15 deletions(-)

diff --git a/hw/qxl.c b/hw/qxl.c
index d36c06c..d040bee 100644
--- a/hw/qxl.c
+++ b/hw/qxl.c
 <at>  <at>  -1083,24 +1083,33  <at>  <at>  static void pipe_read(void *opaque)
 {
     PCIQXLDevice *d = opaque;
     unsigned char cmd;
-    int len;
+    int len, again = 1, set_irq_done = 0;

     do {
+        cmd = 0;
         len = read(d->pipe[0], &cmd, sizeof(cmd));
-    } while (len == sizeof(cmd));
-    switch (cmd) {
-    case QXL_SERVER_SET_IRQ:
-        qxl_set_irq(d);
-        break;
-    case QXL_SERVER_CREATE_UPDATE:
-        d->ssd.update = qemu_spice_create_update(&d->ssd);
-        len = write(d->pipe_out[1], &cmd, 1);
-        ASSERT(len == 1);
-        break;
-    default:
-        fprintf(stderr, "%s: unknown cmd %u\n", __FUNCTION__, cmd);
-        abort();
-    }
+        if ((len < 0) && (errno == EINTR)) {
+            continue;
+        }
+        switch (cmd) {
+        case QXL_SERVER_SET_IRQ:
+            if (set_irq_done == 0) {
+                 /* no need to do it more than once */
+                 set_irq_done = 1;
+                 qxl_set_irq(d);
+            }
+            break;
+        case QXL_SERVER_CREATE_UPDATE:
+            again = 0;
+            d->ssd.update = qemu_spice_create_update(&d->ssd);
+            len = write(d->pipe_out[1], &cmd, 1);
+            ASSERT(len == 1);
+            break;
+        default:
+            fprintf(stderr, "%s: unknown cmd %u\n", __FUNCTION__, cmd);
+            abort();
+        }
+    } while (again);
 }

 static void qxl_send_events(PCIQXLDevice *d, uint32_t events)
-- 
1.7.4.1

>From 861be2ff3c860e180db90f7f6928fbb427d7971a Mon Sep 17 00:00:00 2001
From: Alon Levy <alevy <at> redhat.com>
Date: Sun, 13 Mar 2011 21:58:24 +0200
Subject: [PATCH 4/6] qxl vga update: don't read, preventing pipe loop of death

---
 hw/qxl.c           |   44 +++++++++++++++++++++++++-------------------
 ui/spice-display.h |    1 +
 2 files changed, 26 insertions(+), 19 deletions(-)

diff --git a/hw/qxl.c b/hw/qxl.c
index d040bee..dfbb740 100644
--- a/hw/qxl.c
+++ b/hw/qxl.c
 <at>  <at>  -356,7 +356,7  <at>  <at>  static int interface_get_command(QXLInstance *sin, struct QXLCommandExt *ext)
     QXLCommand *cmd;
     int notify;
     int r;
-    unsigned char req, ack;
+    unsigned char req;

     switch (qxl->mode) {
     case QXL_MODE_VGA:
 <at>  <at>  -364,21 +364,21  <at>  <at>  static int interface_get_command(QXLInstance *sin, struct QXLCommandExt *ext)

         /* TODO -- 1. check write+read return codes. retry upon e.g. EINTR */
         /* TODO -- 2. change the imlpementation inside qemu_spice_create_update (option rename+add functions) */
-        req = QXL_SERVER_CREATE_UPDATE;
-        r = write(qxl->pipe[1], &req , 1);
-        ASSERT(r == 1);
-        ack = 0;
-        r = read(qxl->pipe_out[0], &ack, 1);
-        ASSERT(r == 1);
-        ASSERT(ack == QXL_SERVER_CREATE_UPDATE); // ack==req
         update = qxl->ssd.update;
-        //update = qemu_spice_create_update(&qxl->ssd);
-        if (update == NULL) {
+        if (update != NULL) {
+            qxl->ssd.update = NULL;
+            *ext = update->ext;
+            qxl_log_command(qxl, "vga", ext);
+            return true;
+        } else {
+            if (!qxl->ssd.waiting_for_update) {
+                qxl->ssd.waiting_for_update = 1;
+                req = QXL_SERVER_CREATE_UPDATE;
+                r = write(qxl->pipe[1], &req , 1);
+                ASSERT(r == 1);
+            }
             return false;
         }
-        *ext = update->ext;
-        qxl_log_command(qxl, "vga", ext);
-        return true;
     case QXL_MODE_COMPAT:
     case QXL_MODE_NATIVE:
     case QXL_MODE_UNDEFINED:
 <at>  <at>  -611,6 +611,7  <at>  <at>  static void qxl_enter_vga_mode(PCIQXLDevice *d)
     qemu_spice_create_host_primary(&d->ssd);
     d->mode = QXL_MODE_VGA;
     memset(&d->ssd.dirty, 0, sizeof(d->ssd.dirty));
+    d->ssd.waiting_for_update = 0;
 }

 static void qxl_exit_vga_mode(PCIQXLDevice *d)
 <at>  <at>  -1084,6 +1085,7  <at>  <at>  static void pipe_read(void *opaque)
     PCIQXLDevice *d = opaque;
     unsigned char cmd;
     int len, again = 1, set_irq_done = 0;
+    int create_update = 0;

     do {
         cmd = 0;
 <at>  <at>  -1091,6 +1093,9  <at>  <at>  static void pipe_read(void *opaque)
         if ((len < 0) && (errno == EINTR)) {
             continue;
         }
+        if (len <= 0) {
+            break;
+        }
         switch (cmd) {
         case QXL_SERVER_SET_IRQ:
             if (set_irq_done == 0) {
 <at>  <at>  -1100,16 +1105,19  <at>  <at>  static void pipe_read(void *opaque)
             }
             break;
         case QXL_SERVER_CREATE_UPDATE:
-            again = 0;
-            d->ssd.update = qemu_spice_create_update(&d->ssd);
-            len = write(d->pipe_out[1], &cmd, 1);
-            ASSERT(len == 1);
+            create_update = 1;
             break;
         default:
             fprintf(stderr, "%s: unknown cmd %u\n", __FUNCTION__, cmd);
             abort();
         }
     } while (again);
+    if (create_update) {
+        if (d->ssd.update == NULL) {
+            d->ssd.update = qemu_spice_create_update(&d->ssd);
+        }
+        d->ssd.waiting_for_update = 0;
+    }
 }

 static void qxl_send_events(PCIQXLDevice *d, uint32_t events)
 <at>  <at>  -1145,14 +1153,12  <at>  <at>  static void init_pipe_signaling(PCIQXLDevice *d)
        return;
    }

-#if 0 // why non-blocking ? code does not check that case
 #ifdef CONFIG_IOTHREAD
    fcntl(d->pipe[0], F_SETFL, O_NONBLOCK);
 #else
    fcntl(d->pipe[0], F_SETFL, O_NONBLOCK /* | O_ASYNC */);
 #endif
    fcntl(d->pipe[1], F_SETFL, O_NONBLOCK);
-#endif //(if 0)

    fcntl(d->pipe[0], F_SETOWN, getpid());

diff --git a/ui/spice-display.h b/ui/spice-display.h
index e1fc398..37ce297 100644
--- a/ui/spice-display.h
+++ b/ui/spice-display.h
 <at>  <at>  -48,6 +48,7  <at>  <at>  typedef struct SimpleSpiceDisplay {

     /* ssd updates (one request/command at a time) */
     struct SimpleSpiceUpdate *update;
+    int waiting_for_update;
 } SimpleSpiceDisplay;

 typedef struct SimpleSpiceUpdate {
-- 
1.7.4.1

>From 19a69e023bf4eeb02070c14576c1964af5feaa8d Mon Sep 17 00:00:00 2001
From: Alon Levy <alevy <at> redhat.com>
Date: Mon, 14 Mar 2011 21:36:53 +0200
Subject: [PATCH 5/6] hw/qxl-render: add TODO's for cursor updated

when server calls get_cursor_command, and we have an active ds
cursor related callback in non vga mode, we need to lock to prevent
the iothread (via sdl/vnc) from touching the ds as well.

This is currently untested, since it requires running spice with sdl/vnc
at the same time. It appears it will be broken unless we use the same
pipe we pass QXL_SERVER_* stuff to (SET_IRQ and CREATE_UPDATE) atm.
---
 hw/qxl-render.c |    4 ++++
 1 files changed, 4 insertions(+), 0 deletions(-)

diff --git a/hw/qxl-render.c b/hw/qxl-render.c
index 58965e0..643b924 100644
--- a/hw/qxl-render.c
+++ b/hw/qxl-render.c
 <at>  <at>  -209,6 +209,8  <at>  <at>  void qxl_render_cursor(PCIQXLDevice *qxl, QXLCommandExt *ext)
         if (c == NULL) {
             c = cursor_builtin_left_ptr();
         }
+        /* TODO LOCK: move to pipe via QXL_SERVER_CURSOR_SET?
+         * can this be fire and forget (i.e. can be async)? */
         qemu_mutex_lock_iothread();
         qxl->ssd.ds->cursor_define(c);
         qxl->ssd.ds->mouse_set(x, y, 1);
 <at>  <at>  -218,6 +220,8  <at>  <at>  void qxl_render_cursor(PCIQXLDevice *qxl, QXLCommandExt *ext)
     case QXL_CURSOR_MOVE:
         x = cmd->u.position.x;
         y = cmd->u.position.y;
+        /* TODO LOCK: move to pipe via QXL_SERVER_MOUSE_SET?
+         * can this be fire and forget (i.e. can be async)? */
         qemu_mutex_lock_iothread();
         qxl->ssd.ds->mouse_set(x, y, 1);
         qemu_mutex_unlock_iothread();
-- 
1.7.4.1

>From 7a91084fa2515070787c454dc9a998de0ba4eff9 Mon Sep 17 00:00:00 2001
From: Alon Levy <alevy <at> redhat.com>
Date: Mon, 14 Mar 2011 21:39:10 +0200
Subject: [PATCH 6/6] qxl/spice: remove left lock dropping

now that we don't need the lock in the spice-server thread, there
is no reason to drop it in the first place. This means we no longer
need to keep track of cpu_single_env either.
---
 hw/qxl.c           |    8 --------
 ui/spice-display.c |    6 ------
 2 files changed, 0 insertions(+), 14 deletions(-)

diff --git a/hw/qxl.c b/hw/qxl.c
index dfbb740..c26f6df 100644
--- a/hw/qxl.c
+++ b/hw/qxl.c
 <at>  <at>  -687,10 +687,8  <at>  <at>  static void qxl_hard_reset(PCIQXLDevice *d, int loadvm)
     dprint(d, 1, "%s: start%s\n", __FUNCTION__,
            loadvm ? " (loadvm)" : "");

-    qemu_mutex_unlock_iothread();
     d->ssd.worker->reset_cursor(d->ssd.worker);
     d->ssd.worker->reset_image_cache(d->ssd.worker);
-    qemu_mutex_lock_iothread();
     qxl_reset_surfaces(d);
     qxl_reset_memslots(d);

 <at>  <at>  -820,9 +818,7  <at>  <at>  static void qxl_reset_surfaces(PCIQXLDevice *d)
 {
     dprint(d, 1, "%s:\n", __FUNCTION__);
     d->mode = QXL_MODE_UNDEFINED;
-    qemu_mutex_unlock_iothread();
     d->ssd.worker->destroy_surfaces(d->ssd.worker);
-    qemu_mutex_lock_iothread();
     memset(&d->guest_surfaces.cmds, 0, sizeof(d->guest_surfaces.cmds));
 }

 <at>  <at>  -891,9 +887,7  <at>  <at>  static void qxl_destroy_primary(PCIQXLDevice *d)
     dprint(d, 1, "%s\n", __FUNCTION__);

     d->mode = QXL_MODE_UNDEFINED;
-    qemu_mutex_unlock_iothread();
     d->ssd.worker->destroy_primary_surface(d->ssd.worker, 0);
-    qemu_mutex_lock_iothread();
 }

 static void qxl_set_mode(PCIQXLDevice *d, int modenr, int loadvm)
 <at>  <at>  -963,10 +957,8  <at>  <at>  static void ioport_write(void *opaque, uint32_t addr, uint32_t val)
     case QXL_IO_UPDATE_AREA:
     {
         QXLRect update = d->ram->update_area;
-        qemu_mutex_unlock_iothread();
         d->ssd.worker->update_area(d->ssd.worker, d->ram->update_surface,
                                    &update, NULL, 0, 0);
-        qemu_mutex_lock_iothread();
         break;
     }
     case QXL_IO_NOTIFY_CMD:
diff --git a/ui/spice-display.c b/ui/spice-display.c
index c7cf3b8..33760e6 100644
--- a/ui/spice-display.c
+++ b/ui/spice-display.c
 <at>  <at>  -187,18 +187,14  <at>  <at>  void qemu_spice_create_host_primary(SimpleSpiceDisplay *ssd)
     surface.mem        = (intptr_t)ssd->buf;
     surface.group_id   = MEMSLOT_GROUP_HOST;

-    qemu_mutex_unlock_iothread();
     ssd->worker->create_primary_surface(ssd->worker, 0, &surface);
-    qemu_mutex_lock_iothread();
 }

 void qemu_spice_destroy_host_primary(SimpleSpiceDisplay *ssd)
 {
     dprint(1, "%s:\n", __FUNCTION__);

-    qemu_mutex_unlock_iothread();
     ssd->worker->destroy_primary_surface(ssd->worker, 0);
-    qemu_mutex_lock_iothread();
 }

 void qemu_spice_vm_change_state_handler(void *opaque, int running, int reason)
 <at>  <at>  -208,9 +204,7  <at>  <at>  void qemu_spice_vm_change_state_handler(void *opaque, int running, int reason)
     if (running) {
         ssd->worker->start(ssd->worker);
     } else {
-        qemu_mutex_unlock_iothread();
         ssd->worker->stop(ssd->worker);
-        qemu_mutex_lock_iothread();
     }
     ssd->running = running;
 }
--

-- 
1.7.4.1

_______________________________________________
virt mailing list
virt <at> lists.fedoraproject.org
https://admin.fedoraproject.org/mailman/listinfo/virt

Gmane