diff options
-rw-r--r-- | rts/GetTime.h | 1 | ||||
-rw-r--r-- | rts/posix/GetTime.c | 77 | ||||
-rw-r--r-- | rts/win32/GetTime.c | 14 |
3 files changed, 71 insertions, 21 deletions
diff --git a/rts/GetTime.h b/rts/GetTime.h index 97f499cd6c..5bff00c9cb 100644 --- a/rts/GetTime.h +++ b/rts/GetTime.h @@ -13,6 +13,7 @@ void initializeTimer (void); Time getProcessCPUTime (void); +Time getCurrentThreadCPUTime (void); void getProcessTimes (Time *user, Time *elapsed); /* Get the current date and time. diff --git a/rts/posix/GetTime.c b/rts/posix/GetTime.c index 8d20d18bfb..1c77708131 100644 --- a/rts/posix/GetTime.c +++ b/rts/posix/GetTime.c @@ -44,11 +44,61 @@ void initializeTimer() #endif } +#if defined(HAVE_CLOCK_GETTIME) +static Time getClockTime(clockid_t clock) +{ + struct timespec ts; + int res = clock_gettime(clock, &ts); + if (res == 0) { + return SecondsToTime(ts.tv_sec) + NSToTime(ts.tv_nsec); + } else { + sysErrorBelch("clock_gettime"); + stg_exit(EXIT_FAILURE); + } +} +#endif + +Time getCurrentThreadCPUTime(void) +{ +#if defined(HAVE_CLOCK_GETTIME) && \ + defined(CLOCK_PROCESS_CPUTIME_ID) && \ + defined(HAVE_SYSCONF) + static bool have_checked_usability = false; + if (!have_checked_usability) { + // The Linux clock_getres(2) manpage claims that some early versions of + // Linux will return values which are uninterpretable in the presence + // of migration across CPUs. They claim that clock_getcpuclockid(0) + // will return ENOENT in this case. Check this. + clockid_t clkid; + if (clock_getcpuclockid(0, &clkid)) { + sysErrorBelch("getCurrentThreadCPUTime: no supported"); + stg_exit(EXIT_FAILURE); + } + have_checked_usability = true; + } + return getClockTime(CLOCK_THREAD_CPUTIME_ID); +#elif defined(darwin_HOST_OS) + mach_port_t port = pthread_mach_thread_np(osThreadId()); + thread_basic_info_data_t info = { 0 }; + mach_msg_type_number_t info_count = THREAD_BASIC_INFO_COUNT; + kern_return_t kern_err = thread_info(mach_thread_self(), THREAD_BASIC_INFO, + (thread_info_t) &info, &info_count); + if (kern_err == KERN_SUCCESS) { + return SecondsToTime(info.user_time.seconds) + USToTime(info.user_time.microseconds); + } else { + sysErrorBelch("getThreadCPUTime"); + stg_exit(EXIT_FAILURE); + } +#else +#error I know of no means to find the CPU time of current thread on this platform. +#endif +} + Time getProcessCPUTime(void) { #if !defined(BE_CONSERVATIVE) && \ defined(HAVE_CLOCK_GETTIME) && \ - defined(_SC_CPUTIME) && \ + defined(_SC_CPUTIME) && \ defined(CLOCK_PROCESS_CPUTIME_ID) && \ defined(HAVE_SYSCONF) static int checked_sysconf = 0; @@ -59,15 +109,7 @@ Time getProcessCPUTime(void) checked_sysconf = 1; } if (sysconf_result != -1) { - struct timespec ts; - int res; - res = clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &ts); - if (res == 0) { - return SecondsToTime(ts.tv_sec) + NSToTime(ts.tv_nsec); - } else { - sysErrorBelch("clock_gettime"); - stg_exit(EXIT_FAILURE); - } + return getClockTime(CLOCK_PROCESS_CPUTIME_ID); } #endif @@ -82,16 +124,7 @@ Time getProcessCPUTime(void) StgWord64 getMonotonicNSec(void) { #if defined(HAVE_CLOCK_GETTIME) - struct timespec ts; - int res; - - res = clock_gettime(CLOCK_ID, &ts); - if (res != 0) { - sysErrorBelch("clock_gettime"); - stg_exit(EXIT_FAILURE); - } - return (StgWord64)ts.tv_sec * 1000000000 + - (StgWord64)ts.tv_nsec; + return getClockTime(CLOCK_ID); #elif defined(darwin_HOST_OS) @@ -102,7 +135,9 @@ StgWord64 getMonotonicNSec(void) struct timeval tv; - gettimeofday(&tv, (struct timezone *) NULL); + if (gettimeofday(&tv, (struct timezone *) NULL) != 0) { + debugBlech("getMonotonicNSec: gettimeofday failed: %s", strerror(errno)); + }; return (StgWord64)tv.tv_sec * 1000000000 + (StgWord64)tv.tv_usec * 1000; diff --git a/rts/win32/GetTime.c b/rts/win32/GetTime.c index 61a978e2aa..e0f5e7d406 100644 --- a/rts/win32/GetTime.c +++ b/rts/win32/GetTime.c @@ -35,6 +35,20 @@ getProcessTimes(Time *user, Time *elapsed) } Time +getCurrentThreadCPUTime(void) +{ + FILETIME creationTime, exitTime, userTime, kernelTime = {0,0}; + + if (!GetThreadTimes(GetCurrentThread(), &creationTime, + &exitTime, &kernelTime, &userTime)) { + sysErrorBelch("getCurrentThreadCPUTime: Win32 error %lu", GetLastError()); + return 0; + } + + return fileTimeToRtsTime(userTime); +} + +Time getProcessCPUTime(void) { FILETIME creationTime, exitTime, userTime, kernelTime = {0,0}; |