123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241 |
- /* Wrappers for platform timing functions.
- Copyright (C) 2003-2015 Free Software Foundation, Inc.
- This file is part of the GNU Fortran runtime library (libgfortran).
- Libgfortran is free software; you can redistribute it and/or
- modify it under the terms of the GNU General Public
- License as published by the Free Software Foundation; either
- version 3 of the License, or (at your option) any later version.
- Libgfortran is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
- Under Section 7 of GPL version 3, you are granted additional
- permissions described in the GCC Runtime Library Exception, version
- 3.1, as published by the Free Software Foundation.
- You should have received a copy of the GNU General Public License and
- a copy of the GCC Runtime Library Exception along with this program;
- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
- <http://www.gnu.org/licenses/>. */
- #ifndef LIBGFORTRAN_TIME_H
- #define LIBGFORTRAN_TIME_H
- #ifdef HAVE_UNISTD_H
- #include <unistd.h>
- #endif
- #include <errno.h>
- /* The time related intrinsics (DTIME, ETIME, CPU_TIME) to "compare
- different algorithms on the same computer or discover which parts
- are the most expensive", need a way to get the CPU time with the
- finest resolution possible. We can only be accurate up to
- microseconds.
- As usual with UNIX systems, unfortunately no single way is
- available for all systems. */
- #ifdef HAVE_SYS_TIME_H
- #include <sys/time.h>
- #endif
- #include <time.h>
- #ifdef HAVE_SYS_TYPES_H
- #include <sys/types.h>
- #endif
- /* The most accurate way to get the CPU time is getrusage (). */
- #if defined (HAVE_GETRUSAGE) && defined (HAVE_SYS_RESOURCE_H)
- # include <sys/resource.h>
- #endif /* HAVE_GETRUSAGE && HAVE_SYS_RESOURCE_H */
- /* The most accurate way to get the CPU time is getrusage ().
- If we have times(), that's good enough, too. */
- #if !defined (HAVE_GETRUSAGE) || !defined (HAVE_SYS_RESOURCE_H)
- /* For times(), we _must_ know the number of clock ticks per second. */
- # if defined (HAVE_TIMES) && (defined (HZ) || defined (_SC_CLK_TCK) || defined (CLK_TCK))
- # ifdef HAVE_SYS_PARAM_H
- # include <sys/param.h>
- # endif
- # if defined (HAVE_SYS_TIMES_H)
- # include <sys/times.h>
- # endif
- # ifndef HZ
- # if defined _SC_CLK_TCK
- # define HZ sysconf(_SC_CLK_TCK)
- # else
- # define HZ CLK_TCK
- # endif
- # endif
- # endif /* HAVE_TIMES etc. */
- #endif /* !HAVE_GETRUSAGE || !HAVE_SYS_RESOURCE_H */
- /* If the re-entrant version of localtime is not available, provide a
- fallback implementation. On some targets where the _r version is
- not available, localtime uses thread-local storage so it's
- threadsafe. */
- #ifndef HAVE_LOCALTIME_R
- /* If _POSIX is defined localtime_r gets defined by mingw-w64 headers. */
- #ifdef localtime_r
- #undef localtime_r
- #endif
- static inline struct tm *
- localtime_r (const time_t * timep, struct tm * result)
- {
- *result = *localtime (timep);
- return result;
- }
- #endif
- /* Helper function for the actual implementation of the DTIME, ETIME and
- CPU_TIME intrinsics. Returns 0 for success or -1 if no
- CPU time could be computed. */
- #if defined(__MINGW32__) || defined(__CYGWIN__)
- #define WIN32_LEAN_AND_MEAN
- #include <windows.h>
- static inline int
- gf_cputime (long *user_sec, long *user_usec, long *system_sec, long *system_usec)
- {
- union {
- FILETIME ft;
- unsigned long long ulltime;
- } kernel_time, user_time;
- FILETIME unused1, unused2;
- /* No support for Win9x. The high order bit of the DWORD
- returned by GetVersion is 0 for NT and higher. */
- if (GetVersion () >= 0x80000000)
- {
- *user_sec = *system_sec = 0;
- *user_usec = *system_usec = 0;
- return -1;
- }
- /* The FILETIME structs filled in by GetProcessTimes represent
- time in 100 nanosecond units. */
- GetProcessTimes (GetCurrentProcess (), &unused1, &unused2,
- &kernel_time.ft, &user_time.ft);
- *user_sec = user_time.ulltime / 10000000;
- *user_usec = (user_time.ulltime % 10000000) / 10;
- *system_sec = kernel_time.ulltime / 10000000;
- *system_usec = (kernel_time.ulltime % 10000000) / 10;
- return 0;
- }
- #else
- static inline int
- gf_cputime (long *user_sec, long *user_usec, long *system_sec, long *system_usec)
- {
- #if defined (HAVE_GETRUSAGE) && defined (HAVE_SYS_RESOURCE_H)
- struct rusage usage;
- int err;
- err = getrusage (RUSAGE_SELF, &usage);
- *user_sec = usage.ru_utime.tv_sec;
- *user_usec = usage.ru_utime.tv_usec;
- *system_sec = usage.ru_stime.tv_sec;
- *system_usec = usage.ru_stime.tv_usec;
- return err;
- #elif defined HAVE_TIMES
- struct tms buf;
- clock_t err;
- err = times (&buf);
- long hz = HZ;
- *user_sec = buf.tms_utime / hz;
- *user_usec = (buf.tms_utime % hz) * (1000000. / hz);
- *system_sec = buf.tms_stime / hz;
- *system_usec = (buf.tms_stime % hz) * (1000000. / hz);
- if ((err == (clock_t) -1) && errno != 0)
- return -1;
- return 0;
- #elif defined(HAVE_CLOCK_GETTIME) && (defined(CLOCK_PROCESS_CPUTIME_ID) \
- || defined(CLOCK_THREAD_CPUTIME_ID))
- /* Newer versions of VxWorks have CLOCK_THREAD_CPUTIME_ID giving
- per-thread CPU time. CLOCK_PROCESS_CPUTIME_ID would be better
- but is not available. */
- #ifndef CLOCK_PROCESS_CPUTIME_ID
- #define CLOCK_PROCESS_CPUTIME_ID CLOCK_THREAD_CPUTIME_ID
- #endif
- struct timespec ts;
- int err = clock_gettime (CLOCK_PROCESS_CPUTIME_ID, &ts);
- *user_sec = ts.tv_sec;
- *user_usec = ts.tv_nsec / 1000;
- *system_sec = *system_usec = 0;
- return err;
- #else
- clock_t c = clock ();
- *user_sec = c / CLOCKS_PER_SEC;
- *user_usec = (c % CLOCKS_PER_SEC) * (1000000. / CLOCKS_PER_SEC);
- *system_sec = *system_usec = 0;
- if (c == (clock_t) -1)
- return -1;
- return 0;
- #endif
- }
- #endif
- /* Realtime clock with microsecond resolution, falling back to other
- functions if the target does not support gettimeofday().
- Arguments:
- secs - OUTPUT, seconds
- usecs - OUTPUT, microseconds
- The OUTPUT arguments shall represent the number of seconds and
- microseconds since the Epoch.
- Return value: 0 for success, -1 for error. In case of error, errno
- is set.
- */
- static inline int
- gf_gettime (time_t * secs, long * usecs)
- {
- #ifdef HAVE_GETTIMEOFDAY
- struct timeval tv;
- int err;
- err = gettimeofday (&tv, NULL);
- *secs = tv.tv_sec;
- *usecs = tv.tv_usec;
- return err;
- #elif defined(HAVE_CLOCK_GETTIME)
- struct timespec ts;
- int err = clock_gettime (CLOCK_REALTIME, &ts);
- *secs = ts.tv_sec;
- *usecs = ts.tv_nsec / 1000;
- return err;
- #else
- time_t t = time (NULL);
- *secs = t;
- *usecs = 0;
- if (t == ((time_t)-1))
- return -1;
- return 0;
- #endif
- }
- #endif /* LIBGFORTRAN_TIME_H */
|