OSDN Git Service

* intrinsics/cpu_time.c: Don't include headers already included
[pf3gnuchains/gcc-fork.git] / libgfortran / intrinsics / cpu_time.c
1 /* Implementation of the CPU_TIME intrinsic.
2    Copyright (C) 2003 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 "config.h"
31 #include "libgfortran.h"
32
33 #ifdef HAVE_UNISTD_H
34 #include <unistd.h>
35 #endif
36
37 /* The CPU_TIME intrinsic to "compare different algorithms on the same
38    computer or discover which parts are the most expensive", so we
39    need a way to get the CPU time with the finest resolution possible.
40    We can only be accurate up to microseconds.
41
42    As usual with UNIX systems, unfortunately no single way is
43    available for all systems.  */
44
45 #ifdef TIME_WITH_SYS_TIME
46 #  include <sys/time.h>
47 #  include <time.h>
48 #else
49 #  if HAVE_SYS_TIME_H
50 #    include <sys/time.h>
51 #  else
52 #    ifdef HAVE_TIME_H
53 #      include <time.h>
54 #    endif
55 #  endif
56 #endif
57
58 /* The most accurate way to get the CPU time is getrusage ().
59    If we have times(), that's good enough, too.  */
60 #if defined (HAVE_GETRUSAGE) && defined (HAVE_SYS_RESOURCE_H)
61 #  include <sys/resource.h>
62 #else
63 /* For times(), we _must_ know the number of clock ticks per second.  */
64 #  if defined (HAVE_TIMES) && (defined (HZ) || defined (_SC_CLK_TCK) || defined (CLK_TCK))
65 #    ifdef HAVE_SYS_PARAM_H
66 #      include <sys/param.h>
67 #    endif
68 #    if defined (HAVE_SYS_TIMES_H)
69 #      include <sys/times.h>
70 #    endif
71 #    ifndef HZ
72 #      if defined _SC_CLK_TCK
73 #        define HZ  sysconf(_SC_CLK_TCK)
74 #      else
75 #        define HZ  CLK_TCK
76 #      endif
77 #    endif
78 #  endif  /* HAVE_TIMES etc.  */
79 #endif  /* HAVE_GETRUSAGE && HAVE_SYS_RESOURCE_H  */
80
81 #if defined (__GNUC__) && (__GNUC__ >= 3)
82 #  define ATTRIBUTE_ALWAYS_INLINE __attribute__ ((__always_inline__))
83 #else
84 #  define ATTRIBUTE_ALWAYS_INLINE
85 #endif
86
87 static inline void __cpu_time_1 (long *, long *) ATTRIBUTE_ALWAYS_INLINE;
88
89 /* Helper function for the actual implementation of the CPU_TIME
90    intrinsic.  Returns a CPU time in microseconds or -1 if no CPU time
91    could be computed.  */
92
93 #ifdef __MINGW32__
94
95 #define WIN32_LEAN_AND_MEAN
96 #include <windows.h>
97
98 static void
99 __cpu_time_1 (long *sec, long *usec)
100 {
101   union {
102     FILETIME ft;
103     unsigned long long ulltime;
104   } kernel_time,  user_time;
105
106   FILETIME unused1, unused2;
107   unsigned long long total_time;
108
109   /* No support for Win9x.  The high order bit of the DWORD
110      returned by GetVersion is 0 for NT and higher. */
111   if (GetVersion () >= 0x80000000)
112     {
113       *sec = -1;
114       *usec = 0;
115       return;
116     }
117
118   /* The FILETIME structs filled in by GetProcessTimes represent
119      time in 100 nanosecond units. */
120   GetProcessTimes (GetCurrentProcess (), &unused1, &unused2,
121                    &kernel_time.ft, &user_time.ft);
122       
123   total_time = (kernel_time.ulltime + user_time.ulltime)/10; 
124   *sec = total_time / 1000000;
125   *usec = total_time % 1000000;
126 }
127
128 #else
129
130 static inline void
131 __cpu_time_1 (long *sec, long *usec)
132 {
133 #if defined (HAVE_GETRUSAGE) && defined (HAVE_SYS_RESOURCE_H)
134   struct rusage usage;
135   getrusage (0, &usage);
136   *sec = usage.ru_utime.tv_sec + usage.ru_stime.tv_sec;
137   *usec = usage.ru_utime.tv_usec + usage.ru_stime.tv_usec;
138 #else /* ! HAVE_GETRUSAGE || ! HAVE_SYS_RESOURCE_H  */
139 #ifdef HAVE_TIMES
140   struct tms buf;
141   times (&buf);
142   *sec = 0;
143   *usec = (buf.tms_utime + buf.tms_stime) * (1000000 / HZ);
144 #else /* ! HAVE_TIMES */
145   /* We have nothing to go on.  Return -1.  */
146   *sec = -1;
147   *usec = 0;
148 #endif  /* HAVE_TIMES */
149 #endif  /* HAVE_GETRUSAGE */
150 }
151
152 #endif
153
154 extern void cpu_time_4 (GFC_REAL_4 *);
155 iexport_proto(cpu_time_4);
156
157 void cpu_time_4 (GFC_REAL_4 *time)
158 {
159   long sec, usec;
160   __cpu_time_1 (&sec, &usec);
161   *time = sec + usec * (GFC_REAL_4)1.e-6;
162 }
163 iexport(cpu_time_4);
164
165 extern void cpu_time_8 (GFC_REAL_8 *);
166 export_proto(cpu_time_8);
167
168 void cpu_time_8 (GFC_REAL_8 *time)
169 {
170   long sec, usec;
171   __cpu_time_1 (&sec, &usec);
172   *time = sec + usec * (GFC_REAL_8)1.e-6;
173 }
174
175 #ifdef HAVE_GFC_REAL_10
176 extern void cpu_time_10 (GFC_REAL_10 *);
177 export_proto(cpu_time_10);
178
179 void cpu_time_10 (GFC_REAL_10 *time)
180 {
181   long sec, usec;
182   __cpu_time_1 (&sec, &usec);
183   *time = sec + usec * (GFC_REAL_10)1.e-6;
184 }
185 #endif
186
187 #ifdef HAVE_GFC_REAL_16
188 extern void cpu_time_16 (GFC_REAL_16 *);
189 export_proto(cpu_time_16);
190
191 void cpu_time_16 (GFC_REAL_16 *time)
192 {
193   long sec, usec;
194   __cpu_time_1 (&sec, &usec);
195   *time = sec + usec * (GFC_REAL_16)1.e-6;
196 }
197 #endif
198
199 extern void second_sub (GFC_REAL_4 *);
200 export_proto(second_sub);
201
202 void
203 second_sub (GFC_REAL_4 *s)
204 {
205   cpu_time_4 (s);
206 }
207
208 extern GFC_REAL_4 second (void);
209 export_proto(second);
210
211 GFC_REAL_4
212 second (void)
213 {
214   GFC_REAL_4 s;
215   cpu_time_4 (&s);
216   return s;
217 }