Commit 06d9f2f7d468d8ffdae107f33bc0391e42f4c6b7
1 parent
eade0f19
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
Showing
1 changed file
with
61 additions
and
12 deletions
vl.c
... | ... | @@ -518,9 +518,15 @@ int64_t cpu_get_real_ticks(void) |
518 | 518 | |
519 | 519 | int64_t cpu_get_real_ticks(void) |
520 | 520 | { |
521 | +#ifdef _WIN32 | |
522 | + LARGE_INTEGER ti; | |
523 | + QueryPerformanceCounter(&ti); | |
524 | + return ti.QuadPart; | |
525 | +#else | |
521 | 526 | int64_t val; |
522 | 527 | asm volatile ("rdtsc" : "=A" (val)); |
523 | 528 | return val; |
529 | +#endif | |
524 | 530 | } |
525 | 531 | |
526 | 532 | #elif defined(__x86_64__) |
... | ... | @@ -598,17 +604,26 @@ void cpu_disable_ticks(void) |
598 | 604 | } |
599 | 605 | } |
600 | 606 | |
601 | -static int64_t get_clock(void) | |
602 | -{ | |
603 | 607 | #ifdef _WIN32 |
604 | - struct _timeb tb; | |
605 | - _ftime(&tb); | |
606 | - return ((int64_t)tb.time * 1000 + (int64_t)tb.millitm) * 1000; | |
608 | +void cpu_calibrate_ticks(void) | |
609 | +{ | |
610 | + LARGE_INTEGER freq; | |
611 | + int ret; | |
612 | + | |
613 | + ret = QueryPerformanceFrequency(&freq); | |
614 | + if (ret == 0) { | |
615 | + fprintf(stderr, "Could not calibrate ticks\n"); | |
616 | + exit(1); | |
617 | + } | |
618 | + ticks_per_sec = freq.QuadPart; | |
619 | +} | |
620 | + | |
607 | 621 | #else |
622 | +static int64_t get_clock(void) | |
623 | +{ | |
608 | 624 | struct timeval tv; |
609 | 625 | gettimeofday(&tv, NULL); |
610 | 626 | return tv.tv_sec * 1000000LL + tv.tv_usec; |
611 | -#endif | |
612 | 627 | } |
613 | 628 | |
614 | 629 | void cpu_calibrate_ticks(void) |
... | ... | @@ -617,15 +632,12 @@ void cpu_calibrate_ticks(void) |
617 | 632 | |
618 | 633 | usec = get_clock(); |
619 | 634 | ticks = cpu_get_real_ticks(); |
620 | -#ifdef _WIN32 | |
621 | - Sleep(50); | |
622 | -#else | |
623 | 635 | usleep(50 * 1000); |
624 | -#endif | |
625 | 636 | usec = get_clock() - usec; |
626 | 637 | ticks = cpu_get_real_ticks() - ticks; |
627 | 638 | ticks_per_sec = (ticks * 1000000LL + (usec >> 1)) / usec; |
628 | 639 | } |
640 | +#endif /* !_WIN32 */ | |
629 | 641 | |
630 | 642 | /* compute with 96 bit intermediate result: (a*b)/c */ |
631 | 643 | uint64_t muldiv64(uint64_t a, uint32_t b, uint32_t c) |
... | ... | @@ -673,6 +685,8 @@ QEMUClock *vm_clock; |
673 | 685 | static QEMUTimer *active_timers[2]; |
674 | 686 | #ifdef _WIN32 |
675 | 687 | static MMRESULT timerID; |
688 | +static HANDLE host_alarm = NULL; | |
689 | +static unsigned int period = 1; | |
676 | 690 | #else |
677 | 691 | /* frequency of the times() clock tick */ |
678 | 692 | static int timer_freq; |
... | ... | @@ -895,6 +909,9 @@ static void host_alarm_handler(int host_signum) |
895 | 909 | qemu_get_clock(vm_clock)) || |
896 | 910 | qemu_timer_expired(active_timers[QEMU_TIMER_REALTIME], |
897 | 911 | qemu_get_clock(rt_clock))) { |
912 | +#ifdef _WIN32 | |
913 | + SetEvent(host_alarm); | |
914 | +#endif | |
898 | 915 | CPUState *env = cpu_single_env; |
899 | 916 | if (env) { |
900 | 917 | /* stop the currently executing cpu because a timer occured */ |
... | ... | @@ -955,8 +972,15 @@ static void init_timers(void) |
955 | 972 | #ifdef _WIN32 |
956 | 973 | { |
957 | 974 | int count=0; |
975 | + TIMECAPS tc; | |
976 | + | |
977 | + ZeroMemory(&tc, sizeof(TIMECAPS)); | |
978 | + timeGetDevCaps(&tc, sizeof(TIMECAPS)); | |
979 | + if (period < tc.wPeriodMin) | |
980 | + period = tc.wPeriodMin; | |
981 | + timeBeginPeriod(period); | |
958 | 982 | timerID = timeSetEvent(1, // interval (ms) |
959 | - 0, // resolution | |
983 | + period, // resolution | |
960 | 984 | host_alarm_handler, // function |
961 | 985 | (DWORD)&count, // user parameter |
962 | 986 | TIME_PERIODIC | TIME_CALLBACK_FUNCTION); |
... | ... | @@ -964,6 +988,12 @@ static void init_timers(void) |
964 | 988 | perror("failed timer alarm"); |
965 | 989 | exit(1); |
966 | 990 | } |
991 | + host_alarm = CreateEvent(NULL, FALSE, FALSE, NULL); | |
992 | + if (!host_alarm) { | |
993 | + perror("failed CreateEvent"); | |
994 | + exit(1); | |
995 | + } | |
996 | + ResetEvent(host_alarm); | |
967 | 997 | } |
968 | 998 | pit_min_timer_count = ((uint64_t)10000 * PIT_FREQ) / 1000000; |
969 | 999 | #else |
... | ... | @@ -1023,6 +1053,11 @@ void quit_timers(void) |
1023 | 1053 | { |
1024 | 1054 | #ifdef _WIN32 |
1025 | 1055 | timeKillEvent(timerID); |
1056 | + timeEndPeriod(period); | |
1057 | + if (host_alarm) { | |
1058 | + CloseHandle(host_alarm); | |
1059 | + host_alarm = NULL; | |
1060 | + } | |
1026 | 1061 | #endif |
1027 | 1062 | } |
1028 | 1063 | |
... | ... | @@ -4383,7 +4418,21 @@ void main_loop_wait(int timeout) |
4383 | 4418 | } |
4384 | 4419 | #ifdef _WIN32 |
4385 | 4420 | if (ret == 0 && timeout > 0) { |
4386 | - Sleep(timeout); | |
4421 | + int err; | |
4422 | + HANDLE hEvents[1]; | |
4423 | + | |
4424 | + hEvents[0] = host_alarm; | |
4425 | + ret = WaitForMultipleObjects(1, hEvents, FALSE, timeout); | |
4426 | + switch(ret) { | |
4427 | + case WAIT_OBJECT_0 + 0: | |
4428 | + break; | |
4429 | + case WAIT_TIMEOUT: | |
4430 | + break; | |
4431 | + default: | |
4432 | + err = GetLastError(); | |
4433 | + fprintf(stderr, "Wait error %d %d\n", ret, err); | |
4434 | + break; | |
4435 | + } | |
4387 | 4436 | } |
4388 | 4437 | #endif |
4389 | 4438 | /* poll any events */ | ... | ... |