EPICS Controls Argonne National Laboratory

Experimental Physics and
Industrial Control System

2002  2003  2004  2005  2006  2007  2008  2009  2010  2011  <20122013  2014  2015  2016  2017  2018  2019  2020  2021  2022  2023  2024  Index 2002  2003  2004  2005  2006  2007  2008  2009  2010  2011  <20122013  2014  2015  2016  2017  2018  2019  2020  2021  2022  2023  2024 
<== Date ==> <== Thread ==>

Subject: Re: timer delay compensation
From: Andrew Johnson <[email protected]>
To: Eric Norum <[email protected]>
Cc: EPICS core-talk <[email protected]>
Date: Thu, 14 Jun 2012 17:52:59 -0500
Hi Eric,

On 2012-06-14 Eric Norum wrote:
> Well -- do all architectures provide float.h?

Yes, that's in ANSI C89 which everything supports.

> If so, then:
> void epicsThreadSleep(double seconds)
> {
>    STATUS status;
>    int ticks;
> 
>    if (seconds <= 0.0) {
>        ticks = 0;
>    } else {
>        ticks = (seconds * sysClkRateGet()) + (1.0 - DBL_EPSILON);
>    }
>    status = taskDelay(ticks);
>    if (status) errlogPrintf("epicsThreadSleep\n");
> }

I thought that would work, but it adds an extra tick to longer delays.  Sorry, 
my bad for suggesting it.  With sysClkRate = 60 it actually gives:

delay =   0.000  =>  ticks =    0
delay =   0.001  =>  ticks =    1
delay =   0.010  =>  ticks =    1
delay =   0.100  =>  ticks =    7
delay =   1.000  =>  ticks =   61
delay =  10.000  =>  ticks =  601
delay = 100.000  =>  ticks = 6001

> But I think that:
> void epicsThreadSleep(double seconds)
> {
>    STATUS status;
>    int ticks;
> 
>    if (seconds <= 0.0) {
>        ticks = 0;
>    } else {
>        ticks = (seconds * sysClkRateGet()) + 0.999999;
>    }
>    status = taskDelay(ticks);
>    if (status) errlogPrintf("epicsThreadSleep\n");
> }
> 
> is just as good.

Lets go with 0.999999999, chosen since we only represent time down to the 
nanosecond anyway.

Original algorithm
request =   0.000000000  =>  ticks =    0, error =   0.000000000
request =   0.000000001  =>  ticks =    1, error =   0.016666666
request =   0.000001000  =>  ticks =    1, error =   0.016665667
request =   0.001000000  =>  ticks =    1, error =   0.015666667
request =   0.010000000  =>  ticks =    1, error =   0.006666667
request =   0.016666667  =>  ticks =    1, error =   0.000000000
request =   0.020000000  =>  ticks =    1, error =  -0.003333333
request =   0.030000000  =>  ticks =    2, error =   0.003333333
request =   0.033333333  =>  ticks =    2, error =   0.000000000
request =   0.040000000  =>  ticks =    2, error =  -0.006666667
request =   0.050000000  =>  ticks =    3, error =   0.000000000
request =   0.060000000  =>  ticks =    4, error =   0.006666667
request =   0.070000000  =>  ticks =    4, error =  -0.003333333
request =   0.080000000  =>  ticks =    5, error =   0.003333333
request =   0.090000000  =>  ticks =    5, error =  -0.006666667
request =   0.100000000  =>  ticks =    6, error =   0.000000000
request =   0.166666667  =>  ticks =   10, error =   0.000000000
request =   0.200000000  =>  ticks =   12, error =   0.000000000
request =   0.300000000  =>  ticks =   18, error =   0.000000000
request =   0.333333333  =>  ticks =   20, error =   0.000000000
request =   0.500000000  =>  ticks =   30, error =   0.000000000
request =   0.666666667  =>  ticks =   40, error =   0.000000000
request =   0.750000000  =>  ticks =   45, error =   0.000000000
request =   1.000000000  =>  ticks =   60, error =   0.000000000
request =   5.000000000  =>  ticks =  300, error =   0.000000000
request =  10.000000000  =>  ticks =  600, error =   0.000000000
request =  60.000000000  =>  ticks = 3600, error =   0.000000000
request = 100.000000000  =>  ticks = 6000, error =   0.000000000

