#5865: threadDelay is disrupted by system clock changes
---------------------------------+------------------------------------------
    Reporter:  joeyadams         |       Owner:  pcapriotti                 
        Type:  bug               |      Status:  patch                      
    Priority:  high              |   Milestone:  7.4.2                      
   Component:  Runtime System    |     Version:  7.4.1                      
    Keywords:                    |          Os:  Unknown/Multiple           
Architecture:  Unknown/Multiple  |     Failure:  Incorrect result at runtime
  Difficulty:  Unknown           |    Testcase:                             
   Blockedby:                    |    Blocking:                             
     Related:                    |  
---------------------------------+------------------------------------------

Comment(by joeyadams):

 Replying to [comment:11 pcapriotti]:
 > Added patch for win32, using `QueryPerformanceCounter` instead of
 `GetSystemTimeAsFileTime`.

 Thanks for addressing the problem on Windows, too.  However, two things
 worry me about this patch:

  * The documentation for [http://msdn.microsoft.com/en-
 us/library/windows/desktop/ms644905%28v=vs.85%29.aspx
 QueryPerformanceFrequency] implies that some hardware does not support a
 high-resolution performance counter.  On the other hand, I don't know how
 likely we are to see such systems running Windows 2000 or later.  A
 [http://www.virtualdub.org/blog/pivot/entry.php?id=106 post on
 virtualdub.org] has some interesting things to say about
 `QueryPerformanceCounter`, too.

  * The return values of `QueryPerformanceCounter` and
 `QueryPerformanceFrequency` aren't even checked.  Thus, if one of these
 functions fail, the program will silently start acting strangely.

 We should at the very least check the return value of
 `QueryPerformanceCounter`.  Ideally, we would fall back to
 [http://msdn.microsoft.com/en-
 us/library/windows/desktop/ms724408%28v=vs.85%29.aspx GetTickCount].

 Note that `GetTickCount` has a wraparound problem due to its 32-bit return
 value.  There is a [http://msdn.microsoft.com/en-
 us/library/windows/desktop/ms724411%28v=vs.85%29.aspx GetTickCount64]
 function, but it is only available for Vista and later.

 The easy way to work around the problem: never compare two times more than
 49 days apart, and do the subtraction with the original `DWORD`s to make
 wraparound work for you.  See my
 [http://stackoverflow.com/a/9232314/149391 StackOverflow answer] about
 this for more details.

 One way to emulate a 64-bit counter is to associate the return value of
 `GetTickCount` with a 64-bit value that represents, in a sense, the
 current time.  Something like this:

 {{{
 uint64_t initMonotonicClock(void)
 {
     return GetTickCount();
 }

 uint64_t updateMonotonicClock(uint64_t before)
 {
     DWORD now    = GetTickCount();
     DWORD offset = now - (DWORD)before;
     return before + offset;
 }
 }}}

 So for every call to `getMonotonicUSec`, update a global variable using
 the result of `updateMonotonicClock`.  As long as `getMonotonicUSec` is
 called at least once every 49 days, any pair of return values from
 `getMonotonicUSec` can be compared without overflow issues (that is,
 unless the program runs for about 500 million years).

-- 
Ticket URL: <http://hackage.haskell.org/trac/ghc/ticket/5865#comment:14>
GHC <http://www.haskell.org/ghc/>
The Glasgow Haskell Compiler

_______________________________________________
Glasgow-haskell-bugs mailing list
[email protected]
http://www.haskell.org/mailman/listinfo/glasgow-haskell-bugs

Reply via email to