[Haskell-cafe] help with threadDelay

Ian Lynagh igloo at earth.li
Tue Nov 21 21:34:39 EST 2006


[moving to glasgow-haskell-bugs]

On Wed, Nov 15, 2006 at 11:40:12PM +0000, Neil Davies wrote:
> 
> however when -threaded is used you get some interesting effects,
> including returning too early:
> 
> Tgt/Actual = 0.000125/0.000034s, diff = -0.000091s

Thanks for the report; I can reproduce it on Linux/amd64.

OK, so the bug here is that threadDelay n might return after less than n
microseconds.

This looks like it's caused by truncation problems when converting times
to ticks (where a tick is 1/50 of a second), e.g. while trying to sleep
for 1.953125s one run started at 1164157960.773726s which is
  (Int) 1164157960 * 50 + 773726 * 50 / 1000000
= (Int) 58207898038.6863
= 58207898038 ticks
and woke the thread up at 1164157962.708609s which is
  (Int) 1164157962 * 50 + 708609 * 50 / 1000000
= (Int) 58207898135.4305
= 58207898135 ticks

The difference is 58207898135 - 58207898038 = 97 ticks.

Meanwhile we're trying to sleep for
  (Int) 50 * 1.953125
= (Int) 97.65625
= 97 ticks

However, 1164157962.708609s - 1164157960.773726s = 1.93488311767578s
which is 0.0182418823242201s too short.

The problem is that we have counted 0.6863 ticks before the start time,
not counted 0.4305 ticks before the finish time and have been waiting
0.65625 ticks too short a time. Thus we have counted
(0.6863-0.4305 + 0.65625) / 50 == 0.018241 too much time.

I think the answer is that

    let target = now + usecs `quot` tick_usecs

in GHC/Conc.lhs should be

    let target = 1 + now + (usecs + tick_usecs - 1) `quot` tick_usecs

I'm also a bit dubious about the use of the constant "50" for the number
of ticks per second, but the results with +RTS -V0.001 don't look any
more wrong so perhaps I just need to get some sleep.

You can get the same symptoms with the non-threaded RTS with
+RTS -V0.001, although they are less frequent. I suspect we need a
similar fix to

    target = (R1 / (TO_W_(RtsFlags_MiscFlags_tickInterval(RtsFlags))*1000)) + time;

in delayzh_fast in PrimOps.cmm.


Thanks
Ian



More information about the Haskell-Cafe mailing list