From 32f556637de8c0b9de626290f0859fc24f7ccf89 Mon Sep 17 00:00:00 2001 From: Andrew Johnson Date: Mon, 18 Jun 2012 14:52:03 -0500 Subject: [PATCH] libCom/osi: Fixed all epicsThreadSleep() implementations All are now robust against overflow, NAN or negative argument. Passing seconds=0 calls the OS scheduler, offering to yield. Passing seconds>0 delays at least the requested time, up to a limit which usually depends on the OS tick rate. --- src/libCom/osi/os/RTEMS/osdThread.c | 18 +++++++++--------- src/libCom/osi/os/WIN32/osdThread.c | 17 +++++++---------- src/libCom/osi/os/posix/osdThread.c | 12 +++++++++--- src/libCom/osi/os/vxWorks/osdThread.c | 11 +++++++---- 4 files changed, 32 insertions(+), 26 deletions(-) diff --git a/src/libCom/osi/os/RTEMS/osdThread.c b/src/libCom/osi/os/RTEMS/osdThread.c index 7fa541bfd..f735671b1 100644 --- a/src/libCom/osi/os/RTEMS/osdThread.c +++ b/src/libCom/osi/os/RTEMS/osdThread.c @@ -25,6 +25,7 @@ #include #include #include +#include #include #include @@ -364,16 +365,15 @@ epicsThreadSleep (double seconds) { rtems_status_code sc; rtems_interval delay; - extern double rtemsTicksPerTwoSeconds_double; - - if (seconds <= 0.0) { - delay = 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 { - delay = seconds * rtemsTicksPerTwoSeconds_double; - delay = (delay + 1) / 2; - if (delay == 0) - delay++; + else { /* seconds <= 0 or NAN */ + delay = 0; } sc = rtems_task_wake_after (delay); if(sc != RTEMS_SUCCESSFUL) diff --git a/src/libCom/osi/os/WIN32/osdThread.c b/src/libCom/osi/os/WIN32/osdThread.c index 86f7b7df7..46c1009c8 100644 --- a/src/libCom/osi/os/WIN32/osdThread.c +++ b/src/libCom/osi/os/WIN32/osdThread.c @@ -779,18 +779,15 @@ epicsShareFunc void epicsShareAPI epicsThreadSleep ( double seconds ) 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 ); } diff --git a/src/libCom/osi/os/posix/osdThread.c b/src/libCom/osi/os/posix/osdThread.c index 3755d943a..30583e162 100644 --- a/src/libCom/osi/os/posix/osdThread.c +++ b/src/libCom/osi/os/posix/osdThread.c @@ -673,9 +673,15 @@ epicsShareFunc void epicsShareAPI epicsThreadSleep(double seconds) 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; diff --git a/src/libCom/osi/os/vxWorks/osdThread.c b/src/libCom/osi/os/vxWorks/osdThread.c index 09d451fab..69034b794 100644 --- a/src/libCom/osi/os/vxWorks/osdThread.c +++ b/src/libCom/osi/os/vxWorks/osdThread.c @@ -18,6 +18,7 @@ #include #include #include +#include #include #include @@ -279,11 +280,13 @@ void epicsThreadSleep(double seconds) 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");