111
|
1 /* Wrappers for platform timing functions.
|
145
|
2 Copyright (C) 2003-2020 Free Software Foundation, Inc.
|
111
|
3
|
|
4 This file is part of the GNU Fortran 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 3 of the License, or (at your option) any later version.
|
|
10
|
|
11 Libgfortran is distributed in the hope that it will be useful,
|
|
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
14 GNU General Public License for more details.
|
|
15
|
|
16 Under Section 7 of GPL version 3, you are granted additional
|
|
17 permissions described in the GCC Runtime Library Exception, version
|
|
18 3.1, as published by the Free Software Foundation.
|
|
19
|
|
20 You should have received a copy of the GNU General Public License and
|
|
21 a copy of the GCC Runtime Library Exception along with this program;
|
|
22 see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
|
|
23 <http://www.gnu.org/licenses/>. */
|
|
24
|
|
25 #ifndef LIBGFORTRAN_TIME_H
|
|
26 #define LIBGFORTRAN_TIME_H
|
|
27
|
|
28 #ifdef HAVE_UNISTD_H
|
|
29 #include <unistd.h>
|
|
30 #endif
|
|
31
|
|
32 #include <errno.h>
|
|
33
|
|
34 /* The time related intrinsics (DTIME, ETIME, CPU_TIME) to "compare
|
|
35 different algorithms on the same computer or discover which parts
|
|
36 are the most expensive", need a way to get the CPU time with the
|
|
37 finest resolution possible. We can only be accurate up to
|
|
38 microseconds.
|
|
39
|
|
40 As usual with UNIX systems, unfortunately no single way is
|
|
41 available for all systems. */
|
|
42
|
|
43 #ifdef HAVE_SYS_TIME_H
|
|
44 #include <sys/time.h>
|
|
45 #endif
|
|
46
|
|
47 #include <time.h>
|
|
48
|
|
49 #ifdef HAVE_SYS_TYPES_H
|
|
50 #include <sys/types.h>
|
|
51 #endif
|
|
52
|
|
53 /* The most accurate way to get the CPU time is getrusage (). */
|
|
54 #if defined (HAVE_GETRUSAGE) && defined (HAVE_SYS_RESOURCE_H)
|
|
55 # include <sys/resource.h>
|
|
56 #endif /* HAVE_GETRUSAGE && HAVE_SYS_RESOURCE_H */
|
|
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 /* For times(), we _must_ know the number of clock ticks per second. */
|
|
62 # if defined (HAVE_TIMES) && (defined (HZ) || defined (_SC_CLK_TCK) || defined (CLK_TCK))
|
|
63 # ifdef HAVE_SYS_PARAM_H
|
|
64 # include <sys/param.h>
|
|
65 # endif
|
|
66 # if defined (HAVE_SYS_TIMES_H)
|
|
67 # include <sys/times.h>
|
|
68 # endif
|
|
69 # ifndef HZ
|
|
70 # if defined _SC_CLK_TCK
|
|
71 # define HZ sysconf(_SC_CLK_TCK)
|
|
72 # else
|
|
73 # define HZ CLK_TCK
|
|
74 # endif
|
|
75 # endif
|
|
76 # endif /* HAVE_TIMES etc. */
|
|
77 #endif /* !HAVE_GETRUSAGE || !HAVE_SYS_RESOURCE_H */
|
|
78
|
|
79
|
|
80 /* If the re-entrant version of localtime is not available, provide a
|
|
81 fallback implementation. On some targets where the _r version is
|
|
82 not available, localtime uses thread-local storage so it's
|
|
83 threadsafe. */
|
|
84
|
|
85 #ifndef HAVE_LOCALTIME_R
|
|
86 /* If _POSIX is defined localtime_r gets defined by mingw-w64 headers. */
|
|
87 #ifdef localtime_r
|
|
88 #undef localtime_r
|
|
89 #endif
|
|
90
|
|
91 static inline struct tm *
|
|
92 localtime_r (const time_t * timep, struct tm * result)
|
|
93 {
|
|
94 *result = *localtime (timep);
|
|
95 return result;
|
|
96 }
|
|
97 #endif
|
|
98
|
|
99
|
|
100 /* Helper function for the actual implementation of the DTIME, ETIME and
|
|
101 CPU_TIME intrinsics. Returns 0 for success or -1 if no
|
|
102 CPU time could be computed. */
|
|
103
|
|
104 #if defined(__MINGW32__)
|
|
105
|
|
106 #define WIN32_LEAN_AND_MEAN
|
|
107 #include <windows.h>
|
|
108
|
|
109 static inline int
|
|
110 gf_cputime (long *user_sec, long *user_usec, long *system_sec, long *system_usec)
|
|
111 {
|
|
112 union {
|
|
113 FILETIME ft;
|
|
114 unsigned long long ulltime;
|
|
115 } kernel_time, user_time;
|
|
116
|
|
117 FILETIME unused1, unused2;
|
|
118
|
|
119 /* No support for Win9x. The high order bit of the DWORD
|
|
120 returned by GetVersion is 0 for NT and higher. */
|
|
121 if (GetVersion () >= 0x80000000)
|
|
122 {
|
|
123 *user_sec = *system_sec = 0;
|
|
124 *user_usec = *system_usec = 0;
|
|
125 return -1;
|
|
126 }
|
|
127
|
|
128 /* The FILETIME structs filled in by GetProcessTimes represent
|
|
129 time in 100 nanosecond units. */
|
|
130 GetProcessTimes (GetCurrentProcess (), &unused1, &unused2,
|
|
131 &kernel_time.ft, &user_time.ft);
|
|
132
|
|
133 *user_sec = user_time.ulltime / 10000000;
|
|
134 *user_usec = (user_time.ulltime % 10000000) / 10;
|
|
135
|
|
136 *system_sec = kernel_time.ulltime / 10000000;
|
|
137 *system_usec = (kernel_time.ulltime % 10000000) / 10;
|
|
138 return 0;
|
|
139 }
|
|
140
|
|
141 #else
|
|
142
|
|
143 static inline int
|
|
144 gf_cputime (long *user_sec, long *user_usec, long *system_sec, long *system_usec)
|
|
145 {
|
|
146 #if defined (HAVE_GETRUSAGE) && defined (HAVE_SYS_RESOURCE_H)
|
|
147 struct rusage usage;
|
|
148 int err;
|
|
149 err = getrusage (RUSAGE_SELF, &usage);
|
|
150
|
|
151 *user_sec = usage.ru_utime.tv_sec;
|
|
152 *user_usec = usage.ru_utime.tv_usec;
|
|
153 *system_sec = usage.ru_stime.tv_sec;
|
|
154 *system_usec = usage.ru_stime.tv_usec;
|
|
155 return err;
|
|
156
|
|
157 #elif defined HAVE_TIMES
|
|
158 struct tms buf;
|
|
159 clock_t err;
|
|
160 err = times (&buf);
|
|
161 long hz = HZ;
|
|
162 *user_sec = buf.tms_utime / hz;
|
|
163 *user_usec = (buf.tms_utime % hz) * (1000000. / hz);
|
|
164 *system_sec = buf.tms_stime / hz;
|
|
165 *system_usec = (buf.tms_stime % hz) * (1000000. / hz);
|
|
166 if ((err == (clock_t) -1) && errno != 0)
|
|
167 return -1;
|
|
168 return 0;
|
|
169
|
|
170 #elif defined(HAVE_CLOCK_GETTIME) && (defined(CLOCK_PROCESS_CPUTIME_ID) \
|
|
171 || defined(CLOCK_THREAD_CPUTIME_ID))
|
|
172 /* Newer versions of VxWorks have CLOCK_THREAD_CPUTIME_ID giving
|
|
173 per-thread CPU time. CLOCK_PROCESS_CPUTIME_ID would be better
|
|
174 but is not available. */
|
|
175 #ifndef CLOCK_PROCESS_CPUTIME_ID
|
|
176 #define CLOCK_PROCESS_CPUTIME_ID CLOCK_THREAD_CPUTIME_ID
|
|
177 #endif
|
|
178 struct timespec ts;
|
|
179 int err = clock_gettime (CLOCK_PROCESS_CPUTIME_ID, &ts);
|
|
180 *user_sec = ts.tv_sec;
|
|
181 *user_usec = ts.tv_nsec / 1000;
|
|
182 *system_sec = *system_usec = 0;
|
|
183 return err;
|
|
184
|
|
185 #else
|
|
186 clock_t c = clock ();
|
|
187 *user_sec = c / CLOCKS_PER_SEC;
|
|
188 *user_usec = (c % CLOCKS_PER_SEC) * (1000000. / CLOCKS_PER_SEC);
|
|
189 *system_sec = *system_usec = 0;
|
|
190 if (c == (clock_t) -1)
|
|
191 return -1;
|
|
192 return 0;
|
|
193
|
|
194 #endif
|
|
195 }
|
|
196
|
|
197 #endif
|
|
198
|
|
199
|
|
200 /* Realtime clock with microsecond resolution, falling back to other
|
|
201 functions if the target does not support gettimeofday().
|
|
202
|
|
203 Arguments:
|
|
204 secs - OUTPUT, seconds
|
|
205 usecs - OUTPUT, microseconds
|
|
206
|
|
207 The OUTPUT arguments shall represent the number of seconds and
|
|
208 microseconds since the Epoch.
|
|
209
|
|
210 Return value: 0 for success, -1 for error. In case of error, errno
|
|
211 is set.
|
|
212 */
|
|
213 static inline int
|
|
214 gf_gettime (time_t * secs, long * usecs)
|
|
215 {
|
|
216 #ifdef HAVE_GETTIMEOFDAY
|
|
217 struct timeval tv;
|
|
218 int err;
|
|
219 err = gettimeofday (&tv, NULL);
|
|
220 *secs = tv.tv_sec;
|
|
221 *usecs = tv.tv_usec;
|
|
222 return err;
|
|
223 #elif defined(HAVE_CLOCK_GETTIME)
|
|
224 struct timespec ts;
|
|
225 int err = clock_gettime (CLOCK_REALTIME, &ts);
|
|
226 *secs = ts.tv_sec;
|
|
227 *usecs = ts.tv_nsec / 1000;
|
|
228 return err;
|
|
229 #else
|
|
230 time_t t = time (NULL);
|
|
231 *secs = t;
|
|
232 *usecs = 0;
|
|
233 if (t == ((time_t)-1))
|
|
234 return -1;
|
|
235 return 0;
|
|
236 #endif
|
|
237 }
|
|
238
|
|
239
|
|
240 #endif /* LIBGFORTRAN_TIME_H */
|