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
This commit is contained in:
Janne Blomqvist 2013-04-15 15:43:15 +03:00
parent 1c50eadaae
commit 83584eab1b
5 changed files with 100 additions and 23 deletions

View 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.

View 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.
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} 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)}.
@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, @var{COUNT} is set to @code{-HUGE(COUNT)}, and
@var{COUNT_RATE} and @var{COUNT_MAX} are set to zero.
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), 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
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

View 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

View 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
}

View 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>