PR 56919 Improve SYSTEM_CLOCK intrinsic on Windows.
authorJanne Blomqvist <jb@gcc.gnu.org>
Mon, 15 Apr 2013 12:43:15 +0000 (15:43 +0300)
committerJanne Blomqvist <jb@gcc.gnu.org>
Mon, 15 Apr 2013 12:43:15 +0000 (15:43 +0300)
frontend ChangeLog:

2013-04-15  Janne Blomqvist  <jb@gcc.gnu.org>

PR fortran/56919
* intrinsics.texi (SYSTEM_CLOCK): Update documentation.

libgfortran ChangeLog:

2013-04-15  Janne Blomqvist  <jb@gcc.gnu.org>

PR fortran/56919
* intrinsics/time_1.h: Check __CYGWIN__ in addition to
__MINGW32__.
* intrinsics/system_clock.c (GF_CLOCK_MONOTONIC): Check
_POSIX_MONOTONIC_CLOCK as well.
(system_clock_4): Use GetTickCount on Windows.
(system_clock_8): Use QueryPerformanceCounter and
QueryPerformanceCounterFrequency on Windows.

From-SVN: r197968

gcc/fortran/ChangeLog
gcc/fortran/intrinsic.texi
libgfortran/ChangeLog
libgfortran/intrinsics/system_clock.c
libgfortran/intrinsics/time_1.h

index 262f2571d84afb50ef4cc1e795318703b52ce96b..012d531bdeb6c42d6cc2146d7a45160477f6680d 100644 (file)
@@ -1,3 +1,8 @@
+2013-04-15  Janne Blomqvist  <jb@gcc.gnu.org>
+
+       PR fortran/56919
+       * intrinsics.texi (SYSTEM_CLOCK): Update documentation.
+
 2013-04-15  Tobias Burnus  <burnus@net-b.de>
 
        * class.c (gfc_find_intrinsic_vtab): Removed unused var.
index 8c0edc712a0c62e1d362ebad9e810c996828b2f4..d5ff9a048dcd0014e4df1db50297b4348c8951b1 100644 (file)
@@ -12038,27 +12038,38 @@ and should considered in new code for future portability.
 @item @emph{Description}:
 Determines the @var{COUNT} of a processor clock since an unspecified
 time in the past modulo @var{COUNT_MAX}, @var{COUNT_RATE} determines
-the number of clock ticks per second.  If the platform supports a high
-resolution monotonic clock, that clock is used and can provide up to
-nanosecond resolution.  If a high resolution monotonic clock is not
-available, the implementation falls back to a potentially lower
-resolution realtime clock.
-
-@var{COUNT_RATE} is system dependent and can vary depending on the kind of the
-arguments. For @var{kind=4} arguments, @var{COUNT} usually represents
-milliseconds, while for @var{kind=8} arguments, @var{COUNT} typically
-represents micro- or nanoseconds. @var{COUNT_MAX} usually equals
-@code{HUGE(COUNT_MAX)}.
-
-If there is no clock, @var{COUNT} is set to @code{-HUGE(COUNT)}, and
-@var{COUNT_RATE} and @var{COUNT_MAX} are set to zero.
-
-When running on a platform using the GNU C library (glibc), or a
-derivative thereof, the high resolution monotonic clock is available
-only when linking with the @var{rt} library.  This can be done
-explicitly by adding the @code{-lrt} flag when linking the
+the number of clock ticks per second.  If the platform supports a
+monotonic clock, that clock is used and can, depending on the platform
+clock implementation, provide up to nanosecond resolution.  If a
+monotonic clock is not available, the implementation falls back to a
+realtime clock.
+
+@var{COUNT_RATE} is system dependent and can vary depending on the
+kind of the arguments. For @var{kind=4} arguments, @var{COUNT}
+represents milliseconds, while for @var{kind=8} arguments, @var{COUNT}
+typically represents micro- or nanoseconds depending on resolution of
+the underlying platform clock. @var{COUNT_MAX} usually equals
+@code{HUGE(COUNT_MAX)}. Note that the millisecond resolution of the
+@var{kind=4} version implies that the @var{COUNT} will wrap around in
+roughly 25 days. In order to avoid issues with the wrap around and for
+more precise timing, please use the @var{kind=4} version.
+
+If there is no clock, or querying the clock fails, @var{COUNT} is set
+to @code{-HUGE(COUNT)}, and @var{COUNT_RATE} and @var{COUNT_MAX} are
+set to zero.
+
+When running on a platform using the GNU C library (glibc) version
+2.16 or older, or a derivative thereof, the high resolution monotonic
+clock is available only when linking with the @var{rt} library.  This
+can be done explicitly by adding the @code{-lrt} flag when linking the
 application, but is also done implicitly when using OpenMP.
 
+On the Windows platform, the version with @var{kind=4} arguments uses
+the @code{GetTickCount} function, whereas the @var{kind=8} version
+uses @code{QueryPerformanceCounter} and
+@code{QueryPerformanceCounterFrequency}. For more information, and
+potential caveats, please see the platform documentation.
+
 @item @emph{Standard}:
 Fortran 95 and later
 
index a963d45d2f1db960c0d6f6b799e7f217cfb48437..55f6dd7a5336136976de8ff2967f32b50fc78072 100644 (file)
@@ -1,3 +1,14 @@
+2013-04-15  Janne Blomqvist  <jb@gcc.gnu.org>
+
+       PR fortran/56919
+       * intrinsics/time_1.h: Check __CYGWIN__ in addition to
+       __MINGW32__.
+       * intrinsics/system_clock.c (GF_CLOCK_MONOTONIC): Check
+       _POSIX_MONOTONIC_CLOCK as well.
+       (system_clock_4): Use GetTickCount on Windows.
+       (system_clock_8): Use QueryPerformanceCounter and
+       QueryPerformanceCounterFrequency on Windows.
+
 2013-04-04  Tobias Burnus  <burnus@net-b.de>
 
        PR fortran/56810
