qemu-devel
[Top][All Lists]
Advanced

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

Re: [Qemu-devel] [PATCH] Remove support for non-threaded VNC server


From: Anthony Liguori
Subject: Re: [Qemu-devel] [PATCH] Remove support for non-threaded VNC server
Date: Wed, 27 Jun 2012 16:32:58 -0500
User-agent: Mozilla/5.0 (X11; Linux x86_64; rv:11.0) Gecko/20120329 Thunderbird/11.0.1

On 06/20/2012 08:24 AM, Daniel P. Berrange wrote:
From: "Daniel P. Berrange"<address@hidden>

QEMU now has a fundamental requirement for pthreads, so there
is no compelling reason to retain support for the non-threaded
VNC server. Remove the --{enable,disable}-vnc-thread configure
arguments, and all CONFIG_VNC_THREAD conditionals

Signed-off-by: Daniel P. Berrange<address@hidden>

Applied.  Thanks.

Regards,

Anthony Liguori

---
  configure           |    9 --
  ui/Makefile.objs    |    6 +-
  ui/vnc-jobs-async.c |  351 ---------------------------------------------------
  ui/vnc-jobs-sync.c  |   73 -----------
  ui/vnc-jobs.c       |  351 +++++++++++++++++++++++++++++++++++++++++++++++++++
  ui/vnc-jobs.h       |   16 ---
  ui/vnc.c            |   21 ---
  ui/vnc.h            |   17 ---
  8 files changed, 352 insertions(+), 492 deletions(-)
  delete mode 100644 ui/vnc-jobs-async.c
  delete mode 100644 ui/vnc-jobs-sync.c
  create mode 100644 ui/vnc-jobs.c

diff --git a/configure b/configure
index b68c0ca..4767532 100755
--- a/configure
+++ b/configure
@@ -134,7 +134,6 @@ vnc_tls=""
  vnc_sasl=""
  vnc_jpeg=""
  vnc_png=""
-vnc_thread="no"
  xen=""
  xen_ctrl_version=""
  linux_aio=""
@@ -666,10 +665,6 @@ for opt do
    ;;
    --enable-vnc-png) vnc_png="yes"
    ;;
-  --disable-vnc-thread) vnc_thread="no"
-  ;;
-  --enable-vnc-thread) vnc_thread="yes"
-  ;;
    --disable-slirp) slirp="no"
    ;;
    --disable-uuid) uuid="no"
@@ -2998,7 +2993,6 @@ if test "$vnc" = "yes" ; then
      echo "VNC SASL support  $vnc_sasl"
      echo "VNC JPEG support  $vnc_jpeg"
      echo "VNC PNG support   $vnc_png"
-    echo "VNC thread        $vnc_thread"
  fi
  if test -n "$sparc_cpu"; then
      echo "Target Sparc Arch $sparc_cpu"
@@ -3174,9 +3168,6 @@ if test "$vnc_png" = "yes" ; then
    echo "CONFIG_VNC_PNG=y">>  $config_host_mak
    echo "VNC_PNG_CFLAGS=$vnc_png_cflags">>  $config_host_mak
  fi
-if test "$vnc_thread" = "yes" ; then
-  echo "CONFIG_VNC_THREAD=y">>  $config_host_mak
-fi
  if test "$fnmatch" = "yes" ; then
    echo "CONFIG_FNMATCH=y">>  $config_host_mak
  fi
diff --git a/ui/Makefile.objs b/ui/Makefile.objs
index 3687c8a..adc07be 100644
--- a/ui/Makefile.objs
+++ b/ui/Makefile.objs
@@ -4,11 +4,7 @@ vnc-obj-y += vnc-enc-tight.o vnc-palette.o
  vnc-obj-y += vnc-enc-zrle.o
  vnc-obj-$(CONFIG_VNC_TLS) += vnc-tls.o vnc-auth-vencrypt.o
  vnc-obj-$(CONFIG_VNC_SASL) += vnc-auth-sasl.o
-ifdef CONFIG_VNC_THREAD
-vnc-obj-y += vnc-jobs-async.o
-else
-vnc-obj-y += vnc-jobs-sync.o
-endif
+vnc-obj-y += vnc-jobs.o

  common-obj-y += keymaps.o
  common-obj-$(CONFIG_SPICE) += spice-core.o spice-input.o spice-display.o
