WARNING - OLD ARCHIVES

This is an archived copy of the Xen.org mailing list, which we have preserved to ensure that existing links to archives are not broken. The live archive, which contains the latest emails, can be found at http://lists.xen.org/
   
 
 
Xen 
 
Home Products Support Community News
 
   
 

xen-changelog

[Xen-changelog] [xen-unstable] [HVM][VNC] Add a backoff feature to the v

To: xen-changelog@xxxxxxxxxxxxxxxxxxx
Subject: [Xen-changelog] [xen-unstable] [HVM][VNC] Add a backoff feature to the vnc server, so that if it detects
From: Xen patchbot-unstable <patchbot-unstable@xxxxxxxxxxxxxxxxxxx>
Date: Thu, 21 Sep 2006 20:02:37 +0000
Delivery-date: Thu, 21 Sep 2006 13:03:20 -0700
Envelope-to: www-data@xxxxxxxxxxxxxxxxxx
List-help: <mailto:xen-changelog-request@lists.xensource.com?subject=help>
List-id: BK change log <xen-changelog.lists.xensource.com>
List-post: <mailto:xen-changelog@lists.xensource.com>
List-subscribe: <http://lists.xensource.com/cgi-bin/mailman/listinfo/xen-changelog>, <mailto:xen-changelog-request@lists.xensource.com?subject=subscribe>
List-unsubscribe: <http://lists.xensource.com/cgi-bin/mailman/listinfo/xen-changelog>, <mailto:xen-changelog-request@lists.xensource.com?subject=unsubscribe>
Reply-to: xen-devel@xxxxxxxxxxxxxxxxxxx
Sender: xen-changelog-bounces@xxxxxxxxxxxxxxxxxxx
# HG changeset patch
# User Steven Smith <ssmith@xxxxxxxxxxxxx>
# Node ID 449dcaff25513813da8bcda94ffc85f3f14c5857
# Parent  c742b2ae920c45c476a4c8b7fd28870df124071e
[HVM][VNC] Add a backoff feature to the vnc server, so that if it detects
that the display hasn't changed for a while it starts scanning more slowly.

Signed-off-by: Steven Smith <sos22@xxxxxxxxx>
---
 tools/ioemu/vl.c  |    6 +
 tools/ioemu/vl.h  |    1 
 tools/ioemu/vnc.c |  254 ++++++++++++++++++++++++++++++++----------------------
 3 files changed, 158 insertions(+), 103 deletions(-)

diff -r c742b2ae920c -r 449dcaff2551 tools/ioemu/vl.c
--- a/tools/ioemu/vl.c  Thu Sep 21 17:56:14 2006 +0100
+++ b/tools/ioemu/vl.c  Thu Sep 21 18:29:48 2006 +0100
@@ -723,6 +723,12 @@ void qemu_del_timer(QEMUTimer *ts)
         }
         pt = &t->next;
     }
+}
+
+void qemu_advance_timer(QEMUTimer *ts, int64_t expire_time)
+{
+    if (ts->expire_time > expire_time)
+       qemu_mod_timer(ts, expire_time);
 }
 
 /* modify the current timer so that it will be fired when current_time
diff -r c742b2ae920c -r 449dcaff2551 tools/ioemu/vl.h
--- a/tools/ioemu/vl.h  Thu Sep 21 17:56:14 2006 +0100
+++ b/tools/ioemu/vl.h  Thu Sep 21 18:29:48 2006 +0100
@@ -405,6 +405,7 @@ void qemu_free_timer(QEMUTimer *ts);
 void qemu_free_timer(QEMUTimer *ts);
 void qemu_del_timer(QEMUTimer *ts);
 void qemu_mod_timer(QEMUTimer *ts, int64_t expire_time);
+void qemu_advance_timer(QEMUTimer *ts, int64_t expire_time);
 int qemu_timer_pending(QEMUTimer *ts);
 
 extern int64_t ticks_per_sec;
diff -r c742b2ae920c -r 449dcaff2551 tools/ioemu/vnc.c
--- a/tools/ioemu/vnc.c Thu Sep 21 17:56:14 2006 +0100
+++ b/tools/ioemu/vnc.c Thu Sep 21 18:29:48 2006 +0100
@@ -27,7 +27,19 @@
 #include "vl.h"
 #include "qemu_socket.h"
 
-#define VNC_REFRESH_INTERVAL (1000 / 30)
+/* The refresh interval starts at BASE.  If we scan the buffer and
+   find no change, we increase by INC, up to MAX.  If the mouse moves
+   or we get a keypress, the interval is set back to BASE.  If we find
+   an update, halve the interval.
+
+   All times in milliseconds. */
+#define VNC_REFRESH_INTERVAL_BASE 30
+#define VNC_REFRESH_INTERVAL_INC  50
+#define VNC_REFRESH_INTERVAL_MAX  2000
+
+/* Wait at most one second between updates, so that we can detect a
+   minimised vncviewer reasonably quickly. */
+#define VNC_MAX_UPDATE_INTERVAL   5000
 
 #include "vnc_keysym.h"
 #include "keymaps.c"
