summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBen Gamari <ben@smart-cactus.org>2019-05-17 15:40:26 -0400
committerBen Gamari <ben@smart-cactus.org>2020-02-20 21:21:37 -0500
commit75f46ab1e83a3139e0d6fe521e73650ea527069e (patch)
treea5d8a493083582a978ba23be3d3379594ff3ef63
parent6880d6aa1e6e96579bbff89712efd813489cc828 (diff)
downloadhaskell-75f46ab1e83a3139e0d6fe521e73650ea527069e.tar.gz
rts: Add getCurrentThreadCPUTime helper
-rw-r--r--rts/GetTime.h1
-rw-r--r--rts/posix/GetTime.c77
-rw-r--r--rts/win32/GetTime.c14
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};