Commit 06d9f2f7d468d8ffdae107f33bc0391e42f4c6b7

Authored by bellard
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
@@ -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 */