Commit c0461976 authored by pcapriotti's avatar pcapriotti
Browse files

Move getMonotonicUSec from base to the RTS.

parent d7bb8cd2
......@@ -11,6 +11,9 @@
#include "BeginPrivate.h"
void initializeTimer (void);
StgWord64 getMonotonicNSec (void);
Time getProcessCPUTime (void);
Time getThreadCPUTime (void);
Time getProcessElapsedTime (void);
......
......@@ -1283,6 +1283,7 @@ typedef struct _RtsSymbolVal {
SymI_HasProto(n_capabilities) \
SymI_HasProto(stg_traceCcszh) \
SymI_HasProto(stg_traceEventzh) \
SymI_HasProto(getMonotonicNSec) \
RTS_USER_SIGNALS_SYMBOLS \
RTS_INTCHAR_SYMBOLS
......
......@@ -128,6 +128,9 @@ hs_init_ghc(int *argc, char **argv[], RtsConfig rts_config)
/* Initialise the stats department, phase 0 */
initStats0();
/* Initialize system timer before starting to collect stats */
initializeTimer();
/* Next we do is grab the start time...just in case we're
* collecting timing statistics.
*/
......
......@@ -33,6 +33,19 @@
// we'll implement getProcessCPUTime() and getProcessElapsedTime()
// separately, using getrusage() and gettimeofday() respectively
#ifdef darwin_HOST_OS
static double timer_scaling_factor_ns = 0.0;
#endif
void initializeTimer()
{
#ifdef darwin_HOST_OS
mach_timebase_info_data_t info;
(void) mach_timebase_info(&info);
timer_scaling_factor_ns = (double)info.numer / (double)info.denom * 1e9;
#endif
}
Time getProcessCPUTime(void)
{
#if !defined(BE_CONSERVATIVE) && defined(HAVE_CLOCK_GETTIME) && defined (_SC_CPUTIME) && defined(CLOCK_PROCESS_CPUTIME_ID) && defined(HAVE_SYSCONF)
......@@ -64,32 +77,31 @@ Time getProcessCPUTime(void)
}
}
Time getProcessElapsedTime(void)
StgWord64 getMonotonicNSec(void)
{
#ifdef HAVE_CLOCK_GETTIME
struct timespec ts;
clock_gettime(CLOCK_ID, &ts);
return SecondsToTime(ts.tv_sec) + NSToTime(ts.tv_nsec);
return (StgWord64)ts.tv_sec * 1000000000 +
(StgWord64)ts.tv_nsec;
#elif defined(darwin_HOST_OS)
uint64_t time = mach_absolute_time();
static double scaling_factor = 0.0;
if (scaling_factor == 0.0) {
mach_timebase_info_data_t info;
(void) mach_timebase_info(&info);
scaling_factor = (double)info.numer / (double)info.denom;
}
return (Time)((double)time * scaling_factor);
return (double)time * timer_scaling_factor_ns;
#else
struct timeval tv;
gettimeofday(&tv, (struct timezone *) NULL);
return SecondsToTime(tv.tv_sec) + USToTime(tv.tv_usec);
return (StgWord64)tv.tv_sec * 1000000000 +
(StgWord64)tv.tv_usec * 1000;
#endif
}
Time getProcessElapsedTime(void)
{
return NSToTime(getMonotonicNSec());
}
void getProcessTimes(Time *user, Time *elapsed)
{
*user = getProcessCPUTime();
......
......@@ -47,37 +47,57 @@ getProcessCPUTime(void)
return fileTimeToRtsTime(userTime);
}
// getProcessElapsedTime relies on QueryPerformanceFrequency
// which should be available on any Windows computer thay you
// would want to run Haskell on. Satnam Singh, 5 July 2010.
Time
getProcessElapsedTime(void)
// Number of ticks per second used by the QueryPerformanceFrequency
// implementaiton, represented by a 64-bit union type.
static LARGE_INTEGER qpc_frequency = {.QuadPart = 0};
// Initialize qpc_frequency. This function should be called before any call to
// getMonotonicNSec. If QPC is not supported on this system, qpc_frequency is
// set to 0.
void initializeTimer()
{
// frequency represents the number of ticks per second
// used by the QueryPerformanceFrequency implementaiton
// and is represented by a 64-bit union type initially set to 0
// and updated just once (hence use of static).
static LARGE_INTEGER frequency = {.QuadPart = 0} ;
BOOL qpc_supported = QueryPerformanceFrequency(&qpc_frequency);
if (!qpc_supported)
{
qpc_frequency.QuadPart = 0;
}
}
HsWord64
getMonotonicNSec()
{
if (qpc_frequency.QuadPart)
{
// system_time is a 64-bit union type used to represent the
// tick count returned by QueryPerformanceCounter
LARGE_INTEGER system_time ;
LARGE_INTEGER system_time;
// If this is the first time we are calling getProcessElapsedTime
// then record the ticks per second used by QueryPerformanceCounter
if (frequency.QuadPart == 0) {
QueryPerformanceFrequency(&frequency);
}
// get the tick count.
QueryPerformanceCounter(&system_time);
// Get the tick count.
QueryPerformanceCounter(&system_time) ;
// compute elapsed seconds as double
double secs = (double)system_time.QuadPart /
(double)qpc_frequency.QuadPart;
// Return the tick count as a Time value.
// Using double to compute the intermediate value, because a 64-bit
// int would overflow when multiplied by TICK_RESOLUTION in about 81 days.
return fsecondsToTime((double)system_time.QuadPart /
(double)frequency.QuadPart) ;
// return elapsed time in nanoseconds
return (HsWord64)(secs * 1e9);
}
else // fallback to GetTickCount
{
// NOTE: GetTickCount is a 32-bit millisecond value, so it wraps around
// every 49 days.
DWORD count = GetTickCount();
// getTickCount is in milliseconds, so multiply it by 1000000 to get
// nanoseconds.
return (HsWord64)count * 1000000;
}
}
Time
getProcessElapsedTime(void)
{
return NSToTime(getMonotonicNSec());
}
Time
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment