lguest: suppress notifications in example Launcher
authorRusty Russell <rusty@rustcorp.com.au>
Sat, 13 Jun 2009 04:27:12 +0000 (22:27 -0600)
committerRusty Russell <rusty@rustcorp.com.au>
Fri, 12 Jun 2009 12:57:13 +0000 (22:27 +0930)
The Guest only really needs to tell us about activity when we're going
to listen to the eventfd: normally, we don't want to know.

So if there are no available buffers, turn on notifications, re-check,
then wait for the Guest to notify us via the eventfd, then turn
notifications off again.

There's enough else going on that the differences are in the noise.

Before: Secs RxKicks TxKicks
 1G TCP Guest->Host: 3.94   4686   32815
 1M normal pings: 104 142862 1000010
 1M 1k pings (-l 120): 57 142026 1000007

After:
 1G TCP Guest->Host: 3.76   4691   32811
 1M normal pings: 111 142859  997467
 1M 1k pings (-l 120): 55  19648  501549

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

index 64110797044adfb0b5c11510bcdba72f46aa2968..bb5e3c28d9d60bdcf6bf69a9241b281f5ae65ddc 100644 (file)
@@ -172,6 +172,7 @@ static struct termios orig_term;
  * threads and so we need to make sure that changes visible to the Guest happen
  * in precise order. */
 #define wmb() __asm__ __volatile__("" : : : "memory")
+#define mb() __asm__ __volatile__("" : : : "memory")
 
 /* Convert an iovec element to the given type.
  *
@@ -593,9 +594,23 @@ static unsigned wait_for_vq_desc(struct virtqueue *vq,
                /* OK, tell Guest about progress up to now. */
                trigger_irq(vq);
 
+               /* OK, now we need to know about added descriptors. */
+               vq->vring.used->flags &= ~VRING_USED_F_NO_NOTIFY;
+
+               /* They could have slipped one in as we were doing that: make
+                * sure it's written, then check again. */
+               mb();
+               if (last_avail != vq->vring.avail->idx) {
+                       vq->vring.used->flags |= VRING_USED_F_NO_NOTIFY;
+                       break;
+               }
+
                /* Nothing new?  Wait for eventfd to tell us they refilled. */
                if (read(vq->eventfd, &event, sizeof(event)) != sizeof(event))
                        errx(1, "Event read failed?");
+
+               /* We don't need to be notified again. */
+               vq->vring.used->flags |= VRING_USED_F_NO_NOTIFY;
        }
 
        /* Check it isn't doing very strange things with descriptor numbers. */