Simbody
3.4 (development)
|
00001 #ifndef SimTK_SimTKCOMMON_TIMING_H_ 00002 #define SimTK_SimTKCOMMON_TIMING_H_ 00003 00004 /* -------------------------------------------------------------------------- * 00005 * Simbody(tm): SimTKcommon * 00006 * -------------------------------------------------------------------------- * 00007 * This is part of the SimTK 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/home/simbody. * 00011 * * 00012 * Portions copyright (c) 2010-12 Stanford University and the Authors. * 00013 * Authors: Michael Sherman * 00014 * Contributors: * 00015 * * 00016 * Licensed under the Apache License, Version 2.0 (the "License"); you may * 00017 * not use this file except in compliance with the License. You may obtain a * 00018 * copy of the License at http://www.apache.org/licenses/LICENSE-2.0. * 00019 * * 00020 * Unless required by applicable law or agreed to in writing, software * 00021 * distributed under the License is distributed on an "AS IS" BASIS, * 00022 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * 00023 * See the License for the specific language governing permissions and * 00024 * limitations under the License. * 00025 * -------------------------------------------------------------------------- */ 00026 00051 #include "SimTKcommon/internal/common.h" 00052 #include "SimTKcommon/Constants.h" 00053 00054 // This header is needed on Mac and Linux for some or all of the Posix time 00055 // functions and the timespec struct. We include it on Windows also for 00056 // uniform cross-platform behavior, since there are many other useful time- 00057 // date-handling symbols declared here on all platforms. 00058 #include <ctime> 00059 00060 #if defined(_MSC_VER) 00061 /* On Windows, the timespec struct is not defined. However, note that the 00062 timespec struct is also defined in the pthread.h header on Windows, so the 00063 guard symbols must match here to avoid a duplicate declaration. */ 00064 #ifndef HAVE_STRUCT_TIMESPEC 00065 #define HAVE_STRUCT_TIMESPEC 1 00066 struct timespec { 00067 long tv_sec; // TODO: this should be time_t but must fix in pthreads too 00068 long tv_nsec; 00069 }; 00070 #endif /* HAVE_STRUCT_TIMESPEC */ 00071 00072 /* Posix nanosleep() sleeps the indicated number of nanoseconds and returns 00073 0, or if it is interrupted early it returns how much time was left in 00074 rem and returns EINTR. Ours is not interruptable so will always succeed and 00075 return rem==0. It is OK if rem is NULL, but req==NULL or req<0 returns 00076 EINVAL. A time of req==0 is allowed and our interpretation is that the 00077 thread relinquishes its time slice to another ready-to-run thread if there 00078 is one, otherwise returns immediately. This implementation rounds the 00079 desired sleep time to the nearest millisecond. On a Linux system, this 00080 requires including <time.h> (or <ctime>), which we already included 00081 above. */ 00082 SimTK_SimTKCOMMON_EXPORT int nanosleep(const struct timespec* req, struct timespec* rem); 00083 00084 /* Posix declares this handy function obsolete, but I don't think it is in 00085 any danger of going away. It sleeps for the given number of microseconds. 00086 However, using SimTK::sleepInNs() or SimTK::sleepInSec() is safer. */ 00087 typedef unsigned int useconds_t; 00088 inline int usleep(useconds_t us) { 00089 struct timespec req; 00090 req.tv_sec = (long) (us / 1000000U); 00091 req.tv_nsec = (long)((us % 1000000U)*1000U); 00092 int status = nanosleep(&req,0); 00093 return status ? -1 : 0; 00094 } 00095 #endif 00096 00097 #if defined(_MSC_VER) || defined(__APPLE__) 00098 // On Windows and OSX, the Posix clock_gettime function is missing. 00099 typedef long clockid_t; 00100 00101 /* These constants are the clock ids we support. All the varieties of 00102 CLOCK_MONOTONIC are high resolution with no NTP adjustments. I measured 00103 the resolutions on a single Windows 7 machine; hopefully they are typical 00104 (resolution here means how often they are updated): 00105 - MONOTONIC (counter): 0.001ms 1us 00106 - REALTIME (time of day): 1ms 1000us 00107 - CPUTIME (either): 20ms 20000us 00108 These are slightly conservative resolutions so you should be able to 00109 achieve them in practice. */ 00110 #define CLOCK_REALTIME 1 // time of day clock, from 1/1/1970 00111 #define CLOCK_MONOTONIC 2 // counter from last boot time 00112 #define CLOCK_MONOTONIC_HR 3 // "high resolution" (same) 00113 #define CLOCK_MONOTONIC_RAW 4 // "not subject to NTP adjustments" (same) 00114 #define CLOCK_THREAD_CPUTIME_ID 5 // current thread's cpu time (kernel+user) 00115 #define CLOCK_PROCESS_CPUTIME_ID 6 // cumulative cpu time of all threads of 00116 // this process, live or dead 00117 00118 /* Returns zero if it succeeds (or if tp==NULL); otherwise EINVAL. On a 00119 Linux system, this requires including <time.h> (or <ctime>) and linking 00120 with -lrt to get the realtime library. */ 00121 SimTK_SimTKCOMMON_EXPORT int clock_gettime(clockid_t clock_id, 00122 struct timespec *tp); 00123 #endif 00124 00125 00126 00127 namespace SimTK { 00128 00155 inline long long timespecToNs(const timespec& ts) 00156 { return (long long)ts.tv_sec*1000000000LL + (long long)ts.tv_nsec; } 00157 00160 inline void nsToTimespec(const long long& ns, timespec& ts) 00161 { ts.tv_sec = (long)(ns / 1000000000LL); // signed 00162 if (ns >= 0) ts.tv_nsec = (long)( ns % 1000000000LL); 00163 else ts.tv_nsec = -(long)((-ns) % 1000000000LL); } 00164 00168 inline double nsToSec(const long long& ns) 00169 { return (double)(ns*SimTK_NS_TO_S); } 00170 00174 inline long long secToNs(const double& s) 00175 { return (long long)(s*SimTK_S_TO_NS); } 00197 inline double cpuTime() 00198 { timespec ts; 00199 clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &ts); 00200 return (double)(timespecToNs(ts)*SimTK_NS_TO_S); } 00201 00208 inline double threadCpuTime() 00209 { timespec ts; 00210 clock_gettime(CLOCK_THREAD_CPUTIME_ID, &ts); 00211 return (double)(timespecToNs(ts)*SimTK_NS_TO_S); } 00242 inline long long realTimeInNs() { 00243 timespec ts; 00244 #ifdef CLOCK_MONOTONIC_RAW 00245 clock_gettime(CLOCK_MONOTONIC_RAW, &ts); 00246 #else 00247 clock_gettime(CLOCK_MONOTONIC, &ts); 00248 #endif 00249 return timespecToNs(ts); 00250 } 00251 00259 inline double realTime() {return nsToSec(realTimeInNs());} 00260 00268 inline void sleepInNs(const long long& ns) 00269 { timespec ts; 00270 nsToTimespec(ns, ts); 00271 nanosleep(&ts, 0); } 00272 00280 inline void sleepInSec(const double& seconds) {sleepInNs(secToNs(seconds));} 00283 } // namespace SimTK 00284 00285 #endif // SimTK_SimTKCOMMON_TIMING_H_