summary refs log tree commit diff stats
path: root/ui/vnc-enc-zlib.c
diff options
context:
space:
mode:
authorAkihiko Odaki <odaki@rsg.ci.i.u-tokyo.ac.jp>2025-06-03 18:18:29 +0900
committerMarc-André Lureau <marcandre.lureau@redhat.com>2025-07-14 14:51:12 +0400
commit37ff925d5d4a70a951ade42094896246c989742f (patch)
tree4c2d92b4b36b860862d9a31ed3a5ab2e0405d19a /ui/vnc-enc-zlib.c
parentaef22331b5a4670f42638a5f63a26e93bf779aae (diff)
downloadfocaccia-qemu-37ff925d5d4a70a951ade42094896246c989742f.tar.gz
focaccia-qemu-37ff925d5d4a70a951ade42094896246c989742f.zip
ui/vnc: Introduce the VncWorker type
The worker thread copies data in VncState to avoid race, but some
data are too big to copy. Such data are held with pointers to avoid
the overhead to copy, but it requires tedious memory management and
makes them vulnerable to race.

Introduce the VncWorker type to contain all data shared without copying.
It allows allocating and freeing all shared data at once and shows that
the race with the worker thread needs to be taken care of when
accessing them.

Signed-off-by: Akihiko Odaki <odaki@rsg.ci.i.u-tokyo.ac.jp>
Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Message-Id: <20250603-zlib-v3-2-20b857bd8d05@rsg.ci.i.u-tokyo.ac.jp>
Diffstat (limited to 'ui/vnc-enc-zlib.c')
-rw-r--r--ui/vnc-enc-zlib.c47
1 files changed, 24 insertions, 23 deletions
diff --git a/ui/vnc-enc-zlib.c b/ui/vnc-enc-zlib.c
index 52e9193eab..a6d287118a 100644
--- a/ui/vnc-enc-zlib.c
+++ b/ui/vnc-enc-zlib.c
@@ -46,23 +46,23 @@ void vnc_zlib_zfree(void *x, void *addr)
     g_free(addr);
 }
 
-static void vnc_zlib_start(VncState *vs)
+static void vnc_zlib_start(VncState *vs, VncWorker *worker)
 {
-    buffer_reset(&vs->zlib->zlib);
+    buffer_reset(&worker->zlib.zlib);
 
     // make the output buffer be the zlib buffer, so we can compress it later
-    vs->zlib->tmp = vs->output;
-    vs->output = vs->zlib->zlib;
+    worker->zlib.tmp = vs->output;
+    vs->output = worker->zlib.zlib;
 }
 
-static int vnc_zlib_stop(VncState *vs)
+static int vnc_zlib_stop(VncState *vs, VncWorker *worker)
 {
-    z_streamp zstream = &vs->zlib->stream;
+    z_streamp zstream = &worker->zlib.stream;
     int previous_out;
 
     // switch back to normal output/zlib buffers
-    vs->zlib->zlib = vs->output;
-    vs->output = vs->zlib->tmp;
+    worker->zlib.zlib = vs->output;
+    vs->output = worker->zlib.tmp;
 
     // compress the zlib buffer
 
@@ -76,7 +76,7 @@ static int vnc_zlib_stop(VncState *vs)
         zstream->zalloc = vnc_zlib_zalloc;
         zstream->zfree = vnc_zlib_zfree;
 
-        err = deflateInit2(zstream, vs->tight->compression, Z_DEFLATED,
+        err = deflateInit2(zstream, worker->tight.compression, Z_DEFLATED,
                            MAX_WBITS,
                            MAX_MEM_LEVEL, Z_DEFAULT_STRATEGY);
 
@@ -85,24 +85,24 @@ static int vnc_zlib_stop(VncState *vs)
             return -1;
         }
 
-        vs->zlib->level = vs->tight->compression;
+        worker->zlib.level = worker->tight.compression;
         zstream->opaque = vs;
     }
 
-    if (vs->tight->compression != vs->zlib->level) {
-        if (deflateParams(zstream, vs->tight->compression,
+    if (worker->tight.compression != worker->zlib.level) {
+        if (deflateParams(zstream, worker->tight.compression,
                           Z_DEFAULT_STRATEGY) != Z_OK) {
             return -1;
         }
-        vs->zlib->level = vs->tight->compression;
+        worker->zlib.level = worker->tight.compression;
     }
 
     // reserve memory in output buffer
-    buffer_reserve(&vs->output, vs->zlib->zlib.offset + 64);
+    buffer_reserve(&vs->output, worker->zlib.zlib.offset + 64);
 
     // set pointers
-    zstream->next_in = vs->zlib->zlib.buffer;
-    zstream->avail_in = vs->zlib->zlib.offset;
+    zstream->next_in = worker->zlib.zlib.buffer;
+    zstream->avail_in = worker->zlib.zlib.offset;
     zstream->next_out = vs->output.buffer + vs->output.offset;
     zstream->avail_out = vs->output.capacity - vs->output.offset;
     previous_out = zstream->avail_out;
@@ -118,7 +118,8 @@ static int vnc_zlib_stop(VncState *vs)
     return previous_out - zstream->avail_out;
 }
 
-int vnc_zlib_send_framebuffer_update(VncState *vs, int x, int y, int w, int h)
+int vnc_zlib_send_framebuffer_update(VncState *vs, VncWorker *worker,
+                                     int x, int y, int w, int h)
 {
     int old_offset, new_offset, bytes_written;
 
@@ -129,9 +130,9 @@ int vnc_zlib_send_framebuffer_update(VncState *vs, int x, int y, int w, int h)
     vnc_write_s32(vs, 0);
 
     // compress the stream
-    vnc_zlib_start(vs);
+    vnc_zlib_start(vs, worker);
     vnc_raw_send_framebuffer_update(vs, x, y, w, h);
-    bytes_written = vnc_zlib_stop(vs);
+    bytes_written = vnc_zlib_stop(vs, worker);
 
     if (bytes_written == -1)
         return 0;
@@ -145,10 +146,10 @@ int vnc_zlib_send_framebuffer_update(VncState *vs, int x, int y, int w, int h)
     return 1;
 }
 
-void vnc_zlib_clear(VncState *vs)
+void vnc_zlib_clear(VncWorker *worker)
 {
-    if (vs->zlib->stream.opaque) {
-        deflateEnd(&vs->zlib->stream);
+    if (worker->zlib.stream.opaque) {
+        deflateEnd(&worker->zlib.stream);
     }
-    buffer_free(&vs->zlib->zlib);
+    buffer_free(&worker->zlib.zlib);
 }