merge upstream HEAD
[ghc-hetmet.git] / rts / posix / GetTime.c
index 0e591ef..15643b8 100644 (file)
 # include <sys/times.h>
 #endif
 
+#ifdef USE_PAPI
+# include <papi.h>
+#endif
+
 #if ! ((defined(HAVE_GETRUSAGE) && !irix_HOST_OS) || defined(HAVE_TIMES))
 #error No implementation for getProcessCPUTime() available.
 #endif
 
 Ticks getProcessCPUTime(void)
 {
-    struct rusage t;
-    getrusage(RUSAGE_SELF, &t);
-    return ((Ticks)t.ru_utime.tv_sec * TICKS_PER_SECOND + 
-           ((Ticks)t.ru_utime.tv_usec * TICKS_PER_SECOND)/1000000);
+#if !defined(BE_CONSERVATIVE) && defined(HAVE_CLOCK_GETTIME) && defined (_SC_CPUTIME) && defined(CLOCK_PROCESS_CPUTIME_ID) && defined(HAVE_SYSCONF)
+    static int checked_sysconf = 0;
+    static int sysconf_result = 0;
+
+    if (!checked_sysconf) {
+        sysconf_result = sysconf(_SC_CPUTIME);
+        checked_sysconf = 1;
+    }
+    if (sysconf_result != -1) {
+        struct timespec ts;
+        int res;
+        res = clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &ts);
+        if (res == 0) {
+            return ((Ticks)ts.tv_sec * TICKS_PER_SECOND +
+                    ((Ticks)ts.tv_nsec * TICKS_PER_SECOND) / 1000000000);
+        }
+    }
+#endif
+
+    // fallback to getrusage
+    {
+        struct rusage t;
+        getrusage(RUSAGE_SELF, &t);
+        return ((Ticks)t.ru_utime.tv_sec * TICKS_PER_SECOND +
+                ((Ticks)t.ru_utime.tv_usec * TICKS_PER_SECOND)/1000000);
+    }
 }
 
 Ticks getProcessElapsedTime(void)
@@ -68,9 +94,17 @@ void getProcessTimes(Ticks *user, Ticks *elapsed)
 
 Ticks getProcessCPUTime(void)
 {
+#if !defined(THREADED_RTS) && USE_PAPI
+    long long usec;
+    if ((usec = PAPI_get_virt_usec()) < 0) {
+       barf("PAPI_get_virt_usec: %lld", usec);
+    }
+    return ((usec * TICKS_PER_SECOND) / 1000000);
+#else
     Ticks user, elapsed;
     getProcessTimes(&user,&elapsed);
     return user;
+#endif
 }
 
 Ticks getProcessElapsedTime(void)
@@ -115,22 +149,42 @@ void getProcessTimes(Ticks *user, Ticks *elapsed)
 
 Ticks getThreadCPUTime(void)
 {
-#if defined(HAVE_CLOCK_GETTIME) && defined(CLOCK_THREAD_CPUTIME_ID)
-    // clock_gettime() gives us per-thread CPU time.  It isn't
-    // reliable on Linux, but it's the best we have.
-    struct timespec ts;
-    clock_gettime(CLOCK_THREAD_CPUTIME_ID, &ts);
-    return ((Ticks)ts.tv_sec * TICKS_PER_SECOND + 
-           ((Ticks)ts.tv_nsec * TICKS_PER_SECOND) / 1000000000);
-#else
-    return getProcessCPUTime();
+#if USE_PAPI
+    long long usec;
+    if ((usec = PAPI_get_virt_usec()) < 0) {
+       barf("PAPI_get_virt_usec: %lld", usec);
+    }
+    return ((usec * TICKS_PER_SECOND) / 1000000);
+
+#elif !defined(BE_CONSERVATIVE) && defined(HAVE_CLOCK_GETTIME) && defined (_SC_THREAD_CPUTIME) && defined(CLOCK_THREAD_CPUTIME_ID) && defined(HAVE_SYSCONF)
+    {
+        static int checked_sysconf = 0;
+        static int sysconf_result = 0;
+        
+        if (!checked_sysconf) {
+            sysconf_result = sysconf(_SC_THREAD_CPUTIME);
+            checked_sysconf = 1;
+        }
+        if (sysconf_result != -1) {
+            // clock_gettime() gives us per-thread CPU time.  It isn't
+            // reliable on Linux, but it's the best we have.
+            struct timespec ts;
+            int res;
+            res = clock_gettime(CLOCK_THREAD_CPUTIME_ID, &ts);
+            if (res == 0) {
+                return ((Ticks)ts.tv_sec * TICKS_PER_SECOND +
+                        ((Ticks)ts.tv_nsec * TICKS_PER_SECOND) / 1000000000);
+            }
+        }
+    }
 #endif
+    return getProcessCPUTime();
 }
 
 nat
 getPageFaults(void)
 {
-#if !defined(HAVE_GETRUSAGE) || irix_HOST_OS
+#if !defined(HAVE_GETRUSAGE) || irix_HOST_OS || haiku_HOST_OS
     return 0;
 #else
     struct rusage t;