Aurelien Jarno <[EMAIL PROTECTED]> writes: > The patch below from KVM improves network transfers in a huge way. > wget in a MIPS target now gives me a transfer speed of up to 120 > Mbits/s with an e1000 emulated card.
Without I/O signals, qemu is relying on periodic timer events to poll the I/O. That seems wrong, even though it works reasonably well because timers are so frequent. In KVM, timers are less frequent, and it does not work quite as well. Here is a quick try at a more elaborate patch. It attaches a signal to all[1] file descriptors that will be used in select(). Also, it uses a dedicated SIGIO handler rather than piggybacking on the alarm handler, so alarm I/O is changed to use SIGALRM. I copied the handler function from the alarm case, quite frankly I do not quite understand what is going on. Also, I left _WIN32 out, since I have no idea how signals work there. [1] The slirp file descriptors are not included yet. Anders. diff --git a/vl.c b/vl.c index c87e8bc..ff8ceef 100644 --- a/vl.c +++ b/vl.c @@ -1148,6 +1148,25 @@ static int timer_load(QEMUFile *f, void *opaque, int version_id) return 0; } +#ifndef _WIN32 +static void host_io_handler(int host_signum) +{ + CPUState *env = next_cpu; + + if (env) { + /* stop the currently executing cpu because io occured */ + cpu_interrupt(env, CPU_INTERRUPT_EXIT); +#ifdef USE_KQEMU + if (env->kqemu_enabled) { + kqemu_cpu_interrupt(env); + } +#endif + } + + event_pending = 1; +} +#endif + #ifdef _WIN32 void CALLBACK host_alarm_handler(UINT uTimerID, UINT uMsg, DWORD_PTR dwUser, DWORD_PTR dw1, DWORD_PTR dw2) @@ -1240,7 +1259,20 @@ static uint64_t qemu_next_deadline(void) #define RTC_FREQ 1024 -static void enable_sigio_timer(int fd) +static void enable_sigio(int fd) +{ + struct sigaction act; + + sigfillset(&act.sa_mask); + act.sa_flags = 0; + act.sa_handler = host_io_handler; + + sigaction(SIGIO, &act, NULL); + fcntl(fd, F_SETFL, O_ASYNC); + fcntl(fd, F_SETOWN, getpid()); +} + +static void enable_sigalrm(int fd) { struct sigaction act; @@ -1249,8 +1281,9 @@ static void enable_sigio_timer(int fd) act.sa_flags = 0; act.sa_handler = host_alarm_handler; - sigaction(SIGIO, &act, NULL); + sigaction(SIGALRM, &act, NULL); fcntl(fd, F_SETFL, O_ASYNC); + fcntl(fd, F_SETSIG, SIGALRM); fcntl(fd, F_SETOWN, getpid()); } @@ -1287,7 +1320,7 @@ static int hpet_start_timer(struct qemu_alarm_timer *t) if (r < 0) goto fail; - enable_sigio_timer(fd); + enable_sigalrm(fd); t->priv = (void *)(long)fd; return 0; @@ -1325,7 +1358,7 @@ static int rtc_start_timer(struct qemu_alarm_timer *t) return -1; } - enable_sigio_timer(rtc_fd); + enable_sigalrm(rtc_fd); t->priv = (void *)(long)rtc_fd; @@ -5481,6 +5514,10 @@ int qemu_set_fd_handler2(int fd, return -1; ioh->next = first_io_handler; first_io_handler = ioh; +#ifndef _WIN32 + enable_sigio(fd); +#endif + found: ioh->fd = fd; ioh->fd_read_poll = fd_read_poll;