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