Commit 83584eab by Janne Blomqvist

PR 56919 Improve SYSTEM_CLOCK intrinsic on Windows.

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
parent 1c50eada
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> 2013-04-15 Tobias Burnus <burnus@net-b.de>
* class.c (gfc_find_intrinsic_vtab): Removed unused var. * class.c (gfc_find_intrinsic_vtab): Removed unused var.
......
...@@ -12038,27 +12038,38 @@ and should considered in new code for future portability. ...@@ -12038,27 +12038,38 @@ and should considered in new code for future portability.
@item @emph{Description}: @item @emph{Description}:
Determines the @var{COUNT} of a processor clock since an unspecified Determines the @var{COUNT} of a processor clock since an unspecified
time in the past modulo @var{COUNT_MAX}, @var{COUNT_RATE} determines 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 the number of clock ticks per second. If the platform supports a
resolution monotonic clock, that clock is used and can provide up to monotonic clock, that clock is used and can, depending on the platform
nanosecond resolution. If a high resolution monotonic clock is not clock implementation, provide up to nanosecond resolution. If a
available, the implementation falls back to a potentially lower monotonic clock is not available, the implementation falls back to a
resolution realtime clock. realtime clock.
@var{COUNT_RATE} is system dependent and can vary depending on the kind of the @var{COUNT_RATE} is system dependent and can vary depending on the
arguments. For @var{kind=4} arguments, @var{COUNT} usually represents kind of the arguments. For @var{kind=4} arguments, @var{COUNT}
milliseconds, while for @var{kind=8} arguments, @var{COUNT} typically represents milliseconds, while for @var{kind=8} arguments, @var{COUNT}
represents micro- or nanoseconds. @var{COUNT_MAX} usually equals typically represents micro- or nanoseconds depending on resolution of
@code{HUGE(COUNT_MAX)}. the underlying platform clock. @var{COUNT_MAX} usually equals
@code{HUGE(COUNT_MAX)}. Note that the millisecond resolution of the
If there is no clock, @var{COUNT} is set to @code{-HUGE(COUNT)}, and @var{kind=4} version implies that the @var{COUNT} will wrap around in
@var{COUNT_RATE} and @var{COUNT_MAX} are set to zero. roughly 25 days. In order to avoid issues with the wrap around and for
more precise timing, please use the @var{kind=4} version.
When running on a platform using the GNU C library (glibc), or a
derivative thereof, the high resolution monotonic clock is available If there is no clock, or querying the clock fails, @var{COUNT} is set
only when linking with the @var{rt} library. This can be done to @code{-HUGE(COUNT)}, and @var{COUNT_RATE} and @var{COUNT_MAX} are
explicitly by adding the @code{-lrt} flag when linking the 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. 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}: @item @emph{Standard}:
Fortran 95 and later Fortran 95 and later
......
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> 2013-04-04 Tobias Burnus <burnus@net-b.de>
PR fortran/56810 PR fortran/56810
......
...@@ -29,20 +29,23 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see ...@@ -29,20 +29,23 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
#include "time_1.h" #include "time_1.h"
#if !defined(__MINGW32__) && !defined(__CYGWIN__)
/* POSIX states that CLOCK_REALTIME must be present if clock_gettime /* POSIX states that CLOCK_REALTIME must be present if clock_gettime
is available, others are optional. */ is available, others are optional. */
#if defined(HAVE_CLOCK_GETTIME) || defined(HAVE_CLOCK_GETTIME_LIBRT) #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 #define GF_CLOCK_MONOTONIC CLOCK_MONOTONIC
#else #else
#define GF_CLOCK_MONOTONIC CLOCK_REALTIME #define GF_CLOCK_MONOTONIC CLOCK_REALTIME
#endif #endif
#endif #endif
/* Weakref trickery for clock_gettime(). On Glibc, clock_gettime() /* Weakref trickery for clock_gettime(). On Glibc <= 2.16,
requires us to link in librt, which also pulls in libpthread. In clock_gettime() requires us to link in librt, which also pulls in
order to avoid this by default, only call clock_gettime() through a libpthread. In order to avoid this by default, only call
weak reference. clock_gettime() through a weak reference.
Some targets don't support weak undefined references; on these 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 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) ...@@ -105,6 +108,8 @@ gf_gettime_mono (time_t * secs, long * nanosecs, long * tck)
#endif #endif
} }
#endif /* !__MINGW32 && !__CYGWIN__ */
extern void system_clock_4 (GFC_INTEGER_4 *, GFC_INTEGER_4 *, GFC_INTEGER_4 *); extern void system_clock_4 (GFC_INTEGER_4 *, GFC_INTEGER_4 *, GFC_INTEGER_4 *);
export_proto(system_clock_4); export_proto(system_clock_4);
...@@ -115,12 +120,28 @@ export_proto(system_clock_8); ...@@ -115,12 +120,28 @@ export_proto(system_clock_8);
/* prefix(system_clock_4) is the INTEGER(4) version of the SYSTEM_CLOCK /* 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 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 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 void
system_clock_4(GFC_INTEGER_4 *count, GFC_INTEGER_4 *count_rate, system_clock_4(GFC_INTEGER_4 *count, GFC_INTEGER_4 *count_rate,
GFC_INTEGER_4 *count_max) 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 cnt;
GFC_INTEGER_4 mx; GFC_INTEGER_4 mx;
...@@ -158,6 +179,7 @@ system_clock_4(GFC_INTEGER_4 *count, GFC_INTEGER_4 *count_rate, ...@@ -158,6 +179,7 @@ system_clock_4(GFC_INTEGER_4 *count, GFC_INTEGER_4 *count_rate,
*count_rate = tck; *count_rate = tck;
if (count_max != NULL) if (count_max != NULL)
*count_max = mx; *count_max = mx;
#endif
} }
...@@ -167,6 +189,33 @@ void ...@@ -167,6 +189,33 @@ void
system_clock_8 (GFC_INTEGER_8 *count, GFC_INTEGER_8 *count_rate, system_clock_8 (GFC_INTEGER_8 *count, GFC_INTEGER_8 *count_rate,
GFC_INTEGER_8 *count_max) 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 cnt;
GFC_INTEGER_8 mx; GFC_INTEGER_8 mx;
...@@ -204,4 +253,5 @@ system_clock_8 (GFC_INTEGER_8 *count, GFC_INTEGER_8 *count_rate, ...@@ -204,4 +253,5 @@ system_clock_8 (GFC_INTEGER_8 *count, GFC_INTEGER_8 *count_rate,
*count_rate = tck; *count_rate = tck;
if (count_max != NULL) if (count_max != NULL)
*count_max = mx; *count_max = mx;
#endif
} }
...@@ -101,7 +101,7 @@ localtime_r (const time_t * timep, struct tm * result) ...@@ -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 intrinsics. Returns 0 for success or -1 if no
CPU time could be computed. */ CPU time could be computed. */
#ifdef __MINGW32__ #if defined(__MINGW32__) || defined(__CYGWIN__)
#define WIN32_LEAN_AND_MEAN #define WIN32_LEAN_AND_MEAN
#include <windows.h> #include <windows.h>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment