This is the mail archive of the cygwin-developers mailing list for the Cygwin project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: timeBeginPeriod considered harmful


At 11:10 PM 11/13/2005 -0500, Christopher Faylor wrote:
>On Sun, Nov 13, 2005 at 10:37:50PM -0500, Pierre A. Humblet wrote:
>>At 06:16 PM 11/12/2005 -0500, Christopher Faylor wrote:
>>>On Fri, Nov 11, 2005 at 05:47:17PM -0500, Pierre A. Humblet wrote:
>>>>I worked on the resolution issue a while back, to insure the following
>>>>Posix behavior (exim relies on it):
>>>>If you 1) call time() or equivalent, 2) sleep() or alarm() for some
>>>>interval, 3) call time() again, then the difference between the times in
>>>>3) and 1) cannot be smaller than the interval in 2).  Insuring that is
>>>>easier if the resolution is known.
>>>>I am not sure if Cygwin still behaves that way, insuring it requiring
>>>>rounding up at various places.
>>>
>>>I was thinking about the above in the thinking room today and it
>>>occurred to me that the right way (tm) to fix this problem would be to
>>>modify sleep/alarm so that the above is true.  alarm might be slightly
>>>trickier than sleep but I don't think it would be unbelievably hard.  It
>>>seems like adding a low_priority_sleep loop to nanosleep and alarm which
>>>waits until the time delta was >= what was expected would be preferable
>>>to forcing the resolution to 1ms for the whole program forever.
>>
>>I was just indicating what I had done with the time routines, this is not
>>directly related to the 1 ms resolution (it was there before, as I recall).
>>No matter what the resolution is, it should be possible to get it and do
>>the right thing, for example in nanosleep:
>>  DWORD resolution = gtod.resolution ();
>>  DWORD req = ((rqtp->tv_sec * 1000 + (rqtp->tv_nsec + 999999) / 1000000
>>                + resolution - 1) / resolution) * resolution;
>>Your approach can surely also be made to work.
>>I will take another look this week, on WinME and XP.
>
>Ah.  I thought you were saying that you were relying on the 1ms
>behavior.  I should have known better, though, since I have looked at
>nanosleep recently.
>
>I am not convinced that trying to factor in the resolution into the amount
>of time to sleep is going to always do the right thing but I'm not overly
>worried about it, I guess.  If the above expression is right then it should
>continue to work even when the resolution is != 1ms, AFAICT.

I made some experiments to find the clock resolution, using 
- NtQueryTimerResolution , see
http://www.sysinternals.com/Information/HighResolutionTimers.html
- GetSystemTimeAdjustment (used in sysinternals' ClockRes applet)
- the method used by hires_ms::resolution in current cvs (referred
  to as the "timeGetTime resolution" below)
- the WaitForX series
Here are my results, your mileage may vary (my program is attached)

1) The timeGetTime resolution is always equal to the rounded (up or down) 
   NtQueryTimerResolution resolution (on NT) and to the resolution actually
   obtained by WaitForX  
2) GetSystemTimeAdjustment reports an interval that is not affected by 
   timeBeginPeriod and that is never less than NtQueryTimerResolution (on
NT). 
   That makes technical sense to me (time of day clock adjustment period
   vs. timer resolution), and I am ready to consider that the timeGetTime 
   resolution is never worse than what GetSystemTimeAdjustment reports. 
3) On WinMe and Win98, the resolutions of timeGetTime and of the WaitFor
   calls is always 1 ms. This matches the documentation.
4) These resolutions are also 1 ms on my XP home SP2 (result may depend on
   other programs) 
5) On an XP Pro SP2: 
  5a) the "normal" resolution is 1/64 s (15.625 ms), but is improved to
      1/1024 s (.9765 ms) when cygwin processes such as rxvt are running.
      However for brief periods of time (a few seconds) it can change to
      1/128, 1/256, 1/512 or 1/1024 s (without Cygwin processes, of course).
  5b) The resolution is not constant inside a single process. It changes
      depending on what's happening in other processes.
  5c) timeBeginPeriod works as advertised
6) When WaitForX asks for a timeout d, the actual delay measured by
timeGetTime
   is never less than d. This is an observation. I could find no such
   statement in the Microsoft documentation, but I think it makes
   technical sense.

This is what we can conclude:
- Because of 5b), the current method in cvs for hires_ms::resolution is not
  reliable. It can err in both directions.
- If 6) is true, and because our alarm and sleep calls ultimately rely
  on WaitForX, the Posix requirement at the top of this e-mail can be met
  without calling  gtod.resolution () in nanosleep. On could simply set
  DWORD req = rqtp->tv_sec * 1000 + (rqtp->tv_nsec + 999999) / 1000000
  and get rid of hires_ms::resolution
- clock_getres should report 1 ms on 9X and probably 15.625 ms on a "standard"
  NT. Instead of hard coding 15.625 ms, I believe that one could safely use
  the interval reported by GetSystemTimeAdjustment [see 2) above]. 
  To play absolutely safe, one should report the worst resolution according
  to timeGetDevCaps.
  However if clock_setres has been called, then clock_getres should report
  that resolution.
- If we don't take 6) as being guaranteed, then we should keep 
  gtod.resolution () in nanosleep and add it in timer_thread.
  We should also keep using timeBeginPeriod to guarantee some value for
  hires_ms::resolution, or have gtod.resolution () report the same value
  as discussed above for clock_getres. 

Pierre

Attachment: clockres.c
Description: Text document


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]