diff mbox

qemu-clock: add an alarm timer based on timerfd

Message ID 5059738E.5070004@redhat.com
State New
Headers show

Commit Message

Paolo Bonzini Sept. 19, 2012, 7:26 a.m. UTC
Il 18/09/2012 22:37, Anthony Liguori ha scritto:
> Unfortunately, there's a lot of Windows code in qemu-timer.c and main-loop.c
> right now otherwise the refactoring would be trivial.  I'll leave that for
> another day.
> 
> Cc: Paolo Bonzini <pbonzini@redhat.com>
> Cc: Jan Kiszka <jan.kiszka@siemens.com>
> Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
> ---
> Please note, this is lightly tested.  Since this is such a fundamental change,
> I'd like to do some performance analysis before committing but wanted to share
> early.

Looks good.  I think Peter Portante tested something similar, and found no big
difference between the two.  But it's a good thing and, in my opinion, for
non-timerfd OSes we should simply adjust the select() timeout and not bother
with signals.

I'm not sure if the same can be done for Windows, but I think it's possible as long
as you keep the timeBeginPeriod/timeEndPeriod calls.  As a start, Stefan, can you
check if the win32 timer works for you with the calls added?  Like this:


Paolo

Comments

Jan Kiszka Sept. 19, 2012, 7:44 a.m. UTC | #1
On 2012-09-19 09:26, Paolo Bonzini wrote:
> Il 18/09/2012 22:37, Anthony Liguori ha scritto:
>> Unfortunately, there's a lot of Windows code in qemu-timer.c and main-loop.c
>> right now otherwise the refactoring would be trivial.  I'll leave that for
>> another day.
>>
>> Cc: Paolo Bonzini <pbonzini@redhat.com>
>> Cc: Jan Kiszka <jan.kiszka@siemens.com>
>> Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
>> ---
>> Please note, this is lightly tested.  Since this is such a fundamental change,
>> I'd like to do some performance analysis before committing but wanted to share
>> early.
> 
> Looks good.  I think Peter Portante tested something similar, and found no big
> difference between the two.  But it's a good thing and, in my opinion, for
> non-timerfd OSes we should simply adjust the select() timeout and not bother
> with signals.

What would be the advantage of timerfd over select? On Linux, both use
hrtimers (and low slack for RT processes). I'm starting to like the
select/WaitForMultipleObjects pattern as it would allow to consolidate
over basically two versions of timers and simplify the code.

Jan

