]> git.proxmox.com Git - qemu.git/commitdiff
variable timer intervals
authorStefano Stabellini <stefano.stabellini@eu.citrix.com>
Mon, 3 Aug 2009 09:56:01 +0000 (10:56 +0100)
committerAnthony Liguori <aliguori@us.ibm.com>
Mon, 10 Aug 2009 18:05:31 +0000 (13:05 -0500)
This patch introduces dynamic timer intervals: we slow down the refresh
rate when there in no much activity but we get back to a fast refresh
rate when the activity resume.

Please note that qemu_timer_expired is not an inline function any more
because I needed to call it from vnc.c however I don't think this change
should have any serious consequence.

Signed-off-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
Message-Id:

qemu-timer.h
vl.c
vnc.c
vnc.h

index 3f8880ddfaa39dc4f2976ea1762640dd09dfb851..8f6946763b67c7b4bbd4e44159e34ab400dae039 100644 (file)
@@ -24,6 +24,7 @@ void qemu_free_timer(QEMUTimer *ts);
 void qemu_del_timer(QEMUTimer *ts);
 void qemu_mod_timer(QEMUTimer *ts, int64_t expire_time);
 int qemu_timer_pending(QEMUTimer *ts);
+int qemu_timer_expired(QEMUTimer *timer_head, int64_t current_time);
 
 extern int64_t ticks_per_sec;
 
diff --git a/vl.c b/vl.c
index 9b390e74d9394382b249b749828cafe185820861..978041f3390ae999db9f9362e1d579d59268e2a5 100644 (file)
--- a/vl.c
+++ b/vl.c
@@ -992,7 +992,7 @@ int qemu_timer_pending(QEMUTimer *ts)
     return 0;
 }
 
-static inline int qemu_timer_expired(QEMUTimer *timer_head, int64_t current_time)
+int qemu_timer_expired(QEMUTimer *timer_head, int64_t current_time)
 {
     if (!timer_head)
         return 0;
diff --git a/vnc.c b/vnc.c
index cfaf7ba29cc13017d995a64cca6ecd4d9ba5befb..4fde9aae5de5bdc2817121e35745a6c59ef27919 100644 (file)
--- a/vnc.c
+++ b/vnc.c
@@ -30,7 +30,9 @@
 #include "qemu-timer.h"
 #include "acl.h"
 
-#define VNC_REFRESH_INTERVAL (1000 / 30)
+#define VNC_REFRESH_INTERVAL_BASE 30
+#define VNC_REFRESH_INTERVAL_INC  50
+#define VNC_REFRESH_INTERVAL_MAX  2000
 
 #include "vnc_keysym.h"
 #include "d3des.h"
@@ -215,7 +217,7 @@ static inline uint32_t vnc_has_feature(VncState *vs, int feature) {
    3) resolutions > 1024
 */
 
-static void vnc_update_client(VncState *vs, int has_dirty);
+static int vnc_update_client(VncState *vs, int has_dirty);
 static void vnc_disconnect_start(VncState *vs);
 static void vnc_disconnect_finish(VncState *vs);
 static void vnc_init_timer(VncDisplay *vd);
@@ -751,7 +753,7 @@ static int find_and_clear_dirty_height(struct VncState *vs,
     return h;
 }
 
-static void vnc_update_client(VncState *vs, int has_dirty)
+static int vnc_update_client(VncState *vs, int has_dirty)
 {
     if (vs->need_update && vs->csock != -1) {
         VncDisplay *vd = vs->vd;
@@ -761,10 +763,10 @@ static void vnc_update_client(VncState *vs, int has_dirty)
 
         if (vs->output.offset && !vs->audio_cap && !vs->force_update)
             /* kernel send buffers are full -> drop frames to throttle */
-            return;
+            return 0;
 
         if (!has_dirty && !vs->audio_cap && !vs->force_update)
-            return;
+            return 0;
 
         /*
          * Send screen updates to the vnc client using the server
@@ -806,11 +808,13 @@ static void vnc_update_client(VncState *vs, int has_dirty)
         vs->output.buffer[saved_offset + 1] = n_rectangles & 0xFF;
         vnc_flush(vs);
         vs->force_update = 0;
-
+        return n_rectangles;
     }
 
     if (vs->csock == -1)
         vnc_disconnect_finish(vs);
+
+    return 0;
 }
 
 /* audio */
@@ -1701,6 +1705,13 @@ static int protocol_client_msg(VncState *vs, uint8_t *data, size_t len)
 {
     int i;
     uint16_t limit;
+    VncDisplay *vd = vs->vd;
+
+    if (data[0] > 3) {
+        vd->timer_interval = VNC_REFRESH_INTERVAL_BASE;
+        if (!qemu_timer_expired(vd->timer, qemu_get_clock(rt_clock) + vd->timer_interval))
+            qemu_mod_timer(vd->timer, qemu_get_clock(rt_clock) + vd->timer_interval);
+    }
 
     switch (data[0]) {
     case 0:
@@ -2104,7 +2115,7 @@ static void vnc_refresh(void *opaque)
 {
     VncDisplay *vd = opaque;
     VncState *vs = NULL;
-    int has_dirty = 0;
+    int has_dirty = 0, rects = 0;
 
     vga_hw_update();
 
@@ -2112,15 +2123,25 @@ static void vnc_refresh(void *opaque)
 
     vs = vd->clients;
     while (vs != NULL) {
-        vnc_update_client(vs, has_dirty);
+        rects += vnc_update_client(vs, has_dirty);
         vs = vs->next;
     }
 
-    qemu_mod_timer(vd->timer, qemu_get_clock(rt_clock) + VNC_REFRESH_INTERVAL);
+    if (has_dirty && rects) {
+        vd->timer_interval /= 2;
+        if (vd->timer_interval < VNC_REFRESH_INTERVAL_BASE)
+            vd->timer_interval = VNC_REFRESH_INTERVAL_BASE;
+    } else {
+        vd->timer_interval += VNC_REFRESH_INTERVAL_INC;
+        if (vd->timer_interval > VNC_REFRESH_INTERVAL_MAX)
+            vd->timer_interval = VNC_REFRESH_INTERVAL_MAX;
+    }
+    qemu_mod_timer(vd->timer, qemu_get_clock(rt_clock) + vd->timer_interval);
 }
 
 static void vnc_init_timer(VncDisplay *vd)
 {
+    vd->timer_interval = VNC_REFRESH_INTERVAL_BASE;
     if (vd->timer == NULL && vd->clients != NULL) {
         vd->timer = qemu_new_timer(rt_clock, vnc_refresh, vd);
         vnc_refresh(vd);
diff --git a/vnc.h b/vnc.h
index 5c903dec7575c06cc838228ab8087abfea37c215..fcc68241275b8d9d6a722a72929f1937d9893440 100644 (file)
--- a/vnc.h
+++ b/vnc.h
@@ -93,6 +93,7 @@ struct VncSurface
 struct VncDisplay
 {
     QEMUTimer *timer;
+    int timer_interval;
     int lsock;
     DisplayState *ds;
     VncState *clients;