lguest: implement deferred interrupts in example Launcher
[safe/jmp/linux-2.6] / Documentation / lguest / lguest.c
index 5470b8e..84c471b 100644 (file)
@@ -551,6 +551,21 @@ static unsigned next_desc(struct virtqueue *vq, unsigned int i)
        return next;
 }
 
+/* This actually sends the interrupt for this virtqueue */
+static void trigger_irq(struct virtqueue *vq)
+{
+       unsigned long buf[] = { LHREQ_IRQ, vq->config.irq };
+
+       /* 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)
+               return;
+
+       /* Send the Guest an interrupt tell them we used something up. */
+       if (write(lguest_fd, buf, sizeof(buf)) != 0)
+               err(1, "Triggering irq %i", vq->config.irq);
+}
+
 /* This looks in the virtqueue and for the first available buffer, and converts
  * it to an iovec for convenient access.  Since descriptors consist of some
  * number of output then some number of input descriptors, it's actually two
@@ -567,6 +582,9 @@ static unsigned wait_for_vq_desc(struct virtqueue *vq,
        while (last_avail == vq->vring.avail->idx) {
                u64 event;
 
+               /* OK, tell Guest about progress up to now. */
+               trigger_irq(vq);
+
                /* Nothing new?  Wait for eventfd to tell us they refilled. */
                if (read(vq->eventfd, &event, sizeof(event)) != sizeof(event))
                        errx(1, "Event read failed?");
@@ -631,21 +649,6 @@ static void add_used(struct virtqueue *vq, unsigned int head, int len)
        vq->vring.used->idx++;
 }
 
-/* This actually sends the interrupt for this virtqueue */
-static void trigger_irq(struct virtqueue *vq)
-{
-       unsigned long buf[] = { LHREQ_IRQ, vq->config.irq };
-
-       /* 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)
-               return;
-
-       /* Send the Guest an interrupt tell them we used something up. */
-       if (write(lguest_fd, buf, sizeof(buf)) != 0)
-               err(1, "Triggering irq %i", vq->config.irq);
-}
-
 /* And here's the combo meal deal.  Supersize me! */
 static void add_used_and_trigger(struct virtqueue *vq, unsigned head, int len)
 {
@@ -730,7 +733,7 @@ static void console_output(struct virtqueue *vq)
                        err(1, "Write to stdout gave %i", len);
                iov_consume(iov, out, len);
        }
-       add_used_and_trigger(vq, head, 0);
+       add_used(vq, head, 0);
 }
 
 /*
@@ -754,7 +757,7 @@ static void net_output(struct virtqueue *vq)
                errx(1, "Input buffers in net output queue?");
        if (writev(net_info->tunfd, iov, out) < 0)
                errx(1, "Write to tun failed?");
-       add_used_and_trigger(vq, head, 0);
+       add_used(vq, head, 0);
 }
 
 /* This is where we handle packets coming in from the tun device to our
@@ -1422,7 +1425,7 @@ static void blk_request(struct virtqueue *vq)
        if (out->type & VIRTIO_BLK_T_BARRIER)
                fdatasync(vblk->fd);
 
-       add_used_and_trigger(vq, head, wlen);
+       add_used(vq, head, wlen);
 }
 
 /*L:198 This actually sets up a virtual block device. */
@@ -1496,7 +1499,7 @@ static void rng_input(struct virtqueue *vq)
        }
 
        /* Tell the Guest about the new input. */
-       add_used_and_trigger(vq, head, totlen);
+       add_used(vq, head, totlen);
 }
 
 /* And this creates a "hardware" random number device for the Guest. */