> 
> I'm not sure if the same can be done for Windows, but I think it's possible as long
> as you keep the timeBeginPeriod/timeEndPeriod calls.  As a start, Stefan, can you
> check if the win32 timer works for you with the calls added?  Like this:
> 
> diff --git a/qemu-timer.c b/qemu-timer.c
> index c7a1551..721c769 100644
> --- a/qemu-timer.c
> +++ b/qemu-timer.c
> @@ -673,6 +673,10 @@ static int win32_start_timer(struct qemu_alarm_timer *t)
>      HANDLE hTimer;
>      BOOLEAN success;
>  
> +    timeGetDevCaps(&mm_tc, sizeof(mm_tc));
> +
> +    timeBeginPeriod(mm_tc.wPeriodMin);
> +
>      /* If you call ChangeTimerQueueTimer on a one-shot timer (its period
>         is zero) that has already expired, the timer is not updated.  Since
>         creating a new timer is relatively expensive, set a bogus one-hour
> @@ -688,6 +692,7 @@ static int win32_start_timer(struct qemu_alarm_timer *t)
>      if (!success) {
>          fprintf(stderr, "Failed to initialize win32 alarm timer: %ld\n",
>                  GetLastError());
> +        timeEndPeriod(mm_tc.wPeriodMin);
>          return -1;
>      }
>  
> @@ -702,6 +707,7 @@ static void win32_stop_timer(struct qemu_alarm_timer *t)
>      if (hTimer) {
>          DeleteTimerQueueTimer(NULL, hTimer, NULL);
>      }
> +    timeEndPeriod(mm_tc.wPeriodMin);
>  }
>  
>  static void win32_rearm_timer(struct qemu_alarm_timer *t,
> 
> Paolo
>
Paolo Bonzini Sept. 19, 2012, 8:39 a.m. UTC | #2
Il 19/09/2012 09:44, Jan Kiszka ha scritto:
>> > Looks good.  I think Peter Portante tested something similar, and found no big
>> > difference between the two.  But it's a good thing and, in my opinion, for
>> > non-timerfd OSes we should simply adjust the select() timeout and not bother
>> > with signals.
> What would be the advantage of timerfd over select? On Linux, both use
> hrtimers (and low slack for RT processes). I'm starting to like the
> select/WaitForMultipleObjects pattern as it would allow to consolidate
> over basically two versions of timers and simplify the code.

Oh, I didn't know this.  Even better.

Paolo
Peter Portante Sept. 19, 2012, 2:15 p.m. UTC | #3
On Wed, Sep 19, 2012 at 3:44 AM, Jan Kiszka <jan.kiszka@siemens.com> wrote:

> On 2012-09-19 09:26, Paolo Bonzini wrote:
> > Il 18/09/2012 22:37, Anthony Liguori ha scritto:
> >> Unfortunately, there's a lot of Windows code in qemu-timer.c and
> main-loop.c
> >> right now otherwise the refactoring would be trivial.  I'll leave that
> for
> >> another day.
> >>
> >> Cc: Paolo Bonzini <pbonzini@redhat.com>
> >> Cc: Jan Kiszka <jan.kiszka@siemens.com>
> >> Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
> >> ---
> >> Please note, this is lightly tested.  Since this is such a fundamental
> change,
> >> I'd like to do some performance analysis before committing but wanted
> to share
> >> early.
> >
> > Looks good.  I think Peter Portante tested something similar, and found
> no big
> > difference between the two.  But it's a good thing and, in my opinion,
> for
> > non-timerfd OSes we should simply adjust the select() timeout and not
> bother
> > with signals.
>
> What would be the advantage of timerfd over select? On Linux, both use
> hrtimers (and low slack for RT processes).


I am not sure the comparison is timerfd v. select, but timerfd v signal
based timer (setitimer). The timerfd path allows you to integrate with
select/poll/epoll loops, where as signal based timers make that more
difficult. One can do the same thing with signalfd, but only for one
signal, where as you can setup multiple timers at the expense of file
descriptors.

Additionally, FWIW, select() has a resolution capped by its use of struct
timeval, which is microseconds, where timerfd_settime allows for nanosecond
resolution.


> I'm starting to like the
> select/WaitForMultipleObjects pattern as it would allow to consolidate
> over basically two versions of timers and simplify the code.
>

With timerfd, signalfd and eventfd, Linux seems to have provided all the
coverage needed to make that happen.


>
> Jan
>
> >
> > I'm not sure if the same can be done for Windows, but I think it's
> possible as long
> > as you keep the timeBeginPeriod/timeEndPeriod calls.  As a start,
> Stefan, can you
> > check if the win32 timer works for you with the calls added?  Like this:
> >
> > diff --git a/qemu-timer.c b/qemu-timer.c
> > index c7a1551..721c769 100644
> > --- a/qemu-timer.c
> > +++ b/qemu-timer.c
> > @@ -673,6 +673,10 @@ static int win32_start_timer(struct
> qemu_alarm_timer *t)
> >      HANDLE hTimer;
> >      BOOLEAN success;
> >
> > +    timeGetDevCaps(&mm_tc, sizeof(mm_tc));
> > +
> > +    timeBeginPeriod(mm_tc.wPeriodMin);
> > +
> >      /* If you call ChangeTimerQueueTimer on a one-shot timer (its period
> >         is zero) that has already expired, the timer is not updated.
>  Since
> >         creating a new timer is relatively expensive, set a bogus
> one-hour
> > @@ -688,6 +692,7 @@ static int win32_start_timer(struct qemu_alarm_timer
> *t)
> >      if (!success) {
> >          fprintf(stderr, "Failed to initialize win32 alarm timer: %ld\n",
> >                  GetLastError());
> > +        timeEndPeriod(mm_tc.wPeriodMin);
> >          return -1;
> >      }
> >
> > @@ -702,6 +707,7 @@ static void win32_stop_timer(struct qemu_alarm_timer
> *t)
> >      if (hTimer) {
> >          DeleteTimerQueueTimer(NULL, hTimer, NULL);
> >      }
> > +    timeEndPeriod(mm_tc.wPeriodMin);
> >  }
> >
> >  static void win32_rearm_timer(struct qemu_alarm_timer *t,
> >
> > Paolo
> >
>
> --
> Siemens AG, Corporate Technology, CT RTC ITP SDP-DE
> Corporate Competence Center Embedded Linux
>
>
Jan Kiszka Sept. 19, 2012, 2:27 p.m. UTC | #4
Please turn of HTML in you mailer. It's very hard to parse your reply.

On 2012-09-19 16:15, Peter Portante wrote:
> On Wed, Sep 19, 2012 at 3:44 AM, Jan Kiszka <jan.kiszka@siemens.com<mailto:jan.kiszka@siemens.com>> wrote:
> On 2012-09-19 09:26, Paolo Bonzini wrote:
>> Il 18/09/2012 22:37, Anthony Liguori ha scritto:
>>> Unfortunately, there's a lot of Windows code in qemu-timer.c and main-loop.c
>>> right now otherwise the refactoring would be trivial.  I'll leave that for
>>> another day.
>>>
>>> Cc: Paolo Bonzini <pbonzini@redhat.com<mailto:pbonzini@redhat.com>>
>>> Cc: Jan Kiszka <jan.kiszka@siemens.com<mailto:jan.kiszka@siemens.com>>
>>> Signed-off-by: Anthony Liguori <aliguori@us.ibm.com<mailto:aliguori@us.ibm.com>>
>>> ---
>>> Please note, this is lightly tested.  Since this is such a fundamental change,
>>> I'd like to do some performance analysis before committing but wanted to share
>>> early.
>>
>> Looks good.  I think Peter Portante tested something similar, and found no big
>> difference between the two.  But it's a good thing and, in my opinion, for
>> non-timerfd OSes we should simply adjust the select() timeout and not bother
>> with signals.
> 
> What would be the advantage of timerfd over select? On Linux, both use
> hrtimers (and low slack for RT processes).
> 
> I am not sure the comparison is timerfd v. select, but timerfd v signal based timer (setitimer). The timerfd path allows you to integrate with select/poll/epoll loops, where as signal based timers make that more difficult. One can do the same thing with signalfd, but only for one signal, where as you can setup multiple timers at the expense of file descriptors.
> 
> Additionally, FWIW, select() has a resolution capped by its use of struct timeval, which is microseconds, where timerfd_settime allows for nanosecond resolution.

< 1µs resolution is pointless, even on RT-hardened kernels with fast
hardware underneath and when running natively.

> 
> I'm starting to like the
> select/WaitForMultipleObjects pattern as it would allow to consolidate
> over basically two versions of timers and simplify the code.
> 
> With timerfd, signalfd and eventfd, Linux seems to have provided all the coverage needed to make that happen.

The advantage is that timers based on select/poll timeouts will allow to
unify a lot of code for _all_ host platforms, i.e. even Windows. We
still need to evaluate the precise impact and look for potentially
missed limitations (aka: someone has to write patches and test them).
But if there are no relevant ones, it should be the better architecture.

That said, a timerfd based solution for Linux may be an intermediate
step of the select-based work takes longer.

Jan
Stefan Weil Sept. 19, 2012, 4:04 p.m. UTC | #5
Am 19.09.2012 09:26, schrieb Paolo Bonzini:
> Il 18/09/2012 22:37, Anthony Liguori ha scritto:
>> Unfortunately, there's a lot of Windows code in qemu-timer.c and main-loop.c
>> right now otherwise the refactoring would be trivial.  I'll leave that for
>> another day.
>>
>> Cc: Paolo Bonzini <pbonzini@redhat.com>
>> Cc: Jan Kiszka <jan.kiszka@siemens.com>
>> Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
>> ---
>> Please note, this is lightly tested.  Since this is such a fundamental change,
>> I'd like to do some performance analysis before committing but wanted to share
>> early.
> Looks good.  I think Peter Portante tested something similar, and found no big
> difference between the two.  But it's a good thing and, in my opinion, for
> non-timerfd OSes we should simply adjust the select() timeout and not bother
> with signals.
>
> I'm not sure if the same can be done for Windows, but I think it's possible as long
> as you keep the timeBeginPeriod/timeEndPeriod calls.  As a start, Stefan, can you
> check if the win32 timer works for you with the calls added?  Like this:
>
> diff --git a/qemu-timer.c b/qemu-timer.c
> index c7a1551..721c769 100644
> --- a/qemu-timer.c
> +++ b/qemu-timer.c
> @@ -673,6 +673,10 @@ static int win32_start_timer(struct qemu_alarm_timer *t)
>       HANDLE hTimer;
>       BOOLEAN success;
>   
> +    timeGetDevCaps(&mm_tc, sizeof(mm_tc));
> +
> +    timeBeginPeriod(mm_tc.wPeriodMin);
> +
>       /* If you call ChangeTimerQueueTimer on a one-shot timer (its period
>          is zero) that has already expired, the timer is not updated.  Since
>          creating a new timer is relatively expensive, set a bogus one-hour
> @@ -688,6 +692,7 @@ static int win32_start_timer(struct qemu_alarm_timer *t)
>       if (!success) {
>           fprintf(stderr, "Failed to initialize win32 alarm timer: %ld\n",
>                   GetLastError());
> +        timeEndPeriod(mm_tc.wPeriodMin);
>           return -1;
>       }
>   
> @@ -702,6 +707,7 @@ static void win32_stop_timer(struct qemu_alarm_timer *t)
>       if (hTimer) {
>           DeleteTimerQueueTimer(NULL, hTimer, NULL);
>       }
> +    timeEndPeriod(mm_tc.wPeriodMin);
>   }
>   
>   static void win32_rearm_timer(struct qemu_alarm_timer *t,
>
> Paolo

The win32 timer still works when these modifications were applied.
What are they good for?

Stefan
Paolo Bonzini Sept. 19, 2012, 4:12 p.m. UTC | #6
Il 19/09/2012 18:04, Stefan Weil ha scritto:
> The win32 timer still works when these modifications were applied.
> What are they good for?

IIUC the Win32 did _not_ work (except on Wine) without these.  Note I'm
talking about "-clock win32".

So these provide a hint that the problem with the Win32 timer is not in
the bowels of Windows, but only that it does not adjust the Windows
scheduler quantum.  Wine does not need it because the Linux scheduler is
not as lame.

So if we just eliminated timers and used the g_poll timeout (what was
proposed upthread), Windows would work provided
timeBeginPeriod/timeEndPeriod are called correctly.

Paolo
Stefan Weil Sept. 19, 2012, 4:22 p.m. UTC | #7
Am 19.09.2012 18:12, schrieb Paolo Bonzini:
> Il 19/09/2012 18:04, Stefan Weil ha scritto:
>> The win32 timer still works when these modifications were applied.
>> What are they good for?
> IIUC the Win32 did _not_ work (except on Wine) without these.  Note I'm
> talking about "-clock win32".
>
> So these provide a hint that the problem with the Win32 timer is not in
> the bowels of Windows, but only that it does not adjust the Windows
> scheduler quantum.  Wine does not need it because the Linux scheduler is
> not as lame.
>
> So if we just eliminated timers and used the g_poll timeout (what was
> proposed upthread), Windows would work provided
> timeBeginPeriod/timeEndPeriod are called correctly.
>
> Paolo

I tested with -clock win32 (not the mm timer), and it worked on
Win7 (64 bit QEMU) with and without the modification.

Maybe I can run some more tests on 32 bit Windows (also with g_poll),
but don't expect results soon.

Stefan
Avi Kivity Sept. 19, 2012, 4:55 p.m. UTC | #8
On 09/19/2012 10:44 AM, Jan Kiszka wrote:
> On 2012-09-19 09:26, Paolo Bonzini wrote:
>> Il 18/09/2012 22:37, Anthony Liguori ha scritto:
>>> Unfortunately, there's a lot of Windows code in qemu-timer.c and main-loop.c
>>> right now otherwise the refactoring would be trivial.  I'll leave that for
>>> another day.
>>>
>>> Cc: Paolo Bonzini <pbonzini@redhat.com>
>>> Cc: Jan Kiszka <jan.kiszka@siemens.com>
>>> Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
>>> ---
>>> Please note, this is lightly tested.  Since this is such a fundamental change,
>>> I'd like to do some performance analysis before committing but wanted to share
>>> early.
>> 
>> Looks good.  I think Peter Portante tested something similar, and found no big
>> difference between the two.  But it's a good thing and, in my opinion, for
>> non-timerfd OSes we should simply adjust the select() timeout and not bother
>> with signals.
> 
> What would be the advantage of timerfd over select? On Linux, both use
> hrtimers (and low slack for RT processes). I'm starting to like the
> select/WaitForMultipleObjects pattern as it would allow to consolidate
> over basically two versions of timers and simplify the code.

An advantage is that if you have a lot of fd events but fewer timer
events, then you do not need to rearm the timer needlessly.  It just
waits in the background.  I doubt whether that advantage amounts to
anything in practice.
Alon Ziv Sept. 19, 2012, 5:13 p.m. UTC | #9
Jan Kiszka <jan.kiszka <at> siemens.com> writes:
> What would be the advantage of timerfd over select? On Linux, both use
> hrtimers (and low slack for RT processes). I'm starting to like the
> select/WaitForMultipleObjects pattern as it would allow to consolidate
> over basically two versions of timers and simplify the code.

Why not use CreateWaitableTimer on Windows, then, to implement the same pattern?

-a
Anthony Liguori Sept. 20, 2012, 2:54 a.m. UTC | #10
Jan Kiszka <jan.kiszka@siemens.com> writes:

> On 2012-09-19 09:26, Paolo Bonzini wrote:
>> Il 18/09/2012 22:37, Anthony Liguori ha scritto:
>>> Unfortunately, there's a lot of Windows code in qemu-timer.c and main-loop.c
>>> right now otherwise the refactoring would be trivial.  I'll leave that for
>>> another day.
>>>
>>> Cc: Paolo Bonzini <pbonzini@redhat.com>
>>> Cc: Jan Kiszka <jan.kiszka@siemens.com>
>>> Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
>>> ---
>>> Please note, this is lightly tested.  Since this is such a fundamental change,
>>> I'd like to do some performance analysis before committing but wanted to share
>>> early.
>> 
>> Looks good.  I think Peter Portante tested something similar, and found no big
>> difference between the two.  But it's a good thing and, in my opinion, for
>> non-timerfd OSes we should simply adjust the select() timeout and not bother
>> with signals.
>
> What would be the advantage of timerfd over select? On Linux, both use
> hrtimers (and low slack for RT processes). I'm starting to like the
> select/WaitForMultipleObjects pattern as it would allow to consolidate
> over basically two versions of timers and simplify the code.

I don't think it's an either or.  Ideally we get to a complete glib main
loop and our timer implementation could fall back to use the timeout if
timerfd wasn't available.

Practically speaking, timerfd allows selecting the clock to use which
select() doesn't and it also supports absolute events instead of
relative events.  Not sure either matters all that much, but no doubt
it's better than using signals.

Regarding microsecond granularity, note that while select() provides
microsecond granualrity, poll() only provides millisecond granularity.

I think there are a lot of good reasons to evaluate moving to poll()
(glib uses poll by default).  With poll(), we definitely need timerfd.

Regards,

Anthony Liguori

>
> Jan
>
>> 
>> I'm not sure if the same can be done for Windows, but I think it's possible as long
>> as you keep the timeBeginPeriod/timeEndPeriod calls.  As a start, Stefan, can you
>> check if the win32 timer works for you with the calls added?  Like this:
>> 
>> diff --git a/qemu-timer.c b/qemu-timer.c
>> index c7a1551..721c769 100644
>> --- a/qemu-timer.c
>> +++ b/qemu-timer.c
>> @@ -673,6 +673,10 @@ static int win32_start_timer(struct qemu_alarm_timer *t)
>>      HANDLE hTimer;
>>      BOOLEAN success;
>>  
>> +    timeGetDevCaps(&mm_tc, sizeof(mm_tc));
>> +
>> +    timeBeginPeriod(mm_tc.wPeriodMin);
>> +
>>      /* If you call ChangeTimerQueueTimer on a one-shot timer (its period
>>         is zero) that has already expired, the timer is not updated.  Since
>>         creating a new timer is relatively expensive, set a bogus one-hour
>> @@ -688,6 +692,7 @@ static int win32_start_timer(struct qemu_alarm_timer *t)
>>      if (!success) {
>>          fprintf(stderr, "Failed to initialize win32 alarm timer: %ld\n",
>>                  GetLastError());
>> +        timeEndPeriod(mm_tc.wPeriodMin);
>>          return -1;
>>      }
>>  
>> @@ -702,6 +707,7 @@ static void win32_stop_timer(struct qemu_alarm_timer *t)
>>      if (hTimer) {
>>          DeleteTimerQueueTimer(NULL, hTimer, NULL);
>>      }
>> +    timeEndPeriod(mm_tc.wPeriodMin);
>>  }
>>  
>>  static void win32_rearm_timer(struct qemu_alarm_timer *t,
>> 
>> Paolo
>> 
>
> -- 
> Siemens AG, Corporate Technology, CT RTC ITP SDP-DE
> Corporate Competence Center Embedded Linux
Peter Portante Sept. 20, 2012, 5:51 a.m. UTC | #11
On Wed, Sep 19, 2012 at 10:27 AM, Jan Kiszka <jan.kiszka@siemens.com> wrote:
> Please turn of HTML in you mailer. It's very hard to parse your reply.
>
> On 2012-09-19 16:15, Peter Portante wrote:
>> On Wed, Sep 19, 2012 at 3:44 AM, Jan Kiszka <jan.kiszka@siemens.com<mailto:jan.kiszka@siemens.com>> wrote:
>> On 2012-09-19 09:26, Paolo Bonzini wrote:
>>> Il 18/09/2012 22:37, Anthony Liguori ha scritto:
>>>> Unfortunately, there's a lot of Windows code in qemu-timer.c and main-loop.c
>>>> right now otherwise the refactoring would be trivial.  I'll leave that for
>>>> another day.
>>>>
>>>> Cc: Paolo Bonzini <pbonzini@redhat.com<mailto:pbonzini@redhat.com>>
>>>> Cc: Jan Kiszka <jan.kiszka@siemens.com<mailto:jan.kiszka@siemens.com>>
>>>> Signed-off-by: Anthony Liguori <aliguori@us.ibm.com<mailto:aliguori@us.ibm.com>>
>>>> ---
>>>> Please note, this is lightly tested.  Since this is such a fundamental change,
>>>> I'd like to do some performance analysis before committing but wanted to share
>>>> early.
>>>
>>> Looks good.  I think Peter Portante tested something similar, and found no big
>>> difference between the two.  But it's a good thing and, in my opinion, for
>>> non-timerfd OSes we should simply adjust the select() timeout and not bother
>>> with signals.
>>
>> What would be the advantage of timerfd over select? On Linux, both use
>> hrtimers (and low slack for RT processes).
>>
>> I am not sure the comparison is timerfd v. select, but timerfd v signal based timer (setitimer). The timerfd path allows you to integrate with select/poll/epoll loops, where as signal based timers make that more difficult. One can do the same thing with signalfd, but only for one signal, where as you can setup multiple timers at the expense of file descriptors.
>>
>> Additionally, FWIW, select() has a resolution capped by its use of struct timeval, which is microseconds, where timerfd_settime allows for nanosecond resolution.
>
> < 1us resolution is pointless, even on RT-hardened kernels with fast
> hardware underneath and when running natively.

Perhaps.

Under Linux, we have been unable to demonstrate sub-50us resolution
for timeouts outside of RT scheduling classes. We have been able to
get around 1us resolution using SCHED_RR or SCHED_FIFO.

However, if native clocks return timer values at nanosecond
resolution, why would you not want to maintain those units to avoid
rounding errors or simple logic errors during conversions? Not sure
how pointless all the work has been to create software APIs and
hardware interfaces that use nanosecond resolution.

>>
>> I'm starting to like the
>> select/WaitForMultipleObjects pattern as it would allow to consolidate
>> over basically two versions of timers and simplify the code.
>>
>> With timerfd, signalfd and eventfd, Linux seems to have provided all the coverage needed to make that happen.
>
> The advantage is that timers based on select/poll timeouts will allow to
> unify a lot of code for _all_ host platforms, i.e. even Windows. We
> still need to evaluate the precise impact and look for potentially
> missed limitations (aka: someone has to write patches and test them).
> But if there are no relevant ones, it should be the better architecture.
>
> That said, a timerfd based solution for Linux may be an intermediate
> step of the select-based work takes longer.
>
> Jan
>
> --
> Siemens AG, Corporate Technology, CT RTC ITP SDP-DE
> Corporate Competence Center Embedded Linux
diff mbox

Patch

diff --git a/qemu-timer.c b/qemu-timer.c
index c7a1551..721c769 100644
--- a/qemu-timer.c
+++ b/qemu-timer.c
@@ -673,6 +673,10 @@  static int win32_start_timer(struct qemu_alarm_timer *t)
     HANDLE hTimer;
     BOOLEAN success;
 
+    timeGetDevCaps(&mm_tc, sizeof(mm_tc));
+
+    timeBeginPeriod(mm_tc.wPeriodMin);
+
     /* If you call ChangeTimerQueueTimer on a one-shot timer (its period
        is zero) that has already expired, the timer is not updated.  Since
        creating a new timer is relatively expensive, set a bogus one-hour
@@ -688,6 +692,7 @@  static int win32_start_timer(struct qemu_alarm_timer *t)
     if (!success) {
         fprintf(stderr, "Failed to initialize win32 alarm timer: %ld\n",
                 GetLastError());
+        timeEndPeriod(mm_tc.wPeriodMin);
         return -1;
     }
 
@@ -702,6 +707,7 @@  static void win32_stop_timer(struct qemu_alarm_timer *t)
     if (hTimer) {
         DeleteTimerQueueTimer(NULL, hTimer, NULL);
     }
+    timeEndPeriod(mm_tc.wPeriodMin);
 }
 
 static void win32_rearm_timer(struct qemu_alarm_timer *t,