use win32 timer queues

Multimedia timers are only useful for compatibility with Windows NT 4.0
and earlier.  Plus, the implementation in Wine is extremely heavyweight.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Blue Swirl <blauwirbel@gmail.com>
This commit is contained in:
Paolo Bonzini 2011-03-12 17:43:50 +01:00 committed by Blue Swirl
parent cfced5b2e6
commit 68c23e5520
1 changed files with 32 additions and 48 deletions

View File

@ -200,11 +200,6 @@ static void qemu_rearm_alarm_timer(struct qemu_alarm_timer *t)
#ifdef _WIN32 #ifdef _WIN32
struct qemu_alarm_win32 {
MMRESULT timerId;
unsigned int period;
} alarm_win32_data = {0, 0};
static int win32_start_timer(struct qemu_alarm_timer *t); static int win32_start_timer(struct qemu_alarm_timer *t);
static void win32_stop_timer(struct qemu_alarm_timer *t); static void win32_stop_timer(struct qemu_alarm_timer *t);
static void win32_rearm_timer(struct qemu_alarm_timer *t); static void win32_rearm_timer(struct qemu_alarm_timer *t);
@ -298,9 +293,9 @@ static struct qemu_alarm_timer alarm_timers[] = {
{"unix", unix_start_timer, unix_stop_timer, NULL, NULL}, {"unix", unix_start_timer, unix_stop_timer, NULL, NULL},
#else #else
{"dynticks", win32_start_timer, {"dynticks", win32_start_timer,
win32_stop_timer, win32_rearm_timer, &alarm_win32_data}, win32_stop_timer, win32_rearm_timer, NULL},
{"win32", win32_start_timer, {"win32", win32_start_timer,
win32_stop_timer, NULL, &alarm_win32_data}, win32_stop_timer, NULL, NULL},
#endif #endif
{NULL, } {NULL, }
}; };
@ -636,9 +631,7 @@ void qemu_run_all_timers(void)
static int64_t qemu_next_alarm_deadline(void); static int64_t qemu_next_alarm_deadline(void);
#ifdef _WIN32 #ifdef _WIN32
static void CALLBACK host_alarm_handler(UINT uTimerID, UINT uMsg, static void CALLBACK host_alarm_handler(PVOID lpParam, BOOLEAN unused)
DWORD_PTR dwUser, DWORD_PTR dw1,
DWORD_PTR dw2)
#else #else
static void host_alarm_handler(int host_signum) static void host_alarm_handler(int host_signum)
#endif #endif
@ -961,50 +954,45 @@ static void unix_stop_timer(struct qemu_alarm_timer *t)
static int win32_start_timer(struct qemu_alarm_timer *t) static int win32_start_timer(struct qemu_alarm_timer *t)
{ {
TIMECAPS tc; HANDLE hTimer;
struct qemu_alarm_win32 *data = t->priv; BOOLEAN success;
UINT flags;
memset(&tc, 0, sizeof(tc)); /* If you call ChangeTimerQueueTimer on a one-shot timer (its period
timeGetDevCaps(&tc, sizeof(tc)); is zero) that has already expired, the timer is not updated. Since
creating a new timer is relatively expensive, set a bogus one-hour
interval in the dynticks case. */
success = CreateTimerQueueTimer(&hTimer,
NULL,
host_alarm_handler,
t,
1,
alarm_has_dynticks(t) ? 3600000 : 1,
WT_EXECUTEINTIMERTHREAD);
data->period = tc.wPeriodMin; if (!success) {
timeBeginPeriod(data->period);
flags = TIME_CALLBACK_FUNCTION;
if (alarm_has_dynticks(t))
flags |= TIME_ONESHOT;
else
flags |= TIME_PERIODIC;
data->timerId = timeSetEvent(1, // interval (ms)
data->period, // resolution
host_alarm_handler, // function
(DWORD)t, // parameter
flags);
if (!data->timerId) {
fprintf(stderr, "Failed to initialize win32 alarm timer: %ld\n", fprintf(stderr, "Failed to initialize win32 alarm timer: %ld\n",
GetLastError()); GetLastError());
timeEndPeriod(data->period);
return -1; return -1;
} }
t->priv = (PVOID) hTimer;
return 0; return 0;
} }
static void win32_stop_timer(struct qemu_alarm_timer *t) static void win32_stop_timer(struct qemu_alarm_timer *t)
{ {
struct qemu_alarm_win32 *data = t->priv; HANDLE hTimer = t->priv;
timeKillEvent(data->timerId); if (hTimer) {
timeEndPeriod(data->period); DeleteTimerQueueTimer(NULL, hTimer, NULL);
}
} }
static void win32_rearm_timer(struct qemu_alarm_timer *t) static void win32_rearm_timer(struct qemu_alarm_timer *t)
{ {
struct qemu_alarm_win32 *data = t->priv; HANDLE hTimer = t->priv;
int nearest_delta_ms; int nearest_delta_ms;
BOOLEAN success;
assert(alarm_has_dynticks(t)); assert(alarm_has_dynticks(t));
if (!active_timers[QEMU_CLOCK_REALTIME] && if (!active_timers[QEMU_CLOCK_REALTIME] &&
@ -1012,25 +1000,21 @@ static void win32_rearm_timer(struct qemu_alarm_timer *t)
!active_timers[QEMU_CLOCK_HOST]) !active_timers[QEMU_CLOCK_HOST])
return; return;
timeKillEvent(data->timerId);
nearest_delta_ms = (qemu_next_alarm_deadline() + 999999) / 1000000; nearest_delta_ms = (qemu_next_alarm_deadline() + 999999) / 1000000;
if (nearest_delta_ms < 1) { if (nearest_delta_ms < 1) {
nearest_delta_ms = 1; nearest_delta_ms = 1;
} }
data->timerId = timeSetEvent(nearest_delta_ms, success = ChangeTimerQueueTimer(NULL,
data->period, hTimer,
host_alarm_handler, nearest_delta_ms,
(DWORD)t, 3600000);
TIME_ONESHOT | TIME_CALLBACK_FUNCTION);
if (!data->timerId) { if (!success) {
fprintf(stderr, "Failed to re-arm win32 alarm timer %ld\n", fprintf(stderr, "Failed to rearm win32 alarm timer: %ld\n",
GetLastError()); GetLastError());
exit(-1);
timeEndPeriod(data->period);
exit(1);
} }
} }
#endif /* _WIN32 */ #endif /* _WIN32 */