From patchwork Thu Oct 18 20:31:31 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paolo Bonzini X-Patchwork-Id: 986270 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=nongnu.org (client-ip=2001:4830:134:3::11; helo=lists.gnu.org; envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=redhat.com Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="TmiC6/BC"; dkim-atps=neutral Received: from lists.gnu.org (lists.gnu.org [IPv6:2001:4830:134:3::11]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 42bh8412CSz9s1c for ; Fri, 19 Oct 2018 07:52:52 +1100 (AEDT) Received: from localhost ([::1]:44609 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gDFHl-0007JC-MW for incoming@patchwork.ozlabs.org; Thu, 18 Oct 2018 16:52:49 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:47965) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gDEy8-000765-P6 for qemu-devel@nongnu.org; Thu, 18 Oct 2018 16:32:34 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1gDEy5-0006Ab-EF for qemu-devel@nongnu.org; Thu, 18 Oct 2018 16:32:31 -0400 Received: from mail-wm1-x344.google.com ([2a00:1450:4864:20::344]:35971) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1gDEy1-00066Y-Qs for qemu-devel@nongnu.org; Thu, 18 Oct 2018 16:32:27 -0400 Received: by mail-wm1-x344.google.com with SMTP id a8-v6so1626269wmf.1 for ; Thu, 18 Oct 2018 13:32:22 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=sender:from:to:cc:subject:date:message-id:in-reply-to:references; bh=RjqBrvJxw4+BzQE5/W7t9Zaud/Hwg2+ea952w8wVXT0=; b=TmiC6/BCVe+aLE9jNu2O/HbB8T2RleKizASr092dw1XG5qoauAfFzg6eI3c++D5vKA dx6TuBis+4DiBz1Kdp63gPSeug+gXcDWd7Hf3kVYGlaNFZwgIG9ka6VFx4m02IhTkREQ 6A7UGNUfcdBEEpwy19aSrsZGsG9P86dRFpeLrkyXURtwx2I+gr47CPyrIXYFl0TQtezq xsaVh4BbajvnkvV3zsxyPKqxDDP8M829xPoVzxkriS9CGbYiNmGT52/dXkt7vWDNlmWv SEyJJgBFEJOjwiKpGa45KO3ORBdSnjMMCy3q23RZ8godpl5i4ZPr4ragOdC9RXd8VzH1 ROAg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:sender:from:to:cc:subject:date:message-id :in-reply-to:references; bh=RjqBrvJxw4+BzQE5/W7t9Zaud/Hwg2+ea952w8wVXT0=; b=KoaC+G9agL94dEDCwXfFMgI/djBq8ovBr+D8u8CCuadBfAorCcPnRNO+ESPwU8EBDn BBOALfLR/rSjSlv6dFhh2HZR9T/YeIfCYrmIF0qcY/Hw0LIqJZGf1cqQ7uDagHAh6d4x 5V1jcU9BLguvl7QZzMSfAq5EauWe+p/IjKgvFJ+nU5nvgCX5LyhgybzJglvgH2zX+OfX 6D1ST97i8twzaE+HV3jzT7PK0ptNh6OONQfn7cjjmDjtOHG2PwDi22go3exZJYlrMjj3 z58yNWldpp2C9Y2oAgnZqe8KDXjryPXMtldBvWrH5A1hC+dzqopUdv4WRMPcpTW19RsZ k6sg== X-Gm-Message-State: ABuFfohp7y6gkz+jS96LZ4EEUFthUgYI0O5irkZ+dnpPZA364Yq/wuAr p/kkWEuk2y9LamHpqYcPiCjIQIrO X-Google-Smtp-Source: ACcGV615vWHCZajFUU1V0Ls1Ur/VliY0kervUXM9twXCtYJrt0/MNybCGgQMvmUxRGF1HSgExyxRhw== X-Received: by 2002:a1c:a683:: with SMTP id p125-v6mr1961332wme.24.1539894741472; Thu, 18 Oct 2018 13:32:21 -0700 (PDT) Received: from 640k.lan (dynamic-adsl-78-12-231-174.clienti.tiscali.it. [78.12.231.174]) by smtp.gmail.com with ESMTPSA id a12-v6sm14270952wrr.71.2018.10.18.13.32.20 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 18 Oct 2018 13:32:20 -0700 (PDT) From: Paolo Bonzini To: qemu-devel@nongnu.org Date: Thu, 18 Oct 2018 22:31:31 +0200 Message-Id: <1539894735-14232-5-git-send-email-pbonzini@redhat.com> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1539894735-14232-1-git-send-email-pbonzini@redhat.com> References: <1539894735-14232-1-git-send-email-pbonzini@redhat.com> X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 2a00:1450:4864:20::344 Subject: [Qemu-devel] [PULL 04/48] qemu-timer: avoid checkpoints for virtual clock timers in external subsystems X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Artem Pisarenko Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: "Qemu-devel" From: Artem Pisarenko Adds EXTERNAL attribute definition to qemu timers subsystem and assigns it to virtual clock timers, used in slirp (ICMP IPv6) and ui (key queue). Virtual clock processing in rr mode can use this attribute instead of a separate clock type. Fixes: 87f4fe7653baf55b5c2f2753fe6003f473c07342 Fixes: 775a412bf83f6bc0c5c02091ee06cf649b34c593 Fixes: 9888091404a702d7ec79d51b088d994b9fc121bd Signed-off-by: Artem Pisarenko Message-Id: Signed-off-by: Paolo Bonzini --- include/qemu/timer.h | 10 +++++++++- slirp/ip6_icmp.c | 4 +++- ui/input.c | 5 +++-- util/qemu-timer.c | 50 +++++++++++++++++++++++++++++++++++++++++++------- 4 files changed, 58 insertions(+), 11 deletions(-) diff --git a/include/qemu/timer.h b/include/qemu/timer.h index 8ff1092..9f37c92 100644 --- a/include/qemu/timer.h +++ b/include/qemu/timer.h @@ -60,9 +60,17 @@ typedef enum { * Each attribute corresponds to one bit. Attributes modify the processing * of timers when they fire. * - * No attributes defined currently. + * The following attributes are available: + * + * QEMU_TIMER_ATTR_EXTERNAL: drives external subsystem + * + * Timers with this attribute do not recorded in rr mode, therefore it could be + * used for the subsystems that operate outside the guest core. Applicable only + * with virtual clock type. */ +#define QEMU_TIMER_ATTR_EXTERNAL BIT(0) + typedef struct QEMUTimerList QEMUTimerList; struct QEMUTimerListGroup { diff --git a/slirp/ip6_icmp.c b/slirp/ip6_icmp.c index ee333d0..cd1e0b9 100644 --- a/slirp/ip6_icmp.c +++ b/slirp/ip6_icmp.c @@ -27,7 +27,9 @@ void icmp6_init(Slirp *slirp) return; } - slirp->ra_timer = timer_new_ms(QEMU_CLOCK_VIRTUAL, ra_timer_handler, slirp); + slirp->ra_timer = timer_new_full(NULL, QEMU_CLOCK_VIRTUAL, + SCALE_MS, QEMU_TIMER_ATTR_EXTERNAL, + ra_timer_handler, slirp); timer_mod(slirp->ra_timer, qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL) + NDP_Interval); } diff --git a/ui/input.c b/ui/input.c index 51b1019..7c9a410 100644 --- a/ui/input.c +++ b/ui/input.c @@ -448,8 +448,9 @@ void qemu_input_event_send_key_delay(uint32_t delay_ms) } if (!kbd_timer) { - kbd_timer = timer_new_ms(QEMU_CLOCK_VIRTUAL, qemu_input_queue_process, - &kbd_queue); + kbd_timer = timer_new_full(NULL, QEMU_CLOCK_VIRTUAL, + SCALE_MS, QEMU_TIMER_ATTR_EXTERNAL, + qemu_input_queue_process, &kbd_queue); } if (queue_count < queue_limit) { qemu_input_queue_delay(&kbd_queue, kbd_timer, diff --git a/util/qemu-timer.c b/util/qemu-timer.c index 04527a3..1cc1b2f 100644 --- a/util/qemu-timer.c +++ b/util/qemu-timer.c @@ -489,6 +489,7 @@ bool timerlist_run_timers(QEMUTimerList *timer_list) bool progress = false; QEMUTimerCB *cb; void *opaque; + bool need_replay_checkpoint = false; if (!atomic_read(&timer_list->active_timers)) { return false; @@ -504,8 +505,15 @@ bool timerlist_run_timers(QEMUTimerList *timer_list) break; default: case QEMU_CLOCK_VIRTUAL: - if (!replay_checkpoint(CHECKPOINT_CLOCK_VIRTUAL)) { - goto out; + if (replay_mode != REPLAY_MODE_NONE) { + /* Checkpoint for virtual clock is redundant in cases where + * it's being triggered with only non-EXTERNAL timers, because + * these timers don't change guest state directly. + * Since it has conditional dependence on specific timers, it is + * subject to race conditions and requires special handling. + * See below. + */ + need_replay_checkpoint = true; } break; case QEMU_CLOCK_HOST: @@ -520,14 +528,39 @@ bool timerlist_run_timers(QEMUTimerList *timer_list) break; } + /* + * Extract expired timers from active timers list and and process them. + * + * In rr mode we need "filtered" checkpointing for virtual clock. The + * checkpoint must be recorded/replayed before processing any non-EXTERNAL timer, + * and that must only be done once since the clock value stays the same. Because + * non-EXTERNAL timers may appear in the timers list while it being processed, + * the checkpoint can be issued at a time until no timers are left and we are + * done". + */ current_time = qemu_clock_get_ns(timer_list->clock->type); - for(;;) { - qemu_mutex_lock(&timer_list->active_timers_lock); - ts = timer_list->active_timers; + qemu_mutex_lock(&timer_list->active_timers_lock); + while ((ts = timer_list->active_timers)) { if (!timer_expired_ns(ts, current_time)) { - qemu_mutex_unlock(&timer_list->active_timers_lock); + /* No expired timers left. The checkpoint can be skipped + * if no timers fired or they were all external. + */ break; } + if (need_replay_checkpoint + && !(ts->attributes & QEMU_TIMER_ATTR_EXTERNAL)) { + /* once we got here, checkpoint clock only once */ + need_replay_checkpoint = false; + qemu_mutex_unlock(&timer_list->active_timers_lock); + if (!replay_checkpoint(CHECKPOINT_CLOCK_VIRTUAL)) { + goto out; + } + qemu_mutex_lock(&timer_list->active_timers_lock); + /* The lock was released; start over again in case the list was + * modified. + */ + continue; + } /* remove timer from the list before calling the callback */ timer_list->active_timers = ts->next; @@ -535,12 +568,15 @@ bool timerlist_run_timers(QEMUTimerList *timer_list) ts->expire_time = -1; cb = ts->cb; opaque = ts->opaque; - qemu_mutex_unlock(&timer_list->active_timers_lock); /* run the callback (the timer list can be modified) */ + qemu_mutex_unlock(&timer_list->active_timers_lock); cb(opaque); + qemu_mutex_lock(&timer_list->active_timers_lock); + progress = true; } + qemu_mutex_unlock(&timer_list->active_timers_lock); out: qemu_event_set(&timer_list->timers_done_ev);