From patchwork Tue Feb 9 15:11:29 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stefan Hajnoczi X-Patchwork-Id: 8262981 Return-Path: X-Original-To: patchwork-qemu-devel@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork1.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork1.web.kernel.org (Postfix) with ESMTP id CBF4B9F38B for ; Tue, 9 Feb 2016 15:41:03 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 2BC8C20138 for ; Tue, 9 Feb 2016 15:41:03 +0000 (UTC) Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id BE50D20220 for ; Tue, 9 Feb 2016 15:41:01 +0000 (UTC) Received: from localhost ([::1]:57206 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1aTAPV-0000Am-5l for patchwork-qemu-devel@patchwork.kernel.org; Tue, 09 Feb 2016 10:41:01 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:35526) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1aTAP2-00008g-PP for qemu-devel@nongnu.org; Tue, 09 Feb 2016 10:40:34 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1aTAOz-0003Om-VQ for qemu-devel@nongnu.org; Tue, 09 Feb 2016 10:40:32 -0500 Received: from mx1.redhat.com ([209.132.183.28]:46814) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1aTAOz-0003OI-OS for qemu-devel@nongnu.org; Tue, 09 Feb 2016 10:40:29 -0500 Received: from int-mx09.intmail.prod.int.phx2.redhat.com (int-mx09.intmail.prod.int.phx2.redhat.com [10.5.11.22]) by mx1.redhat.com (Postfix) with ESMTPS id E1ACFC0ABF2D; Tue, 9 Feb 2016 15:40:28 +0000 (UTC) Received: from localhost (ovpn-112-47.ams2.redhat.com [10.36.112.47]) by int-mx09.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id u19FeR5h016363; Tue, 9 Feb 2016 10:40:28 -0500 From: Stefan Hajnoczi To: Date: Tue, 9 Feb 2016 15:11:29 +0000 Message-Id: <1455030691-18489-2-git-send-email-stefanha@redhat.com> In-Reply-To: <1455030691-18489-1-git-send-email-stefanha@redhat.com> References: <1455030691-18489-1-git-send-email-stefanha@redhat.com> X-Scanned-By: MIMEDefang 2.68 on 10.5.11.22 X-detected-operating-system: by eggs.gnu.org: GNU/Linux 3.x X-Received-From: 209.132.183.28 Cc: Peter Maydell , Stefan Hajnoczi , Paolo Bonzini Subject: [Qemu-devel] [PULL 1/3] iov: avoid memcpy for "simple" iov_from_buf/iov_to_buf 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+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Sender: qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org X-Spam-Status: No, score=-6.9 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_HI, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP From: Paolo Bonzini memcpy can take a large amount of time for small reads and writes. For virtio it is a common case that the first iovec can satisfy the whole read or write. In that case, and if bytes is a constant to avoid excessive growth of code, inline the first iteration into the caller. Signed-off-by: Paolo Bonzini Message-id: 1450782213-14227-1-git-send-email-pbonzini@redhat.com Signed-off-by: Stefan Hajnoczi --- include/qemu/iov.h | 34 ++++++++++++++++++++++++++++++---- util/iov.c | 8 ++++---- 2 files changed, 34 insertions(+), 8 deletions(-) diff --git a/include/qemu/iov.h b/include/qemu/iov.h index 569b2c2..2847551 100644 --- a/include/qemu/iov.h +++ b/include/qemu/iov.h @@ -39,10 +39,36 @@ size_t iov_size(const struct iovec *iov, const unsigned int iov_cnt); * such "large" value is -1 (sinice size_t is unsigned), * so specifying `-1' as `bytes' means 'up to the end of iovec'. */ -size_t iov_from_buf(const struct iovec *iov, unsigned int iov_cnt, - size_t offset, const void *buf, size_t bytes); -size_t iov_to_buf(const struct iovec *iov, const unsigned int iov_cnt, - size_t offset, void *buf, size_t bytes); +size_t iov_from_buf_full(const struct iovec *iov, unsigned int iov_cnt, + size_t offset, const void *buf, size_t bytes); +size_t iov_to_buf_full(const struct iovec *iov, const unsigned int iov_cnt, + size_t offset, void *buf, size_t bytes); + +static inline size_t +iov_from_buf(const struct iovec *iov, unsigned int iov_cnt, + size_t offset, const void *buf, size_t bytes) +{ + if (__builtin_constant_p(bytes) && iov_cnt && + offset <= iov[0].iov_len && bytes <= iov[0].iov_len - offset) { + memcpy(iov[0].iov_base + offset, buf, bytes); + return bytes; + } else { + return iov_from_buf_full(iov, iov_cnt, offset, buf, bytes); + } +} + +static inline size_t +iov_to_buf(const struct iovec *iov, const unsigned int iov_cnt, + size_t offset, void *buf, size_t bytes) +{ + if (__builtin_constant_p(bytes) && iov_cnt && + offset <= iov[0].iov_len && bytes <= iov[0].iov_len - offset) { + memcpy(buf, iov[0].iov_base + offset, bytes); + return bytes; + } else { + return iov_to_buf_full(iov, iov_cnt, offset, buf, bytes); + } +} /** * Set data bytes pointed out by iovec `iov' of size `iov_cnt' elements, diff --git a/util/iov.c b/util/iov.c index e802ee1..062f4e5 100644 --- a/util/iov.c +++ b/util/iov.c @@ -20,8 +20,8 @@ #include "qemu/iov.h" #include "qemu/sockets.h" -size_t iov_from_buf(const struct iovec *iov, unsigned int iov_cnt, - size_t offset, const void *buf, size_t bytes) +size_t iov_from_buf_full(const struct iovec *iov, unsigned int iov_cnt, + size_t offset, const void *buf, size_t bytes) { size_t done; unsigned int i; @@ -39,8 +39,8 @@ size_t iov_from_buf(const struct iovec *iov, unsigned int iov_cnt, return done; } -size_t iov_to_buf(const struct iovec *iov, const unsigned int iov_cnt, - size_t offset, void *buf, size_t bytes) +size_t iov_to_buf_full(const struct iovec *iov, const unsigned int iov_cnt, + size_t offset, void *buf, size_t bytes) { size_t done; unsigned int i;