From patchwork Thu Apr 28 13:40:45 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sasha Levin X-Patchwork-Id: 739321 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by demeter1.kernel.org (8.14.4/8.14.3) with ESMTP id p3SDfQui008583 for ; Thu, 28 Apr 2011 13:41:26 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S932727Ab1D1NlR (ORCPT ); Thu, 28 Apr 2011 09:41:17 -0400 Received: from mail-bw0-f46.google.com ([209.85.214.46]:52574 "EHLO mail-bw0-f46.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1757509Ab1D1NlP (ORCPT ); Thu, 28 Apr 2011 09:41:15 -0400 Received: by mail-bw0-f46.google.com with SMTP id 15so2302490bwz.19 for ; Thu, 28 Apr 2011 06:41:14 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=gamma; h=domainkey-signature:from:to:cc:subject:date:message-id:x-mailer :in-reply-to:references; bh=JJzcHYZTnLrQMiyKcTcLZ9DsCY06sMgpZI3YwXgvqgo=; b=S4dyHYeGpu558emqMnweldxBXNXVwQ+j/78gzBwHvm4zgO57IBdXuDtYE3XiXSyerX 9C/DCAMMn/eJASjkpAdbCsRykAdOX84JLILRoKs37ybpEKSQqFxauY4U+BcG3OabZXS3 1ebmv1n/5XU/ZunVZM6Os4/e0SRqa3yxDmdlc= DomainKey-Signature: a=rsa-sha1; c=nofws; d=gmail.com; s=gamma; h=from:to:cc:subject:date:message-id:x-mailer:in-reply-to:references; b=Qg4th0yACVSWnfZfdIpIiORkZYP6mTKu1Oh+uG1LlgwVBNUvolyOF67cZVyifHtIfB gRHt0JJQtJdDKUG+X6Le1PWI/XHOOvteXdZ8ae+VNvste7KKEQcM256iHZ02AZyi62Hg rFJSbuJWVXdr5e3IR9QMKCHSqo67nFr918pLs= Received: by 10.204.50.1 with SMTP id x1mr2215246bkf.213.1303998074536; Thu, 28 Apr 2011 06:41:14 -0700 (PDT) Received: from localhost.localdomain ([188.120.129.206]) by mx.google.com with ESMTPS id w3sm1033795bkt.17.2011.04.28.06.41.12 (version=TLSv1/SSLv3 cipher=OTHER); Thu, 28 Apr 2011 06:41:14 -0700 (PDT) From: Sasha Levin To: penberg@kernel.org Cc: mingo@elte.hu, asias.hejun@gmail.com, gorcunov@gmail.com, prasadjoshi124@gmail.com, kvm@vger.kernel.org, Sasha Levin Subject: [PATCH 6/6] kvm tools: Use threadpool for virtio-net Date: Thu, 28 Apr 2011 16:40:45 +0300 Message-Id: <1303998045-22932-6-git-send-email-levinsasha928@gmail.com> X-Mailer: git-send-email 1.7.5.rc3 In-Reply-To: <1303998045-22932-1-git-send-email-levinsasha928@gmail.com> References: <1303998045-22932-1-git-send-email-levinsasha928@gmail.com> Sender: kvm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org X-Greylist: IP, sender and recipient auto-whitelisted, not delayed by milter-greylist-4.2.6 (demeter1.kernel.org [140.211.167.41]); Thu, 28 Apr 2011 13:41:26 +0000 (UTC) virtio-net has been converted to use the threadpool. This is very similar to the change done in virtio-blk, only here we had 2 queues to handle. Signed-off-by: Sasha Levin --- tools/kvm/virtio-net.c | 101 ++++++++++++------------------------------------ 1 files changed, 25 insertions(+), 76 deletions(-) diff --git a/tools/kvm/virtio-net.c b/tools/kvm/virtio-net.c index 3e13429..58b3de4 100644 --- a/tools/kvm/virtio-net.c +++ b/tools/kvm/virtio-net.c @@ -7,6 +7,7 @@ #include "kvm/util.h" #include "kvm/kvm.h" #include "kvm/pci.h" +#include "kvm/threadpool.h" #include #include @@ -40,16 +41,9 @@ struct net_device { uint8_t status; uint16_t queue_selector; - pthread_t io_rx_thread; - pthread_mutex_t io_rx_mutex; - pthread_cond_t io_rx_cond; - - pthread_t io_tx_thread; - pthread_mutex_t io_tx_mutex; - pthread_cond_t io_tx_cond; - int tap_fd; char tap_name[IFNAMSIZ]; + void *jobs[VIRTIO_NET_NUM_QUEUES]; }; static struct net_device net_device = { @@ -69,70 +63,44 @@ static struct net_device net_device = { 1UL << VIRTIO_NET_F_GUEST_TSO6, }; -static void *virtio_net_rx_thread(void *p) +static void virtio_net_rx_callback(struct kvm *self, void *param) { struct iovec iov[VIRTIO_NET_QUEUE_SIZE]; struct virt_queue *vq; - struct kvm *self; uint16_t out, in; uint16_t head; int len; - self = p; - vq = &net_device.vqs[VIRTIO_NET_RX_QUEUE]; - - while (1) { - mutex_lock(&net_device.io_rx_mutex); - if (!virt_queue__available(vq)) - pthread_cond_wait(&net_device.io_rx_cond, &net_device.io_rx_mutex); - mutex_unlock(&net_device.io_rx_mutex); - - while (virt_queue__available(vq)) { - head = virt_queue__get_iov(vq, iov, &out, &in, self); - len = readv(net_device.tap_fd, iov, in); - virt_queue__set_used_elem(vq, head, len); - /* We should interrupt guest right now, otherwise latency is huge. */ - kvm__irq_line(self, VIRTIO_NET_IRQ, 1); - } + vq = param; + while (virt_queue__available(vq)) { + head = virt_queue__get_iov(vq, iov, &out, &in, self); + len = readv(net_device.tap_fd, iov, in); + virt_queue__set_used_elem(vq, head, len); } - pthread_exit(NULL); - return NULL; - + kvm__irq_line(self, VIRTIO_NET_IRQ, 1); } -static void *virtio_net_tx_thread(void *p) +static void virtio_net_tx_callback(struct kvm *self, void *param) { struct iovec iov[VIRTIO_NET_QUEUE_SIZE]; struct virt_queue *vq; - struct kvm *self; uint16_t out, in; uint16_t head; int len; - self = p; - vq = &net_device.vqs[VIRTIO_NET_TX_QUEUE]; - - while (1) { - mutex_lock(&net_device.io_tx_mutex); - if (!virt_queue__available(vq)) - pthread_cond_wait(&net_device.io_tx_cond, &net_device.io_tx_mutex); - mutex_unlock(&net_device.io_tx_mutex); + vq = param; - while (virt_queue__available(vq)) { - head = virt_queue__get_iov(vq, iov, &out, &in, self); - len = writev(net_device.tap_fd, iov, out); - virt_queue__set_used_elem(vq, head, len); - } - - kvm__irq_line(self, VIRTIO_NET_IRQ, 1); + while (virt_queue__available(vq)) { + head = virt_queue__get_iov(vq, iov, &out, &in, self); + len = writev(net_device.tap_fd, iov, out); + virt_queue__set_used_elem(vq, head, len); } - pthread_exit(NULL); - return NULL; - + kvm__irq_line(self, VIRTIO_NET_IRQ, 1); } + static bool virtio_net_pci_io_device_specific_in(void *data, unsigned long offset, int size, uint32_t count) { uint8_t *config_space = (uint8_t *) &net_device.net_config; @@ -193,19 +161,7 @@ static bool virtio_net_pci_io_in(struct kvm *self, uint16_t port, void *data, in static void virtio_net_handle_callback(struct kvm *self, uint16_t queue_index) { - if (queue_index == VIRTIO_NET_TX_QUEUE) { - - mutex_lock(&net_device.io_tx_mutex); - pthread_cond_signal(&net_device.io_tx_cond); - mutex_unlock(&net_device.io_tx_mutex); - - } else if (queue_index == VIRTIO_NET_RX_QUEUE) { - - mutex_lock(&net_device.io_rx_mutex); - pthread_cond_signal(&net_device.io_rx_cond); - mutex_unlock(&net_device.io_rx_mutex); - - } + thread_pool__signal_work(net_device.jobs[queue_index]); } static bool virtio_net_pci_io_out(struct kvm *self, uint16_t port, void *data, int size, uint32_t count) @@ -231,6 +187,13 @@ static bool virtio_net_pci_io_out(struct kvm *self, uint16_t port, void *data, i vring_init(&queue->vring, VIRTIO_NET_QUEUE_SIZE, p, 4096); + if (net_device.queue_selector == VIRTIO_NET_TX_QUEUE) + net_device.jobs[net_device.queue_selector] = + thread_pool__add_jobtype(self, virtio_net_tx_callback, queue); + else if (net_device.queue_selector == VIRTIO_NET_RX_QUEUE) + net_device.jobs[net_device.queue_selector] = + thread_pool__add_jobtype(self, virtio_net_rx_callback, queue); + break; } case VIRTIO_PCI_QUEUE_SEL: @@ -367,24 +330,10 @@ fail: return 0; } -static void virtio_net__io_thread_init(struct kvm *self) -{ - pthread_mutex_init(&net_device.io_rx_mutex, NULL); - pthread_cond_init(&net_device.io_tx_cond, NULL); - - pthread_mutex_init(&net_device.io_rx_mutex, NULL); - pthread_cond_init(&net_device.io_tx_cond, NULL); - - pthread_create(&net_device.io_rx_thread, NULL, virtio_net_rx_thread, (void *)self); - pthread_create(&net_device.io_tx_thread, NULL, virtio_net_tx_thread, (void *)self); -} - void virtio_net__init(const struct virtio_net_parameters *params) { if (virtio_net__tap_init(params)) { pci__register(&virtio_net_pci_device, PCI_VIRTIO_NET_DEVNUM); ioport__register(IOPORT_VIRTIO_NET, &virtio_net_io_ops, IOPORT_VIRTIO_NET_SIZE); - - virtio_net__io_thread_init(params->self); } }