OSDN Git Service

* m4/minloc1.m4: Update copyright year and ajust headers order.
[pf3gnuchains/gcc-fork.git] / libgfortran / intrinsics / cpu_time.c
1 /* Implementation of the CPU_TIME intrinsic.
2    Copyright (C) 2003, 2007 Free Software Foundation, Inc.
3
4 This file is part of the GNU Fortran 95 runtime library (libgfortran).
5
6 Libgfortran is free software; you can redistribute it and/or
7 modify it under the terms of the GNU General Public
8 License as published by the Free Software Foundation; either
9 version 2 of the License, or (at your option) any later version.
10
11 In addition to the permissions in the GNU General Public License, the
12 Free Software Foundation gives you unlimited permission to link the
13 compiled version of this file into combinations with other programs,
14 and to distribute those combinations without any restriction coming
15 from the use of this file.  (The General Public License restrictions
16 do apply in other respects; for example, they cover modification of
17 the file, and distribution when not linked into a combine
18 executable.)
19
20 Libgfortran is distributed in the hope that it will be useful,
21 but WITHOUT ANY WARRANTY; without even the implied warranty of
22 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
23 GNU General Public License for more details.
24
25 You should have received a copy of the GNU General Public
26 License along with libgfortran; see the file COPYING.  If not,
27 write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
28 Boston, MA 02110-1301, USA.  */
29
30 #include "libgfortran.h"
31
32 #ifdef HAVE_UNISTD_H
33 #include <unistd.h>
34 #endif
35
36 /* The CPU_TIME intrinsic to "compare different algorithms on the same
37    computer or discover which parts are the most expensive", so we
38    need a way to get the CPU time with the finest resolution possible.
39    We can only be accurate up to microseconds.
40
41    As usual with UNIX systems, unfortunately no single way is
42    available for all systems.  */
43
44 #ifdef TIME_WITH_SYS_TIME
45 #  include <sys/time.h>
46 #  include <time.h>
47 #else
48 #  if HAVE_SYS_TIME_H
49 #    include <sys/time.h>
50 #  else
51 #    ifdef HAVE_TIME_H
52 #      include <time.h>
53 #    endif
54 #  endif
55 #endif
56
57 /* The most accurate way to get the CPU time is getrusage ().
58    If we have times(), that's good enough, too.  */
59 #if defined (HAVE_GETRUSAGE) && defined (HAVE_SYS_RESOURCE_H)
60 #  include <sys/resource.h>
61 #else
62 /* For times(), we _must_ know the number of clock ticks per second.  */
63 #  if defined (HAVE_TIMES) && (defined (HZ) || defined (_SC_CLK_TCK) || defined (CLK_TCK))
64 #    ifdef HAVE_SYS_PARAM_H
65 #      include <sys/param.h>
66 #    endif
67 #    if defined (HAVE_SYS_TIMES_H)
68 #      include <sys/times.h>
69 #    endif
70 #    ifndef HZ
71 #      if defined _SC_CLK_TCK
72 #        define HZ  sysconf(_SC_CLK_TCK)
73 #      else
74 #        define HZ  CLK_TCK
75 #      endif
76 #    endif
77 #  endif  /* HAVE_TIMES etc.  */
78 #endif  /* HAVE_GETRUSAGE && HAVE_SYS_RESOURCE_H  */
79
80 #if defined (__GNUC__) && (__GNUC__ >= 3)
81 #  define ATTRIBUTE_ALWAYS_INLINE __attribute__ ((__always_inline__))
82 #else
83 #  define ATTRIBUTE_ALWAYS_INLINE
84 #endif
85
86 static inline void __cpu_time_1 (long *, long *) ATTRIBUTE_ALWAYS_INLINE;
87
88 /* Helper function for the actual implementation of the CPU_TIME
89    intrinsic.  Returns a CPU time in microseconds or -1 if no CPU time
90    could be computed.  */
91
92 #ifdef __MINGW32__
93
94 #define WIN32_LEAN_AND_MEAN
95 #include <windows.h>
96
97 static void
98 __cpu_time_1 (long *sec, long *usec)
99 {
100   union {
101     FILETIME ft;
102     unsigned long long ulltime;
103   } kernel_time,  user_time;
104
105   FILETIME unused1, unused2;
106   unsigned long long total_time;
107
108   /* No support for Win9x.  The high order bit of the DWORD
109      returned by GetVersion is 0 for NT and higher. */
110   if (GetVersion () >= 0x80000000)
111     {
112       *sec = -1;
113       *usec = 0;
114       return;
115     }
116
117   /* The FILETIME structs filled in by GetProcessTimes represent
118      time in 100 nanosecond units. */
119   GetProcessTimes (GetCurrentProcess (), &unused1, &unused2,
120                    &kernel_time.ft, &user_time.ft);
121       
122   total_time = (kernel_time.ulltime + user_time.ulltime)/10; 
123   *sec = total_time / 1000000;
124   *usec = total_time % 1000000;
125 }
126
127 #else
128
129 static inline void
130 __cpu_time_1 (long *sec, long *usec)
131 {
132 #if defined (HAVE_GETRUSAGE) && defined (HAVE_SYS_RESOURCE_H)
133   struct rusage usage;
134   getrusage (0, &usage);
135   *sec = usage.ru_utime.tv_sec + usage.ru_stime.tv_sec;
136   *usec = usage.ru_utime.tv_usec + usage.ru_stime.tv_usec;
137 #else /* ! HAVE_GETRUSAGE || ! HAVE_SYS_RESOURCE_H  */
138 #ifdef HAVE_TIMES
139   struct tms buf;
140   times (&buf);
141   *sec = 0;
142   *usec = (buf.tms_utime + buf.tms_stime) * (1000000 / HZ);
143 #else /* ! HAVE_TIMES */
144   /* We have nothing to go on.  Return -1.  */
145   *sec = -1;
146   *usec = 0;
147 #endif  /* HAVE_TIMES */
148 #endif  /* HAVE_GETRUSAGE */
149 }
150
151 #endif
152
153 extern void cpu_time_4 (GFC_REAL_4 *);
154 iexport_proto(cpu_time_4);
155
156 void cpu_time_4 (GFC_REAL_4 *time)
157 {
158   long sec, usec;
159   __cpu_time_1 (&sec, &usec);
160   *time = sec + usec * (GFC_REAL_4)1.e-6;
161 }
162 iexport(cpu_time_4);
163
164 extern void cpu_time_8 (GFC_REAL_8 *);
165 export_proto(cpu_time_8);
166
167 void cpu_time_8 (GFC_REAL_8 *time)
168 {
169   long sec, usec;
170   __cpu_time_1 (&sec, &usec);
171   *time = sec + usec * (GFC_REAL_8)1.e-6;
172 }
173
174 #ifdef HAVE_GFC_REAL_10
175 extern void cpu_time_10 (GFC_REAL_10 *);
176 export_proto(cpu_time_10);
177
178 void cpu_time_10 (GFC_REAL_10 *time)
179 {
180   long sec, usec;
181   __cpu_time_1 (&sec, &usec);
182   *time = sec + usec * (GFC_REAL_10)1.e-6;
183 }
184 #endif
185
186 #ifdef HAVE_GFC_REAL_16
187 extern void cpu_time_16 (GFC_REAL_16 *);
188 export_proto(cpu_time_16);
189
190 void cpu_time_16 (GFC_REAL_16 *time)
191 {
192   long sec, usec;
193   __cpu_time_1 (&sec, &usec);
194   *time = sec + usec * (GFC_REAL_16)1.e-6;
195 }
196 #endif
197
198 extern void second_sub (GFC_REAL_4 *);
199 export_proto(second_sub);
200
201 void
202 second_sub (GFC_REAL_4 *s)
203 {
204   cpu_time_4 (s);
205 }
206
207 extern GFC_REAL_4 second (void);
208 export_proto(second);
209
210 GFC_REAL_4
211 second (void)
212 {
213   GFC_REAL_4 s;
214   cpu_time_4 (&s);
215   return s;
216 }