root / ui / vnc-jobs-async.c @ 957f1f99
History | View | Annotate | Download (8.8 kB)
1 | bd023f95 | Corentin Chary | /*
|
---|---|---|---|
2 | bd023f95 | Corentin Chary | * QEMU VNC display driver
|
3 | bd023f95 | Corentin Chary | *
|
4 | bd023f95 | Corentin Chary | * Copyright (C) 2006 Anthony Liguori <anthony@codemonkey.ws>
|
5 | bd023f95 | Corentin Chary | * Copyright (C) 2006 Fabrice Bellard
|
6 | bd023f95 | Corentin Chary | * Copyright (C) 2009 Red Hat, Inc
|
7 | bd023f95 | Corentin Chary | * Copyright (C) 2010 Corentin Chary <corentin.chary@gmail.com>
|
8 | bd023f95 | Corentin Chary | *
|
9 | bd023f95 | Corentin Chary | * Permission is hereby granted, free of charge, to any person obtaining a copy
|
10 | bd023f95 | Corentin Chary | * of this software and associated documentation files (the "Software"), to deal
|
11 | bd023f95 | Corentin Chary | * in the Software without restriction, including without limitation the rights
|
12 | bd023f95 | Corentin Chary | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
13 | bd023f95 | Corentin Chary | * copies of the Software, and to permit persons to whom the Software is
|
14 | bd023f95 | Corentin Chary | * furnished to do so, subject to the following conditions:
|
15 | bd023f95 | Corentin Chary | *
|
16 | bd023f95 | Corentin Chary | * The above copyright notice and this permission notice shall be included in
|
17 | bd023f95 | Corentin Chary | * all copies or substantial portions of the Software.
|
18 | bd023f95 | Corentin Chary | *
|
19 | bd023f95 | Corentin Chary | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
20 | bd023f95 | Corentin Chary | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
21 | bd023f95 | Corentin Chary | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
22 | bd023f95 | Corentin Chary | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
23 | bd023f95 | Corentin Chary | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
24 | bd023f95 | Corentin Chary | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
25 | bd023f95 | Corentin Chary | * THE SOFTWARE.
|
26 | bd023f95 | Corentin Chary | */
|
27 | bd023f95 | Corentin Chary | |
28 | bd023f95 | Corentin Chary | |
29 | bd023f95 | Corentin Chary | #include "vnc.h" |
30 | bd023f95 | Corentin Chary | #include "vnc-jobs.h" |
31 | bd023f95 | Corentin Chary | |
32 | bd023f95 | Corentin Chary | /*
|
33 | bd023f95 | Corentin Chary | * Locking:
|
34 | bd023f95 | Corentin Chary | *
|
35 | bd023f95 | Corentin Chary | * There is three levels of locking:
|
36 | bd023f95 | Corentin Chary | * - jobs queue lock: for each operation on the queue (push, pop, isEmpty?)
|
37 | bd023f95 | Corentin Chary | * - VncDisplay global lock: mainly used for framebuffer updates to avoid
|
38 | bd023f95 | Corentin Chary | * screen corruption if the framebuffer is updated
|
39 | bd023f95 | Corentin Chary | * while the worker is doing something.
|
40 | bd023f95 | Corentin Chary | * - VncState::output lock: used to make sure the output buffer is not corrupted
|
41 | bd023f95 | Corentin Chary | * if two threads try to write on it at the same time
|
42 | bd023f95 | Corentin Chary | *
|
43 | bd023f95 | Corentin Chary | * While the VNC worker thread is working, the VncDisplay global lock is hold
|
44 | bd023f95 | Corentin Chary | * to avoid screen corruptions (this does not block vnc_refresh() because it
|
45 | bd023f95 | Corentin Chary | * uses trylock()) but the output lock is not hold because the thread work on
|
46 | bd023f95 | Corentin Chary | * its own output buffer.
|
47 | bd023f95 | Corentin Chary | * When the encoding job is done, the worker thread will hold the output lock
|
48 | bd023f95 | Corentin Chary | * and copy its output buffer in vs->output.
|
49 | bd023f95 | Corentin Chary | */
|
50 | bd023f95 | Corentin Chary | |
51 | bd023f95 | Corentin Chary | struct VncJobQueue {
|
52 | bd023f95 | Corentin Chary | QemuCond cond; |
53 | bd023f95 | Corentin Chary | QemuMutex mutex; |
54 | bd023f95 | Corentin Chary | QemuThread thread; |
55 | bd023f95 | Corentin Chary | Buffer buffer; |
56 | bd023f95 | Corentin Chary | bool exit;
|
57 | bd023f95 | Corentin Chary | QTAILQ_HEAD(, VncJob) jobs; |
58 | bd023f95 | Corentin Chary | }; |
59 | bd023f95 | Corentin Chary | |
60 | bd023f95 | Corentin Chary | typedef struct VncJobQueue VncJobQueue; |
61 | bd023f95 | Corentin Chary | |
62 | bd023f95 | Corentin Chary | /*
|
63 | bd023f95 | Corentin Chary | * We use a single global queue, but most of the functions are
|
64 | bd023f95 | Corentin Chary | * already reetrant, so we can easilly add more than one encoding thread
|
65 | bd023f95 | Corentin Chary | */
|
66 | bd023f95 | Corentin Chary | static VncJobQueue *queue;
|
67 | bd023f95 | Corentin Chary | |
68 | bd023f95 | Corentin Chary | static void vnc_lock_queue(VncJobQueue *queue) |
69 | bd023f95 | Corentin Chary | { |
70 | bd023f95 | Corentin Chary | qemu_mutex_lock(&queue->mutex); |
71 | bd023f95 | Corentin Chary | } |
72 | bd023f95 | Corentin Chary | |
73 | bd023f95 | Corentin Chary | static void vnc_unlock_queue(VncJobQueue *queue) |
74 | bd023f95 | Corentin Chary | { |
75 | bd023f95 | Corentin Chary | qemu_mutex_unlock(&queue->mutex); |
76 | bd023f95 | Corentin Chary | } |
77 | bd023f95 | Corentin Chary | |
78 | bd023f95 | Corentin Chary | VncJob *vnc_job_new(VncState *vs) |
79 | bd023f95 | Corentin Chary | { |
80 | 7267c094 | Anthony Liguori | VncJob *job = g_malloc0(sizeof(VncJob));
|
81 | bd023f95 | Corentin Chary | |
82 | bd023f95 | Corentin Chary | job->vs = vs; |
83 | bd023f95 | Corentin Chary | vnc_lock_queue(queue); |
84 | bd023f95 | Corentin Chary | QLIST_INIT(&job->rectangles); |
85 | bd023f95 | Corentin Chary | vnc_unlock_queue(queue); |
86 | bd023f95 | Corentin Chary | return job;
|
87 | bd023f95 | Corentin Chary | } |
88 | bd023f95 | Corentin Chary | |
89 | bd023f95 | Corentin Chary | int vnc_job_add_rect(VncJob *job, int x, int y, int w, int h) |
90 | bd023f95 | Corentin Chary | { |
91 | 7267c094 | Anthony Liguori | VncRectEntry *entry = g_malloc0(sizeof(VncRectEntry));
|
92 | bd023f95 | Corentin Chary | |
93 | bd023f95 | Corentin Chary | entry->rect.x = x; |
94 | bd023f95 | Corentin Chary | entry->rect.y = y; |
95 | bd023f95 | Corentin Chary | entry->rect.w = w; |
96 | bd023f95 | Corentin Chary | entry->rect.h = h; |
97 | bd023f95 | Corentin Chary | |
98 | bd023f95 | Corentin Chary | vnc_lock_queue(queue); |
99 | bd023f95 | Corentin Chary | QLIST_INSERT_HEAD(&job->rectangles, entry, next); |
100 | bd023f95 | Corentin Chary | vnc_unlock_queue(queue); |
101 | bd023f95 | Corentin Chary | return 1; |
102 | bd023f95 | Corentin Chary | } |
103 | bd023f95 | Corentin Chary | |
104 | bd023f95 | Corentin Chary | void vnc_job_push(VncJob *job)
|
105 | bd023f95 | Corentin Chary | { |
106 | bd023f95 | Corentin Chary | vnc_lock_queue(queue); |
107 | bd023f95 | Corentin Chary | if (queue->exit || QLIST_EMPTY(&job->rectangles)) {
|
108 | 7267c094 | Anthony Liguori | g_free(job); |
109 | bd023f95 | Corentin Chary | } else {
|
110 | bd023f95 | Corentin Chary | QTAILQ_INSERT_TAIL(&queue->jobs, job, next); |
111 | bd023f95 | Corentin Chary | qemu_cond_broadcast(&queue->cond); |
112 | bd023f95 | Corentin Chary | } |
113 | bd023f95 | Corentin Chary | vnc_unlock_queue(queue); |
114 | bd023f95 | Corentin Chary | } |
115 | bd023f95 | Corentin Chary | |
116 | bd023f95 | Corentin Chary | static bool vnc_has_job_locked(VncState *vs) |
117 | bd023f95 | Corentin Chary | { |
118 | bd023f95 | Corentin Chary | VncJob *job; |
119 | bd023f95 | Corentin Chary | |
120 | bd023f95 | Corentin Chary | QTAILQ_FOREACH(job, &queue->jobs, next) { |
121 | bd023f95 | Corentin Chary | if (job->vs == vs || !vs) {
|
122 | bd023f95 | Corentin Chary | return true; |
123 | bd023f95 | Corentin Chary | } |
124 | bd023f95 | Corentin Chary | } |
125 | bd023f95 | Corentin Chary | return false; |
126 | bd023f95 | Corentin Chary | } |
127 | bd023f95 | Corentin Chary | |
128 | bd023f95 | Corentin Chary | bool vnc_has_job(VncState *vs)
|
129 | bd023f95 | Corentin Chary | { |
130 | bd023f95 | Corentin Chary | bool ret;
|
131 | bd023f95 | Corentin Chary | |
132 | bd023f95 | Corentin Chary | vnc_lock_queue(queue); |
133 | bd023f95 | Corentin Chary | ret = vnc_has_job_locked(vs); |
134 | bd023f95 | Corentin Chary | vnc_unlock_queue(queue); |
135 | bd023f95 | Corentin Chary | return ret;
|
136 | bd023f95 | Corentin Chary | } |
137 | bd023f95 | Corentin Chary | |
138 | bd023f95 | Corentin Chary | void vnc_jobs_clear(VncState *vs)
|
139 | bd023f95 | Corentin Chary | { |
140 | bd023f95 | Corentin Chary | VncJob *job, *tmp; |
141 | bd023f95 | Corentin Chary | |
142 | bd023f95 | Corentin Chary | vnc_lock_queue(queue); |
143 | bd023f95 | Corentin Chary | QTAILQ_FOREACH_SAFE(job, &queue->jobs, next, tmp) { |
144 | bd023f95 | Corentin Chary | if (job->vs == vs || !vs) {
|
145 | bd023f95 | Corentin Chary | QTAILQ_REMOVE(&queue->jobs, job, next); |
146 | bd023f95 | Corentin Chary | } |
147 | bd023f95 | Corentin Chary | } |
148 | bd023f95 | Corentin Chary | vnc_unlock_queue(queue); |
149 | bd023f95 | Corentin Chary | } |
150 | bd023f95 | Corentin Chary | |
151 | bd023f95 | Corentin Chary | void vnc_jobs_join(VncState *vs)
|
152 | bd023f95 | Corentin Chary | { |
153 | bd023f95 | Corentin Chary | vnc_lock_queue(queue); |
154 | bd023f95 | Corentin Chary | while (vnc_has_job_locked(vs)) {
|
155 | bd023f95 | Corentin Chary | qemu_cond_wait(&queue->cond, &queue->mutex); |
156 | bd023f95 | Corentin Chary | } |
157 | bd023f95 | Corentin Chary | vnc_unlock_queue(queue); |
158 | bd023f95 | Corentin Chary | } |
159 | bd023f95 | Corentin Chary | |
160 | bd023f95 | Corentin Chary | /*
|
161 | bd023f95 | Corentin Chary | * Copy data for local use
|
162 | bd023f95 | Corentin Chary | */
|
163 | bd023f95 | Corentin Chary | static void vnc_async_encoding_start(VncState *orig, VncState *local) |
164 | bd023f95 | Corentin Chary | { |
165 | bd023f95 | Corentin Chary | local->vnc_encoding = orig->vnc_encoding; |
166 | bd023f95 | Corentin Chary | local->features = orig->features; |
167 | bd023f95 | Corentin Chary | local->ds = orig->ds; |
168 | bd023f95 | Corentin Chary | local->vd = orig->vd; |
169 | 7d964c9d | Corentin Chary | local->lossy_rect = orig->lossy_rect; |
170 | bd023f95 | Corentin Chary | local->write_pixels = orig->write_pixels; |
171 | bd023f95 | Corentin Chary | local->clientds = orig->clientds; |
172 | bd023f95 | Corentin Chary | local->tight = orig->tight; |
173 | bd023f95 | Corentin Chary | local->zlib = orig->zlib; |
174 | bd023f95 | Corentin Chary | local->hextile = orig->hextile; |
175 | 148954fa | Corentin Chary | local->zrle = orig->zrle; |
176 | bd023f95 | Corentin Chary | local->output = queue->buffer; |
177 | bd023f95 | Corentin Chary | local->csock = -1; /* Don't do any network work on this thread */ |
178 | bd023f95 | Corentin Chary | |
179 | bd023f95 | Corentin Chary | buffer_reset(&local->output); |
180 | bd023f95 | Corentin Chary | } |
181 | bd023f95 | Corentin Chary | |
182 | bd023f95 | Corentin Chary | static void vnc_async_encoding_end(VncState *orig, VncState *local) |
183 | bd023f95 | Corentin Chary | { |
184 | bd023f95 | Corentin Chary | orig->tight = local->tight; |
185 | bd023f95 | Corentin Chary | orig->zlib = local->zlib; |
186 | bd023f95 | Corentin Chary | orig->hextile = local->hextile; |
187 | 148954fa | Corentin Chary | orig->zrle = local->zrle; |
188 | 7d964c9d | Corentin Chary | orig->lossy_rect = local->lossy_rect; |
189 | c53af37f | Corentin Chary | |
190 | c53af37f | Corentin Chary | queue->buffer = local->output; |
191 | bd023f95 | Corentin Chary | } |
192 | bd023f95 | Corentin Chary | |
193 | bd023f95 | Corentin Chary | static int vnc_worker_thread_loop(VncJobQueue *queue) |
194 | bd023f95 | Corentin Chary | { |
195 | bd023f95 | Corentin Chary | VncJob *job; |
196 | bd023f95 | Corentin Chary | VncRectEntry *entry, *tmp; |
197 | bd023f95 | Corentin Chary | VncState vs; |
198 | bd023f95 | Corentin Chary | int n_rectangles;
|
199 | bd023f95 | Corentin Chary | int saved_offset;
|
200 | bd023f95 | Corentin Chary | bool flush;
|
201 | bd023f95 | Corentin Chary | |
202 | bd023f95 | Corentin Chary | vnc_lock_queue(queue); |
203 | bd023f95 | Corentin Chary | while (QTAILQ_EMPTY(&queue->jobs) && !queue->exit) {
|
204 | bd023f95 | Corentin Chary | qemu_cond_wait(&queue->cond, &queue->mutex); |
205 | bd023f95 | Corentin Chary | } |
206 | bd023f95 | Corentin Chary | /* Here job can only be NULL if queue->exit is true */
|
207 | bd023f95 | Corentin Chary | job = QTAILQ_FIRST(&queue->jobs); |
208 | bd023f95 | Corentin Chary | vnc_unlock_queue(queue); |
209 | bd023f95 | Corentin Chary | |
210 | bd023f95 | Corentin Chary | if (queue->exit) {
|
211 | bd023f95 | Corentin Chary | return -1; |
212 | bd023f95 | Corentin Chary | } |
213 | bd023f95 | Corentin Chary | |
214 | bd023f95 | Corentin Chary | vnc_lock_output(job->vs); |
215 | bd023f95 | Corentin Chary | if (job->vs->csock == -1 || job->vs->abort == true) { |
216 | bd023f95 | Corentin Chary | goto disconnected;
|
217 | bd023f95 | Corentin Chary | } |
218 | bd023f95 | Corentin Chary | vnc_unlock_output(job->vs); |
219 | bd023f95 | Corentin Chary | |
220 | bd023f95 | Corentin Chary | /* Make a local copy of vs and switch output buffers */
|
221 | bd023f95 | Corentin Chary | vnc_async_encoding_start(job->vs, &vs); |
222 | bd023f95 | Corentin Chary | |
223 | bd023f95 | Corentin Chary | /* Start sending rectangles */
|
224 | bd023f95 | Corentin Chary | n_rectangles = 0;
|
225 | bd023f95 | Corentin Chary | vnc_write_u8(&vs, VNC_MSG_SERVER_FRAMEBUFFER_UPDATE); |
226 | bd023f95 | Corentin Chary | vnc_write_u8(&vs, 0);
|
227 | bd023f95 | Corentin Chary | saved_offset = vs.output.offset; |
228 | bd023f95 | Corentin Chary | vnc_write_u16(&vs, 0);
|
229 | bd023f95 | Corentin Chary | |
230 | bd023f95 | Corentin Chary | vnc_lock_display(job->vs->vd); |
231 | bd023f95 | Corentin Chary | QLIST_FOREACH_SAFE(entry, &job->rectangles, next, tmp) { |
232 | bd023f95 | Corentin Chary | int n;
|
233 | bd023f95 | Corentin Chary | |
234 | bd023f95 | Corentin Chary | if (job->vs->csock == -1) { |
235 | bd023f95 | Corentin Chary | vnc_unlock_display(job->vs->vd); |
236 | 73eb4c04 | Corentin Chary | /* output mutex must be locked before going to
|
237 | 73eb4c04 | Corentin Chary | * disconnected:
|
238 | 73eb4c04 | Corentin Chary | */
|
239 | 73eb4c04 | Corentin Chary | vnc_lock_output(job->vs); |
240 | bd023f95 | Corentin Chary | goto disconnected;
|
241 | bd023f95 | Corentin Chary | } |
242 | bd023f95 | Corentin Chary | |
243 | bd023f95 | Corentin Chary | n = vnc_send_framebuffer_update(&vs, entry->rect.x, entry->rect.y, |
244 | bd023f95 | Corentin Chary | entry->rect.w, entry->rect.h); |
245 | bd023f95 | Corentin Chary | |
246 | bd023f95 | Corentin Chary | if (n >= 0) { |
247 | bd023f95 | Corentin Chary | n_rectangles += n; |
248 | bd023f95 | Corentin Chary | } |
249 | 7267c094 | Anthony Liguori | g_free(entry); |
250 | bd023f95 | Corentin Chary | } |
251 | bd023f95 | Corentin Chary | vnc_unlock_display(job->vs->vd); |
252 | bd023f95 | Corentin Chary | |
253 | bd023f95 | Corentin Chary | /* Put n_rectangles at the beginning of the message */
|
254 | bd023f95 | Corentin Chary | vs.output.buffer[saved_offset] = (n_rectangles >> 8) & 0xFF; |
255 | bd023f95 | Corentin Chary | vs.output.buffer[saved_offset + 1] = n_rectangles & 0xFF; |
256 | bd023f95 | Corentin Chary | |
257 | bd023f95 | Corentin Chary | /* Switch back buffers */
|
258 | bd023f95 | Corentin Chary | vnc_lock_output(job->vs); |
259 | bd023f95 | Corentin Chary | if (job->vs->csock == -1) { |
260 | bd023f95 | Corentin Chary | goto disconnected;
|
261 | bd023f95 | Corentin Chary | } |
262 | bd023f95 | Corentin Chary | |
263 | bd023f95 | Corentin Chary | vnc_write(job->vs, vs.output.buffer, vs.output.offset); |
264 | bd023f95 | Corentin Chary | |
265 | bd023f95 | Corentin Chary | disconnected:
|
266 | bd023f95 | Corentin Chary | /* Copy persistent encoding data */
|
267 | bd023f95 | Corentin Chary | vnc_async_encoding_end(job->vs, &vs); |
268 | bd023f95 | Corentin Chary | flush = (job->vs->csock != -1 && job->vs->abort != true); |
269 | bd023f95 | Corentin Chary | vnc_unlock_output(job->vs); |
270 | bd023f95 | Corentin Chary | |
271 | bd023f95 | Corentin Chary | if (flush) {
|
272 | bd023f95 | Corentin Chary | vnc_flush(job->vs); |
273 | bd023f95 | Corentin Chary | } |
274 | bd023f95 | Corentin Chary | |
275 | bd023f95 | Corentin Chary | vnc_lock_queue(queue); |
276 | bd023f95 | Corentin Chary | QTAILQ_REMOVE(&queue->jobs, job, next); |
277 | bd023f95 | Corentin Chary | vnc_unlock_queue(queue); |
278 | bd023f95 | Corentin Chary | qemu_cond_broadcast(&queue->cond); |
279 | 7267c094 | Anthony Liguori | g_free(job); |
280 | bd023f95 | Corentin Chary | return 0; |
281 | bd023f95 | Corentin Chary | } |
282 | bd023f95 | Corentin Chary | |
283 | bd023f95 | Corentin Chary | static VncJobQueue *vnc_queue_init(void) |
284 | bd023f95 | Corentin Chary | { |
285 | 7267c094 | Anthony Liguori | VncJobQueue *queue = g_malloc0(sizeof(VncJobQueue));
|
286 | bd023f95 | Corentin Chary | |
287 | bd023f95 | Corentin Chary | qemu_cond_init(&queue->cond); |
288 | bd023f95 | Corentin Chary | qemu_mutex_init(&queue->mutex); |
289 | bd023f95 | Corentin Chary | QTAILQ_INIT(&queue->jobs); |
290 | bd023f95 | Corentin Chary | return queue;
|
291 | bd023f95 | Corentin Chary | } |
292 | bd023f95 | Corentin Chary | |
293 | bd023f95 | Corentin Chary | static void vnc_queue_clear(VncJobQueue *q) |
294 | bd023f95 | Corentin Chary | { |
295 | bd023f95 | Corentin Chary | qemu_cond_destroy(&queue->cond); |
296 | bd023f95 | Corentin Chary | qemu_mutex_destroy(&queue->mutex); |
297 | bd023f95 | Corentin Chary | buffer_free(&queue->buffer); |
298 | 7267c094 | Anthony Liguori | g_free(q); |
299 | bd023f95 | Corentin Chary | queue = NULL; /* Unset global queue */ |
300 | bd023f95 | Corentin Chary | } |
301 | bd023f95 | Corentin Chary | |
302 | bd023f95 | Corentin Chary | static void *vnc_worker_thread(void *arg) |
303 | bd023f95 | Corentin Chary | { |
304 | bd023f95 | Corentin Chary | VncJobQueue *queue = arg; |
305 | bd023f95 | Corentin Chary | |
306 | b7680cb6 | Jan Kiszka | qemu_thread_get_self(&queue->thread); |
307 | bd023f95 | Corentin Chary | |
308 | bd023f95 | Corentin Chary | while (!vnc_worker_thread_loop(queue)) ;
|
309 | bd023f95 | Corentin Chary | vnc_queue_clear(queue); |
310 | bd023f95 | Corentin Chary | return NULL; |
311 | bd023f95 | Corentin Chary | } |
312 | bd023f95 | Corentin Chary | |
313 | bd023f95 | Corentin Chary | void vnc_start_worker_thread(void) |
314 | bd023f95 | Corentin Chary | { |
315 | bd023f95 | Corentin Chary | VncJobQueue *q; |
316 | bd023f95 | Corentin Chary | |
317 | bd023f95 | Corentin Chary | if (vnc_worker_thread_running())
|
318 | bd023f95 | Corentin Chary | return ;
|
319 | bd023f95 | Corentin Chary | |
320 | bd023f95 | Corentin Chary | q = vnc_queue_init(); |
321 | bd023f95 | Corentin Chary | qemu_thread_create(&q->thread, vnc_worker_thread, q); |
322 | bd023f95 | Corentin Chary | queue = q; /* Set global queue */
|
323 | bd023f95 | Corentin Chary | } |
324 | bd023f95 | Corentin Chary | |
325 | bd023f95 | Corentin Chary | bool vnc_worker_thread_running(void) |
326 | bd023f95 | Corentin Chary | { |
327 | bd023f95 | Corentin Chary | return queue; /* Check global queue */ |
328 | bd023f95 | Corentin Chary | } |
329 | bd023f95 | Corentin Chary | |
330 | bd023f95 | Corentin Chary | void vnc_stop_worker_thread(void) |
331 | bd023f95 | Corentin Chary | { |
332 | bd023f95 | Corentin Chary | if (!vnc_worker_thread_running())
|
333 | bd023f95 | Corentin Chary | return ;
|
334 | bd023f95 | Corentin Chary | |
335 | bd023f95 | Corentin Chary | /* Remove all jobs and wake up the thread */
|
336 | bd023f95 | Corentin Chary | vnc_lock_queue(queue); |
337 | bd023f95 | Corentin Chary | queue->exit = true;
|
338 | bd023f95 | Corentin Chary | vnc_unlock_queue(queue); |
339 | bd023f95 | Corentin Chary | vnc_jobs_clear(NULL);
|
340 | bd023f95 | Corentin Chary | qemu_cond_broadcast(&queue->cond); |
341 | bd023f95 | Corentin Chary | } |