index 87a87e22f1d31381628d8b45a63e6016654e4bbf..74a294db810f3b7199f2e55c50b64b1772ab184d 100644 (file)
@@ -29,20 +29,23 @@ see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
 #include "time_1.h"
 
 
+#if !defined(__MINGW32__) && !defined(__CYGWIN__)
+
 /* POSIX states that CLOCK_REALTIME must be present if clock_gettime
    is available, others are optional.  */
 #if defined(HAVE_CLOCK_GETTIME) || defined(HAVE_CLOCK_GETTIME_LIBRT)
-#ifdef CLOCK_MONOTONIC
+#if defined(CLOCK_MONOTONIC) && defined(_POSIX_MONOTONIC_CLOCK) \
+  && _POSIX_MONOTONIC_CLOCK >= 0
 #define GF_CLOCK_MONOTONIC CLOCK_MONOTONIC
 #else
 #define GF_CLOCK_MONOTONIC CLOCK_REALTIME
 #endif
 #endif
 
-/* Weakref trickery for clock_gettime().  On Glibc, clock_gettime()
-   requires us to link in librt, which also pulls in libpthread.  In
-   order to avoid this by default, only call clock_gettime() through a
-   weak reference. 
+/* Weakref trickery for clock_gettime().  On Glibc <= 2.16,
+   clock_gettime() requires us to link in librt, which also pulls in
+   libpthread.  In order to avoid this by default, only call
+   clock_gettime() through a weak reference.
 
    Some targets don't support weak undefined references; on these
    GTHREAD_USE_WEAK is 0. So we need to define it to 1 on other
@@ -105,6 +108,8 @@ gf_gettime_mono (time_t * secs, long * nanosecs, long * tck)
 #endif
 }
 
+#endif /* !__MINGW32 && !__CYGWIN__  */
+
 extern void system_clock_4 (GFC_INTEGER_4 *, GFC_INTEGER_4 *, GFC_INTEGER_4 *);
 export_proto(system_clock_4);
 
@@ -115,12 +120,28 @@ export_proto(system_clock_8);
 /* prefix(system_clock_4) is the INTEGER(4) version of the SYSTEM_CLOCK
    intrinsic subroutine.  It returns the number of clock ticks for the current
    system time, the number of ticks per second, and the maximum possible value
-   for COUNT.  On the first call to SYSTEM_CLOCK, COUNT is set to zero. */
+   for COUNT.  */
 
 void
 system_clock_4(GFC_INTEGER_4 *count, GFC_INTEGER_4 *count_rate,
               GFC_INTEGER_4 *count_max)
 {
+#if defined(__MINGW32__) || defined(__CYGWIN__) 
+  if (count)
+    {
+      /* Use GetTickCount here as the resolution and range is
+        sufficient for the INTEGER(kind=4) version, and
+        QueryPerformanceCounter has potential issues.  */
+      uint32_t cnt = GetTickCount ();
+      if (cnt > GFC_INTEGER_4_HUGE)
+       cnt -= GFC_INTEGER_4_HUGE - 1;
+      *count = cnt;
+    }
+  if (count_rate)
+    *count_rate = 1000;
+  if (count_max)
+    *count_max = GFC_INTEGER_4_HUGE;
+#else
   GFC_INTEGER_4 cnt;
   GFC_INTEGER_4 mx;
 
@@ -158,6 +179,7 @@ system_clock_4(GFC_INTEGER_4 *count, GFC_INTEGER_4 *count_rate,
     *count_rate = tck;
   if (count_max != NULL)
     *count_max = mx;
+#endif
 }
 
 
@@ -167,6 +189,33 @@ void
 system_clock_8 (GFC_INTEGER_8 *count, GFC_INTEGER_8 *count_rate,
                GFC_INTEGER_8 *count_max)
 {
+#if defined(__MINGW32__) || defined(__CYGWIN__) 
+  LARGE_INTEGER cnt;
+  LARGE_INTEGER freq;
+  bool fail = false;
+  if (count && !QueryPerformanceCounter (&cnt))
+    fail = true;
+  if (count_rate && !QueryPerformanceFrequency (&freq))
+    fail = true;
+  if (fail)
+    {
+      if (count)
+       *count = - GFC_INTEGER_8_HUGE;
+      if (count_rate)
+       *count_rate = 0;
+      if (count_max)
+       *count_max = 0;
+    }
+  else
+    {
+      if (count)
+       *count = cnt.QuadPart;
+      if (count_rate)
+       *count_rate = freq.QuadPart;
+      if (count_max)
+       *count_max = GFC_INTEGER_8_HUGE;
+    }
+#else
   GFC_INTEGER_8 cnt;
   GFC_INTEGER_8 mx;
 
@@ -204,4 +253,5 @@ system_clock_8 (GFC_INTEGER_8 *count, GFC_INTEGER_8 *count_rate,
     *count_rate = tck;
   if (count_max != NULL)
     *count_max = mx;
+#endif
 }
index f21e0ea92980281756a7700df1e10f1d3331c086..de6472c62623a7a40f3a94ce3d2e84a6e51b9bf9 100644 (file)
@@ -101,7 +101,7 @@ localtime_r (const time_t * timep, struct tm * result)
    CPU_TIME intrinsics.  Returns 0 for success or -1 if no
    CPU time could be computed.  */
 
-#ifdef __MINGW32__
+#if defined(__MINGW32__) || defined(__CYGWIN__)
 
 #define WIN32_LEAN_AND_MEAN
 #include <windows.h>