diff --git a/ui/vnc-jobs-async.c b/ui/vnc-jobs-async.c
deleted file mode 100644
index 087b84d..0000000
--- a/ui/vnc-jobs-async.c
+++ /dev/null
@@ -1,351 +0,0 @@
-/*
- * QEMU VNC display driver
- *
- * Copyright (C) 2006 Anthony Liguori<address@hidden>
- * Copyright (C) 2006 Fabrice Bellard
- * Copyright (C) 2009 Red Hat, Inc
- * Copyright (C) 2010 Corentin Chary<address@hidden>
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to 
deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 
FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
-
-
-#include "vnc.h"
-#include "vnc-jobs.h"
-#include "qemu_socket.h"
-
-/*
- * Locking:
- *
- * There is three levels of locking:
- * - jobs queue lock: for each operation on the queue (push, pop, isEmpty?)
- * - VncDisplay global lock: mainly used for framebuffer updates to avoid
- *                      screen corruption if the framebuffer is updated
- *                     while the worker is doing something.
- * - VncState::output lock: used to make sure the output buffer is not 
corrupted
- *                      if two threads try to write on it at the same time
- *
- * While the VNC worker thread is working, the VncDisplay global lock is hold
- * to avoid screen corruptions (this does not block vnc_refresh() because it
- * uses trylock()) but the output lock is not hold because the thread work on
- * its own output buffer.
- * When the encoding job is done, the worker thread will hold the output lock
- * and copy its output buffer in vs->output.
-*/
-
-struct VncJobQueue {
-    QemuCond cond;
-    QemuMutex mutex;
-    QemuThread thread;
-    Buffer buffer;
-    bool exit;
-    QTAILQ_HEAD(, VncJob) jobs;
-};
-
-typedef struct VncJobQueue VncJobQueue;
-
-/*
- * We use a single global queue, but most of the functions are
- * already reetrant, so we can easilly add more than one encoding thread
- */
-static VncJobQueue *queue;
-
-static void vnc_lock_queue(VncJobQueue *queue)
-{
-    qemu_mutex_lock(&queue->mutex);
-}
-
-static void vnc_unlock_queue(VncJobQueue *queue)
-{
-    qemu_mutex_unlock(&queue->mutex);
-}
-
-VncJob *vnc_job_new(VncState *vs)
-{
-    VncJob *job = g_malloc0(sizeof(VncJob));
-
-    job->vs = vs;
-    vnc_lock_queue(queue);
-    QLIST_INIT(&job->rectangles);
-    vnc_unlock_queue(queue);
-    return job;
-}
-
-int vnc_job_add_rect(VncJob *job, int x, int y, int w, int h)
-{
-    VncRectEntry *entry = g_malloc0(sizeof(VncRectEntry));
-
-    entry->rect.x = x;
-    entry->rect.y = y;
-    entry->rect.w = w;
-    entry->rect.h = h;
-
-    vnc_lock_queue(queue);
-    QLIST_INSERT_HEAD(&job->rectangles, entry, next);
-    vnc_unlock_queue(queue);
-    return 1;
-}
-
-void vnc_job_push(VncJob *job)
-{
-    vnc_lock_queue(queue);
-    if (queue->exit || QLIST_EMPTY(&job->rectangles)) {
-        g_free(job);
-    } else {
-        QTAILQ_INSERT_TAIL(&queue->jobs, job, next);
-        qemu_cond_broadcast(&queue->cond);
-    }
-    vnc_unlock_queue(queue);
-}
-
-static bool vnc_has_job_locked(VncState *vs)
-{
-    VncJob *job;
-
-    QTAILQ_FOREACH(job,&queue->jobs, next) {
-        if (job->vs == vs || !vs) {
-            return true;
-        }
-    }
-    return false;
-}
-
-bool vnc_has_job(VncState *vs)
-{
-    bool ret;
-
-    vnc_lock_queue(queue);
-    ret = vnc_has_job_locked(vs);
-    vnc_unlock_queue(queue);
-    return ret;
-}
-
-void vnc_jobs_clear(VncState *vs)
-{
-    VncJob *job, *tmp;
-
-    vnc_lock_queue(queue);
-    QTAILQ_FOREACH_SAFE(job,&queue->jobs, next, tmp) {
-        if (job->vs == vs || !vs) {
-            QTAILQ_REMOVE(&queue->jobs, job, next);
-        }
-    }
-    vnc_unlock_queue(queue);
-}
-
-void vnc_jobs_join(VncState *vs)
-{
-    vnc_lock_queue(queue);
-    while (vnc_has_job_locked(vs)) {
-        qemu_cond_wait(&queue->cond,&queue->mutex);
-    }
-    vnc_unlock_queue(queue);
-    vnc_jobs_consume_buffer(vs);
-}
-
-void vnc_jobs_consume_buffer(VncState *vs)
-{
-    bool flush;
-
-    vnc_lock_output(vs);
-    if (vs->jobs_buffer.offset) {
-        vnc_write(vs, vs->jobs_buffer.buffer, vs->jobs_buffer.offset);
-        buffer_reset(&vs->jobs_buffer);
-    }
-    flush = vs->csock != -1&&  vs->abort != true;
-    vnc_unlock_output(vs);
-
-    if (flush) {
-      vnc_flush(vs);
-    }
-}
-
-/*
- * Copy data for local use
- */
-static void vnc_async_encoding_start(VncState *orig, VncState *local)
-{
-    local->vnc_encoding = orig->vnc_encoding;
-    local->features = orig->features;
-    local->ds = orig->ds;
-    local->vd = orig->vd;
-    local->lossy_rect = orig->lossy_rect;
-    local->write_pixels = orig->write_pixels;
-    local->clientds = orig->clientds;
-    local->tight = orig->tight;
-    local->zlib = orig->zlib;
-    local->hextile = orig->hextile;
-    local->zrle = orig->zrle;
-    local->output =  queue->buffer;
-    local->csock = -1; /* Don't do any network work on this thread */
-
-    buffer_reset(&local->output);
-}
-
-static void vnc_async_encoding_end(VncState *orig, VncState *local)
-{
-    orig->tight = local->tight;
-    orig->zlib = local->zlib;
-    orig->hextile = local->hextile;
-    orig->zrle = local->zrle;
-    orig->lossy_rect = local->lossy_rect;
-
-    queue->buffer = local->output;
-}
-
-static int vnc_worker_thread_loop(VncJobQueue *queue)
-{
-    VncJob *job;
-    VncRectEntry *entry, *tmp;
-    VncState vs;
-    int n_rectangles;
-    int saved_offset;
-
-    vnc_lock_queue(queue);
-    while (QTAILQ_EMPTY(&queue->jobs)&&  !queue->exit) {
-        qemu_cond_wait(&queue->cond,&queue->mutex);
-    }
-    /* Here job can only be NULL if queue->exit is true */
-    job = QTAILQ_FIRST(&queue->jobs);
-    vnc_unlock_queue(queue);
-
-    if (queue->exit) {
-        return -1;
-    }
-
-    vnc_lock_output(job->vs);
-    if (job->vs->csock == -1 || job->vs->abort == true) {
-        vnc_unlock_output(job->vs);
-        goto disconnected;
-    }
-    vnc_unlock_output(job->vs);
-
-    /* Make a local copy of vs and switch output buffers */
-    vnc_async_encoding_start(job->vs,&vs);
-
-    /* Start sending rectangles */
-    n_rectangles = 0;
-    vnc_write_u8(&vs, VNC_MSG_SERVER_FRAMEBUFFER_UPDATE);
-    vnc_write_u8(&vs, 0);
-    saved_offset = vs.output.offset;
-    vnc_write_u16(&vs, 0);
-
-    vnc_lock_display(job->vs->vd);
-    QLIST_FOREACH_SAFE(entry,&job->rectangles, next, tmp) {
-        int n;
-
-        if (job->vs->csock == -1) {
-            vnc_unlock_display(job->vs->vd);
-            goto disconnected;
-        }
-
-        n = vnc_send_framebuffer_update(&vs, entry->rect.x, entry->rect.y,
-                                        entry->rect.w, entry->rect.h);
-
-        if (n>= 0) {
-            n_rectangles += n;
-        }
-        g_free(entry);
-    }
-    vnc_unlock_display(job->vs->vd);
-
-    /* Put n_rectangles at the beginning of the message */
-    vs.output.buffer[saved_offset] = (n_rectangles>>  8)&  0xFF;
-    vs.output.buffer[saved_offset + 1] = n_rectangles&  0xFF;
-
-    vnc_lock_output(job->vs);
-    if (job->vs->csock != -1) {
-        buffer_reserve(&job->vs->jobs_buffer, vs.output.offset);
-        buffer_append(&job->vs->jobs_buffer, vs.output.buffer,
-                      vs.output.offset);
-        /* Copy persistent encoding data */
-        vnc_async_encoding_end(job->vs,&vs);
-
-       qemu_bh_schedule(job->vs->bh);
-    }
-    vnc_unlock_output(job->vs);
-
-disconnected:
-    vnc_lock_queue(queue);
-    QTAILQ_REMOVE(&queue->jobs, job, next);
-    vnc_unlock_queue(queue);
-    qemu_cond_broadcast(&queue->cond);
-    g_free(job);
-    return 0;
-}
-
-static VncJobQueue *vnc_queue_init(void)
-{
-    VncJobQueue *queue = g_malloc0(sizeof(VncJobQueue));
-
-    qemu_cond_init(&queue->cond);
-    qemu_mutex_init(&queue->mutex);
-    QTAILQ_INIT(&queue->jobs);
-    return queue;
-}
-
-static void vnc_queue_clear(VncJobQueue *q)
-{
-    qemu_cond_destroy(&queue->cond);
-    qemu_mutex_destroy(&queue->mutex);
-    buffer_free(&queue->buffer);
-    g_free(q);
-    queue = NULL; /* Unset global queue */
-}
-
-static void *vnc_worker_thread(void *arg)
-{
-    VncJobQueue *queue = arg;
-
-    qemu_thread_get_self(&queue->thread);
-
-    while (!vnc_worker_thread_loop(queue)) ;
-    vnc_queue_clear(queue);
-    return NULL;
-}
-
-void vnc_start_worker_thread(void)
-{
-    VncJobQueue *q;
-
-    if (vnc_worker_thread_running())
-        return ;
-
-    q = vnc_queue_init();
-    qemu_thread_create(&q->thread, vnc_worker_thread, q, QEMU_THREAD_DETACHED);
-    queue = q; /* Set global queue */
-}
-
-bool vnc_worker_thread_running(void)
-{
-    return queue; /* Check global queue */
-}
-
-void vnc_stop_worker_thread(void)
-{
-    if (!vnc_worker_thread_running())
-        return ;
-
-    /* Remove all jobs and wake up the thread */
-    vnc_lock_queue(queue);
-    queue->exit = true;
-    vnc_unlock_queue(queue);
-    vnc_jobs_clear(NULL);
-    qemu_cond_broadcast(&queue->cond);
-}
diff --git a/ui/vnc-jobs-sync.c b/ui/vnc-jobs-sync.c
deleted file mode 100644
index 49b77af..0000000
--- a/ui/vnc-jobs-sync.c
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * QEMU VNC display driver
- *
- * Copyright (C) 2006 Anthony Liguori<address@hidden>
- * Copyright (C) 2006 Fabrice Bellard
- * Copyright (C) 2009 Red Hat, Inc
- * Copyright (C) 2010 Corentin Chary<address@hidden>
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to 
deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 
FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
-
-#include "vnc.h"
-#include "vnc-jobs.h"
-
-void vnc_jobs_clear(VncState *vs)
-{
-}
-
-void vnc_jobs_join(VncState *vs)
-{
-}
-
-VncJob *vnc_job_new(VncState *vs)
-{
-    vs->job.vs = vs;
-    vs->job.rectangles = 0;
-
-    vnc_write_u8(vs, VNC_MSG_SERVER_FRAMEBUFFER_UPDATE);
-    vnc_write_u8(vs, 0);
-    vs->job.saved_offset = vs->output.offset;
-    vnc_write_u16(vs, 0);
-    return&vs->job;
-}
-
-void vnc_job_push(VncJob *job)
-{
-    VncState *vs = job->vs;
-
-    vs->output.buffer[job->saved_offset] = (job->rectangles>>  8)&  0xFF;
-    vs->output.buffer[job->saved_offset + 1] = job->rectangles&  0xFF;
-    vnc_flush(job->vs);
-}
-
-int vnc_job_add_rect(VncJob *job, int x, int y, int w, int h)
-{
-    int n;
-
-    n = vnc_send_framebuffer_update(job->vs, x, y, w, h);
-    if (n>= 0)
-        job->rectangles += n;
-    return n;
-}
-
-bool vnc_has_job(VncState *vs)
-{
-    return false;
-}
diff --git a/ui/vnc-jobs.c b/ui/vnc-jobs.c
new file mode 100644
index 0000000..087b84d
--- /dev/null
+++ b/ui/vnc-jobs.c
@@ -0,0 +1,351 @@
+/*
+ * QEMU VNC display driver
+ *
+ * Copyright (C) 2006 Anthony Liguori<address@hidden>
+ * Copyright (C) 2006 Fabrice Bellard
+ * Copyright (C) 2009 Red Hat, Inc
+ * Copyright (C) 2010 Corentin Chary<address@hidden>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to 
deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 
FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+
+#include "vnc.h"
+#include "vnc-jobs.h"
+#include "qemu_socket.h"
+
+/*
+ * Locking:
+ *
+ * There is three levels of locking:
+ * - jobs queue lock: for each operation on the queue (push, pop, isEmpty?)
+ * - VncDisplay global lock: mainly used for framebuffer updates to avoid
+ *                      screen corruption if the framebuffer is updated
+ *                     while the worker is doing something.
+ * - VncState::output lock: used to make sure the output buffer is not 
corrupted
+ *                      if two threads try to write on it at the same time
+ *
+ * While the VNC worker thread is working, the VncDisplay global lock is hold
+ * to avoid screen corruptions (this does not block vnc_refresh() because it
+ * uses trylock()) but the output lock is not hold because the thread work on
+ * its own output buffer.
+ * When the encoding job is done, the worker thread will hold the output lock
+ * and copy its output buffer in vs->output.
+*/
+
+struct VncJobQueue {
+    QemuCond cond;
+    QemuMutex mutex;
+    QemuThread thread;
+    Buffer buffer;
+    bool exit;
+    QTAILQ_HEAD(, VncJob) jobs;
+};
+
+typedef struct VncJobQueue VncJobQueue;
+
+/*
+ * We use a single global queue, but most of the functions are
+ * already reetrant, so we can easilly add more than one encoding thread
+ */
+static VncJobQueue *queue;
+
+static void vnc_lock_queue(VncJobQueue *queue)
+{
+    qemu_mutex_lock(&queue->mutex);
+}
+
+static void vnc_unlock_queue(VncJobQueue *queue)
+{
+    qemu_mutex_unlock(&queue->mutex);
+}
+
+VncJob *vnc_job_new(VncState *vs)
+{
+    VncJob *job = g_malloc0(sizeof(VncJob));
+
+    job->vs = vs;
+    vnc_lock_queue(queue);
+    QLIST_INIT(&job->rectangles);
+    vnc_unlock_queue(queue);
+    return job;
+}
+
+int vnc_job_add_rect(VncJob *job, int x, int y, int w, int h)
+{
+    VncRectEntry *entry = g_malloc0(sizeof(VncRectEntry));
+
+    entry->rect.x = x;
+    entry->rect.y = y;
+    entry->rect.w = w;
+    entry->rect.h = h;
+
+    vnc_lock_queue(queue);
+    QLIST_INSERT_HEAD(&job->rectangles, entry, next);
+    vnc_unlock_queue(queue);
+    return 1;
+}
+
+void vnc_job_push(VncJob *job)
+{
+    vnc_lock_queue(queue);
+    if (queue->exit || QLIST_EMPTY(&job->rectangles)) {
+        g_free(job);
+    } else {
+        QTAILQ_INSERT_TAIL(&queue->jobs, job, next);
+        qemu_cond_broadcast(&queue->cond);
+    }
+    vnc_unlock_queue(queue);
+}
+
+static bool vnc_has_job_locked(VncState *vs)
+{
+    VncJob *job;
+
+    QTAILQ_FOREACH(job,&queue->jobs, next) {
+        if (job->vs == vs || !vs) {
+            return true;
+        }
+    }
+    return false;
+}
+
+bool vnc_has_job(VncState *vs)
+{
+    bool ret;
+
+    vnc_lock_queue(queue);
+    ret = vnc_has_job_locked(vs);
+    vnc_unlock_queue(queue);
+    return ret;
+}
+
+void vnc_jobs_clear(VncState *vs)
+{
+    VncJob *job, *tmp;
+
+    vnc_lock_queue(queue);
+    QTAILQ_FOREACH_SAFE(job,&queue->jobs, next, tmp) {
+        if (job->vs == vs || !vs) {
+            QTAILQ_REMOVE(&queue->jobs, job, next);
+        }
+    }
+    vnc_unlock_queue(queue);
+}
+
+void vnc_jobs_join(VncState *vs)
+{
+    vnc_lock_queue(queue);
+    while (vnc_has_job_locked(vs)) {
+        qemu_cond_wait(&queue->cond,&queue->mutex);
+    }
+    vnc_unlock_queue(queue);
+    vnc_jobs_consume_buffer(vs);
+}
+
+void vnc_jobs_consume_buffer(VncState *vs)
+{
+    bool flush;
+
+    vnc_lock_output(vs);
+    if (vs->jobs_buffer.offset) {
+        vnc_write(vs, vs->jobs_buffer.buffer, vs->jobs_buffer.offset);
+        buffer_reset(&vs->jobs_buffer);
+    }
+    flush = vs->csock != -1&&  vs->abort != true;
+    vnc_unlock_output(vs);
+
+    if (flush) {
+      vnc_flush(vs);
+    }
+}
+
+/*
+ * Copy data for local use
+ */
+static void vnc_async_encoding_start(VncState *orig, VncState *local)
+{
+    local->vnc_encoding = orig->vnc_encoding;
+    local->features = orig->features;
+    local->ds = orig->ds;
+    local->vd = orig->vd;
+    local->lossy_rect = orig->lossy_rect;
+    local->write_pixels = orig->write_pixels;
+    local->clientds = orig->clientds;
+    local->tight = orig->tight;
+    local->zlib = orig->zlib;
+    local->hextile = orig->hextile;
+    local->zrle = orig->zrle;
+    local->output =  queue->buffer;
+    local->csock = -1; /* Don't do any network work on this thread */
+
+    buffer_reset(&local->output);
+}
+
+static void vnc_async_encoding_end(VncState *orig, VncState *local)
+{
+    orig->tight = local->tight;
+    orig->zlib = local->zlib;
+    orig->hextile = local->hextile;
+    orig->zrle = local->zrle;
+    orig->lossy_rect = local->lossy_rect;
+
+    queue->buffer = local->output;
+}
+
+static int vnc_worker_thread_loop(VncJobQueue *queue)
+{
+    VncJob *job;
+    VncRectEntry *entry, *tmp;
+    VncState vs;
+    int n_rectangles;
+    int saved_offset;
+
+    vnc_lock_queue(queue);
+    while (QTAILQ_EMPTY(&queue->jobs)&&  !queue->exit) {
+        qemu_cond_wait(&queue->cond,&queue->mutex);
+    }
+    /* Here job can only be NULL if queue->exit is true */
+    job = QTAILQ_FIRST(&queue->jobs);
+    vnc_unlock_queue(queue);
+
+    if (queue->exit) {
+        return -1;
+    }
+
+    vnc_lock_output(job->vs);
+    if (job->vs->csock == -1 || job->vs->abort == true) {
+        vnc_unlock_output(job->vs);
+        goto disconnected;
+    }
+    vnc_unlock_output(job->vs);
+
+    /* Make a local copy of vs and switch output buffers */
+    vnc_async_encoding_start(job->vs,&vs);
+
+    /* Start sending rectangles */
+    n_rectangles = 0;
+    vnc_write_u8(&vs, VNC_MSG_SERVER_FRAMEBUFFER_UPDATE);
+    vnc_write_u8(&vs, 0);
+    saved_offset = vs.output.offset;
+    vnc_write_u16(&vs, 0);
+
+    vnc_lock_display(job->vs->vd);
+    QLIST_FOREACH_SAFE(entry,&job->rectangles, next, tmp) {
+        int n;
+
+        if (job->vs->csock == -1) {
+            vnc_unlock_display(job->vs->vd);
+            goto disconnected;
+        }
+
+        n = vnc_send_framebuffer_update(&vs, entry->rect.x, entry->rect.y,
+                                        entry->rect.w, entry->rect.h);
+
+        if (n>= 0) {
+            n_rectangles += n;
+        }
+        g_free(entry);
+    }
+    vnc_unlock_display(job->vs->vd);
+
+    /* Put n_rectangles at the beginning of the message */
+    vs.output.buffer[saved_offset] = (n_rectangles>>  8)&  0xFF;
+    vs.output.buffer[saved_offset + 1] = n_rectangles&  0xFF;
+
+    vnc_lock_output(job->vs);
+    if (job->vs->csock != -1) {
+        buffer_reserve(&job->vs->jobs_buffer, vs.output.offset);
+        buffer_append(&job->vs->jobs_buffer, vs.output.buffer,
+                      vs.output.offset);
+        /* Copy persistent encoding data */
+        vnc_async_encoding_end(job->vs,&vs);
+
+       qemu_bh_schedule(job->vs->bh);
+    }
+    vnc_unlock_output(job->vs);
+
+disconnected:
+    vnc_lock_queue(queue);
+    QTAILQ_REMOVE(&queue->jobs, job, next);
+    vnc_unlock_queue(queue);
+    qemu_cond_broadcast(&queue->cond);
+    g_free(job);
+    return 0;
+}
+
+static VncJobQueue *vnc_queue_init(void)
+{
+    VncJobQueue *queue = g_malloc0(sizeof(VncJobQueue));
+
+    qemu_cond_init(&queue->cond);
+    qemu_mutex_init(&queue->mutex);
+    QTAILQ_INIT(&queue->jobs);
+    return queue;
+}
+
+static void vnc_queue_clear(VncJobQueue *q)
+{
+    qemu_cond_destroy(&queue->cond);
+    qemu_mutex_destroy(&queue->mutex);
+    buffer_free(&queue->buffer);
+    g_free(q);
+    queue = NULL; /* Unset global queue */
+}
+
+static void *vnc_worker_thread(void *arg)
+{
+    VncJobQueue *queue = arg;
+
+    qemu_thread_get_self(&queue->thread);
+
+    while (!vnc_worker_thread_loop(queue)) ;
+    vnc_queue_clear(queue);
+    return NULL;
+}
+
+void vnc_start_worker_thread(void)
+{
+    VncJobQueue *q;
+
+    if (vnc_worker_thread_running())
+        return ;
+
+    q = vnc_queue_init();
+    qemu_thread_create(&q->thread, vnc_worker_thread, q, QEMU_THREAD_DETACHED);
+    queue = q; /* Set global queue */
+}
+
+bool vnc_worker_thread_running(void)
+{
+    return queue; /* Check global queue */
+}
+
+void vnc_stop_worker_thread(void)
+{
+    if (!vnc_worker_thread_running())
+        return ;
+
+    /* Remove all jobs and wake up the thread */
+    vnc_lock_queue(queue);
+    queue->exit = true;
+    vnc_unlock_queue(queue);
+    vnc_jobs_clear(NULL);
+    qemu_cond_broadcast(&queue->cond);
+}
diff --git a/ui/vnc-jobs.h b/ui/vnc-jobs.h
index 4c661f9..86e6d88 100644
--- a/ui/vnc-jobs.h
+++ b/ui/vnc-jobs.h
@@ -38,51 +38,35 @@ bool vnc_has_job(VncState *vs);
  void vnc_jobs_clear(VncState *vs);
  void vnc_jobs_join(VncState *vs);

