From 2624bab836662d37f08336408a99d97652fc9c4d Mon Sep 17 00:00:00 2001 From: "Daniel P. Berrange" Date: Wed, 20 Jun 2012 14:24:28 +0100 Subject: Remove support for non-threaded VNC server 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 Signed-off-by: Anthony Liguori --- 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 --- 7 files changed, 352 insertions(+), 483 deletions(-) delete mode 100644 ui/vnc-jobs-async.c delete mode 100644 ui/vnc-jobs-sync.c create mode 100644 ui/vnc-jobs.c (limited to 'ui') diff --git a/ui/Makefile.objs b/ui/Makefile.objs index 3687c8a518..adc07be761 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 087b84d319..0000000000 --- a/ui/vnc-jobs-async.c +++ /dev/null @@ -1,351 +0,0 @@ -/* - * QEMU VNC display driver - * - * Copyright (C) 2006 Anthony Liguori - * Copyright (C) 2006 Fabrice Bellard - * Copyright (C) 2009 Red Hat, Inc - * Copyright (C) 2010 Corentin Chary - * - * 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 49b77afcc9..0000000000 --- a/ui/vnc-jobs-sync.c +++ /dev/null @@ -1,73 +0,0 @@ -/* - * QEMU VNC display driver - * - * Copyright (C) 2006 Anthony Liguori - * Copyright (C) 2006 Fabrice Bellard - * Copyright (C) 2009 Red Hat, Inc - * Copyright (C) 2010 Corentin Chary - * - * 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 0000000000..087b84d319 --- /dev/null +++ b/ui/vnc-jobs.c @@ -0,0 +1,351 @@ +/* + * QEMU VNC display driver + * + * Copyright (C) 2006 Anthony Liguori + * Copyright (C) 2006 Fabrice Bellard + * Copyright (C) 2009 Red Hat, Inc + * Copyright (C) 2010 Corentin Chary + * + * 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 4c661f95e5..86e6d888c6 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 54bc5adab6..cf1cae2de4 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 a851ebd8ea..068c2fcda5 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() -- cgit v1.2.1