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: [email protected]
Date: Fri, 15 Jun 2012 16:02:59 -0500
Hi,

I will not be working on the documentation change which was Ralph's first 
issue, although if someone else writes the words I don't mind doing the 
necessary edit and commit.

After spending longer than I should have on the second issue, I propose to 
commit the following changes to the 3.14 branch, which I believe fixes all 
reported issues with the epicsThreadSleep() implementations and makes them 
robust against overflows and negative or NAN arguments.


=== modified file 'src/libCom/osi/os/RTEMS/osdThread.c'
--- src/libCom/osi/os/RTEMS/osdThread.c 2010-10-05 19:27:37 +0000
+++ src/libCom/osi/os/RTEMS/osdThread.c 2012-06-15 18:38:51 +0000
@@ -25,6 +25,7 @@
 #include <stdio.h>
 #include <assert.h>
 #include <syslog.h>
+#include <limits.h>
 
 #include <rtems.h>
 #include <rtems/error.h>
@@ -364,17 +365,16 @@
 {
     rtems_status_code sc;
     rtems_interval delay;
-    extern double rtemsTicksPerTwoSeconds_double;
-    
-    if (seconds <= 0.0) {
+    extern double rtemsTicksPerSecond_double;
+
+    if (seconds > 0.0) {
+        seconds *= rtemsTicksPerSecond_double;
+        seconds += 0.99999999;  /* 8 9s here is optimal */
+        delay = (seconds >= INT_MAX) ? INT_MAX : (int) seconds;
+    }
+    else {  /* seconds <= 0 or NAN */
         delay = 0;
     }
-    else {
-        delay = seconds * rtemsTicksPerTwoSeconds_double;
-        delay = (delay + 1) / 2;
-        if (delay == 0)
-            delay++;
-    }
     sc = rtems_task_wake_after (delay);
     if(sc != RTEMS_SUCCESSFUL)
         errlogPrintf("epicsThreadSleep: %s\n", rtems_status_text (sc));

=== modified file 'src/libCom/osi/os/WIN32/osdThread.c'
--- src/libCom/osi/os/WIN32/osdThread.c 2012-02-03 00:14:01 +0000
+++ src/libCom/osi/os/WIN32/osdThread.c 2012-06-15 18:40:04 +0000
@@ -779,18 +779,15 @@
     static const unsigned mSecPerSec = 1000;
     DWORD milliSecDelay;
 
-    if ( seconds <= 0.0 ) {
+    if ( seconds > 0.0 ) {
+        seconds *= mSecPerSec;
+        seconds += 0.99999999;  /* 8 9s here is optimal */
+        milliSecDelay = ( seconds >= INFINITE ) ?
+            INFINITE - 1 : ( DWORD ) seconds;
+    }
+    else {  /* seconds <= 0 or NAN */
         milliSecDelay = 0u;
     }
-    else if ( seconds >= INFINITE / mSecPerSec ) {
-        milliSecDelay = INFINITE - 1;
-    }
-    else {
-        milliSecDelay = ( DWORD ) ( ( seconds * mSecPerSec ) + 0.5 );
-        if ( milliSecDelay == 0 ) {
-            milliSecDelay = 1;
-        }
-    }
     Sleep ( milliSecDelay );
 }
 

=== modified file 'src/libCom/osi/os/posix/osdThread.c'
--- src/libCom/osi/os/posix/osdThread.c 2012-02-03 00:14:01 +0000
+++ src/libCom/osi/os/posix/osdThread.c 2012-06-15 20:36:21 +0000
@@ -673,9 +673,15 @@
     struct timespec remainingTime;
     double nanoseconds;
 
-    delayTime.tv_sec = (time_t)seconds;
-    nanoseconds = (seconds - (double)delayTime.tv_sec) *1e9;
-    delayTime.tv_nsec = (long)nanoseconds;
+    if (seconds > 0) {
+        delayTime.tv_sec = seconds;
+        nanoseconds = (seconds - delayTime.tv_sec) *1e9;
+        delayTime.tv_nsec = nanoseconds;
+    }
+    else {
+        delayTime.tv_sec = 0;
+        delayTime.tv_nsec = 0;
+    }
     while (nanosleep(&delayTime, &remainingTime) == -1 &&
            errno == EINTR)
         delayTime = remainingTime;

=== modified file 'src/libCom/osi/os/vxWorks/osdThread.c'
--- src/libCom/osi/os/vxWorks/osdThread.c       2010-08-11 15:45:17 +0000
+++ src/libCom/osi/os/vxWorks/osdThread.c       2012-06-15 20:52:58 +0000
@@ -18,6 +18,7 @@
 #include <stdlib.h>
 #include <stddef.h>
 #include <stdio.h>
+#include <limits.h>
 
 #include <vxWorks.h>
 #include <taskLib.h>
@@ -279,11 +280,13 @@
     STATUS status;
     int ticks;
 
-    if(seconds<=0.0) {
+    if (seconds > 0.0) {
+        seconds *= sysClkRateGet();
+        seconds += 0.99999999;  /* 8 9s here is optimal */
+        ticks = (seconds >= INT_MAX) ? INT_MAX : (int) seconds;
+    }
+    else {  /* seconds <= 0 or NAN */
         ticks = 0;
-    } else {
-        ticks = seconds*sysClkRateGet() + 0.5;
-        if(ticks<=0) ticks = 1;
     }
     status = taskDelay(ticks);
     if(status) errlogPrintf("epicsThreadSleep\n");


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

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

Navigate by Date:
Prev: Re: [Merge] lp:~epics-core/epics-base/thread-pool into lp:epics-base mdavidsaver
Next: RE: timer delay compensation Hill, Jeff
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 Andrew Johnson
Next: RE: timer delay compensation Hill, Jeff
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 ·