-#ifdef CONFIG_VNC_THREAD
-
  void vnc_jobs_consume_buffer(VncState *vs);
  void vnc_start_worker_thread(void);
  bool vnc_worker_thread_running(void);
  void vnc_stop_worker_thread(void);

-#endif /* CONFIG_VNC_THREAD */
-
  /* Locks */
  static inline int vnc_trylock_display(VncDisplay *vd)
  {
-#ifdef CONFIG_VNC_THREAD
      return qemu_mutex_trylock(&vd->mutex);
-#else
-    return 0;
-#endif
  }

  static inline void vnc_lock_display(VncDisplay *vd)
  {
-#ifdef CONFIG_VNC_THREAD
      qemu_mutex_lock(&vd->mutex);
-#endif
  }

  static inline void vnc_unlock_display(VncDisplay *vd)
  {
-#ifdef CONFIG_VNC_THREAD
      qemu_mutex_unlock(&vd->mutex);
-#endif
  }

  static inline void vnc_lock_output(VncState *vs)
  {
-#ifdef CONFIG_VNC_THREAD
      qemu_mutex_lock(&vs->output_mutex);
-#endif
  }

  static inline void vnc_unlock_output(VncState *vs)
  {
-#ifdef CONFIG_VNC_THREAD
      qemu_mutex_unlock(&vs->output_mutex);
-#endif
  }

  #endif /* VNC_JOBS_H */
