aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStefano Stabellini <stefano.stabellini@eu.citrix.com>2009-08-03 10:56:01 +0100
committerAnthony Liguori <aliguori@us.ibm.com>2009-08-10 13:05:31 -0500
commit2430ffe4c855d782b157fafd0cd561d7c1561c2f (patch)
tree5cb08279411401e9de387d409eb6422cc0d47a42
parent1fc624122fb923c7fc4c1f426541d953e7df13c9 (diff)
variable timer intervals
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:
-rw-r--r--qemu-timer.h1
-rw-r--r--vl.c2
-rw-r--r--vnc.c39
-rw-r--r--vnc.h1
4 files changed, 33 insertions, 10 deletions
diff --git a/qemu-timer.h b/qemu-timer.h
index 3f8880ddfa..8f6946763b 100644
--- a/qemu-timer.h
+++ b/qemu-timer.h
@@ -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 9b390e74d9..978041f339 100644
--- 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 cfaf7ba29c..4fde9aae5d 100644
--- 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 5c903dec75..fcc6824127 100644
--- 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;