From patchwork Mon Aug 3 09:56:01 2009 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stefano Stabellini X-Patchwork-Id: 30491 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [199.232.76.165]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (Client did not present a certificate) by bilbo.ozlabs.org (Postfix) with ESMTPS id 3E33EB6F2B for ; Mon, 3 Aug 2009 20:05:30 +1000 (EST) Received: from localhost ([127.0.0.1]:34794 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1MXuPv-0004Nj-JJ for incoming@patchwork.ozlabs.org; Mon, 03 Aug 2009 06:05:19 -0400 Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.43) id 1MXuFz-0001NM-2t for qemu-devel@nongnu.org; Mon, 03 Aug 2009 05:55:03 -0400 Received: from exim by lists.gnu.org with spam-scanned (Exim 4.43) id 1MXuFu-0001La-RY for qemu-devel@nongnu.org; Mon, 03 Aug 2009 05:55:02 -0400 Received: from [199.232.76.173] (port=52567 helo=monty-python.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1MXuFu-0001LX-KV for qemu-devel@nongnu.org; Mon, 03 Aug 2009 05:54:58 -0400 Received: from smtp.ctxuk.citrix.com ([62.200.22.115]:55702 helo=SMTP.EU.CITRIX.COM) by monty-python.gnu.org with esmtp (Exim 4.60) (envelope-from ) id 1MXuFu-0002jq-1X for qemu-devel@nongnu.org; Mon, 03 Aug 2009 05:54:58 -0400 X-IronPort-AV: E=Sophos;i="4.43,313,1246838400"; d="scan'208";a="6466556" Received: from lonpmailmx01.citrite.net ([10.30.224.162]) by LONPIPO01.EU.CITRIX.COM with ESMTP; 03 Aug 2009 09:54:57 +0000 Received: from kaball.uk.xensource.com (10.80.2.59) by smtprelay.citirx.com (10.30.224.162) with Microsoft SMTP Server id 8.1.358.0; Mon, 3 Aug 2009 10:54:56 +0100 Date: Mon, 3 Aug 2009 10:56:01 +0100 From: Stefano Stabellini X-X-Sender: sstabellini@kaball-desktop To: qemu-devel@nongnu.org Message-ID: User-Agent: Alpine 2.00 (DEB 1167 2008-08-23) MIME-Version: 1.0 X-detected-operating-system: by monty-python.gnu.org: Genre and OS details not recognized. Subject: [Qemu-devel] [PATCH v3 4 of 4] variable timer intervals X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: qemu-devel.nongnu.org List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org 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 --- qemu-timer.h | 1 + vl.c | 2 +- vnc.c | 39 ++++++++++++++++++++++++++++++--------- vnc.h | 1 + 4 files changed, 33 insertions(+), 10 deletions(-) diff --git a/qemu-timer.h b/qemu-timer.h index 3f8880d..8f69467 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 60a00e1..802c3fb 100644 --- a/vl.c +++ b/vl.c @@ -1207,7 +1207,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 ce5e0cc..5ccc0a3 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 5c903de..fcc6824 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;