lguest: avoid sending interrupts to Guest when no activity occurs.
authorRusty Russell <rusty@rustcorp.com.au>
Sat, 13 Jun 2009 04:27:11 +0000 (22:27 -0600)
committerRusty Russell <rusty@rustcorp.com.au>
Fri, 12 Jun 2009 12:57:12 +0000 (22:27 +0930)
If we track how many buffers we've used, we can tell whether we really
need to interrupt the Guest.  This happens as a side effect of
spurious notifications.

Spurious notifications happen because it can take a while before the
Host thread wakes up and sets the VRING_USED_F_NO_NOTIFY flag, and
meanwhile the Guest can more notifications.

A real fix would be to use wake counts, rather than a suppression
flag, but the practical difference is generally in the noise: the
interrupt is usually coalesced into a pending one anyway so we just
save a system call which isn't clearly measurable.

Secs Spurious IRQS
1G TCP Guest->Host: 3.93 58
1M normal pings: 100 72
1M 1k pings (-l 120): 57 492904

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Documentation/lguest/lguest.c

index 84c471b07c2730686043645bc1c4793f50107802..20f8253881b31506865b76a3c888306728c7fb4a 100644 (file)
@@ -151,6 +151,9 @@ struct virtqueue
        /* Last available index we saw. */
        u16 last_avail_idx;
 
+       /* How many are used since we sent last irq? */
+       unsigned int pending_used;
+
        /* Eventfd where Guest notifications arrive. */
        int eventfd;
 
@@ -556,6 +559,11 @@ static void trigger_irq(struct virtqueue *vq)
 {
        unsigned long buf[] = { LHREQ_IRQ, vq->config.irq };
 
+       /* Don't inform them if nothing used. */
+       if (!vq->pending_used)
+               return;
+       vq->pending_used = 0;
+
        /* If they don't want an interrupt, don't send one, unless empty. */
        if ((vq->vring.avail->flags & VRING_AVAIL_F_NO_INTERRUPT)
            && lg_last_avail(vq) != vq->vring.avail->idx)
@@ -647,6 +655,7 @@ static void add_used(struct virtqueue *vq, unsigned int head, int len)
        /* Make sure buffer is written before we update index. */
        wmb();
        vq->vring.used->idx++;
+       vq->pending_used++;
 }
 
 /* And here's the combo meal deal.  Supersize me! */