From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([2001:4830:134:3::10]:46031) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Uv5S6-00061O-AN for qemu-devel@nongnu.org; Fri, 05 Jul 2013 08:49:33 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1Uv5S0-0008Sd-UP for qemu-devel@nongnu.org; Fri, 05 Jul 2013 08:49:30 -0400 Received: from mx1.redhat.com ([209.132.183.28]:53447) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Uv5S0-0008SN-Lx for qemu-devel@nongnu.org; Fri, 05 Jul 2013 08:49:24 -0400 From: Stefan Hajnoczi Date: Fri, 5 Jul 2013 14:39:46 +0200 Message-Id: <1373027986-17868-4-git-send-email-stefanha@redhat.com> In-Reply-To: <1373027986-17868-1-git-send-email-stefanha@redhat.com> References: <1373027986-17868-1-git-send-email-stefanha@redhat.com> Subject: [Qemu-devel] [PATCH 3/3] qemu-timer: add qemu_alarm_timer->timer_modified_lock List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org Cc: Paolo Bonzini , Anthony Liguori , Stefan Hajnoczi , alex@alex.org.uk, rth@twiddle.net When a timer's expiration time is changed we may need to rearm the alarm timer. Rearming is necessary when the nearest deadline changes. This patch introduces the qemu_alarm_timer->timer_modified boolean and a lock to protect it. It moves rearming the alarm timer from inside qemu_mod_timer_ns() to qemu_run_all_timers() since we cannot rearm outside the QEMU global mutex. The following code is dropped because we always kick the main loop now: /* Interrupt execution to force deadline recalculation. */ qemu_clock_warp(ts->clock); if (use_icount) { qemu_notify_event(); } cpus.c will invoke qemu_clock_warp() again since the main loop ran. It is now safe to call qemu_mod_timer_ns() for outside the QEMU global mutex. Signed-off-by: Stefan Hajnoczi --- qemu-timer.c | 29 +++++++++++++++++++++-------- 1 file changed, 21 insertions(+), 8 deletions(-) diff --git a/qemu-timer.c b/qemu-timer.c index c773af0..9500d12 100644 --- a/qemu-timer.c +++ b/qemu-timer.c @@ -78,6 +78,10 @@ struct qemu_alarm_timer { #endif bool expired; bool pending; + + /* Was the nearest deadline timer modified (possibly by another thread)? */ + QemuMutex timer_modified_lock; + bool timer_modified; }; static struct qemu_alarm_timer *alarm_timer; @@ -371,14 +375,10 @@ void qemu_mod_timer_ns(QEMUTimer *ts, int64_t expire_time) /* Rearm if necessary */ if (pt == &ts->clock->active_timers) { - if (!alarm_timer->pending) { - qemu_rearm_alarm_timer(alarm_timer); - } - /* Interrupt execution to force deadline recalculation. */ - qemu_clock_warp(ts->clock); - if (use_icount) { - qemu_notify_event(); - } + qemu_mutex_lock(&alarm_timer->timer_modified_lock); + alarm_timer->timer_modified = true; + qemu_mutex_unlock(&alarm_timer->timer_modified_lock); + qemu_notify_event(); } } @@ -484,6 +484,8 @@ uint64_t qemu_timer_expire_time_ns(QEMUTimer *ts) void qemu_run_all_timers(void) { + bool timer_modified; + alarm_timer->pending = false; /* vm time timers */ @@ -491,11 +493,20 @@ void qemu_run_all_timers(void) qemu_run_timers(rt_clock); qemu_run_timers(host_clock); + /* Check if qemu_mod_timer_ns() has been called */ + qemu_mutex_lock(&alarm_timer->timer_modified_lock); + timer_modified = alarm_timer->timer_modified; + alarm_timer->timer_modified = false; + qemu_mutex_unlock(&alarm_timer->timer_modified_lock); + /* rearm timer, if not periodic */ if (alarm_timer->expired) { alarm_timer->expired = false; qemu_rearm_alarm_timer(alarm_timer); + } else if (timer_modified) { + qemu_rearm_alarm_timer(alarm_timer); } + } #ifdef _WIN32 @@ -805,6 +816,8 @@ int init_timer_alarm(void) goto fail; } + qemu_mutex_init(&t->timer_modified_lock); + atexit(quit_timers); #ifdef CONFIG_POSIX pthread_atfork(NULL, NULL, reinit_timers); -- 1.8.1.4