Main Page   Class Hierarchy   Alphabetical List   Data Structures   File List   Data Fields   Globals  

_timer.c

Go to the documentation of this file.
00001 /*
00002   timer.cc -- interval timer code.  A TIMER object lets you wait on
00003   the expiration of a cyclic period, to the resolution of the system
00004   clock.
00005 
00006   Ideally, we'd like to use the POSIX struct timespec, in timers.h,
00007   for second-nanosecond resolution in real time.  However, at the
00008   moment, most OSes do not have this interface since the POSIX realtime
00009   draft is still out.
00010 
00011   These functions use the BSD 'gettimeofday' interface for LynxOS and
00012   SunOS, and the tickLib and taskLib interface on VxWorks.
00013 
00014   Modification history:
00015 
00016   29-Oct-1999  FMP pulled out LINUX sections into separate ifdef's, for
00017   clarity
00018   */
00019 
00020 #define NO_SCCS_IDS
00021 
00022 #include "rcs_defs.hh"
00023 #include "rcs_prnt.hh"          /* rcs_print_error */
00024 
00025 #ifndef NO_STDIO
00026 #include <stdio.h>              /* NULL */
00027 #endif
00028 
00029 #ifndef UNDER_CE
00030 #include <errno.h>              /* errno */
00031 #endif
00032 
00033 #include <string.h>             /* strerror() */
00034 
00035 #ifdef VXWORKS
00036 
00037 #include <vxWorks.h>
00038 #include <taskLib.h>            /* taskDelay() */
00039 #include <tickLib.h>            /* tickGet() */
00040 #include <sysLib.h>             /* sysClkRateGet() */
00041 #include <timers.h>             /* clock_gettime */
00042 #ifndef POWERPC
00043 #include "gtimer.hh"            /* global_timer_available, get_Global_time() */
00044 #endif
00045 
00046 #endif /* VXWORKS */
00047 
00048 #ifdef LYNX
00049 
00050 
00051 #include <errno.h>              /* EINTR */
00052 #include <unistd.h>             /* select() */
00053 #include <time.h>               /* CLK_TCK, since no _SC_CLK_TCK */
00054 #include <sys/time.h>           /* struct timeval, gettimeofday(),
00055                                    struct itimerval, setitimer(),
00056                                    ITIMER_REAL */
00057 
00058 
00059 #endif /* LYNX */
00060 
00061 #if  defined(SUN) || defined(SGI) || defined(sparcworks) || defined(darwin) || defined(qnx) || defined(LINUX)
00062 #include <errno.h>              /*  EINTR */
00063 #include <unistd.h>             /* select(), sysconf(), _SC_CLK_TCK */
00064 #include <sys/time.h>           /* struct timeval, gettimeofday(),
00065                                    struct itimerval, setitimer(),
00066                                    ITIMER_REAL */
00067 
00068 #endif /* SUN */
00069 
00070 #ifdef LINUX
00071 #include <linux/version.h>
00072 
00073 #if defined(LINUX_VERSION_CODE) && defined(KERNEL_VERSION)
00074 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,2,0)
00075 #define LINUX_KERNEL_2_2_OR_LATER
00076 #include <sched.h>
00077 #endif
00078 #endif
00079 #endif
00080 
00081 
00082 
00083 #if defined(irix6)
00084 #include <time.h>
00085 #endif
00086 
00087 #ifdef __MSDOS__
00088 #ifdef _Windows
00089 #ifdef USE_TOOL_HELP
00090 /* The timerCount function is more accurate than the GetTickCount() function
00091 but you need toolhelp.dll which comes with Windows 3.1 but not Windows 3.0 or
00092 Windows NT */
00093 #include "toolhelp.h"           /* timerCount() */
00094 #else
00095 #if defined(WIN32) && !defined(USE_OLD_WINSOCK)
00096 /* Lame problem if windows.h is included before winsock2.h many redefined
00097  compiler errors result. */
00098 #include <winsock2.h>
00099 #endif
00100 #include <windows.h>            /* GetTickCount() */
00101 #endif
00102 #endif
00103 #include <time.h>               /* clock(), CLK_TCK */
00104 #ifndef _Windows
00105 #include <dos.h>                /* delay() */
00106 #endif
00107 #endif
00108 
00109 #include "_timer.h"
00110 
00111 
00112 /* number of seconds in a system clock tick */
00113 double
00114 clk_tck ()
00115 {
00116 #ifdef VXWORKS
00117 #ifndef POWERPC
00118   if (global_timer_available)
00119     {
00120       return (1E-6);
00121     }
00122 #endif
00123   return 1.0 / (double) sysClkRateGet ();
00124 #define CLK_TCK_RETURNED
00125 #endif
00126 
00127 #ifdef LYNX
00128   return 1.0 / (double) CLK_TCK;
00129 #define CLK_TCK_RETURNED
00130 #endif
00131 
00132 #if defined(SUN) || defined(SGI) || defined(LINUX) || defined(darwin) || defined(qnx)
00133   return 1.0 / (double) sysconf (_SC_CLK_TCK);
00134 #define CLK_TCK_RETURNED
00135 #endif
00136 
00137 #ifdef _Windows
00138   return (0.001);
00139 #define CLK_TCK_RETURNED
00140 #endif
00141 
00142 #ifdef __MSDOS__
00143   return (1.0 / (double) CLK_TCK);
00144 #define CLK_TCK_RETURNED
00145 #endif
00146 
00147 #ifndef CLK_TCK_RETURNED
00148 #error No definition for clk tck for this platform.
00149 #endif
00150 }
00151 
00152 #include "_sem.h"
00153 
00154 /*
00155  These values can be used with a debugger to prevent
00156  or diliberately cause timeouts.
00157  */
00158 
00159 int etime_disabled = 0;
00160 double etime_disable_time = 0.0;
00161 
00162 /* number of seconds from some epoch, to clock tick resolution */
00163 double
00164 etime ()
00165 {
00166 #ifdef VXWORKS
00167 #ifdef USE_CLOCK_GETTIME
00168   double retval;
00169   struct timespec ts;
00170 #endif
00171 #ifndef POWERPC
00172   if (etime_disabled)
00173     {
00174       return (etime_disable_time);
00175     }
00176   if (global_timer_available)
00177     {
00178       return (((double) get_Global_time ()) * (1E-6));
00179     }
00180 #endif
00181 
00182 #ifdef USE_CLOCK_GETTIME
00183   if (etime_disabled)
00184     {
00185       return (etime_disable_time);
00186     }
00187   if (clock_gettime (CLOCK_REALTIME, &ts))
00188     {
00189       /* rcs_print_error("clock_gettime: errno = %d %s\n", errno, strerror(errno)); */
00190     }
00191   retval = ((double) ts.tv_sec) + ((double) ts.tv_nsec) * 1e-9;
00192   return retval;
00193 #else
00194   if (etime_disabled)
00195     {
00196       return (etime_disable_time);
00197     }
00198   return ((double) tickGet ()) / ((double) sysClkRateGet ());
00199 #endif
00200 #define ETIME_RETURNED
00201 #endif
00202 
00203 #if defined (sunos4) || defined (LYNX) || defined(irix5) || defined(sparcworks_sun4)
00204   double retval = 0.0;
00205   static double last_retval = 0.0;
00206   static struct timeval last_tp;
00207 
00208   struct timeval tp;
00209   if (etime_disabled)
00210     {
00211       return (etime_disable_time);
00212     }
00213   if (gettimeofday (&tp, NULL) == -1)
00214     {
00215       rcs_print_error ("gettimeofday failed: (errno = %d) %s\n", errno,
00216                        strerror (errno));
00217       return 0.0;
00218     }
00219   retval = ((double) tp.tv_sec) + (((double) tp.tv_usec) / 1000000.0);
00220   return (retval);
00221 #define ETIME_RETURNED
00222 #endif
00223 
00224 #if defined(sunos5) || (defined(os5) && defined(sparc))  || defined(irix6) || defined(irix64)
00225   double retval;
00226   struct timespec ts;
00227 
00228   if (etime_disabled)
00229     {
00230       return (etime_disable_time);
00231     }
00232   if (clock_gettime (CLOCK_REALTIME, &ts))
00233     {
00234       rcs_print_error ("clock_gettime: errno = %d %s\n", errno,
00235                        strerror (errno));
00236     }
00237   retval = ((double) ts.tv_sec) + ((double) ts.tv_nsec) * 1e-9;
00238   return retval;
00239 #define ETIME_RETURNED
00240 #endif
00241 
00242 #if defined(LINUX) || defined(darwin) || defined(qnx)
00243 
00244   struct timeval tp;
00245   double retval;
00246 #if 0
00247   static double last_retval = 0.0;
00248 #endif
00249 
00250   if (0 != gettimeofday (&tp, NULL))
00251     {
00252       rcs_print_error ("etime: can't get time\n");
00253       return 0.0;
00254     }
00255 
00256   retval = ((double) tp.tv_sec) + ((double) tp.tv_usec) / 1000000.0;
00257 #if 0
00258   if (retval < last_retval)
00259     {
00260       rcs_print_error ("etime: negative time interval\n");
00261       return 0.0;
00262     }
00263   last_retval = retval;
00264 #endif
00265   return retval;
00266 
00267 #define ETIME_RETURNED
00268 #endif /* LINUX */
00269 
00270 #ifdef _Windows
00271 #ifdef USE_TOOL_HELP
00272 /* The TimerCount function is more accurate than the GetTickCount() function
00273 but you need toolhelp.dll which comes with Windows 3.1 but not Windows 3.0 or
00274 Windows NT */
00275   TIMERINFO timer_info;
00276   if (etime_disabled)
00277     {
00278       return (etime_disable_time);
00279     }
00280   if (TimerCount (&timer_info))
00281     {
00282       return ((double) timer_info.dwmsSinceStart / 1000.0);
00283     }
00284   else
00285     {
00286       rcs_print_error ("etime: TimerCount returned false.\n");
00287       return (0);
00288     }
00289 #define ETIME_RETURNED
00290 #else /* defined(_Windows) && defined(USE_TOOL_HELP) */
00291 #if defined(WIN32) && !defined(UNDER_CE)
00292   BOOL frequency_ok = 0;
00293   BOOL counter_ok = 0;
00294   LARGE_INTEGER frequency;
00295   LARGE_INTEGER counter;
00296   double dfreq;
00297   double dcount;
00298 #define TWO_TO_THIRTYTWO  (4294967296.00)
00299 #endif
00300 
00301   if (etime_disabled)
00302     {
00303       return (etime_disable_time);
00304     }
00305 #if defined(WIN32) && !defined(UNDER_CE)
00306   frequency_ok = QueryPerformanceFrequency (&frequency);
00307   counter_ok = QueryPerformanceCounter (&counter);
00308   if (frequency_ok && counter_ok)
00309     {
00310       dfreq = frequency.HighPart * TWO_TO_THIRTYTWO + frequency.LowPart;
00311       dcount = counter.HighPart * TWO_TO_THIRTYTWO + counter.LowPart;
00312       if (dfreq > 0.0 && dcount > 0.0)
00313         {
00314           return (dcount / dfreq);
00315         }
00316     }
00317 #endif
00318   return ((double) GetTickCount () / 1000.0);
00319 #define ETIME_RETURNED
00320 #endif /* defined(_Windows) && defined(USE_TOOL_HELP) */
00321 #endif
00322 
00323 #if  defined(__MSDOS__) && !defined(_Windows)
00324 #ifndef CLOCKS_PER_SECOND
00325 #define CLOCKS_PER_SECOND CLK_TCK
00326 #endif
00327   if (etime_disabled)
00328     {
00329       return (etime_disable_time);
00330     }
00331   return clock () / CLOCKS_PER_SECOND;
00332 #define ETIME_RETURNED
00333 
00334 #endif /* __MSDOS__ */
00335 
00336 #ifndef ETIME_RETURNED
00337 #error NO definition for etime for this platform
00338 #endif
00339 }
00340 
00341 int esleep_use_yield = 0;
00342 
00343 /* sleeps # of seconds */
00344 void
00345 esleep (double seconds_to_sleep)
00346 {
00347 #ifdef VXWORKS
00348 #if 1
00349   int t = (int) (seconds_to_sleep * (double) sysClkRateGet ());
00350 
00351   taskDelay (t <= 0 ? 1 : t);   /* at least sleep a tick */
00352 #else
00353   struct timespec nantime;
00354   nantime.tv_sec = (time_t) seconds_to_sleep;
00355   nantime.tv_nsec = ((double) (seconds_to_sleep - nantime.tv_sec) * 1e9);
00356   return nanosleep (&nantime, NULL);
00357 #endif
00358   return;
00359 #define ESLEEP_RETURNED
00360 
00361 #endif
00362 
00363 #if defined (SUN) || defined (LYNX) || defined(irix5) || defined(irix6) || defined(irix64) || defined(LINUX) || defined(darwin) || defined(qnx)
00364 #ifndef VXWORKS
00365 #if defined(sunos5) || defined(LINUX_KERNEL_2_2_OR_LATER)
00366   struct timeval tval;
00367   static double clk_tck_val = 0;
00368   double total = seconds_to_sleep;      /* total sleep asked for */
00369   double started = etime ();    /* time when called */
00370   double left = total;
00371   if (seconds_to_sleep <= 0.0)
00372     return;
00373   if (clk_tck_val <= 0)
00374     {
00375       clk_tck_val = clk_tck ();
00376     }
00377   do
00378     {
00379       if (left < clk_tck_val && esleep_use_yield)
00380         {
00381 #ifdef linux
00382           sched_yield ();
00383 #else
00384           yield ();
00385 #endif
00386         }
00387       else
00388         {
00389           tval.tv_sec = (long) left;    /* double->long truncates, ANSI */
00390           tval.tv_usec = (long) ((left - (double) tval.tv_sec) * 1000000.0);
00391           if (tval.tv_sec == 0 && tval.tv_usec == 0)
00392             {
00393               tval.tv_usec = 1;
00394             }
00395           if (select (0, NULL, NULL, NULL, &tval) < 0)
00396             {
00397               if (errno != EINTR)
00398                 {
00399                   break;
00400                 }
00401             }
00402         }
00403       left = total - etime () + started;
00404     }
00405   while (left > 0 && (left > clk_tck_val && esleep_use_yield));
00406   return;
00407 #define ESLEEP_RETURNED
00408 
00409 #else
00410   unsigned int whole_seconds = (int) (seconds_to_sleep);
00411   unsigned int useconds =
00412     (int) ((seconds_to_sleep - ((double) whole_seconds)) * 1e6);
00413   if (seconds_to_sleep <= 1e-6)
00414     return;
00415   if (whole_seconds > 0)
00416     {
00417       sleep (whole_seconds);
00418     }
00419   if (useconds > 0)
00420     {
00421       usleep (useconds);
00422     }
00423   return;
00424 #define ESLEEP_RETURNED
00425 
00426 #endif
00427 #if 0
00428   struct timespec rqtp, rmtp;
00429   rqtp.tv_sec = seconds_to_sleep;
00430   rqtp.tv_nsec = seconds_to_sleep * 1E9;
00431   if (seconds_to_sleep <= 0.0)
00432     return;
00433   if (nanosleep (&rqtp, NULL) < 0)
00434     {
00435       rcs_print_error ("nanosleep error %d %s\n", errno, strerror (errno));
00436     }
00437   return;
00438 #define ESLEEP_RETURNED
00439 
00440 #endif
00441 
00442 #endif
00443 
00444 #endif
00445 
00446 #ifdef WIN32
00447   if (seconds_to_sleep <= 0.0)
00448     return;
00449 #ifndef UNDER_CE
00450   SleepEx (((unsigned long) (seconds_to_sleep * 1000)), FALSE);
00451 #else
00452   Sleep (seconds_to_sleep * 1000);
00453 #endif
00454   return;
00455 #define ESLEEP_RETURNED
00456 
00457 #else
00458 
00459 #if defined(WIN16) || defined(_MSC_VER)
00460   double t0, tf;
00461   if (seconds_to_sleep <= 0.0)
00462     return;
00463   t0 = etime ();
00464   tf = etime ();
00465   while ((tf - t0) < seconds_to_sleep)
00466     {
00467 #ifdef WINDOWS
00468       Yeild ();
00469 #endif
00470       tf = etime ();
00471     }
00472   return;
00473 
00474 #define ESLEEP_RETURNED
00475 
00476 #else
00477 #if defined(__MSDOS__) && !defined(_Windows)
00478   if (seconds_to_sleep <= 0.0)
00479     return;
00480   delay ((unsigned int) (seconds_to_sleep * 1000.0));
00481   return;
00482 #define ESLEEP_RETURNED
00483 
00484 #endif
00485 #endif
00486 #endif
00487 
00488 #ifndef ESLEEP_RETURNED
00489 #error No definition for esleep for this platform.
00490 #endif
00491 
00492 }
00493 
00494 
00495 
00496 #ifndef NO_STDIO
00497 void
00498 print_etime ()
00499 {
00500   printf ("etime = %f\n", etime ());
00501 }
00502 #endif
00503 
00504 #ifdef VXWORKS
00505 /*
00506  * Floating point support seems to be flaking out, isolate
00507  * some of it here for testing.
00508  */
00509 int
00510 covertSecondsToTicks (double secs)
00511 {
00512   int ticks = 0;
00513 
00514   /* If the timeout is less than zero, wait forever,
00515      if it equals zero don't wait otherwise convert the timout,
00516      from seconds to ticks.
00517    */
00518   if (secs < 0)
00519     {
00520       ticks = WAIT_FOREVER;
00521     }
00522   else
00523     {
00524       ticks = (int) (secs * sysClkRateGet ());
00525     }
00526 
00527   return ticks;
00528 }
00529 
00530 #endif

Generated on Sun Dec 2 15:56:48 2001 for rcslib by doxygen1.2.11.1 written by Dimitri van Heesch, © 1997-2001