2 * (c) The GRASP/AQUA Project, Glasgow University, 1994-1998
4 * $Id: getCPUTime.c,v 1.5 1999/05/03 13:22:29 sof Exp $
6 * getCPUTime Runtime Support
10 #define NON_POSIX_SOURCE /*needed for solaris2 only?*/
13 /* how is this to work given we have not read platform.h yet? */
15 #define _INCLUDE_HPUX_SOURCE
20 #ifdef HAVE_SYS_TYPES_H
21 #include <sys/types.h>
28 #ifndef mingw32_TARGET_OS
29 # ifdef HAVE_SYS_TIMES_H
30 # include <sys/times.h>
34 #ifdef HAVE_SYS_TIME_H
38 #if !defined(mingw32_TARGET_OS) && !defined(irix_TARGET_OS)
39 # if defined(HAVE_SYS_RESOURCE_H)
40 # include <sys/resource.h>
44 #ifdef HAVE_SYS_TIMEB_H
45 #include <sys/timeb.h>
49 #include <sys/syscall.h>
50 #define getrusage(a, b) syscall(SYS_GETRUSAGE, a, b)
51 #define HAVE_GETRUSAGE
71 * Our caller wants a pointer to four StgInts,
72 * user seconds, user nanoseconds, system seconds, system nanoseconds.
73 * Yes, the timerval has unsigned components, but nanoseconds take only
74 * 30 bits, and our CPU usage would have to be over 68 years for the
75 * seconds to overflow 31 bits.
80 getCPUTime(StgByteArray cpuStruct)
82 StgInt *cpu=(StgInt *)cpuStruct;
84 /* getrusage() is right royal pain to deal with when targetting multiple
85 versions of Solaris, since some versions supply it in libc (2.3 and 2.5),
86 while 2.4 has got it in libucb (I wouldn't be too surprised if it was back
87 again in libucb in 2.6..)
89 Avoid the problem by resorting to times() instead.
91 #if defined(HAVE_GETRUSAGE) && ! irix_TARGET_OS && ! solaris2_TARGET_OS
94 getrusage(RUSAGE_SELF, &t);
95 cpu[0] = t.ru_utime.tv_sec;
96 cpu[1] = 1000 * t.ru_utime.tv_usec;
97 cpu[2] = t.ru_stime.tv_sec;
98 cpu[3] = 1000 * t.ru_stime.tv_usec;
101 # if defined(HAVE_TIMES)
103 # if defined(CLK_TCK)
104 # define ticks CLK_TCK
107 ticks = sysconf(_SC_CLK_TCK);
111 cpu[0] = t.tms_utime / ticks;
112 cpu[1] = (t.tms_utime - cpu[0] * ticks) * (1000000000 / ticks);
113 cpu[2] = t.tms_stime / ticks;
114 cpu[3] = (t.tms_stime - cpu[2] * ticks) * (1000000000 / ticks);
120 return (StgByteArray) cpuStruct;
126 /* 100ns units per sec, really */
127 #define NS_PER_SEC 10000000LL
128 #define FT2usecs(ll,ft) \
129 (ll)=(ft).dwHighDateTime; \
131 (ll) |= (ft).dwLowDateTime;
135 /* cygwin32 or mingw32 version */
137 getCPUTime(StgByteArray cpuStruct)
139 FILETIME creationTime, exitTime, kernelTime, userTime;
140 StgInt *cpu=(StgInt *)cpuStruct;
141 unsigned long long uT, kT;
143 /* ToDo: pin down elapsed times to just the OS thread(s) that
144 are evaluating/managing Haskell code.
146 if (!GetProcessTimes (GetCurrentProcess(), &creationTime,
147 &exitTime, &kernelTime, &userTime)) {
148 /* Probably on a Win95 box..*/
153 return (StgByteArray)cpu;
156 FT2usecs(uT, userTime);
157 FT2usecs(kT, kernelTime);
159 cpu[0] = (unsigned int)(uT / NS_PER_SEC);
160 cpu[1] = (unsigned int)(uT * 100);
161 cpu[0] = (unsigned int)(kT / NS_PER_SEC);
162 cpu[1] = (unsigned int)(kT * 100);
163 return (StgByteArray)cpu;