summaryrefslogtreecommitdiff
path: root/rts/posix/GetTime.c
diff options
context:
space:
mode:
Diffstat (limited to 'rts/posix/GetTime.c')
-rw-r--r--rts/posix/GetTime.c141
1 files changed, 141 insertions, 0 deletions
diff --git a/rts/posix/GetTime.c b/rts/posix/GetTime.c
new file mode 100644
index 0000000000..3a0764cb91
--- /dev/null
+++ b/rts/posix/GetTime.c
@@ -0,0 +1,141 @@
+/* -----------------------------------------------------------------------------
+ *
+ * (c) The GHC Team 2005
+ *
+ * Machine-dependent time measurement functions
+ *
+ * ---------------------------------------------------------------------------*/
+
+// Not POSIX, due to use of ru_majflt in getPageFaults()
+// #include "PosixSource.h"
+
+#include "Rts.h"
+#include "GetTime.h"
+
+#ifdef HAVE_TIME_H
+# include <time.h>
+#endif
+
+#ifdef HAVE_SYS_TIME_H
+# include <sys/time.h>
+#endif
+
+#if HAVE_SYS_RESOURCE_H
+# include <sys/resource.h>
+#endif
+
+#ifdef HAVE_UNISTD_H
+# include <unistd.h>
+#endif
+
+#ifdef HAVE_SYS_TIMES_H
+# include <sys/times.h>
+#endif
+
+#if ! ((defined(HAVE_GETRUSAGE) && !irix_HOST_OS) || defined(HAVE_TIMES))
+#error No implementation for getProcessCPUTime() available.
+#endif
+
+#if defined(HAVE_GETTIMEOFDAY) && defined(HAVE_GETRUSAGE) && !irix_HOST_OS
+// we'll implement getProcessCPUTime() and getProcessElapsedTime()
+// separately, using getrusage() and gettimeofday() respectively
+
+Ticks getProcessCPUTime(void)
+{
+ struct rusage t;
+ getrusage(RUSAGE_SELF, &t);
+ return (t.ru_utime.tv_sec * TICKS_PER_SECOND +
+ ((Ticks)t.ru_utime.tv_usec * TICKS_PER_SECOND)/1000000);
+}
+
+Ticks getProcessElapsedTime(void)
+{
+ struct timeval tv;
+ gettimeofday(&tv, (struct timezone *) NULL);
+ return (tv.tv_sec * TICKS_PER_SECOND +
+ ((Ticks)tv.tv_usec * TICKS_PER_SECOND)/1000000);
+}
+
+void getProcessTimes(Ticks *user, Ticks *elapsed)
+{
+ *user = getProcessCPUTime();
+ *elapsed = getProcessElapsedTime();
+}
+
+#elif defined(HAVE_TIMES)
+
+// we'll use the old times() API.
+
+Ticks getProcessCPUTime(void)
+{
+ Ticks user, elapsed;
+ getProcessTimes(&user,&elapsed);
+ return user;
+}
+
+Ticks getProcessElapsedTime(void)
+{
+ Ticks user, elapsed;
+ getProcessTimes(&user,&elapsed);
+ return elapsed;
+}
+
+void getProcessTimes(Ticks *user, Ticks *elapsed)
+{
+ static nat ClockFreq = 0;
+
+ if (ClockFreq == 0) {
+#if defined(HAVE_SYSCONF)
+ long ticks;
+ ticks = sysconf(_SC_CLK_TCK);
+ if ( ticks == -1 ) {
+ errorBelch("sysconf\n");
+ stg_exit(EXIT_FAILURE);
+ }
+ ClockFreq = ticks;
+#elif defined(CLK_TCK) /* defined by POSIX */
+ ClockFreq = CLK_TCK;
+#elif defined(HZ)
+ ClockFreq = HZ;
+#elif defined(CLOCKS_PER_SEC)
+ ClockFreq = CLOCKS_PER_SEC;
+#else
+ errorBelch("can't get clock resolution");
+ stg_exit(EXIT_FAILURE);
+#endif
+ }
+
+ struct tms t;
+ clock_t r = times(&t);
+ *user = (((Ticks)t.tms_utime * TICKS_PER_SECOND) / ClockFreq);
+ *elapsed = (((Ticks)r * TICKS_PER_SECOND) / ClockFreq);
+}
+
+#endif // HAVE_TIMES
+
+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 (ts.tv_sec * TICKS_PER_SECOND +
+ ((Ticks)ts.tv_nsec * TICKS_PER_SECOND) / 1000000000);
+#else
+ return getProcessCPUTime();
+#endif
+}
+
+nat
+getPageFaults(void)
+{
+#if !defined(HAVE_GETRUSAGE) || irix_HOST_OS
+ return 0;
+#else
+ struct rusage t;
+ getrusage(RUSAGE_SELF, &t);
+ return(t.ru_majflt);
+#endif
+}
+