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,9 +518,15 @@ int64_t cpu_get_real_ticks(void) | ||
| 518 | 518 | ||
| 519 | int64_t cpu_get_real_ticks(void) | 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 | int64_t val; | 526 | int64_t val; |
| 522 | asm volatile ("rdtsc" : "=A" (val)); | 527 | asm volatile ("rdtsc" : "=A" (val)); |
| 523 | return val; | 528 | return val; |
| 529 | +#endif | ||
| 524 | } | 530 | } |
| 525 | 531 | ||
| 526 | #elif defined(__x86_64__) | 532 | #elif defined(__x86_64__) |
| @@ -598,17 +604,26 @@ void cpu_disable_ticks(void) | @@ -598,17 +604,26 @@ void cpu_disable_ticks(void) | ||
| 598 | } | 604 | } |
| 599 | } | 605 | } |
| 600 | 606 | ||
| 601 | -static int64_t get_clock(void) | ||
| 602 | -{ | ||
| 603 | #ifdef _WIN32 | 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 | #else | 621 | #else |
| 622 | +static int64_t get_clock(void) | ||
| 623 | +{ | ||
| 608 | struct timeval tv; | 624 | struct timeval tv; |
| 609 | gettimeofday(&tv, NULL); | 625 | gettimeofday(&tv, NULL); |
| 610 | return tv.tv_sec * 1000000LL + tv.tv_usec; | 626 | return tv.tv_sec * 1000000LL + tv.tv_usec; |
| 611 | -#endif | ||
| 612 | } | 627 | } |
| 613 | 628 | ||
| 614 | void cpu_calibrate_ticks(void) | 629 | void cpu_calibrate_ticks(void) |
| @@ -617,15 +632,12 @@ void cpu_calibrate_ticks(void) | @@ -617,15 +632,12 @@ void cpu_calibrate_ticks(void) | ||
| 617 | 632 | ||
| 618 | usec = get_clock(); | 633 | usec = get_clock(); |
| 619 | ticks = cpu_get_real_ticks(); | 634 | ticks = cpu_get_real_ticks(); |
| 620 | -#ifdef _WIN32 | ||
| 621 | - Sleep(50); | ||
| 622 | -#else | ||
| 623 | usleep(50 * 1000); | 635 | usleep(50 * 1000); |
| 624 | -#endif | ||
| 625 | usec = get_clock() - usec; | 636 | usec = get_clock() - usec; |
| 626 | ticks = cpu_get_real_ticks() - ticks; | 637 | ticks = cpu_get_real_ticks() - ticks; |
| 627 | ticks_per_sec = (ticks * 1000000LL + (usec >> 1)) / usec; | 638 | ticks_per_sec = (ticks * 1000000LL + (usec >> 1)) / usec; |
| 628 | } | 639 | } |
| 640 | +#endif /* !_WIN32 */ | ||
| 629 | 641 | ||
| 630 | /* compute with 96 bit intermediate result: (a*b)/c */ | 642 | /* compute with 96 bit intermediate result: (a*b)/c */ |
| 631 | uint64_t muldiv64(uint64_t a, uint32_t b, uint32_t c) | 643 | uint64_t muldiv64(uint64_t a, uint32_t b, uint32_t c) |
| @@ -673,6 +685,8 @@ QEMUClock *vm_clock; | @@ -673,6 +685,8 @@ QEMUClock *vm_clock; | ||
| 673 | static QEMUTimer *active_timers[2]; | 685 | static QEMUTimer *active_timers[2]; |
| 674 | #ifdef _WIN32 | 686 | #ifdef _WIN32 |
| 675 | static MMRESULT timerID; | 687 | static MMRESULT timerID; |
| 688 | +static HANDLE host_alarm = NULL; | ||
| 689 | +static unsigned int period = 1; | ||
| 676 | #else | 690 | #else |
| 677 | /* frequency of the times() clock tick */ | 691 | /* frequency of the times() clock tick */ |
| 678 | static int timer_freq; | 692 | static int timer_freq; |
| @@ -895,6 +909,9 @@ static void host_alarm_handler(int host_signum) | @@ -895,6 +909,9 @@ static void host_alarm_handler(int host_signum) | ||
| 895 | qemu_get_clock(vm_clock)) || | 909 | qemu_get_clock(vm_clock)) || |
| 896 | qemu_timer_expired(active_timers[QEMU_TIMER_REALTIME], | 910 | qemu_timer_expired(active_timers[QEMU_TIMER_REALTIME], |
| 897 | qemu_get_clock(rt_clock))) { | 911 | qemu_get_clock(rt_clock))) { |
| 912 | +#ifdef _WIN32 | ||
| 913 | + SetEvent(host_alarm); | ||
| 914 | +#endif | ||
| 898 | CPUState *env = cpu_single_env; | 915 | CPUState *env = cpu_single_env; |
| 899 | if (env) { | 916 | if (env) { |
| 900 | /* stop the currently executing cpu because a timer occured */ | 917 | /* stop the currently executing cpu because a timer occured */ |
| @@ -955,8 +972,15 @@ static void init_timers(void) | @@ -955,8 +972,15 @@ static void init_timers(void) | ||
| 955 | #ifdef _WIN32 | 972 | #ifdef _WIN32 |
| 956 | { | 973 | { |
| 957 | int count=0; | 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 | timerID = timeSetEvent(1, // interval (ms) | 982 | timerID = timeSetEvent(1, // interval (ms) |
| 959 | - 0, // resolution | 983 | + period, // resolution |
| 960 | host_alarm_handler, // function | 984 | host_alarm_handler, // function |
| 961 | (DWORD)&count, // user parameter | 985 | (DWORD)&count, // user parameter |
| 962 | TIME_PERIODIC | TIME_CALLBACK_FUNCTION); | 986 | TIME_PERIODIC | TIME_CALLBACK_FUNCTION); |
| @@ -964,6 +988,12 @@ static void init_timers(void) | @@ -964,6 +988,12 @@ static void init_timers(void) | ||
| 964 | perror("failed timer alarm"); | 988 | perror("failed timer alarm"); |
| 965 | exit(1); | 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 | pit_min_timer_count = ((uint64_t)10000 * PIT_FREQ) / 1000000; | 998 | pit_min_timer_count = ((uint64_t)10000 * PIT_FREQ) / 1000000; |
| 969 | #else | 999 | #else |
| @@ -1023,6 +1053,11 @@ void quit_timers(void) | @@ -1023,6 +1053,11 @@ void quit_timers(void) | ||
| 1023 | { | 1053 | { |
| 1024 | #ifdef _WIN32 | 1054 | #ifdef _WIN32 |
| 1025 | timeKillEvent(timerID); | 1055 | timeKillEvent(timerID); |
| 1056 | + timeEndPeriod(period); | ||
| 1057 | + if (host_alarm) { | ||
| 1058 | + CloseHandle(host_alarm); | ||
| 1059 | + host_alarm = NULL; | ||
| 1060 | + } | ||
| 1026 | #endif | 1061 | #endif |
| 1027 | } | 1062 | } |
| 1028 | 1063 | ||
| @@ -4383,7 +4418,21 @@ void main_loop_wait(int timeout) | @@ -4383,7 +4418,21 @@ void main_loop_wait(int timeout) | ||
| 4383 | } | 4418 | } |
| 4384 | #ifdef _WIN32 | 4419 | #ifdef _WIN32 |
| 4385 | if (ret == 0 && timeout > 0) { | 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 | #endif | 4437 | #endif |
| 4389 | /* poll any events */ | 4438 | /* poll any events */ |