1 /* -----------------------------------------------------------------------------
3 * (c) The GHC Team 2005
5 * Machine-dependent time measurement functions
7 * ---------------------------------------------------------------------------*/
9 // Not POSIX, due to use of ru_majflt in getPageFaults()
10 // #include "PosixSource.h"
19 #ifdef HAVE_SYS_TIME_H
20 # include <sys/time.h>
23 #if HAVE_SYS_RESOURCE_H
24 # include <sys/resource.h>
31 #ifdef HAVE_SYS_TIMES_H
32 # include <sys/times.h>
39 #if ! ((defined(HAVE_GETRUSAGE) && !irix_HOST_OS) || defined(HAVE_TIMES))
40 #error No implementation for getProcessCPUTime() available.
43 #if defined(HAVE_GETTIMEOFDAY) && defined(HAVE_GETRUSAGE) && !irix_HOST_OS
44 // we'll implement getProcessCPUTime() and getProcessElapsedTime()
45 // separately, using getrusage() and gettimeofday() respectively
47 Ticks getProcessCPUTime(void)
49 #if !defined(BE_CONSERVATIVE) && defined(HAVE_CLOCK_GETTIME) && defined (_SC_CPUTIME) && defined(CLOCK_PROCESS_CPUTIME_ID) && defined(HAVE_SYSCONF)
50 static int checked_sysconf = 0;
51 static int sysconf_result = 0;
53 if (!checked_sysconf) {
54 sysconf_result = sysconf(_SC_CPUTIME);
57 if (sysconf_result != -1) {
60 res = clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &ts);
62 return ((Ticks)ts.tv_sec * TICKS_PER_SECOND +
63 ((Ticks)ts.tv_nsec * TICKS_PER_SECOND) / 1000000000);
68 // fallback to getrusage
71 getrusage(RUSAGE_SELF, &t);
72 return ((Ticks)t.ru_utime.tv_sec * TICKS_PER_SECOND +
73 ((Ticks)t.ru_utime.tv_usec * TICKS_PER_SECOND)/1000000);
77 Ticks getProcessElapsedTime(void)
80 gettimeofday(&tv, (struct timezone *) NULL);
81 return ((Ticks)tv.tv_sec * TICKS_PER_SECOND +
82 ((Ticks)tv.tv_usec * TICKS_PER_SECOND)/1000000);
85 void getProcessTimes(Ticks *user, Ticks *elapsed)
87 *user = getProcessCPUTime();
88 *elapsed = getProcessElapsedTime();
91 #elif defined(HAVE_TIMES)
93 // we'll use the old times() API.
95 Ticks getProcessCPUTime(void)
97 #if !defined(THREADED_RTS) && USE_PAPI
99 if ((usec = PAPI_get_virt_usec()) < 0) {
100 barf("PAPI_get_virt_usec: %lld", usec);
102 return ((usec * TICKS_PER_SECOND) / 1000000);
105 getProcessTimes(&user,&elapsed);
110 Ticks getProcessElapsedTime(void)
113 getProcessTimes(&user,&elapsed);
117 void getProcessTimes(Ticks *user, Ticks *elapsed)
119 static nat ClockFreq = 0;
121 if (ClockFreq == 0) {
122 #if defined(HAVE_SYSCONF)
124 ticks = sysconf(_SC_CLK_TCK);
126 sysErrorBelch("sysconf");
127 stg_exit(EXIT_FAILURE);
130 #elif defined(CLK_TCK) /* defined by POSIX */
134 #elif defined(CLOCKS_PER_SEC)
135 ClockFreq = CLOCKS_PER_SEC;
137 errorBelch("can't get clock resolution");
138 stg_exit(EXIT_FAILURE);
143 clock_t r = times(&t);
144 *user = (((Ticks)t.tms_utime * TICKS_PER_SECOND) / ClockFreq);
145 *elapsed = (((Ticks)r * TICKS_PER_SECOND) / ClockFreq);
150 Ticks getThreadCPUTime(void)
154 if ((usec = PAPI_get_virt_usec()) < 0) {
155 barf("PAPI_get_virt_usec: %lld", usec);
157 return ((usec * TICKS_PER_SECOND) / 1000000);
159 #elif !defined(BE_CONSERVATIVE) && defined(HAVE_CLOCK_GETTIME) && defined (_SC_THREAD_CPUTIME) && defined(CLOCK_THREAD_CPUTIME_ID) && defined(HAVE_SYSCONF)
161 static int checked_sysconf = 0;
162 static int sysconf_result = 0;
164 if (!checked_sysconf) {
165 sysconf_result = sysconf(_SC_THREAD_CPUTIME);
168 if (sysconf_result != -1) {
169 // clock_gettime() gives us per-thread CPU time. It isn't
170 // reliable on Linux, but it's the best we have.
173 res = clock_gettime(CLOCK_THREAD_CPUTIME_ID, &ts);
175 return ((Ticks)ts.tv_sec * TICKS_PER_SECOND +
176 ((Ticks)ts.tv_nsec * TICKS_PER_SECOND) / 1000000000);
181 return getProcessCPUTime();
187 #if !defined(HAVE_GETRUSAGE) || irix_HOST_OS || haiku_HOST_OS
191 getrusage(RUSAGE_SELF, &t);