From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([2001:4830:134:3::10]:41769) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1VTSxk-0004vH-1L for qemu-devel@nongnu.org; Tue, 08 Oct 2013 04:48:24 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1VTSxa-0003af-To for qemu-devel@nongnu.org; Tue, 08 Oct 2013 04:48:15 -0400 Received: from mail-ee0-x236.google.com ([2a00:1450:4013:c00::236]:54908) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1VTSxa-0003aK-Mc for qemu-devel@nongnu.org; Tue, 08 Oct 2013 04:48:06 -0400 Received: by mail-ee0-f54.google.com with SMTP id e53so3866990eek.27 for ; Tue, 08 Oct 2013 01:48:05 -0700 (PDT) Sender: Paolo Bonzini From: Paolo Bonzini Date: Tue, 8 Oct 2013 10:47:32 +0200 Message-Id: <1381222058-16701-3-git-send-email-pbonzini@redhat.com> In-Reply-To: <1381222058-16701-1-git-send-email-pbonzini@redhat.com> References: <1381222058-16701-1-git-send-email-pbonzini@redhat.com> Subject: [Qemu-devel] [PATCH 2/8] timers: add timer_mod_anticipate and timer_mod_anticipate_ns List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org Cc: alex@alex.org.uk These let a user anticipate the deadline of a timer, atomically with other sites that call the function. This helps avoiding complicated lock hierarchies. It is useful whenever the timer does work based on the current value of the clock (rather than doing something periodically on every tick). Signed-off-by: Paolo Bonzini --- include/qemu/timer.h | 26 ++++++++++++++++++++++++++ qemu-timer.c | 29 +++++++++++++++++++++++++++++ 2 files changed, 55 insertions(+) diff --git a/include/qemu/timer.h b/include/qemu/timer.h index b58903b..f215b0b 100644 --- a/include/qemu/timer.h +++ b/include/qemu/timer.h @@ -539,6 +539,19 @@ void timer_del(QEMUTimer *ts); void timer_mod_ns(QEMUTimer *ts, int64_t expire_time); /** + * timer_mod_anticipate_ns: + * @ts: the timer + * @expire_time: the expiry time in nanoseconds + * + * Modify a timer to expire at @expire_time or the current time, + * whichever comes earlier. + * + * This function is thread-safe but the timer and its timer list must not be + * freed while this function is running. + */ +void timer_mod_anticipate_ns(QEMUTimer *ts, int64_t expire_time); + +/** * timer_mod: * @ts: the timer * @expire_time: the expire time in the units associated with the timer @@ -552,6 +565,19 @@ void timer_mod_ns(QEMUTimer *ts, int64_t expire_time); void timer_mod(QEMUTimer *ts, int64_t expire_timer); /** + * timer_mod_anticipate: + * @ts: the timer + * @expire_time: the expiry time in nanoseconds + * + * Modify a timer to expire at @expire_time or the current time, whichever + * comes earlier, taking into account the scale associated with the timer. + * + * This function is thread-safe but the timer and its timer list must not be + * freed while this function is running. + */ +void timer_mod_anticipate(QEMUTimer *ts, int64_t expire_time); + +/** * timer_pending: * @ts: the timer * diff --git a/qemu-timer.c b/qemu-timer.c index 95fc6eb..202e9a2 100644 --- a/qemu-timer.c +++ b/qemu-timer.c @@ -393,11 +393,40 @@ void timer_mod_ns(QEMUTimer *ts, int64_t expire_time) } } +/* modify the current timer so that it will be fired when current_time + >= expire_time or the current deadline, whichever comes earlier. + The corresponding callback will be called. */ +void timer_mod_anticipate_ns(QEMUTimer *ts, int64_t expire_time) +{ + QEMUTimerList *timer_list = ts->timer_list; + bool rearm; + + qemu_mutex_lock(&timer_list->active_timers_lock); + if (ts->expire_time == -1 || ts->expire_time > expire_time) { + if (ts->expire_time != -1) { + timer_del_locked(timer_list, ts); + } + rearm = timer_mod_ns_locked(timer_list, ts, expire_time); + } else { + rearm = false; + } + qemu_mutex_unlock(&timer_list->active_timers_lock); + + if (rearm) { + timerlist_rearm(timer_list); + } +} + void timer_mod(QEMUTimer *ts, int64_t expire_time) { timer_mod_ns(ts, expire_time * ts->scale); } +void timer_mod_anticipate(QEMUTimer *ts, int64_t expire_time) +{ + timer_mod_anticipate_ns(ts, expire_time * ts->scale); +} + bool timer_pending(QEMUTimer *ts) { return ts->expire_time >= 0; -- 1.8.3.1