0e591ef5517ed1516b0980a5b163f6702724f76a
[ghc.git] / rts / posix / GetTime.c
1 /* -----------------------------------------------------------------------------
2 *
3 * (c) The GHC Team 2005
4 *
5 * Machine-dependent time measurement functions
6 *
7 * ---------------------------------------------------------------------------*/
8
9 // Not POSIX, due to use of ru_majflt in getPageFaults()
10 // #include "PosixSource.h"
11
12 #include "Rts.h"
13 #include "GetTime.h"
14
15 #ifdef HAVE_TIME_H
16 # include <time.h>
17 #endif
18
19 #ifdef HAVE_SYS_TIME_H
20 # include <sys/time.h>
21 #endif
22
23 #if HAVE_SYS_RESOURCE_H
24 # include <sys/resource.h>
25 #endif
26
27 #ifdef HAVE_UNISTD_H
28 # include <unistd.h>
29 #endif
30
31 #ifdef HAVE_SYS_TIMES_H
32 # include <sys/times.h>
33 #endif
34
35 #if ! ((defined(HAVE_GETRUSAGE) && !irix_HOST_OS) || defined(HAVE_TIMES))
36 #error No implementation for getProcessCPUTime() available.
37 #endif
38
39 #if defined(HAVE_GETTIMEOFDAY) && defined(HAVE_GETRUSAGE) && !irix_HOST_OS
40 // we'll implement getProcessCPUTime() and getProcessElapsedTime()
41 // separately, using getrusage() and gettimeofday() respectively
42
43 Ticks getProcessCPUTime(void)
44 {
45 struct rusage t;
46 getrusage(RUSAGE_SELF, &t);
47 return ((Ticks)t.ru_utime.tv_sec * TICKS_PER_SECOND +
48 ((Ticks)t.ru_utime.tv_usec * TICKS_PER_SECOND)/1000000);
49 }
50
51 Ticks getProcessElapsedTime(void)
52 {
53 struct timeval tv;
54 gettimeofday(&tv, (struct timezone *) NULL);
55 return ((Ticks)tv.tv_sec * TICKS_PER_SECOND +
56 ((Ticks)tv.tv_usec * TICKS_PER_SECOND)/1000000);
57 }
58
59 void getProcessTimes(Ticks *user, Ticks *elapsed)
60 {
61 *user = getProcessCPUTime();
62 *elapsed = getProcessElapsedTime();
63 }
64
65 #elif defined(HAVE_TIMES)
66
67 // we'll use the old times() API.
68
69 Ticks getProcessCPUTime(void)
70 {
71 Ticks user, elapsed;
72 getProcessTimes(&user,&elapsed);
73 return user;
74 }
75
76 Ticks getProcessElapsedTime(void)
77 {
78 Ticks user, elapsed;
79 getProcessTimes(&user,&elapsed);
80 return elapsed;
81 }
82
83 void getProcessTimes(Ticks *user, Ticks *elapsed)
84 {
85 static nat ClockFreq = 0;
86
87 if (ClockFreq == 0) {
88 #if defined(HAVE_SYSCONF)
89 long ticks;
90 ticks = sysconf(_SC_CLK_TCK);
91 if ( ticks == -1 ) {
92 sysErrorBelch("sysconf");
93 stg_exit(EXIT_FAILURE);
94 }
95 ClockFreq = ticks;
96 #elif defined(CLK_TCK) /* defined by POSIX */
97 ClockFreq = CLK_TCK;
98 #elif defined(HZ)
99 ClockFreq = HZ;
100 #elif defined(CLOCKS_PER_SEC)
101 ClockFreq = CLOCKS_PER_SEC;
102 #else
103 errorBelch("can't get clock resolution");
104 stg_exit(EXIT_FAILURE);
105 #endif
106 }
107
108 struct tms t;
109 clock_t r = times(&t);
110 *user = (((Ticks)t.tms_utime * TICKS_PER_SECOND) / ClockFreq);
111 *elapsed = (((Ticks)r * TICKS_PER_SECOND) / ClockFreq);
112 }
113
114 #endif // HAVE_TIMES
115
116 Ticks getThreadCPUTime(void)
117 {
118 #if defined(HAVE_CLOCK_GETTIME) && defined(CLOCK_THREAD_CPUTIME_ID)
119 // clock_gettime() gives us per-thread CPU time. It isn't
120 // reliable on Linux, but it's the best we have.
121 struct timespec ts;
122 clock_gettime(CLOCK_THREAD_CPUTIME_ID, &ts);
123 return ((Ticks)ts.tv_sec * TICKS_PER_SECOND +
124 ((Ticks)ts.tv_nsec * TICKS_PER_SECOND) / 1000000000);
125 #else
126 return getProcessCPUTime();
127 #endif
128 }
129
130 nat
131 getPageFaults(void)
132 {
133 #if !defined(HAVE_GETRUSAGE) || irix_HOST_OS
134 return 0;
135 #else
136 struct rusage t;
137 getrusage(RUSAGE_SELF, &t);
138 return(t.ru_majflt);
139 #endif
140 }
141