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:
This commit is contained in:
parent
1fc624122f
commit
2430ffe4c8
@ -24,6 +24,7 @@ void qemu_free_timer(QEMUTimer *ts);
|
|||||||
void qemu_del_timer(QEMUTimer *ts);
|
void qemu_del_timer(QEMUTimer *ts);
|
||||||
void qemu_mod_timer(QEMUTimer *ts, int64_t expire_time);
|
void qemu_mod_timer(QEMUTimer *ts, int64_t expire_time);
|
||||||
int qemu_timer_pending(QEMUTimer *ts);
|
int qemu_timer_pending(QEMUTimer *ts);
|
||||||
|
int qemu_timer_expired(QEMUTimer *timer_head, int64_t current_time);
|
||||||
|
|
||||||
extern int64_t ticks_per_sec;
|
extern int64_t ticks_per_sec;
|
||||||
|
|
||||||
|
2
vl.c
2
vl.c
@ -992,7 +992,7 @@ int qemu_timer_pending(QEMUTimer *ts)
|
|||||||
return 0;
|
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)
|
if (!timer_head)
|
||||||
return 0;
|
return 0;
|
||||||
|
39
vnc.c
39
vnc.c
@ -30,7 +30,9 @@
|
|||||||
#include "qemu-timer.h"
|
#include "qemu-timer.h"
|
||||||
#include "acl.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 "vnc_keysym.h"
|
||||||
#include "d3des.h"
|
#include "d3des.h"
|
||||||
@ -215,7 +217,7 @@ static inline uint32_t vnc_has_feature(VncState *vs, int feature) {
|
|||||||
3) resolutions > 1024
|
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_start(VncState *vs);
|
||||||
static void vnc_disconnect_finish(VncState *vs);
|
static void vnc_disconnect_finish(VncState *vs);
|
||||||
static void vnc_init_timer(VncDisplay *vd);
|
static void vnc_init_timer(VncDisplay *vd);
|
||||||
@ -751,7 +753,7 @@ static int find_and_clear_dirty_height(struct VncState *vs,
|
|||||||
return h;
|
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) {
|
if (vs->need_update && vs->csock != -1) {
|
||||||
VncDisplay *vd = vs->vd;
|
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)
|
if (vs->output.offset && !vs->audio_cap && !vs->force_update)
|
||||||
/* kernel send buffers are full -> drop frames to throttle */
|
/* kernel send buffers are full -> drop frames to throttle */
|
||||||
return;
|
return 0;
|
||||||
|
|
||||||
if (!has_dirty && !vs->audio_cap && !vs->force_update)
|
if (!has_dirty && !vs->audio_cap && !vs->force_update)
|
||||||
return;
|
return 0;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Send screen updates to the vnc client using the server
|
* 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;
|
vs->output.buffer[saved_offset + 1] = n_rectangles & 0xFF;
|
||||||
vnc_flush(vs);
|
vnc_flush(vs);
|
||||||
vs->force_update = 0;
|
vs->force_update = 0;
|
||||||
|
return n_rectangles;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (vs->csock == -1)
|
if (vs->csock == -1)
|
||||||
vnc_disconnect_finish(vs);
|
vnc_disconnect_finish(vs);
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* audio */
|
/* audio */
|
||||||
@ -1701,6 +1705,13 @@ static int protocol_client_msg(VncState *vs, uint8_t *data, size_t len)
|
|||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
uint16_t limit;
|
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]) {
|
switch (data[0]) {
|
||||||
case 0:
|
case 0:
|
||||||
@ -2104,7 +2115,7 @@ static void vnc_refresh(void *opaque)
|
|||||||
{
|
{
|
||||||
VncDisplay *vd = opaque;
|
VncDisplay *vd = opaque;
|
||||||
VncState *vs = NULL;
|
VncState *vs = NULL;
|
||||||
int has_dirty = 0;
|
int has_dirty = 0, rects = 0;
|
||||||
|
|
||||||
vga_hw_update();
|
vga_hw_update();
|
||||||
|
|
||||||
@ -2112,15 +2123,25 @@ static void vnc_refresh(void *opaque)
|
|||||||
|
|
||||||
vs = vd->clients;
|
vs = vd->clients;
|
||||||
while (vs != NULL) {
|
while (vs != NULL) {
|
||||||
vnc_update_client(vs, has_dirty);
|
rects += vnc_update_client(vs, has_dirty);
|
||||||
vs = vs->next;
|
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)
|
static void vnc_init_timer(VncDisplay *vd)
|
||||||
{
|
{
|
||||||
|
vd->timer_interval = VNC_REFRESH_INTERVAL_BASE;
|
||||||
if (vd->timer == NULL && vd->clients != NULL) {
|
if (vd->timer == NULL && vd->clients != NULL) {
|
||||||
vd->timer = qemu_new_timer(rt_clock, vnc_refresh, vd);
|
vd->timer = qemu_new_timer(rt_clock, vnc_refresh, vd);
|
||||||
vnc_refresh(vd);
|
vnc_refresh(vd);
|
||||||
|
Loading…
Reference in New Issue
Block a user