lguest: Adaptive timeout

Since the correct timeout value varies, use a heuristic which adjusts
the timeout depending on how many packets we've seen. This gives
slightly worse results, but doesn't need tweaking when GSO is
introduced.

500 usec 19.1887 xmit 561141 recv 1 timeout 559657
Dynamic (278) 20.1974 xmit 214510 recv 5 timeout 214491 usec 278

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>

+11 -1
+11 -1
Documentation/lguest/lguest.c
··· 84 static unsigned long guest_limit, guest_max; 85 /* The pipe for signal hander to write to. */ 86 static int timeoutpipe[2]; 87 88 /* a per-cpu variable indicating whose vcpu is currently running */ 89 static unsigned int __thread cpu_id; ··· 906 itm.it_interval.tv_sec = 0; 907 itm.it_interval.tv_usec = 0; 908 itm.it_value.tv_sec = 0; 909 - itm.it_value.tv_usec = 500; 910 911 setitimer(ITIMER_REAL, &itm, NULL); 912 } ··· 923 unsigned int head, out, in, num = 0; 924 int len; 925 struct iovec iov[vq->vring.num]; 926 927 /* Keep getting output buffers from the Guest until we run out. */ 928 while ((head = get_vq_desc(vq, iov, &out, &in)) != vq->vring.num) { ··· 941 /* Block further kicks and set up a timer if we saw anything. */ 942 if (!timeout && num) 943 block_vq(vq); 944 } 945 946 /* This is where we handle a packet coming in from the tun device to our
··· 84 static unsigned long guest_limit, guest_max; 85 /* The pipe for signal hander to write to. */ 86 static int timeoutpipe[2]; 87 + static unsigned int timeout_usec = 500; 88 89 /* a per-cpu variable indicating whose vcpu is currently running */ 90 static unsigned int __thread cpu_id; ··· 905 itm.it_interval.tv_sec = 0; 906 itm.it_interval.tv_usec = 0; 907 itm.it_value.tv_sec = 0; 908 + itm.it_value.tv_usec = timeout_usec; 909 910 setitimer(ITIMER_REAL, &itm, NULL); 911 } ··· 922 unsigned int head, out, in, num = 0; 923 int len; 924 struct iovec iov[vq->vring.num]; 925 + static int last_timeout_num; 926 927 /* Keep getting output buffers from the Guest until we run out. */ 928 while ((head = get_vq_desc(vq, iov, &out, &in)) != vq->vring.num) { ··· 939 /* Block further kicks and set up a timer if we saw anything. */ 940 if (!timeout && num) 941 block_vq(vq); 942 + 943 + if (timeout) { 944 + if (num < last_timeout_num) 945 + timeout_usec += 10; 946 + else if (timeout_usec > 1) 947 + timeout_usec--; 948 + last_timeout_num = num; 949 + } 950 } 951 952 /* This is where we handle a packet coming in from the tun device to our