diff options
author | Rusty Russell <rusty@rustcorp.com.au> | 2009-06-13 00:27:11 -0400 |
---|---|---|
committer | Rusty Russell <rusty@rustcorp.com.au> | 2009-06-12 08:57:12 -0400 |
commit | 95c517c09bad31a03e22f2fdb5f0aa26a490a92d (patch) | |
tree | aa34fdb7ca3a6b7575a2ac7639c157995d334bc3 /Documentation | |
parent | 38bc2b8c56a2e212bbd19de7cf9976dcc7bf9953 (diff) |
lguest: avoid sending interrupts to Guest when no activity occurs.
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>
Diffstat (limited to 'Documentation')
-rw-r--r-- | Documentation/lguest/lguest.c | 9 |
1 files changed, 9 insertions, 0 deletions
diff --git a/Documentation/lguest/lguest.c b/Documentation/lguest/lguest.c index 84c471b07c2..20f8253881b 100644 --- a/Documentation/lguest/lguest.c +++ b/Documentation/lguest/lguest.c | |||
@@ -151,6 +151,9 @@ struct virtqueue | |||
151 | /* Last available index we saw. */ | 151 | /* Last available index we saw. */ |
152 | u16 last_avail_idx; | 152 | u16 last_avail_idx; |
153 | 153 | ||
154 | /* How many are used since we sent last irq? */ | ||
155 | unsigned int pending_used; | ||
156 | |||
154 | /* Eventfd where Guest notifications arrive. */ | 157 | /* Eventfd where Guest notifications arrive. */ |
155 | int eventfd; | 158 | int eventfd; |
156 | 159 | ||
@@ -556,6 +559,11 @@ static void trigger_irq(struct virtqueue *vq) | |||
556 | { | 559 | { |
557 | unsigned long buf[] = { LHREQ_IRQ, vq->config.irq }; | 560 | unsigned long buf[] = { LHREQ_IRQ, vq->config.irq }; |
558 | 561 | ||
562 | /* Don't inform them if nothing used. */ | ||
563 | if (!vq->pending_used) | ||
564 | return; | ||
565 | vq->pending_used = 0; | ||
566 | |||
559 | /* If they don't want an interrupt, don't send one, unless empty. */ | 567 | /* If they don't want an interrupt, don't send one, unless empty. */ |
560 | if ((vq->vring.avail->flags & VRING_AVAIL_F_NO_INTERRUPT) | 568 | if ((vq->vring.avail->flags & VRING_AVAIL_F_NO_INTERRUPT) |
561 | && lg_last_avail(vq) != vq->vring.avail->idx) | 569 | && lg_last_avail(vq) != vq->vring.avail->idx) |
@@ -647,6 +655,7 @@ static void add_used(struct virtqueue *vq, unsigned int head, int len) | |||
647 | /* Make sure buffer is written before we update index. */ | 655 | /* Make sure buffer is written before we update index. */ |
648 | wmb(); | 656 | wmb(); |
649 | vq->vring.used->idx++; | 657 | vq->vring.used->idx++; |
658 | vq->pending_used++; | ||
650 | } | 659 | } |
651 | 660 | ||
652 | /* And here's the combo meal deal. Supersize me! */ | 661 | /* And here's the combo meal deal. Supersize me! */ |