]>
Commit | Line | Data |
---|---|---|
b6e7a3d1 | 1 | /* Wrappers for platform timing functions. |
e3c063ce | 2 | Copyright (C) 2003-2013 Free Software Foundation, Inc. |
a1ba31ce | 3 | |
b6e7a3d1 | 4 | This file is part of the GNU Fortran runtime library (libgfortran). |
a1ba31ce DF |
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 | |
748086b7 | 9 | version 3 of the License, or (at your option) any later version. |
a1ba31ce DF |
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 | ||
748086b7 JJ |
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/>. */ | |
a1ba31ce DF |
24 | |
25 | #ifndef LIBGFORTRAN_TIME_H | |
26 | #define LIBGFORTRAN_TIME_H | |
27 | ||
28 | #ifdef HAVE_UNISTD_H | |
29 | #include <unistd.h> | |
30 | #endif | |
31 | ||
3eaa6afc JB |
32 | #include <errno.h> |
33 | ||
a1ba31ce DF |
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 | ||
74544378 JB |
43 | #ifdef HAVE_SYS_TIME_H |
44 | #include <sys/time.h> | |
a1ba31ce DF |
45 | #endif |
46 | ||
74544378 JB |
47 | #include <time.h> |
48 | ||
4551438c SK |
49 | #ifdef HAVE_SYS_TYPES_H |
50 | #include <sys/types.h> | |
51 | #endif | |
52 | ||
a1ba31ce DF |
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 | ||
b6e7a3d1 JB |
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 | ||
8f17e00c JB |
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 | ||
a1ba31ce | 100 | /* Helper function for the actual implementation of the DTIME, ETIME and |
b6e7a3d1 | 101 | CPU_TIME intrinsics. Returns 0 for success or -1 if no |
a1ba31ce DF |
102 | CPU time could be computed. */ |
103 | ||
104 | #ifdef __MINGW32__ | |
105 | ||
106 | #define WIN32_LEAN_AND_MEAN | |
107 | #include <windows.h> | |
108 | ||
992b0aa1 | 109 | static inline int |
b6e7a3d1 | 110 | gf_cputime (long *user_sec, long *user_usec, long *system_sec, long *system_usec) |
a1ba31ce DF |
111 | { |
112 | union { | |
113 | FILETIME ft; | |
114 | unsigned long long ulltime; | |
115 | } kernel_time, user_time; | |
116 | ||
117 | FILETIME unused1, unused2; | |
a1ba31ce DF |
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; | |
9bd97567 | 134 | *user_usec = (user_time.ulltime % 10000000) / 10; |
a1ba31ce DF |
135 | |
136 | *system_sec = kernel_time.ulltime / 10000000; | |
9bd97567 | 137 | *system_usec = (kernel_time.ulltime % 10000000) / 10; |
a1ba31ce DF |
138 | return 0; |
139 | } | |
140 | ||
141 | #else | |
142 | ||
143 | static inline int | |
b6e7a3d1 | 144 | gf_cputime (long *user_sec, long *user_usec, long *system_sec, long *system_usec) |
a1ba31ce DF |
145 | { |
146 | #if defined (HAVE_GETRUSAGE) && defined (HAVE_SYS_RESOURCE_H) | |
147 | struct rusage usage; | |
b6e7a3d1 JB |
148 | int err; |
149 | err = getrusage (RUSAGE_SELF, &usage); | |
a1ba31ce DF |
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; | |
b6e7a3d1 JB |
155 | return err; |
156 | ||
157 | #elif defined HAVE_TIMES | |
158 | struct tms buf; | |
159 | clock_t err; | |
160 | err = times (&buf); | |
1ca8bef0 JB |
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); | |
b6e7a3d1 JB |
166 | if ((err == (clock_t) -1) && errno != 0) |
167 | return -1; | |
a1ba31ce DF |
168 | return 0; |
169 | ||
44813fe0 JB |
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; | |
1e5c1001 | 181 | *user_usec = ts.tv_nsec / 1000; |
44813fe0 JB |
182 | *system_sec = *system_usec = 0; |
183 | return err; | |
184 | ||
b6e7a3d1 | 185 | #else |
74544378 JB |
186 | clock_t c = clock (); |
187 | *user_sec = c / CLOCKS_PER_SEC; | |
1ca8bef0 | 188 | *user_usec = (c % CLOCKS_PER_SEC) * (1000000. / CLOCKS_PER_SEC); |
74544378 JB |
189 | *system_sec = *system_usec = 0; |
190 | if (c == (clock_t) -1) | |
191 | return -1; | |
192 | return 0; | |
a1ba31ce DF |
193 | |
194 | #endif | |
195 | } | |
196 | ||
197 | #endif | |
198 | ||
199 | ||
c5a6cbd4 JB |
200 | /* Realtime clock with microsecond resolution, falling back to other |
201 | functions if the target does not support gettimeofday(). | |
aa837470 | 202 | |
02b17751 | 203 | Arguments: |
b6e7a3d1 | 204 | secs - OUTPUT, seconds |
02b17751 | 205 | usecs - OUTPUT, microseconds |
b6e7a3d1 | 206 | |
02b17751 | 207 | The OUTPUT arguments shall represent the number of seconds and |
1ca8bef0 | 208 | microseconds since the Epoch. |
b6e7a3d1 JB |
209 | |
210 | Return value: 0 for success, -1 for error. In case of error, errno | |
211 | is set. | |
212 | */ | |
213 | static inline int | |
02b17751 | 214 | gf_gettime (time_t * secs, long * usecs) |
b6e7a3d1 | 215 | { |
aa837470 | 216 | #ifdef HAVE_GETTIMEOFDAY |
b6e7a3d1 JB |
217 | struct timeval tv; |
218 | int err; | |
219 | err = gettimeofday (&tv, NULL); | |
220 | *secs = tv.tv_sec; | |
02b17751 | 221 | *usecs = tv.tv_usec; |
b6e7a3d1 | 222 | return err; |
c5a6cbd4 JB |
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; | |
74544378 | 229 | #else |
9f13f697 JB |
230 | time_t t = time (NULL); |
231 | *secs = t; | |
02b17751 | 232 | *usecs = 0; |
b6e7a3d1 JB |
233 | if (t == ((time_t)-1)) |
234 | return -1; | |
235 | return 0; | |
b6e7a3d1 JB |
236 | #endif |
237 | } | |
238 | ||
239 | ||
a1ba31ce | 240 | #endif /* LIBGFORTRAN_TIME_H */ |