OSDN Git Service

PR fortran/35667
[pf3gnuchains/gcc-fork.git] / libgfortran / intrinsics / time_1.h
index a93b7e0..12d79eb 100644 (file)
@@ -1,7 +1,7 @@
-/* Implementation of the CPU_TIME intrinsic.
-   Copyright (C) 2003, 2007, 2009 Free Software Foundation, Inc.
+/* Wrappers for platform timing functions.
+   Copyright (C) 2003, 2007, 2009, 2011 Free Software Foundation, Inc.
 
-This file is part of the GNU Fortran 95 runtime library (libgfortran).
+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
@@ -29,6 +29,8 @@ see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
 #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
@@ -51,21 +53,67 @@ see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
 #  endif
 #endif
 
+#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
+
+
 #if defined (__GNUC__) && (__GNUC__ >= 3)
 #  define ATTRIBUTE_ALWAYS_INLINE __attribute__ ((__always_inline__))
 #else
 #  define ATTRIBUTE_ALWAYS_INLINE
 #endif
 
-static inline int __time_1 (long *, long *, long *, long *) ATTRIBUTE_ALWAYS_INLINE;
+static inline int gf_cputime (long *, long *, long *, long *) ATTRIBUTE_ALWAYS_INLINE;
 
 /* Helper function for the actual implementation of the DTIME, ETIME and
-   CPU_TIME intrinsics.  Returns a CPU time in microseconds or -1 if no
+   CPU_TIME intrinsics.  Returns 0 for success or -1 if no
    CPU time could be computed.  */
 
 #ifdef __MINGW32__
@@ -74,7 +122,7 @@ static inline int __time_1 (long *, long *, long *, long *) ATTRIBUTE_ALWAYS_INL
 #include <windows.h>
 
 static int
-__time_1 (long *user_sec, long *user_usec, long *system_sec, long *system_usec)
+gf_cputime (long *user_sec, long *user_usec, long *system_sec, long *system_usec)
 {
   union {
     FILETIME ft;
@@ -108,23 +156,37 @@ __time_1 (long *user_sec, long *user_usec, long *system_sec, long *system_usec)
 #else
 
 static inline int
-__time_1 (long *user_sec, long *user_usec, long *system_sec, long *system_usec)
+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;
-  getrusage (0, &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);
+  *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;
 
-#else /* ! HAVE_GETRUSAGE || ! HAVE_SYS_RESOURCE_H  */
+#else 
 
   /* We have nothing to go on.  Return -1.  */
   *user_sec = *system_sec = 0;
   *user_usec = *system_usec = 0;
+  errno = ENOSYS;
   return -1;
 
 #endif
@@ -133,4 +195,44 @@ __time_1 (long *user_sec, long *user_usec, long *system_sec, long *system_usec)
 #endif
 
 
+/* Realtime clock with microsecond resolution, falling back to less
+   precise 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
+   nanoseconds 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 HAVE_TIME
+  time_t t, t2;
+  t = time (&t2);
+  *secs = t2;
+  *usecs = 0;
+  if (t == ((time_t)-1))
+    return -1;
+  return 0;
+#else
+  *secs = 0;
+  *usecs = 0;
+  errno = ENOSYS;
+  return -1;
+#endif
+}
+
+
 #endif /* LIBGFORTRAN_TIME_H */