mirror of https://github.com/xqemu/xqemu.git
better win32 timers - use win32 event to wake up cpu in idle mode (kazu)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1885 c046a42c-6fe2-441c-8c8c-71466251a162
This commit is contained in:
parent
eade0f192e
commit
06d9f2f7d4
73
vl.c
73
vl.c
|
@ -518,9 +518,15 @@ int64_t cpu_get_real_ticks(void)
|
||||||
|
|
||||||
int64_t cpu_get_real_ticks(void)
|
int64_t cpu_get_real_ticks(void)
|
||||||
{
|
{
|
||||||
|
#ifdef _WIN32
|
||||||
|
LARGE_INTEGER ti;
|
||||||
|
QueryPerformanceCounter(&ti);
|
||||||
|
return ti.QuadPart;
|
||||||
|
#else
|
||||||
int64_t val;
|
int64_t val;
|
||||||
asm volatile ("rdtsc" : "=A" (val));
|
asm volatile ("rdtsc" : "=A" (val));
|
||||||
return val;
|
return val;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
#elif defined(__x86_64__)
|
#elif defined(__x86_64__)
|
||||||
|
@ -598,17 +604,26 @@ void cpu_disable_ticks(void)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
void cpu_calibrate_ticks(void)
|
||||||
|
{
|
||||||
|
LARGE_INTEGER freq;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ret = QueryPerformanceFrequency(&freq);
|
||||||
|
if (ret == 0) {
|
||||||
|
fprintf(stderr, "Could not calibrate ticks\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
ticks_per_sec = freq.QuadPart;
|
||||||
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
static int64_t get_clock(void)
|
static int64_t get_clock(void)
|
||||||
{
|
{
|
||||||
#ifdef _WIN32
|
|
||||||
struct _timeb tb;
|
|
||||||
_ftime(&tb);
|
|
||||||
return ((int64_t)tb.time * 1000 + (int64_t)tb.millitm) * 1000;
|
|
||||||
#else
|
|
||||||
struct timeval tv;
|
struct timeval tv;
|
||||||
gettimeofday(&tv, NULL);
|
gettimeofday(&tv, NULL);
|
||||||
return tv.tv_sec * 1000000LL + tv.tv_usec;
|
return tv.tv_sec * 1000000LL + tv.tv_usec;
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void cpu_calibrate_ticks(void)
|
void cpu_calibrate_ticks(void)
|
||||||
|
@ -617,15 +632,12 @@ void cpu_calibrate_ticks(void)
|
||||||
|
|
||||||
usec = get_clock();
|
usec = get_clock();
|
||||||
ticks = cpu_get_real_ticks();
|
ticks = cpu_get_real_ticks();
|
||||||
#ifdef _WIN32
|
|
||||||
Sleep(50);
|
|
||||||
#else
|
|
||||||
usleep(50 * 1000);
|
usleep(50 * 1000);
|
||||||
#endif
|
|
||||||
usec = get_clock() - usec;
|
usec = get_clock() - usec;
|
||||||
ticks = cpu_get_real_ticks() - ticks;
|
ticks = cpu_get_real_ticks() - ticks;
|
||||||
ticks_per_sec = (ticks * 1000000LL + (usec >> 1)) / usec;
|
ticks_per_sec = (ticks * 1000000LL + (usec >> 1)) / usec;
|
||||||
}
|
}
|
||||||
|
#endif /* !_WIN32 */
|
||||||
|
|
||||||
/* compute with 96 bit intermediate result: (a*b)/c */
|
/* compute with 96 bit intermediate result: (a*b)/c */
|
||||||
uint64_t muldiv64(uint64_t a, uint32_t b, uint32_t c)
|
uint64_t muldiv64(uint64_t a, uint32_t b, uint32_t c)
|
||||||
|
@ -673,6 +685,8 @@ QEMUClock *vm_clock;
|
||||||
static QEMUTimer *active_timers[2];
|
static QEMUTimer *active_timers[2];
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
static MMRESULT timerID;
|
static MMRESULT timerID;
|
||||||
|
static HANDLE host_alarm = NULL;
|
||||||
|
static unsigned int period = 1;
|
||||||
#else
|
#else
|
||||||
/* frequency of the times() clock tick */
|
/* frequency of the times() clock tick */
|
||||||
static int timer_freq;
|
static int timer_freq;
|
||||||
|
@ -895,6 +909,9 @@ static void host_alarm_handler(int host_signum)
|
||||||
qemu_get_clock(vm_clock)) ||
|
qemu_get_clock(vm_clock)) ||
|
||||||
qemu_timer_expired(active_timers[QEMU_TIMER_REALTIME],
|
qemu_timer_expired(active_timers[QEMU_TIMER_REALTIME],
|
||||||
qemu_get_clock(rt_clock))) {
|
qemu_get_clock(rt_clock))) {
|
||||||
|
#ifdef _WIN32
|
||||||
|
SetEvent(host_alarm);
|
||||||
|
#endif
|
||||||
CPUState *env = cpu_single_env;
|
CPUState *env = cpu_single_env;
|
||||||
if (env) {
|
if (env) {
|
||||||
/* stop the currently executing cpu because a timer occured */
|
/* stop the currently executing cpu because a timer occured */
|
||||||
|
@ -955,8 +972,15 @@ static void init_timers(void)
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
{
|
{
|
||||||
int count=0;
|
int count=0;
|
||||||
|
TIMECAPS tc;
|
||||||
|
|
||||||
|
ZeroMemory(&tc, sizeof(TIMECAPS));
|
||||||
|
timeGetDevCaps(&tc, sizeof(TIMECAPS));
|
||||||
|
if (period < tc.wPeriodMin)
|
||||||
|
period = tc.wPeriodMin;
|
||||||
|
timeBeginPeriod(period);
|
||||||
timerID = timeSetEvent(1, // interval (ms)
|
timerID = timeSetEvent(1, // interval (ms)
|
||||||
0, // resolution
|
period, // resolution
|
||||||
host_alarm_handler, // function
|
host_alarm_handler, // function
|
||||||
(DWORD)&count, // user parameter
|
(DWORD)&count, // user parameter
|
||||||
TIME_PERIODIC | TIME_CALLBACK_FUNCTION);
|
TIME_PERIODIC | TIME_CALLBACK_FUNCTION);
|
||||||
|
@ -964,6 +988,12 @@ static void init_timers(void)
|
||||||
perror("failed timer alarm");
|
perror("failed timer alarm");
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
host_alarm = CreateEvent(NULL, FALSE, FALSE, NULL);
|
||||||
|
if (!host_alarm) {
|
||||||
|
perror("failed CreateEvent");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
ResetEvent(host_alarm);
|
||||||
}
|
}
|
||||||
pit_min_timer_count = ((uint64_t)10000 * PIT_FREQ) / 1000000;
|
pit_min_timer_count = ((uint64_t)10000 * PIT_FREQ) / 1000000;
|
||||||
#else
|
#else
|
||||||
|
@ -1023,6 +1053,11 @@ void quit_timers(void)
|
||||||
{
|
{
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
timeKillEvent(timerID);
|
timeKillEvent(timerID);
|
||||||
|
timeEndPeriod(period);
|
||||||
|
if (host_alarm) {
|
||||||
|
CloseHandle(host_alarm);
|
||||||
|
host_alarm = NULL;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4383,7 +4418,21 @@ void main_loop_wait(int timeout)
|
||||||
}
|
}
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
if (ret == 0 && timeout > 0) {
|
if (ret == 0 && timeout > 0) {
|
||||||
Sleep(timeout);
|
int err;
|
||||||
|
HANDLE hEvents[1];
|
||||||
|
|
||||||
|
hEvents[0] = host_alarm;
|
||||||
|
ret = WaitForMultipleObjects(1, hEvents, FALSE, timeout);
|
||||||
|
switch(ret) {
|
||||||
|
case WAIT_OBJECT_0 + 0:
|
||||||
|
break;
|
||||||
|
case WAIT_TIMEOUT:
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
err = GetLastError();
|
||||||
|
fprintf(stderr, "Wait error %d %d\n", ret, err);
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
/* poll any events */
|
/* poll any events */
|
||||||
|
|
Loading…
Reference in New Issue