New algorithm
request =   0.000000000  =>  ticks =    0, error =   0.000000000
request =   0.000000001  =>  ticks =    1, error =   0.016666666
request =   0.000001000  =>  ticks =    1, error =   0.016665667
request =   0.001000000  =>  ticks =    1, error =   0.015666667
request =   0.010000000  =>  ticks =    1, error =   0.006666667
request =   0.016666667  =>  ticks =    1, error =   0.000000000
request =   0.020000000  =>  ticks =    2, error =   0.013333333
request =   0.030000000  =>  ticks =    2, error =   0.003333333
request =   0.033333333  =>  ticks =    2, error =   0.000000000
request =   0.040000000  =>  ticks =    3, error =   0.010000000
request =   0.050000000  =>  ticks =    3, error =   0.000000000
request =   0.060000000  =>  ticks =    4, error =   0.006666667
request =   0.070000000  =>  ticks =    5, error =   0.013333333
request =   0.080000000  =>  ticks =    5, error =   0.003333333
request =   0.090000000  =>  ticks =    6, error =   0.010000000
request =   0.100000000  =>  ticks =    6, error =   0.000000000
request =   0.166666667  =>  ticks =   10, error =   0.000000000
request =   0.200000000  =>  ticks =   12, error =   0.000000000
request =   0.300000000  =>  ticks =   18, error =   0.000000000
request =   0.333333333  =>  ticks =   20, error =   0.000000000
request =   0.500000000  =>  ticks =   30, error =   0.000000000
request =   0.666666667  =>  ticks =   40, error =   0.000000000
request =   0.750000000  =>  ticks =   45, error =   0.000000000
request =   1.000000000  =>  ticks =   60, error =   0.000000000
request =   5.000000000  =>  ticks =  300, error =   0.000000000
request =  10.000000000  =>  ticks =  600, error =   0.000000000
request =  60.000000000  =>  ticks = 3600, error =   0.000000000
request = 100.000000000  =>  ticks = 6000, error =   0.000000000

Negative errors are bad.  However this only represents the error in the 
requested delay, not the actual range of delays that could occur depending on 
the time remaining until the next clock tick.  I have no idea whether the OSs 
try to compensate for that...

BTW, on vxWorks the taskDelay() routine only returns an error in interrupt 
context or if the task gets an unblocked signal.  Our code has a problem in 
the first case because we call errlogPrintf(), and in the latter case we never 
check errno or try to restart the delay on an EINTR.  Luckily nobody uses 
signals much on vxWorks...

- Andrew
-- 
Never interrupt your enemy when he is making a mistake.
-- Napoleon Bonaparte

Replies:
Re: timer delay compensation Eric Norum
References:
timer delay compensation Hill, Jeff

Navigate by Date:
Prev: Re: timer delay compensation Andrew Johnson
Next: Re: timer delay compensation Eric Norum
Index: 2002  2003  2004  2005  2006  2007  2008  2009  2010  2011  <20122013  2014  2015  2016  2017  2018  2019  2020  2021  2022  2023  2024 
Navigate by Thread:
Prev: RE: timer delay compensation Hill, Jeff
Next: Re: timer delay compensation Eric Norum
Index: 2002  2003  2004  2005  2006  2007  2008  2009  2010  2011  <20122013  2014  2015  2016  2017  2018  2019  2020  2021  2022  2023  2024 
ANJ, 26 Nov 2012 Valid HTML 4.01! · Home · News · About · Base · Modules · Extensions · Distributions · Download ·
· Search · EPICS V4 · IRMIS · Talk · Bugs · Documents · Links · Licensing ·