int qemu_calculate_timeout(void) { #ifndef CONFIG_IOTHREAD int timeout; if (!vm_running) timeout = 5000; else if (tcg_has_work()) timeout = 0; else if (!use_icount) { #ifdef WIN32 /* This corresponds to the case where the emulated system is * totally idle and waiting for i/o. The problem is that on * Windows, the default value will prevent Windows user events * to be delivered in less than 5 seconds. * * Upstream contains a different way to handle this, for now * this hack should be sufficient until we integrate it into * our tree. */ timeout = 1000/15; /* deliver user events every 15/th of second */ #else timeout = 5000; #endif } else { /* XXX: use timeout computed from timers */ int64_t add; int64_t delta; /* Advance virtual time to the next event. */ delta = qemu_icount_delta(); if (delta > 0) { /* If virtual time is ahead of real time then just wait for IO. */ timeout = (delta + 999999) / 1000000; } else { /* Wait for either IO to occur or the next timer event. */ add = qemu_next_deadline(); /* We advance the timer before checking for IO. Limit the amount we advance so that early IO activity won't get the guest too far ahead. */ if (add > 10000000) add = 10000000; delta += add; qemu_icount += qemu_icount_round (add); timeout = delta / 1000000; if (timeout < 0) timeout = 0; } } return timeout; #else /* CONFIG_IOTHREAD */ return 1000; #endif }
static int tcg_cpu_exec(CPUArchState *env) { int ret; #ifdef CONFIG_PROFILER int64_t ti; #endif #ifdef CONFIG_PROFILER ti = profile_getclock(); #endif if (use_icount) { int64_t count; int64_t deadline; int decr; qemu_icount -= (env->icount_decr.u16.low + env->icount_extra); env->icount_decr.u16.low = 0; env->icount_extra = 0; deadline = qemu_clock_deadline_ns_all(QEMU_CLOCK_VIRTUAL); /* Maintain prior (possibly buggy) behaviour where if no deadline * was set (as there is no QEMU_CLOCK_VIRTUAL timer) or it is more than * INT32_MAX nanoseconds ahead, we still use INT32_MAX * nanoseconds. */ if ((deadline < 0) || (deadline > INT32_MAX)) { deadline = INT32_MAX; } count = qemu_icount_round(deadline); qemu_icount += count; decr = (count > 0xffff) ? 0xffff : count; count -= decr; env->icount_decr.u16.low = decr; env->icount_extra = count; } ret = cpu_exec(env); #ifdef CONFIG_PROFILER qemu_time += profile_getclock() - ti; #endif if (use_icount) { /* Fold pending instructions back into the instruction counter, and clear the interrupt flag. */ qemu_icount -= (env->icount_decr.u16.low + env->icount_extra); env->icount_decr.u32 = 0; env->icount_extra = 0; } return ret; }
int qemu_calculate_timeout(void) { int timeout; #ifdef CONFIG_IOTHREAD /* When using icount, making forward progress with qemu_icount when the guest CPU is idle is critical. We only use the static io-thread timeout for non icount runs. */ if (!use_icount) { return 1000; } #endif if (!vm_running) timeout = 5000; else { /* XXX: use timeout computed from timers */ int64_t add; int64_t delta; /* Advance virtual time to the next event. */ delta = qemu_icount_delta(); if (delta > 0) { /* If virtual time is ahead of real time then just wait for IO. */ timeout = (delta + 999999) / 1000000; } else { /* Wait for either IO to occur or the next timer event. */ add = qemu_next_deadline(); /* We advance the timer before checking for IO. Limit the amount we advance so that early IO activity won't get the guest too far ahead. */ if (add > 10000000) add = 10000000; delta += add; qemu_icount += qemu_icount_round (add); timeout = delta / 1000000; if (timeout < 0) timeout = 0; } } return timeout; }
static int qemu_cpu_exec(CPUState *env) { int ret; #ifdef CONFIG_PROFILER int64_t ti; #endif #if 1 /* yclin */ if (tracer_toggle_request) { tb_flush(env); } #endif #ifdef CONFIG_PROFILER ti = profile_getclock(); #endif if (use_icount) { int64_t count; int decr; qemu_icount -= (env->icount_decr.u16.low + env->icount_extra); env->icount_decr.u16.low = 0; env->icount_extra = 0; count = qemu_icount_round (qemu_next_deadline()); qemu_icount += count; decr = (count > 0xffff) ? 0xffff : count; count -= decr; env->icount_decr.u16.low = decr; env->icount_extra = count; } ret = cpu_exec(env); #ifdef CONFIG_PROFILER qemu_time += profile_getclock() - ti; #endif if (use_icount) { /* Fold pending instructions back into the instruction counter, and clear the interrupt flag. */ qemu_icount -= (env->icount_decr.u16.low + env->icount_extra); env->icount_decr.u32 = 0; env->icount_extra = 0; } return ret; }
int qemu_calculate_timeout(void) { #ifndef CONFIG_IOTHREAD int timeout; if (!vm_running) timeout = 5000; else { /* XXX: use timeout computed from timers */ int64_t add; int64_t delta; /* Advance virtual time to the next event. */ delta = qemu_icount_delta(); if (delta > 0) { /* If virtual time is ahead of real time then just wait for IO. */ timeout = (delta + 999999) / 1000000; } else { /* Wait for either IO to occur or the next timer event. */ add = qemu_next_icount_deadline(); /* We advance the timer before checking for IO. Limit the amount we advance so that early IO activity won't get the guest too far ahead. */ if (add > 10000000) add = 10000000; delta += add; qemu_icount += qemu_icount_round (add); timeout = delta / 1000000; if (timeout < 0) timeout = 0; } } return timeout; #else /* CONFIG_IOTHREAD */ return 1000; #endif }