From patchwork Tue Oct 8 08:47:35 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paolo Bonzini X-Patchwork-Id: 281366 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [IPv6:2001:4830:134:3::11]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id 8660E2C0098 for ; Tue, 8 Oct 2013 19:50:42 +1100 (EST) Received: from localhost ([::1]:35318 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1VTT04-0000Fx-DF for incoming@patchwork.ozlabs.org; Tue, 08 Oct 2013 04:50:40 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:41819) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1VTSxp-0004vM-4Z for qemu-devel@nongnu.org; Tue, 08 Oct 2013 04:48:29 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1VTSxg-0003cI-N8 for qemu-devel@nongnu.org; Tue, 08 Oct 2013 04:48:21 -0400 Received: from mail-ea0-x231.google.com ([2a00:1450:4013:c01::231]:61200) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1VTSxg-0003c5-FR for qemu-devel@nongnu.org; Tue, 08 Oct 2013 04:48:12 -0400 Received: by mail-ea0-f177.google.com with SMTP id f15so3703276eak.8 for ; Tue, 08 Oct 2013 01:48:11 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=sender:from:to:cc:subject:date:message-id:in-reply-to:references; bh=WuPG+u2H8Xt6KLc3GYibIKoJvGGUT1YhK9G5lXfpDOo=; b=DM1bqa5w0P27abXGZZ/AnhC36cVKyoYAGxe/8QO3sXVDGWs2PTqu/jRXEif7Ihlzva mMkNPSTJgLLQvS9oVYYjVEhKzZ5lDzLVPfSqK6lOIGzwZWI305CPeemrWPC5F6DaMsmU eDKXygYIhUhODJEjWCna0KsEbMjaJTzS5i3Tmg1GxRe/1OxKFBghsPxIxvQWhztSsa6r tV+ElwNru+P+dpIEV+8WxywhM2HK75iwBAo3r5AzIGuUFon8wPDkb2hkNv3gX5vcCwjc K7hIoiU3gVdfgUp+LsUp6dtiKDxlO/23XPYtIru8xkPYH399mbYzUfB6Z2e/xHCgGiD2 irTA== X-Received: by 10.15.91.3 with SMTP id r3mr771999eez.4.1381222091583; Tue, 08 Oct 2013 01:48:11 -0700 (PDT) Received: from localhost.localdomain (net-2-39-10-130.cust.dsl.vodafone.it. [2.39.10.130]) by mx.google.com with ESMTPSA id m54sm73201892eex.2.1969.12.31.16.00.00 (version=TLSv1 cipher=RC4-SHA bits=128/128); Tue, 08 Oct 2013 01:48:10 -0700 (PDT) From: Paolo Bonzini To: qemu-devel@nongnu.org Date: Tue, 8 Oct 2013 10:47:35 +0200 Message-Id: <1381222058-16701-6-git-send-email-pbonzini@redhat.com> X-Mailer: git-send-email 1.7.1 In-Reply-To: <1381222058-16701-1-git-send-email-pbonzini@redhat.com> References: <1381222058-16701-1-git-send-email-pbonzini@redhat.com> X-detected-operating-system: by eggs.gnu.org: Error: Malformed IPv6 address (bad octet value). X-Received-From: 2a00:1450:4013:c01::231 Cc: alex@alex.org.uk Subject: [Qemu-devel] [PATCH 5/8] timers: prepare the code for future races in calling qemu_clock_warp 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 Computing the deadline of all vm_clocks is somewhat expensive and calls out to qemu-timer.c; two reasons not to do it in the seqlock's write-side critical section. This however opens the door for races in setting and reading vm_clock_warp_start. To plug them, we need to cover the case where a new deadline slips in between the call to qemu_clock_deadline_ns_all and the actual modification of the icount_warp_timer. Restrict changes to vm_clock_warp_start and the icount_warp_timer's expiration time, to only move them back (which would simply cause an early wakeup). If a vm_clock timer is cancelled while CPUs are idle, this might cause the icount_warp_timer to fire unnecessarily. This is not a problem, after it fires the timer becomes inactive and the next call to timer_mod_anticipate will be precise. In addition to this, we must deactivate the icount_warp_timer _before_ checking whether CPUs are idle. This way, if the "last" CPU becomes idle during the call to timer_del we will still set up the icount_warp_timer. Signed-off-by: Paolo Bonzini --- cpus.c | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/cpus.c b/cpus.c index 9f450ad..08eaf23 100644 --- a/cpus.c +++ b/cpus.c @@ -319,6 +319,7 @@ void qtest_clock_warp(int64_t dest) void qemu_clock_warp(QEMUClockType type) { + int64_t clock; int64_t deadline; /* @@ -338,7 +339,7 @@ void qemu_clock_warp(QEMUClockType type) * the earliest QEMU_CLOCK_VIRTUAL timer. */ icount_warp_rt(NULL); - if (!all_cpu_threads_idle() || !qemu_clock_has_timers(QEMU_CLOCK_VIRTUAL)) { - timer_del(icount_warp_timer); + timer_del(icount_warp_timer); + if (!all_cpu_threads_idle()) { return; } @@ -348,17 +349,11 @@ void qemu_clock_warp(QEMUClockType type) return; } - vm_clock_warp_start = qemu_clock_get_ns(QEMU_CLOCK_REALTIME); /* We want to use the earliest deadline from ALL vm_clocks */ + clock = qemu_clock_get_ns(QEMU_CLOCK_REALTIME); deadline = qemu_clock_deadline_ns_all(QEMU_CLOCK_VIRTUAL); - - /* Maintain prior (possibly buggy) behaviour where if no deadline - * was set (as there is no QEMU_CLOCK_VIRTUAL timer) or it is more than - * INT32_MAX nanoseconds ahead, we still use INT32_MAX - * nanoseconds. - */ - if ((deadline < 0) || (deadline > INT32_MAX)) { - deadline = INT32_MAX; + if (deadline < 0) { + return; } if (deadline > 0) { @@ -379,7 +375,10 @@ void qemu_clock_warp(QEMUClockType type) * you will not be sending network packets continuously instead of * every 100ms. */ - timer_mod(icount_warp_timer, vm_clock_warp_start + deadline); + if (vm_clock_warp_start == -1 || vm_clock_warp_start > clock) { + vm_clock_warp_start = clock; + } + timer_mod_anticipate(icount_warp_timer, clock + deadline); } else if (deadline == 0) { qemu_clock_notify(QEMU_CLOCK_VIRTUAL); }