[project @ 1999-03-01 09:04:07 by sof]
[ghc-hetmet.git] / ghc / lib / std / cbits / getCPUTime.c
1 /* 
2  * (c) The GRASP/AQUA Project, Glasgow University, 1994-1998
3  *
4  * $Id: getCPUTime.c,v 1.4 1999/03/01 09:04:07 sof Exp $
5  *
6  * getCPUTime Runtime Support
7  */
8
9 #ifndef _AIX
10 #define NON_POSIX_SOURCE /*needed for solaris2 only?*/
11 #endif
12
13 /* how is this to work given we have not read platform.h yet? */
14 #ifdef hpux_TARGET_OS
15 #define _INCLUDE_HPUX_SOURCE
16 #endif
17
18 #include "Rts.h"
19
20 #ifdef HAVE_SYS_TYPES_H
21 #include <sys/types.h>
22 #endif
23
24 #ifdef HAVE_UNISTD_H
25 #include <unistd.h>
26 #endif
27
28 #ifndef mingw32_TARGET_OS
29 # ifdef HAVE_SYS_TIMES_H
30 #  include <sys/times.h>
31 # endif
32 #endif
33
34 #ifdef HAVE_SYS_TIME_H
35 #include <sys/time.h>
36 #endif
37
38 #if !defined(mingw32_TARGET_OS) && !defined(irix_TARGET_OS)
39 # if defined(HAVE_SYS_RESOURCE_H)
40 #  include <sys/resource.h>
41 # endif
42 #endif
43
44 #ifdef HAVE_SYS_TIMEB_H
45 #include <sys/timeb.h>
46 #endif
47
48 #ifdef hpux_TARGET_OS
49 #include <sys/syscall.h>
50 #define getrusage(a, b)  syscall(SYS_GETRUSAGE, a, b)
51 #define HAVE_GETRUSAGE
52 #endif
53
54 StgInt 
55 clockTicks ()
56 {
57  return (
58 #if defined(CLK_TCK)
59     CLK_TCK
60 #else
61     sysconf(_SC_CLK_TCK)
62 #endif
63     ); 
64 }
65
66 /* 
67  * Our caller wants a pointer to four StgInts,
68  * user seconds, user nanoseconds, system seconds, system nanoseconds.
69  * Yes, the timerval has unsigned components, but nanoseconds take only
70  * 30 bits, and our CPU usage would have to be over 68 years for the 
71  * seconds to overflow 31 bits.
72  */
73
74 StgByteArray
75 getCPUTime(StgByteArray cpuStruct)
76 {
77     StgInt *cpu=(StgInt *)cpuStruct;
78
79 /* getrusage() is right royal pain to deal with when targetting multiple
80    versions of Solaris, since some versions supply it in libc (2.3 and 2.5),
81    while 2.4 has got it in libucb (I wouldn't be too surprised if it was back
82    again in libucb in 2.6..)
83
84    Avoid the problem by resorting to times() instead.
85 */
86 #if defined(HAVE_GETRUSAGE) && ! irix_TARGET_OS && ! solaris2_TARGET_OS
87     struct rusage t;
88
89     getrusage(RUSAGE_SELF, &t);
90     cpu[0] = t.ru_utime.tv_sec;
91     cpu[1] = 1000 * t.ru_utime.tv_usec;
92     cpu[2] = t.ru_stime.tv_sec;
93     cpu[3] = 1000 * t.ru_stime.tv_usec;
94
95 #else
96 # if defined(HAVE_TIMES)
97     struct tms t;
98 #  if defined(CLK_TCK)
99 #   define ticks CLK_TCK
100 #  else
101     long ticks;
102     ticks = sysconf(_SC_CLK_TCK);
103 #  endif
104
105     times(&t);
106     cpu[0] = t.tms_utime / ticks;
107     cpu[1] = (t.tms_utime - cpu[0] * ticks) * (1000000000 / ticks);
108     cpu[2] = t.tms_stime / ticks;
109     cpu[3] = (t.tms_stime - cpu[2] * ticks) * (1000000000 / ticks);
110
111 # else
112     return NULL;
113 # endif
114 #endif
115     return (StgByteArray) cpuStruct;
116 }