@@ -64,10 +76,11 @@ struct VncState
 struct VncState
 {
     QEMUTimer *timer;
+    int timer_interval;
+    int64_t last_update_time;
     int lsock;
     int csock;
     DisplayState *ds;
-    int need_update;
     int width;
     int height;
     uint64_t *dirty_row;       /* screen regions which are possibly dirty */
@@ -97,8 +110,6 @@ struct VncState
     int visible_y;
     int visible_w;
     int visible_h;
-
-    int slow_client;
 
     int ctl_keys;               /* Ctrl+Alt starts calibration */
 };
@@ -380,7 +391,7 @@ static void vnc_copy(DisplayState *ds, i
     int y = 0;
     int pitch = ds->linesize;
     VncState *vs = ds->opaque;
-    int updating_client = !vs->slow_client;
+    int updating_client = 1;
 
     if (src_x < vs->visible_x || src_y < vs->visible_y ||
        dst_x < vs->visible_x || dst_y < vs->visible_y ||
@@ -389,11 +400,6 @@ static void vnc_copy(DisplayState *ds, i
        (dst_x + w) > (vs->visible_x + vs->visible_w) ||
        (dst_y + h) > (vs->visible_y + vs->visible_h))
        updating_client = 0;
-
-    if (updating_client) {
-       vs->need_update = 1;
-       _vnc_update_client(vs);
-    }
 
     if (dst_y > src_y) {
        y = h - 1;
@@ -445,110 +451,145 @@ static void _vnc_update_client(void *opa
 static void _vnc_update_client(void *opaque)
 {
     VncState *vs = opaque;
-    int64_t now = qemu_get_clock(rt_clock);
-
-    if (vs->need_update && vs->csock != -1) {
-       int y;
-       char *row;
-       char *old_row;
-       uint64_t width_mask;
-       int n_rectangles;
-       int saved_offset;
-       int maxx, maxy;
-       int tile_bytes = vs->depth * DP2X(vs, 1);
-
-       qemu_mod_timer(vs->timer, now + VNC_REFRESH_INTERVAL);
-
-       if (vs->width != DP2X(vs, DIRTY_PIXEL_BITS))
-           width_mask = (1ULL << X2DP_UP(vs, vs->ds->width)) - 1;
-       else
-           width_mask = ~(0ULL);
-
-       /* Walk through the dirty map and eliminate tiles that
-          really aren't dirty */
-       row = vs->ds->data;
-       old_row = vs->old_data;
-
-       for (y = 0; y < vs->ds->height; y++) {
-           if (vs->dirty_row[y] & width_mask) {
-               int x;
-               char *ptr, *old_ptr;
-
-               ptr = row;
-               old_ptr = old_row;
-
-               for (x = 0; x < X2DP_UP(vs, vs->ds->width); x++) {
-                   if (vs->dirty_row[y] & (1ULL << x)) {
-                       if (memcmp(old_ptr, ptr, tile_bytes)) {
-                           vs->has_update = 1;
-                           vs->update_row[y] |= (1ULL << x);
-                           memcpy(old_ptr, ptr, tile_bytes);
-                       }
-                       vs->dirty_row[y] &= ~(1ULL << x);
+    int64_t now;
+    int y;
+    char *row;
+    char *old_row;
+    uint64_t width_mask;
+    int n_rectangles;
+    int saved_offset;
+    int maxx, maxy;
+    int tile_bytes = vs->depth * DP2X(vs, 1);
+
+    if (vs->csock == -1)
+       return;
+
+    now = qemu_get_clock(rt_clock);
+
+    if (vs->width != DP2X(vs, DIRTY_PIXEL_BITS))
+       width_mask = (1ULL << X2DP_UP(vs, vs->ds->width)) - 1;
+    else
+       width_mask = ~(0ULL);
+
+    /* Walk through the dirty map and eliminate tiles that really
+       aren't dirty */
+    row = vs->ds->data;
+    old_row = vs->old_data;
+
+    for (y = 0; y < vs->ds->height; y++) {
+       if (vs->dirty_row[y] & width_mask) {
+           int x;
+           char *ptr, *old_ptr;
+
+           ptr = row;
+           old_ptr = old_row;
+
+           for (x = 0; x < X2DP_UP(vs, vs->ds->width); x++) {
+               if (vs->dirty_row[y] & (1ULL << x)) {
+                   if (memcmp(old_ptr, ptr, tile_bytes)) {
+                       vs->has_update = 1;
+                       vs->update_row[y] |= (1ULL << x);
+                       memcpy(old_ptr, ptr, tile_bytes);
                    }
-
-                   ptr += tile_bytes;
-                   old_ptr += tile_bytes;
+                   vs->dirty_row[y] &= ~(1ULL << x);
                }
+
+               ptr += tile_bytes;
+               old_ptr += tile_bytes;
            }
-
-           row += vs->ds->linesize;
-           old_row += vs->ds->linesize;
        }
-
-       if (!vs->has_update || vs->visible_y >= vs->ds->height ||
-           vs->visible_x >= vs->ds->width)
-           return;
-
-       /* Count rectangles */
-       n_rectangles = 0;
-       vnc_write_u8(vs, 0);  /* msg id */
-       vnc_write_u8(vs, 0);
-       saved_offset = vs->output.offset;
-       vnc_write_u16(vs, 0);
-
-       maxy = vs->visible_y + vs->visible_h;
-       if (maxy > vs->ds->height)
-           maxy = vs->ds->height;
-       maxx = vs->visible_x + vs->visible_w;
-       if (maxx > vs->ds->width)
-           maxx = vs->ds->width;
-
-       for (y = vs->visible_y; y < maxy; y++) {
-           int x;
-           int last_x = -1;
-           for (x = X2DP_DOWN(vs, vs->visible_x);
-                x < X2DP_UP(vs, maxx); x++) {
-               if (vs->update_row[y] & (1ULL << x)) {
-                   if (last_x == -1)
-                       last_x = x;
-                   vs->update_row[y] &= ~(1ULL << x);
-               } else {
-                   if (last_x != -1) {
-                       int h = find_update_height(vs, y, maxy, last_x, x);
+  
+       row += vs->ds->linesize;
+       old_row += vs->ds->linesize;
+    }
+
+    if (!vs->has_update || vs->visible_y >= vs->ds->height ||
+       vs->visible_x >= vs->ds->width)
+       goto backoff;
+
+    /* Count rectangles */
+    n_rectangles = 0;
+    vnc_write_u8(vs, 0);  /* msg id */
+    vnc_write_u8(vs, 0);
+    saved_offset = vs->output.offset;
+    vnc_write_u16(vs, 0);
+    
+    maxy = vs->visible_y + vs->visible_h;
+    if (maxy > vs->ds->height)
+       maxy = vs->ds->height;
+    maxx = vs->visible_x + vs->visible_w;
+    if (maxx > vs->ds->width)
+       maxx = vs->ds->width;
+
+    for (y = vs->visible_y; y < maxy; y++) {
+       int x;
+       int last_x = -1;
+       for (x = X2DP_DOWN(vs, vs->visible_x);
+            x < X2DP_UP(vs, maxx); x++) {
+           if (vs->update_row[y] & (1ULL << x)) {
+               if (last_x == -1)
+                   last_x = x;
+               vs->update_row[y] &= ~(1ULL << x);
+           } else {
+               if (last_x != -1) {
+                   int h = find_update_height(vs, y, maxy, last_x, x);
+                   if (h != 0) {
                        send_framebuffer_update(vs, DP2X(vs, last_x), y,
                                                DP2X(vs, (x - last_x)), h);
                        n_rectangles++;
                    }
-                   last_x = -1;
                }
+               last_x = -1;
            }
-           if (last_x != -1) {
-               int h = find_update_height(vs, y, maxy, last_x, x);
+       }
+       if (last_x != -1) {
+           int h = find_update_height(vs, y, maxy, last_x, x);
+           if (h != 0) {
                send_framebuffer_update(vs, DP2X(vs, last_x), y,
                                        DP2X(vs, (x - last_x)), h);
                n_rectangles++;
            }
        }
-       vs->output.buffer[saved_offset] = (n_rectangles >> 8) & 0xFF;
-       vs->output.buffer[saved_offset + 1] = n_rectangles & 0xFF;
-
-       vs->has_update = 0;
-       vs->need_update = 0;
-       vnc_flush(vs);
-       vs->slow_client = 0;
-    } else
-       vs->slow_client = 1;
+    }
+    vs->output.buffer[saved_offset] = (n_rectangles >> 8) & 0xFF;
+    vs->output.buffer[saved_offset + 1] = n_rectangles & 0xFF;
+
+    if (n_rectangles == 0)
+       goto backoff;
+
+    vs->has_update = 0;
+    vnc_flush(vs);
+    vs->last_update_time = now;
+
+    vs->timer_interval /= 2;
+    if (vs->timer_interval < VNC_REFRESH_INTERVAL_BASE)
+       vs->timer_interval = VNC_REFRESH_INTERVAL_BASE;
+
+    return;
+
+ backoff:
+    /* No update -> back off a bit */
+    vs->timer_interval += VNC_REFRESH_INTERVAL_INC;
+    if (vs->timer_interval > VNC_REFRESH_INTERVAL_MAX) {
+       vs->timer_interval = VNC_REFRESH_INTERVAL_MAX;
+       if (now - vs->last_update_time >= VNC_MAX_UPDATE_INTERVAL) {
+           /* Send a null update.  If the client is no longer
+              interested (e.g. minimised) it'll ignore this, and we
+              can stop scanning the buffer until it sends another
+              update request. */
+           /* Note that there are bugs in xvncviewer which prevent
+              this from actually working.  Leave the code in place
+              for correct clients. */
+           vnc_write_u8(vs, 0);
+           vnc_write_u8(vs, 0);
+           vnc_write_u16(vs, 0);
+           vnc_flush(vs);
+           vs->last_update_time = now;
+           return;
+       }
+    }
+    qemu_mod_timer(vs->timer, now + vs->timer_interval);
+    return;
 }
 
 static void vnc_update_client(void *opaque)
@@ -561,8 +602,10 @@ static void vnc_update_client(void *opaq
 
 static void vnc_timer_init(VncState *vs)
 {
-    if (vs->timer == NULL)
+    if (vs->timer == NULL) {
        vs->timer = qemu_new_timer(rt_clock, vnc_update_client, vs);
+       vs->timer_interval = VNC_REFRESH_INTERVAL_BASE;
+    }
 }
 
 static void vnc_dpy_refresh(DisplayState *ds)
@@ -622,7 +665,6 @@ static int vnc_client_io_error(VncState 
        vs->csock = -1;
        buffer_reset(&vs->input);
        buffer_reset(&vs->output);
-       vs->need_update = 0;
        return 0;
     }
     return ret;
@@ -892,7 +934,6 @@ static void framebuffer_update_request(V
                                       int x_position, int y_position,
                                       int w, int h)
 {
-    vs->need_update = 1;
     if (!incremental)
        framebuffer_set_updated(vs, x_position, y_position, w, h);
     vs->visible_x = x_position;
@@ -1015,6 +1056,7 @@ static int protocol_client_msg(VncState 
 {
     int i;
     uint16_t limit;
+    int64_t now;
 
     switch (data[0]) {
     case 0:
@@ -1054,12 +1096,18 @@ static int protocol_client_msg(VncState 
        if (len == 1)
            return 8;
 
+       vs->timer_interval = VNC_REFRESH_INTERVAL_BASE;
+       qemu_advance_timer(vs->timer,
+                          qemu_get_clock(rt_clock) + vs->timer_interval);
        key_event(vs, read_u8(data, 1), read_u32(data, 4));
        break;
     case 5:
        if (len == 1)
            return 6;
 
+       vs->timer_interval = VNC_REFRESH_INTERVAL_BASE;
+       qemu_advance_timer(vs->timer,
+                          qemu_get_clock(rt_clock) + vs->timer_interval);
        pointer_event(vs, read_u8(data, 1), read_u16(data, 2), read_u16(data, 
4));
        break;
     case 6:
@@ -1268,7 +1316,7 @@ int vnc_start_viewer(int port)
        exit(1);
 
     case 0:    /* child */
-       execlp("vncviewer", "vncviewer", s, 0);
+       execlp("vncviewer", "vncviewer", s, NULL);
        fprintf(stderr, "vncviewer execlp failed\n");
        exit(1);
 

_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog

<Prev in Thread] Current Thread [Next in Thread>
  • [Xen-changelog] [xen-unstable] [HVM][VNC] Add a backoff feature to the vnc server, so that if it detects, Xen patchbot-unstable <=