From 0850601196ac67f7eba21f371463d7efcfbedbe7 Mon Sep 17 00:00:00 2001 From: Pekka Enberg Date: Sat, 30 Apr 2011 12:15:57 +0300 Subject: [PATCH] Revert "kvm tools: Use threadpool for virtio-net" This reverts commit a37089da817ce7aad9789aeb9fc09b68e088ad9a. --- tools/kvm/virtio-net.c | 101 +++++++++++++++++++++++++++++++---------- 1 file changed, 76 insertions(+), 25 deletions(-) diff --git a/tools/kvm/virtio-net.c b/tools/kvm/virtio-net.c index 58b3de451f2b..3e134296d4ad 100644 --- a/tools/kvm/virtio-net.c +++ b/tools/kvm/virtio-net.c @@ -7,7 +7,6 @@ #include "kvm/util.h" #include "kvm/kvm.h" #include "kvm/pci.h" -#include "kvm/threadpool.h" #include #include @@ -41,9 +40,16 @@ 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 = { @@ -63,44 +69,70 @@ static struct net_device net_device = { 1UL << VIRTIO_NET_F_GUEST_TSO6, }; -static void virtio_net_rx_callback(struct kvm *self, void *param) +static void *virtio_net_rx_thread(void *p) { struct iovec iov[VIRTIO_NET_QUEUE_SIZE]; struct virt_queue *vq; + struct kvm *self; uint16_t out, in; uint16_t head; int len; - vq = param; + 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); + } - 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); } - kvm__irq_line(self, VIRTIO_NET_IRQ, 1); + pthread_exit(NULL); + return NULL; + } -static void virtio_net_tx_callback(struct kvm *self, void *param) +static void *virtio_net_tx_thread(void *p) { struct iovec iov[VIRTIO_NET_QUEUE_SIZE]; struct virt_queue *vq; + struct kvm *self; uint16_t out, in; uint16_t head; int len; - vq = param; + 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); - 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); + 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); } - kvm__irq_line(self, VIRTIO_NET_IRQ, 1); -} + pthread_exit(NULL); + return NULL; +} 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; @@ -161,7 +193,19 @@ 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) { - thread_pool__signal_work(net_device.jobs[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); + + } } static bool virtio_net_pci_io_out(struct kvm *self, uint16_t port, void *data, int size, uint32_t count) @@ -187,13 +231,6 @@ 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: @@ -330,10 +367,24 @@ 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); } } -- 2.39.5