00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
#include <ptf/environment/clock.hpp>
00019
#include <ptf/core/ptfcore.hpp>
00020
#if _POSIX_VERSION < 199309
00021
#ifndef _POSIX_TIMERS
00022
#include <sys/time.h>
00023
#endif
00024
#endif
00025
#ifdef MAC
00026
#include <mach/mach_time.h>
00027
#include <mach/mach.h>
00028
#include <mach/clock.h>
00029
00030
static uint64_t relative_time, startup_time;
00031
static double timebase_ratio;
00032
static mach_port_t clock_port;
00033
#endif
00034
#include <stdexcept>
00035
00036
#ifdef MAC
00040
void initMachTimer(){
00041
mach_timebase_info_data_t timebase;
00042 memset( &timebase, 0,
sizeof( timebase ));
00043
00044 mach_timebase_info(&timebase);
00045 timebase_ratio = (
double)timebase.numer / (
double)timebase.denom * (
double)1e-9;
00046
00047 host_get_clock_service(mach_host_self(), REALTIME_CLOCK, &clock_port);
00048
00049 relative_time = startup_time = (uint64_t)(mach_absolute_time() * timebase_ratio);
00050 }
00051
00056 uint64_t getMachTimer(){
00057
return (uint64_t)((mach_absolute_time() * timebase_ratio) * 1e6);
00058 }
00059
#endif
00060
00064 Clock::Clock() {
00065 timespec tspec1, tspec2;
00066
PtfCore::getSingleton().
getMessageLog() <<
MESSAGE(
"Checking clock capabilities.\n");
00067
00068
#ifdef MAC
00069
PtfCore::getSingleton().
getMessageLog()
00070 <<
MESSAGE(
"Using Mac OS X high resolution timer. Initializing it now.\n");
00071 initMachTimer();
00072
#endif
00073
00074
#ifdef _POSIX_TIMERS
00075
PtfCore::getSingleton().
getMessageLog() <<
MESSAGE(
"POSIX.4 timers and clocks support.\n");
00076 clock_getres(CLOCK_REALTIME, &tspec1);
00077
#else
00078
PtfCore::getSingleton().
getMessageLog()
00079 <<
WARNING(
"POSIX.4 timers and clocks not supported. Using low resolution timing.\n");
00080
#endif
00081
calculateClockResolution(tspec2);
00082
#ifdef _POSIX_TIMERS
00083
PtfCore::getSingleton().
getMessageLog() <<
MESSAGE(
"System reported this clock resolution: ")
00084 << tspec1 <<
"\n";
00085
#endif
00086
PtfCore::getSingleton().
getMessageLog() <<
MESSAGE(
"PTF has calculated this clock resolution: ")
00087 << tspec2 <<
"\n";
00088 }
00089
00093 Clock::~Clock() {
00094
00095 }
00096
00102 void Clock::getClock(timespec& tspec) {
00103
#ifdef _POSIX_TIMERS
00104
00105 clock_gettime(CLOCK_REALTIME, &tspec);
00106
#else
00107
#ifdef MAC
00108
00109 uint64_t current_time = getMachTimer() * 1000;
00110 tspec.tv_nsec = current_time % (uint64_t)1e9;
00111 tspec.tv_sec = (
int)(current_time / 1e9);
00112
#else
00113
00114
int err;
00115
struct timeval tv;
00116
struct timezone tz;
00117 err = gettimeofday(&tv, &tz);
00118
if(0 != err) {
00119
PtfCore::getSingleton().
getMessageLog()
00120 <<
"ERROR: Failed to get time from low resolution timer.\n";
00121
throw std::runtime_error(
"Failed to get time from low resolution timer.");
00122 };
00123 tspec.tv_sec = (
long int)tv.tv_sec;
00124 tspec.tv_nsec = (
long int)tv.tv_usec * 1000;
00125
#endif
00126
#endif
00127
}
00128
00136 void Clock::calculateClockResolution(timespec& tspec) {
00137 timespec tspec1, tspec2;
00138
getClock(tspec1);
00139
do {
00140
getClock(tspec2);
00141 }
while ((tspec1.tv_nsec == tspec2.tv_nsec) && ((tspec1.tv_sec == tspec2.tv_sec)));
00142
if (tspec1.tv_sec == tspec2.tv_sec) {
00143 tspec.tv_nsec = tspec2.tv_nsec - tspec1.tv_nsec;
00144 tspec.tv_sec = 0;
00145 }
00146
else {
00147 tspec.tv_nsec = 1000000000 - tspec1.tv_nsec + tspec2.tv_nsec;
00148
if (tspec.tv_nsec >= 1000000000) {
00149 tspec.tv_nsec -= 1000000000;
00150 tspec.tv_sec = tspec2.tv_sec - tspec1.tv_sec;
00151 }
00152
else {
00153 tspec.tv_sec = tspec2.tv_sec - tspec1.tv_sec - 1;
00154 }
00155 }
00156 }