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