From patchwork Thu Aug 8 21:41:59 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alex Bligh X-Patchwork-Id: 265861 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (unknown [IPv6:2001:4830:134:3::12]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id A7C082C00AA for ; Fri, 9 Aug 2013 08:33:45 +1000 (EST) Received: from localhost ([::1]:52760 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1V7Y1A-0000B8-GA for incoming@patchwork.ozlabs.org; Thu, 08 Aug 2013 17:45:12 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:54600) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1V7Xyr-0006J3-My for qemu-devel@nongnu.org; Thu, 08 Aug 2013 17:42:52 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1V7Xyo-0006xS-Lj for qemu-devel@nongnu.org; Thu, 08 Aug 2013 17:42:49 -0400 Received: from mail.avalus.com ([2001:41c8:10:1dd::10]:55264) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1V7Xyo-0006vn-A6 for qemu-devel@nongnu.org; Thu, 08 Aug 2013 17:42:46 -0400 Received: by mail.avalus.com (Postfix) with ESMTPSA id CF9BEC561AB; Thu, 8 Aug 2013 22:42:44 +0100 (BST) From: Alex Bligh To: qemu-devel@nongnu.org Date: Thu, 8 Aug 2013 22:41:59 +0100 Message-Id: <1375998147-24292-3-git-send-email-alex@alex.org.uk> X-Mailer: git-send-email 1.7.9.5 In-Reply-To: <1375998147-24292-1-git-send-email-alex@alex.org.uk> References: <1375998147-24292-1-git-send-email-alex@alex.org.uk> X-detected-operating-system: by eggs.gnu.org: Error: Malformed IPv6 address (bad octet value). X-Received-From: 2001:41c8:10:1dd::10 Cc: Kevin Wolf , Anthony Liguori , Alex Bligh , liu ping fan , Stefan Hajnoczi , Paolo Bonzini , MORITA Kazutaka , rth@twiddle.net Subject: [Qemu-devel] [RFC] [PATCHv8 02/30] aio / timers: add qemu-timer.c utility functions X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Add utility functions to qemu-timer.c for nanosecond timing. Add qemu_clock_deadline_ns to calculate deadlines to nanosecond accuracy. Add utility function qemu_soonest_timeout to calculate soonest deadline. Add qemu_timeout_ns_to_ms to convert a timeout in nanoseconds back to milliseconds for when ppoll is not used. Signed-off-by: Alex Bligh --- include/qemu/timer.h | 42 ++++++++++++++++++++++++++++++++++++++++++ qemu-timer.c | 50 ++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 92 insertions(+) diff --git a/include/qemu/timer.h b/include/qemu/timer.h index 45c745b..0794352 100644 --- a/include/qemu/timer.h +++ b/include/qemu/timer.h @@ -40,6 +40,29 @@ int64_t qemu_get_clock_ns(QEMUClock *clock); int64_t qemu_clock_has_timers(QEMUClock *clock); int64_t qemu_clock_expired(QEMUClock *clock); int64_t qemu_clock_deadline(QEMUClock *clock); + +/** + * qemu_clock_deadline_ns: + * @clock: the clock to operate on + * + * Calculate the timeout of the earliest expiring timer + * in nanoseconds, or -1 if no timer is set to expire. + * + * Returns: time until expiry in nanoseconds or -1 + */ +int64_t qemu_clock_deadline_ns(QEMUClock *clock); + +/** + * qemu_timeout_ns_to_ms: + * @ns: nanosecond timeout value + * + * Convert a nanosecond timeout value (or -1) to + * a millisecond value (or -1), always rounding up. + * + * Returns: millisecond timeout value + */ +int qemu_timeout_ns_to_ms(int64_t ns); + void qemu_clock_enable(QEMUClock *clock, bool enabled); void qemu_clock_warp(QEMUClock *clock); @@ -67,6 +90,25 @@ int64_t cpu_get_ticks(void); void cpu_enable_ticks(void); void cpu_disable_ticks(void); +/** + * qemu_soonest_timeout: + * @timeout1: first timeout in nanoseconds (or -1 for infinite) + * @timeout2: second timeout in nanoseconds (or -1 for infinite) + * + * Calculates the soonest of two timeout values. -1 means infinite, which + * is later than any other value. + * + * Returns: soonest timeout value in nanoseconds (or -1 for infinite) + */ +static inline int64_t qemu_soonest_timeout(int64_t timeout1, int64_t timeout2) +{ + /* we can abuse the fact that -1 (which means infinite) is a maximal + * value when cast to unsigned. As this is disgusting, it's kept in + * one inline function. + */ + return ((uint64_t) timeout1 < (uint64_t) timeout2) ? timeout1 : timeout2; +} + static inline QEMUTimer *qemu_new_timer_ns(QEMUClock *clock, QEMUTimerCB *cb, void *opaque) { diff --git a/qemu-timer.c b/qemu-timer.c index 2d97a13..8f378a9 100644 --- a/qemu-timer.c +++ b/qemu-timer.c @@ -273,6 +273,56 @@ int64_t qemu_clock_deadline(QEMUClock *clock) return delta; } +/* + * As above, but return -1 for no deadline, and do not cap to 2^32 + * as we know the result is always positive. + */ + +int64_t qemu_clock_deadline_ns(QEMUClock *clock) +{ + int64_t delta; + + if (!clock->enabled || !clock->active_timers) { + return -1; + } + + delta = clock->active_timers->expire_time - qemu_get_clock_ns(clock); + + if (delta <= 0) { + return 0; + } + + return delta; +} + +/* Transition function to convert a nanosecond timeout to ms + * This is used where a system does not support ppoll + */ +int qemu_timeout_ns_to_ms(int64_t ns) +{ + int64_t ms; + if (ns < 0) { + return -1; + } + + if (!ns) { + return 0; + } + + /* Always round up, because it's better to wait too long than to wait too + * little and effectively busy-wait + */ + ms = (ns + SCALE_MS - 1) / SCALE_MS; + + /* To avoid overflow problems, limit this to 2^31, i.e. approx 25 days */ + if (ms > (int64_t) INT32_MAX) { + ms = INT32_MAX; + } + + return (int) ms; +} + + QEMUTimer *qemu_new_timer(QEMUClock *clock, int scale, QEMUTimerCB *cb, void *opaque) {