diff --git a/ui/vnc.c b/ui/vnc.c
index 54bc5ad..cf1cae2 100644
--- a/ui/vnc.c
+++ b/ui/vnc.c
@@ -526,7 +526,6 @@ static void vnc_desktop_resize(VncState *vs)
      vnc_flush(vs);
  }

-#ifdef CONFIG_VNC_THREAD
  static void vnc_abort_display_jobs(VncDisplay *vd)
  {
      VncState *vs;
@@ -545,11 +544,6 @@ static void vnc_abort_display_jobs(VncDisplay *vd)
          vnc_unlock_output(vs);
      }
  }
-#else
-static void vnc_abort_display_jobs(VncDisplay *vd)
-{
-}
-#endif

  static void vnc_dpy_resize(DisplayState *ds)
  {
@@ -867,19 +861,12 @@ static int find_and_clear_dirty_height(struct VncState 
*vs,
      return h;
  }

-#ifdef CONFIG_VNC_THREAD
  static int vnc_update_client_sync(VncState *vs, int has_dirty)
  {
      int ret = vnc_update_client(vs, has_dirty);
      vnc_jobs_join(vs);
      return ret;
  }
-#else
-static int vnc_update_client_sync(VncState *vs, int has_dirty)
-{
-    return vnc_update_client(vs, has_dirty);
-}
-#endif

  static int vnc_update_client(VncState *vs, int has_dirty)
  {
@@ -1066,11 +1053,9 @@ static void vnc_disconnect_finish(VncState *vs)
          qemu_remove_led_event_handler(vs->led);
      vnc_unlock_output(vs);

-#ifdef CONFIG_VNC_THREAD
      qemu_mutex_destroy(&vs->output_mutex);
      qemu_bh_delete(vs->bh);
      buffer_free(&vs->jobs_buffer);
-#endif

      for (i = 0; i<  VNC_STAT_ROWS; ++i) {
          g_free(vs->lossy_rect[i]);
@@ -1286,14 +1271,12 @@ static long vnc_client_read_plain(VncState *vs)
      return ret;
  }

-#ifdef CONFIG_VNC_THREAD
  static void vnc_jobs_bh(void *opaque)
  {
      VncState *vs = opaque;

      vnc_jobs_consume_buffer(vs);
  }
-#endif

  /*
   * First function called whenever there is more data to be read from
@@ -2699,10 +2682,8 @@ static void vnc_connect(VncDisplay *vd, int csock, int 
skipauth)
      vs->as.fmt = AUD_FMT_S16;
      vs->as.endianness = 0;

-#ifdef CONFIG_VNC_THREAD
      qemu_mutex_init(&vs->output_mutex);
      vs->bh = qemu_bh_new(vnc_jobs_bh, vs);
-#endif

      QTAILQ_INSERT_HEAD(&vd->clients, vs, next);

@@ -2762,10 +2743,8 @@ void vnc_display_init(DisplayState *ds)
      if (!vs->kbd_layout)
          exit(1);

-#ifdef CONFIG_VNC_THREAD
      qemu_mutex_init(&vs->mutex);
      vnc_start_worker_thread();
-#endif

      dcl->dpy_copy = vnc_dpy_copy;
      dcl->dpy_update = vnc_dpy_update;
diff --git a/ui/vnc.h b/ui/vnc.h
index a851ebd..068c2fc 100644
--- a/ui/vnc.h
+++ b/ui/vnc.h
@@ -29,9 +29,7 @@

  #include "qemu-common.h"
  #include "qemu-queue.h"
-#ifdef CONFIG_VNC_THREAD
  #include "qemu-thread.h"
-#endif
  #include "console.h"
  #include "monitor.h"
  #include "audio/audio.h"
@@ -146,9 +144,7 @@ struct VncDisplay
      DisplayState *ds;
      kbd_layout_t *kbd_layout;
      int lock_key_sync;
-#ifdef CONFIG_VNC_THREAD
      QemuMutex mutex;
-#endif

      QEMUCursor *cursor;
      int cursor_msize;
@@ -216,7 +212,6 @@ typedef struct VncZywrle {
      int buf[VNC_ZRLE_TILE_WIDTH * VNC_ZRLE_TILE_HEIGHT];
  } VncZywrle;

-#ifdef CONFIG_VNC_THREAD
  struct VncRect
  {
      int x;
@@ -238,14 +233,6 @@ struct VncJob
      QLIST_HEAD(, VncRectEntry) rectangles;
      QTAILQ_ENTRY(VncJob) next;
  };
-#else
-struct VncJob
-{
-    VncState *vs;
-    int rectangles;
-    size_t saved_offset;
-};
-#endif

  struct VncState
  {
@@ -300,13 +287,9 @@ struct VncState
      QEMUPutLEDEntry *led;

      bool abort;
-#ifndef CONFIG_VNC_THREAD
-    VncJob job;
-#else
      QemuMutex output_mutex;
      QEMUBH *bh;
      Buffer jobs_buffer;
-#endif

      /* Encoding specific, if you add something here, don't forget to
       *  update vnc_async_encoding_start()




reply via email to

[Prev in Thread] Current Thread [Next in Thread]