---
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<anth...@codemonkey.ws>
- * Copyright (C) 2006 Fabrice Bellard
- * Copyright (C) 2009 Red Hat, Inc
- * Copyright (C) 2010 Corentin Chary<corentin.ch...@gmail.com>
- *
- * 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<anth...@codemonkey.ws>
- * Copyright (C) 2006 Fabrice Bellard
- * Copyright (C) 2009 Red Hat, Inc
- * Copyright (C) 2010 Corentin Chary<corentin.ch...@gmail.com>
- *
- * 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<anth...@codemonkey.ws>
+ * Copyright (C) 2006 Fabrice Bellard
+ * Copyright (C) 2009 Red Hat, Inc
+ * Copyright (C) 2010 Corentin Chary<corentin.ch...@gmail.com>
+ *
+ * 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()