提交 40f08e87 编写于 作者: S Stefan Weil

qemu-timer: Fix limits for w32 mmtimer

timeSetEvent only accepts delays in the range which is returned by
timeGetDevCaps.

The lower limit is typically 1 (= 1 ms), so the constant value of 1
in the old code usually worked.

The upper limit can be as low as 10000 ms, so the latest changes in
QEMU's timer handling which introduced timeout values above that limit
could result in failures of timeSetEvent when the timer was re-armed.
Signed-off-by: NStefan Weil <sw@weilnetz.de>
上级 f156f238
...@@ -611,7 +611,7 @@ static void unix_stop_timer(struct qemu_alarm_timer *t) ...@@ -611,7 +611,7 @@ static void unix_stop_timer(struct qemu_alarm_timer *t)
#ifdef _WIN32 #ifdef _WIN32
static MMRESULT mm_timer; static MMRESULT mm_timer;
static unsigned mm_period; static TIMECAPS mm_tc;
static void CALLBACK mm_alarm_handler(UINT uTimerID, UINT uMsg, static void CALLBACK mm_alarm_handler(UINT uTimerID, UINT uMsg,
DWORD_PTR dwUser, DWORD_PTR dw1, DWORD_PTR dwUser, DWORD_PTR dw1,
...@@ -628,16 +628,12 @@ static void CALLBACK mm_alarm_handler(UINT uTimerID, UINT uMsg, ...@@ -628,16 +628,12 @@ static void CALLBACK mm_alarm_handler(UINT uTimerID, UINT uMsg,
static int mm_start_timer(struct qemu_alarm_timer *t) static int mm_start_timer(struct qemu_alarm_timer *t)
{ {
TIMECAPS tc; timeGetDevCaps(&mm_tc, sizeof(mm_tc));
memset(&tc, 0, sizeof(tc)); timeBeginPeriod(mm_tc.wPeriodMin);
timeGetDevCaps(&tc, sizeof(tc));
mm_period = tc.wPeriodMin; mm_timer = timeSetEvent(mm_tc.wPeriodMin, /* interval (ms) */
timeBeginPeriod(mm_period); mm_tc.wPeriodMin, /* resolution */
mm_timer = timeSetEvent(1, /* interval (ms) */
mm_period, /* resolution */
mm_alarm_handler, /* function */ mm_alarm_handler, /* function */
(DWORD_PTR)t, /* parameter */ (DWORD_PTR)t, /* parameter */
TIME_ONESHOT | TIME_CALLBACK_FUNCTION); TIME_ONESHOT | TIME_CALLBACK_FUNCTION);
...@@ -645,7 +641,7 @@ static int mm_start_timer(struct qemu_alarm_timer *t) ...@@ -645,7 +641,7 @@ static int mm_start_timer(struct qemu_alarm_timer *t)
if (!mm_timer) { if (!mm_timer) {
fprintf(stderr, "Failed to initialize win32 alarm timer: %ld\n", fprintf(stderr, "Failed to initialize win32 alarm timer: %ld\n",
GetLastError()); GetLastError());
timeEndPeriod(mm_period); timeEndPeriod(mm_tc.wPeriodMin);
return -1; return -1;
} }
...@@ -655,23 +651,21 @@ static int mm_start_timer(struct qemu_alarm_timer *t) ...@@ -655,23 +651,21 @@ static int mm_start_timer(struct qemu_alarm_timer *t)
static void mm_stop_timer(struct qemu_alarm_timer *t) static void mm_stop_timer(struct qemu_alarm_timer *t)
{ {
timeKillEvent(mm_timer); timeKillEvent(mm_timer);
timeEndPeriod(mm_period); timeEndPeriod(mm_tc.wPeriodMin);
} }
static void mm_rearm_timer(struct qemu_alarm_timer *t, int64_t delta) static void mm_rearm_timer(struct qemu_alarm_timer *t, int64_t delta)
{ {
int64_t nearest_delta_ms = delta / 1000000; int64_t nearest_delta_ms = delta / 1000000;
if (nearest_delta_ms < 1) { if (nearest_delta_ms < mm_tc.wPeriodMin) {
nearest_delta_ms = 1; nearest_delta_ms = mm_tc.wPeriodMin;
} } else if (nearest_delta_ms > mm_tc.wPeriodMax) {
/* UINT_MAX can be 32 bit */ nearest_delta_ms = mm_tc.wPeriodMax;
if (nearest_delta_ms > UINT_MAX) {
nearest_delta_ms = UINT_MAX;
} }
timeKillEvent(mm_timer); timeKillEvent(mm_timer);
mm_timer = timeSetEvent((unsigned int) nearest_delta_ms, mm_timer = timeSetEvent((UINT)nearest_delta_ms,
mm_period, mm_tc.wPeriodMin,
mm_alarm_handler, mm_alarm_handler,
(DWORD_PTR)t, (DWORD_PTR)t,
TIME_ONESHOT | TIME_CALLBACK_FUNCTION); TIME_ONESHOT | TIME_CALLBACK_FUNCTION);
...@@ -680,7 +674,7 @@ static void mm_rearm_timer(struct qemu_alarm_timer *t, int64_t delta) ...@@ -680,7 +674,7 @@ static void mm_rearm_timer(struct qemu_alarm_timer *t, int64_t delta)
fprintf(stderr, "Failed to re-arm win32 alarm timer %ld\n", fprintf(stderr, "Failed to re-arm win32 alarm timer %ld\n",
GetLastError()); GetLastError());
timeEndPeriod(mm_period); timeEndPeriod(mm_tc.wPeriodMin);
exit(1); exit(1);
} }
} }
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册