Simbody
|
00001 #ifndef SimTK_SimTKCOMMON_TIMING_H_ 00002 #define SimTK_SimTKCOMMON_TIMING_H_ 00003 00004 /* -------------------------------------------------------------------------- * 00005 * SimTK Core: SimTK Simbody(tm) * 00006 * -------------------------------------------------------------------------- * 00007 * This is part of the SimTK Core biosimulation toolkit originating from * 00008 * Simbios, the NIH National Center for Physics-Based Simulation of * 00009 * Biological Structures at Stanford, funded under the NIH Roadmap for * 00010 * Medical Research, grant U54 GM072970. See https://simtk.org. * 00011 * * 00012 * Portions copyright (c) 2010 Stanford University and the Authors. * 00013 * Authors: Peter Eastman * 00014 * Contributors: * 00015 * * 00016 * Permission is hereby granted, free of charge, to any person obtaining a * 00017 * copy of this software and associated documentation files (the "Software"), * 00018 * to deal in the Software without restriction, including without limitation * 00019 * the rights to use, copy, modify, merge, publish, distribute, sublicense, * 00020 * and/or sell copies of the Software, and to permit persons to whom the * 00021 * Software is furnished to do so, subject to the following conditions: * 00022 * * 00023 * The above copyright notice and this permission notice shall be included in * 00024 * all copies or substantial portions of the Software. * 00025 * * 00026 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * 00027 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * 00028 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * 00029 * THE AUTHORS, CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, * 00030 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR * 00031 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE * 00032 * USE OR OTHER DEALINGS IN THE SOFTWARE. * 00033 * -------------------------------------------------------------------------- */ 00034 00059 #include "SimTKcommon/internal/common.h" 00060 #include "SimTKcommon/Constants.h" 00061 00062 // This header is needed on Mac and Linux for some or all of the Posix time 00063 // functions and the timespec struct. We include it on Windows also for 00064 // uniform cross-platform behavior, since there are many other useful time- 00065 // date-handling symbols declared here on all platforms. 00066 #include <ctime> 00067 00068 #if defined(_MSC_VER) 00069 /* On Windows, the timespec struct is not defined. However, note that the 00070 timespec struct is also defined in the pthread.h header on Windows, so the 00071 guard symbols must match here to avoid a duplicate declaration. */ 00072 #ifndef HAVE_STRUCT_TIMESPEC 00073 #define HAVE_STRUCT_TIMESPEC 1 00074 struct timespec { 00075 long tv_sec; // TODO: this should be time_t but must fix in pthreads too 00076 long tv_nsec; 00077 }; 00078 #endif /* HAVE_STRUCT_TIMESPEC */ 00079 00080 /* Posix nanosleep() sleeps the indicated number of nanoseconds and returns 00081 0, or if it is interrupted early it returns how much time was left in 00082 rem and returns EINTR. Ours is not interruptable so will always succeed and 00083 return rem==0. It is OK if rem is NULL, but req==NULL or req<0 returns 00084 EINVAL. A time of req==0 is allowed and our interpretation is that the 00085 thread relinquishes its time slice to another ready-to-run thread if there 00086 is one, otherwise returns immediately. This implementation rounds the 00087 desired sleep time to the nearest millisecond. On a Linux system, this 00088 requires including <time.h> (or <ctime>), which we already included 00089 above. */ 00090 SimTK_SimTKCOMMON_EXPORT int nanosleep(const struct timespec* req, struct timespec* rem); 00091 00092 /* Posix declares this handy function obsolete, but I don't think it is in 00093 any danger of going away. It sleeps for the given number of microseconds. 00094 However, using SimTK::sleepInNs() or SimTK::sleepInSec() is safer. */ 00095 typedef unsigned int useconds_t; 00096 inline int usleep(useconds_t us) { 00097 struct timespec req; 00098 req.tv_sec = (long) (us / 1000000U); 00099 req.tv_nsec = (long)((us % 1000000U)*1000U); 00100 int status = nanosleep(&req,0); 00101 return status ? -1 : 0; 00102 } 00103 #endif 00104 00105 #if defined(_MSC_VER) || defined(__APPLE__) 00106 // On Windows and OSX, the Posix clock_gettime function is missing. 00107 typedef long clockid_t; 00108 00109 /* These constants are the clock ids we support. All the varieties of 00110 CLOCK_MONOTONIC are high resolution with no NTP adjustments. I measured 00111 the resolutions on a single Windows 7 machine; hopefully they are typical 00112 (resolution here means how often they are updated): 00113 - MONOTONIC (counter): 0.001ms 1us 00114 - REALTIME (time of day): 1ms 1000us 00115 - CPUTIME (either): 20ms 20000us 00116 These are slightly conservative resolutions so you should be able to 00117 achieve them in practice. */ 00118 #define CLOCK_REALTIME 1 // time of day clock, from 1/1/1970 00119 #define CLOCK_MONOTONIC 2 // counter from last boot time 00120 #define CLOCK_MONOTONIC_HR 3 // "high resolution" (same) 00121 #define CLOCK_MONOTONIC_RAW 4 // "not subject to NTP adjustments" (same) 00122 #define CLOCK_THREAD_CPUTIME_ID 5 // current thread's cpu time (kernel+user) 00123 #define CLOCK_PROCESS_CPUTIME_ID 6 // cumulative cpu time of all threads of 00124 // this process, live or dead 00125 00126 /* Returns zero if it succeeds (or if tp==NULL); otherwise EINVAL. On a 00127 Linux system, this requires including <time.h> (or <ctime>) and linking 00128 with -lrt to get the realtime library. */ 00129 SimTK_SimTKCOMMON_EXPORT int clock_gettime(clockid_t clock_id, 00130 struct timespec *tp); 00131 #endif 00132 00133 00134 00135 namespace SimTK { 00136 00163 inline long long timespecToNs(const timespec& ts) 00164 { return (long long)ts.tv_sec*1000000000LL + (long long)ts.tv_nsec; } 00165 00168 inline void nsToTimespec(const long long& ns, timespec& ts) 00169 { ts.tv_sec = (long)(ns / 1000000000LL); // signed 00170 if (ns >= 0) ts.tv_nsec = (long)( ns % 1000000000LL); 00171 else ts.tv_nsec = -(long)((-ns) % 1000000000LL); } 00172 00176 inline double nsToSec(const long long& ns) 00177 { return (double)(ns*SimTK_NS_TO_S); } 00178 00182 inline long long secToNs(const double& s) 00183 { return (long long)(s*SimTK_S_TO_NS); } 00205 inline double cpuTime() 00206 { timespec ts; 00207 clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &ts); 00208 return (double)(timespecToNs(ts)*SimTK_NS_TO_S); } 00209 00216 inline double threadCpuTime() 00217 { timespec ts; 00218 clock_gettime(CLOCK_THREAD_CPUTIME_ID, &ts); 00219 return (double)(timespecToNs(ts)*SimTK_NS_TO_S); } 00250 inline long long realTimeInNs() { 00251 timespec ts; 00252 #ifdef CLOCK_MONOTONIC_RAW 00253 clock_gettime(CLOCK_MONOTONIC_RAW, &ts); 00254 #else 00255 clock_gettime(CLOCK_MONOTONIC, &ts); 00256 #endif 00257 return timespecToNs(ts); 00258 } 00259 00267 inline double realTime() {return nsToSec(realTimeInNs());} 00268 00276 inline void sleepInNs(const long long& ns) 00277 { timespec ts; 00278 nsToTimespec(ns, ts); 00279 nanosleep(&ts, 0); } 00280 00288 inline void sleepInSec(const double& seconds) {sleepInNs(secToNs(seconds));} 00291 } // namespace SimTK 00292 00293 #endif // SimTK_SimTKCOMMON_TIMING_H_