aboutsummaryrefslogtreecommitdiff
path: root/libgfortran
diff options
context:
space:
mode:
authorJanne Blomqvist <jb@gcc.gnu.org>2011-01-31 22:52:00 +0200
committerJanne Blomqvist <jb@gcc.gnu.org>2011-01-31 22:52:00 +0200
commitb6e7a3d1f97d5a2c611797ba52e75790888f0379 (patch)
tree218eeedfb68b9af80b02714d695e24e0effb0fbc /libgfortran
parente1bcd685a28f47ae3b70b5a0f3f005e2d327b580 (diff)
downloadgcc-b6e7a3d1f97d5a2c611797ba52e75790888f0379.zip
gcc-b6e7a3d1f97d5a2c611797ba52e75790888f0379.tar.gz
gcc-b6e7a3d1f97d5a2c611797ba52e75790888f0379.tar.bz2
Use clock_gettime in libgfortran timing intrinsics, cleanup
From-SVN: r169449
Diffstat (limited to 'libgfortran')
-rw-r--r--libgfortran/ChangeLog16
-rw-r--r--libgfortran/config.h.in3
-rwxr-xr-xlibgfortran/configure63
-rw-r--r--libgfortran/configure.ac11
-rw-r--r--libgfortran/intrinsics/cpu_time.c50
-rw-r--r--libgfortran/intrinsics/date_and_time.c42
-rw-r--r--libgfortran/intrinsics/dtime.c7
-rw-r--r--libgfortran/intrinsics/etime.c7
-rw-r--r--libgfortran/intrinsics/system_clock.c111
-rw-r--r--libgfortran/intrinsics/time_1.h121
10 files changed, 257 insertions, 174 deletions
diff --git a/libgfortran/ChangeLog b/libgfortran/ChangeLog
index dc10be5..1c75539 100644
--- a/libgfortran/ChangeLog
+++ b/libgfortran/ChangeLog
@@ -1,3 +1,19 @@
+2011-01-31 Janne Blomqvist <jb@gcc.gnu.org>
+
+ * configure.ac: Check for clock_gettime().
+ * configure: Regenerated.
+ * config.h.in: Regenerated.
+ * intrinsics/time_1.h (__time_1): Rename to gf_cputime, add
+ times() fallback.
+ (gf_gettime): New function.
+ * intrinsics/cpu_time.c (__cpu_time_1): Update to call gf_cputime.
+ * intrinsics/date_and_time.c (date_and_time): Use gf_gettime.
+ * intrinsics/dtime.c (dtime_sub): Use gf_cputime.
+ * intrinsics/etime.c (etime_sub): Use gf_cputime.
+ * intrinsics/system_clock.c (system_clock_4): Use gf_gettime.
+ (system_clock_8): Use gf_gettime, increase count rate to allow
+ nanosecond precision, remove overflow prone branch.
+
2011-01-29 Jerry DeLisle <jvdelisle@gcc.gnu.org>
PR libgfortran/47434
diff --git a/libgfortran/config.h.in b/libgfortran/config.h.in
index 913628c..fdf502b 100644
--- a/libgfortran/config.h.in
+++ b/libgfortran/config.h.in
@@ -207,6 +207,9 @@
/* Define to 1 if you have the `clock' function. */
#undef HAVE_CLOCK
+/* Define to 1 if you have the `clock_gettime' function. */
+#undef HAVE_CLOCK_GETTIME
+
/* libm includes clog */
#undef HAVE_CLOG
diff --git a/libgfortran/configure b/libgfortran/configure
index b872106..ec5c7ed 100755
--- a/libgfortran/configure
+++ b/libgfortran/configure
@@ -16380,6 +16380,17 @@ _ACEOF
fi
done
+for ac_func in clock_gettime
+do :
+ ac_fn_c_check_func "$LINENO" "clock_gettime" "ac_cv_func_clock_gettime"
+if test "x$ac_cv_func_clock_gettime" = x""yes; then :
+ cat >>confdefs.h <<_ACEOF
+#define HAVE_CLOCK_GETTIME 1
+_ACEOF
+
+fi
+done
+
# Check for glibc backtrace functions
for ac_func in backtrace backtrace_symbols
@@ -25249,6 +25260,58 @@ $as_echo "#define HAVE_FEENABLEEXCEPT 1" >>confdefs.h
fi
+# At least for glibc, clock_gettime is in librt. But don't pull that
+# in if it still doesn't give us the function we want.
+# This test is copied from libgomp.
+if test $ac_cv_func_clock_gettime = no; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for clock_gettime in -lrt" >&5
+$as_echo_n "checking for clock_gettime in -lrt... " >&6; }
+if test "${ac_cv_lib_rt_clock_gettime+set}" = set; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-lrt $LIBS"
+if test x$gcc_no_link = xyes; then
+ as_fn_error "Link tests are not allowed after GCC_NO_EXECUTABLES." "$LINENO" 5
+fi
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char clock_gettime ();
+int
+main ()
+{
+return clock_gettime ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ ac_cv_lib_rt_clock_gettime=yes
+else
+ ac_cv_lib_rt_clock_gettime=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_rt_clock_gettime" >&5
+$as_echo "$ac_cv_lib_rt_clock_gettime" >&6; }
+if test "x$ac_cv_lib_rt_clock_gettime" = x""yes; then :
+ LIBS="-lrt $LIBS"
+
+$as_echo "#define HAVE_CLOCK_GETTIME 1" >>confdefs.h
+
+fi
+
+fi
+
# Check for SysV fpsetmask
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether fpsetmask is present" >&5
diff --git a/libgfortran/configure.ac b/libgfortran/configure.ac
index e8f842c..ed1e2cc 100644
--- a/libgfortran/configure.ac
+++ b/libgfortran/configure.ac
@@ -252,6 +252,7 @@ AC_CHECK_FUNCS(sleep time ttyname signal alarm ctime clock access fork execl)
AC_CHECK_FUNCS(wait setmode execvp pipe dup2 close fdopen strcasestr getrlimit)
AC_CHECK_FUNCS(gettimeofday stat fstat lstat getpwuid vsnprintf dup getcwd)
AC_CHECK_FUNCS(localtime_r gmtime_r strerror_r getpwuid_r ttyname_r ctime_r)
+AC_CHECK_FUNCS(clock_gettime)
# Check for glibc backtrace functions
AC_CHECK_FUNCS(backtrace backtrace_symbols)
@@ -483,6 +484,16 @@ LIBGFOR_CHECK_FLOAT128
# Check for GNU libc feenableexcept
AC_CHECK_LIB([m],[feenableexcept],[have_feenableexcept=yes AC_DEFINE([HAVE_FEENABLEEXCEPT],[1],[libm includes feenableexcept])])
+# At least for glibc, clock_gettime is in librt. But don't pull that
+# in if it still doesn't give us the function we want.
+# This test is copied from libgomp.
+if test $ac_cv_func_clock_gettime = no; then
+ AC_CHECK_LIB(rt, clock_gettime,
+ [LIBS="-lrt $LIBS"
+ AC_DEFINE(HAVE_CLOCK_GETTIME, 1,
+ [Define to 1 if you have the `clock_gettime' function.])])
+fi
+
# Check for SysV fpsetmask
LIBGFOR_CHECK_FPSETMASK
diff --git a/libgfortran/intrinsics/cpu_time.c b/libgfortran/intrinsics/cpu_time.c
index 8bffe65..619f8d2 100644
--- a/libgfortran/intrinsics/cpu_time.c
+++ b/libgfortran/intrinsics/cpu_time.c
@@ -1,7 +1,7 @@
/* Implementation of the CPU_TIME intrinsic.
- Copyright (C) 2003, 2007, 2009, 2010 Free Software Foundation, Inc.
+ Copyright (C) 2003, 2007, 2009, 2010, 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
@@ -25,49 +25,23 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
#include "libgfortran.h"
#include "time_1.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 */
static inline void __cpu_time_1 (long *, long *) ATTRIBUTE_ALWAYS_INLINE;
static inline void
__cpu_time_1 (long *sec, long *usec)
{
-#if defined(__MINGW32__) || defined (HAVE_GETRUSAGE) && defined (HAVE_SYS_RESOURCE_H)
long user_sec, user_usec, system_sec, system_usec;
- __time_1 (&user_sec, &user_usec, &system_sec, &system_usec);
- *sec = user_sec + system_sec;
- *usec = user_usec + system_usec;
-#else /* ! HAVE_GETRUSAGE || ! HAVE_SYS_RESOURCE_H */
-#ifdef HAVE_TIMES
- struct tms buf;
- times (&buf);
- *sec = 0;
- *usec = (buf.tms_utime + buf.tms_stime) * (1000000 / HZ);
-#else /* ! HAVE_TIMES */
- /* We have nothing to go on. Return -1. */
- *sec = -1;
- *usec = 0;
-#endif /* HAVE_TIMES */
-#endif /* __MINGW32__ || HAVE_GETRUSAGE */
+ if (gf_cputime (&user_sec, &user_usec, &system_sec, &system_usec) == 0)
+ {
+ *sec = user_sec + system_sec;
+ *usec = user_usec + system_usec;
+ }
+ else
+ {
+ *sec = -1;
+ *usec = 0;
+ }
}
diff --git a/libgfortran/intrinsics/date_and_time.c b/libgfortran/intrinsics/date_and_time.c
index dea835b..714df14 100644
--- a/libgfortran/intrinsics/date_and_time.c
+++ b/libgfortran/intrinsics/date_and_time.c
@@ -1,5 +1,5 @@
/* Implementation of the DATE_AND_TIME intrinsic.
- Copyright (C) 2003, 2004, 2005, 2006, 2007, 2009, 2010
+ Copyright (C) 2003, 2004, 2005, 2006, 2007, 2009, 2010, 2011
Free Software Foundation, Inc.
Contributed by Steven Bosscher.
@@ -29,21 +29,7 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
#include <assert.h>
#include <stdlib.h>
-#undef HAVE_NO_DATE_TIME
-#if TIME_WITH_SYS_TIME
-# include <sys/time.h>
-# include <time.h>
-#else
-# if HAVE_SYS_TIME_H
-# include <sys/time.h>
-# else
-# ifdef HAVE_TIME_H
-# include <time.h>
-# else
-# define HAVE_NO_DATE_TIME
-# endif /* HAVE_TIME_H */
-# endif /* HAVE_SYS_TIME_H */
-#endif /* TIME_WITH_SYS_TIME */
+#include "time_1.h"
#ifndef abs
#define abs(x) ((x)>=0 ? (x) : -(x))
@@ -176,28 +162,12 @@ date_and_time (char *__date, char *__time, char *__zone,
struct tm local_time;
struct tm UTC_time;
-#if HAVE_GETTIMEOFDAY
- {
- struct timeval tp;
-
- if (!gettimeofday (&tp, NULL))
- {
- lt = tp.tv_sec;
- values[7] = tp.tv_usec / 1000;
- }
- else
- {
- lt = time (NULL);
- values[7] = 0;
- }
- }
-#else
- lt = time (NULL);
- values[7] = 0;
-#endif /* HAVE_GETTIMEOFDAY */
+ long nanosecs;
- if (lt != (time_t) -1)
+ if (!gf_gettime(GF_CLOCK_REALTIME, &lt, &nanosecs))
{
+ values[7] = nanosecs / 1000000;
+
localtime_r (&lt, &local_time);
gmtime_r (&lt, &UTC_time);
diff --git a/libgfortran/intrinsics/dtime.c b/libgfortran/intrinsics/dtime.c
index d1eb912..e36e1f1 100644
--- a/libgfortran/intrinsics/dtime.c
+++ b/libgfortran/intrinsics/dtime.c
@@ -1,7 +1,8 @@
/* Implementation of the dtime intrinsic.
- Copyright (C) 2004, 2005, 2006, 2007, 2009 Free Software Foundation, Inc.
+ Copyright (C) 2004, 2005, 2006, 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
@@ -47,7 +48,7 @@ dtime_sub (gfc_array_r4 *t, GFC_REAL_4 *result)
runtime_error ("Insufficient number of elements in TARRAY.");
__gthread_mutex_lock (&dtime_update_lock);
- if (__time_1 (&user_sec, &user_usec, &system_sec, &system_usec) == 0)
+ if (gf_cputime (&user_sec, &user_usec, &system_sec, &system_usec) == 0)
{
tu = (GFC_REAL_4) ((user_sec - us) + 1.e-6 * (user_usec - uu));
ts = (GFC_REAL_4) ((system_sec - ss) + 1.e-6 * (system_usec - su));
diff --git a/libgfortran/intrinsics/etime.c b/libgfortran/intrinsics/etime.c
index b0fd742..d90bc30 100644
--- a/libgfortran/intrinsics/etime.c
+++ b/libgfortran/intrinsics/etime.c
@@ -1,8 +1,9 @@
/* Implementation of the ETIME intrinsic.
- Copyright (C) 2004, 2005, 2006, 2007, 2009 Free Software Foundation, Inc.
+ Copyright (C) 2004, 2005, 2006, 2007, 2009, 2011 Free Software
+ Foundation, Inc.
Contributed by Steven G. Kargl <kargls@comcast.net>.
-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
@@ -38,7 +39,7 @@ etime_sub (gfc_array_r4 *t, GFC_REAL_4 *result)
if (((GFC_DESCRIPTOR_EXTENT(t,0))) < 2)
runtime_error ("Insufficient number of elements in TARRAY.");
- if (__time_1 (&user_sec, &user_usec, &system_sec, &system_usec) == 0)
+ if (gf_cputime (&user_sec, &user_usec, &system_sec, &system_usec) == 0)
{
tu = (GFC_REAL_4)(user_sec + 1.e-6 * user_usec);
ts = (GFC_REAL_4)(system_sec + 1.e-6 * system_usec);
diff --git a/libgfortran/intrinsics/system_clock.c b/libgfortran/intrinsics/system_clock.c
index b07d434..3715562 100644
--- a/libgfortran/intrinsics/system_clock.c
+++ b/libgfortran/intrinsics/system_clock.c
@@ -1,5 +1,6 @@
/* Implementation of the SYSTEM_CLOCK intrinsic.
- Copyright (C) 2004, 2005, 2007, 2009, 2010 Free Software Foundation, Inc.
+ Copyright (C) 2004, 2005, 2007, 2009, 2010, 2011 Free Software
+ Foundation, Inc.
This file is part of the GNU Fortran runtime library (libgfortran).
@@ -26,15 +27,7 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
#include <limits.h>
-#if defined(HAVE_SYS_TIME_H) && defined(HAVE_GETTIMEOFDAY)
-# include <sys/time.h>
-#elif defined(HAVE_TIME_H)
-# include <time.h>
-# define TCK 1
-#else
-#define TCK 0
-#endif
-
+#include "time_1.h"
extern void system_clock_4 (GFC_INTEGER_4 *, GFC_INTEGER_4 *, GFC_INTEGER_4 *);
export_proto(system_clock_4);
@@ -52,21 +45,21 @@ void
system_clock_4(GFC_INTEGER_4 *count, GFC_INTEGER_4 *count_rate,
GFC_INTEGER_4 *count_max)
{
+#undef TCK
+#define TCK 1000
GFC_INTEGER_4 cnt;
GFC_INTEGER_4 mx;
-#if defined(HAVE_SYS_TIME_H) && defined(HAVE_GETTIMEOFDAY)
-#undef TCK
-#define TCK 1000
- struct timeval tp1;
+ time_t secs;
+ long nanosecs;
- if (sizeof (tp1.tv_sec) < sizeof (GFC_INTEGER_4))
- internal_error (NULL, "tv_sec too small");
+ if (sizeof (secs) < sizeof (GFC_INTEGER_4))
+ internal_error (NULL, "secs too small");
- if (gettimeofday(&tp1, NULL) == 0)
+ if (gf_gettime (GF_CLOCK_MONOTONIC, &secs, &nanosecs) == 0)
{
- GFC_UINTEGER_4 ucnt = (GFC_UINTEGER_4) tp1.tv_sec * TCK;
- ucnt += (tp1.tv_usec + 500000 / TCK) / (1000000 / TCK);
+ GFC_UINTEGER_4 ucnt = (GFC_UINTEGER_4) secs * TCK;
+ ucnt += (nanosecs + 500000000 / TCK) / (1000000000 / TCK);
if (ucnt > GFC_INTEGER_4_HUGE)
cnt = ucnt - GFC_INTEGER_4_HUGE - 1;
else
@@ -83,22 +76,7 @@ system_clock_4(GFC_INTEGER_4 *count, GFC_INTEGER_4 *count_rate,
*count_max = 0;
return;
}
-#elif defined(HAVE_TIME_H)
- GFC_UINTEGER_4 ucnt;
-
- if (sizeof (time_t) < sizeof (GFC_INTEGER_4))
- internal_error (NULL, "time_t too small");
- ucnt = time (NULL);
- if (ucnt > GFC_INTEGER_4_HUGE)
- cnt = ucnt - GFC_INTEGER_4_HUGE - 1;
- else
- cnt = ucnt;
- mx = GFC_INTEGER_4_HUGE;
-#else
- cnt = - GFC_INTEGER_4_HUGE;
- mx = 0;
-#endif
if (count != NULL)
*count = cnt;
if (count_rate != NULL)
@@ -114,39 +92,26 @@ void
system_clock_8 (GFC_INTEGER_8 *count, GFC_INTEGER_8 *count_rate,
GFC_INTEGER_8 *count_max)
{
+#undef TCK
+#define TCK 1000000000
GFC_INTEGER_8 cnt;
GFC_INTEGER_8 mx;
-#if defined(HAVE_SYS_TIME_H) && defined(HAVE_GETTIMEOFDAY)
-#undef TCK
-#define TCK 1000000
- struct timeval tp1;
+ time_t secs;
+ long nanosecs;
- if (sizeof (tp1.tv_sec) < sizeof (GFC_INTEGER_4))
- internal_error (NULL, "tv_sec too small");
+ if (sizeof (secs) < sizeof (GFC_INTEGER_4))
+ internal_error (NULL, "secs too small");
- if (gettimeofday(&tp1, NULL) == 0)
+ if (gf_gettime (GF_CLOCK_MONOTONIC, &secs, &nanosecs) == 0)
{
- if (sizeof (tp1.tv_sec) < sizeof (GFC_INTEGER_8))
- {
- GFC_UINTEGER_4 ucnt = (GFC_UINTEGER_4) tp1.tv_sec * TCK;
- ucnt += (tp1.tv_usec + 500000 / TCK) / (1000000 / TCK);
- if (ucnt > GFC_INTEGER_4_HUGE)
- cnt = ucnt - GFC_INTEGER_4_HUGE - 1;
- else
- cnt = ucnt;
- mx = GFC_INTEGER_4_HUGE;
- }
+ GFC_UINTEGER_8 ucnt = (GFC_UINTEGER_8) secs * TCK;
+ ucnt += (nanosecs + 500000000 / TCK) / (1000000000 / TCK);
+ if (ucnt > GFC_INTEGER_8_HUGE)
+ cnt = ucnt - GFC_INTEGER_8_HUGE - 1;
else
- {
- GFC_UINTEGER_8 ucnt = (GFC_UINTEGER_8) tp1.tv_sec * TCK;
- ucnt += (tp1.tv_usec + 500000 / TCK) / (1000000 / TCK);
- if (ucnt > GFC_INTEGER_8_HUGE)
- cnt = ucnt - GFC_INTEGER_8_HUGE - 1;
- else
- cnt = ucnt;
- mx = GFC_INTEGER_8_HUGE;
- }
+ cnt = ucnt;
+ mx = GFC_INTEGER_8_HUGE;
}
else
{
@@ -159,31 +124,7 @@ system_clock_8 (GFC_INTEGER_8 *count, GFC_INTEGER_8 *count_rate,
return;
}
-#elif defined(HAVE_TIME_H)
- if (sizeof (time_t) < sizeof (GFC_INTEGER_4))
- internal_error (NULL, "time_t too small");
- else if (sizeof (time_t) == sizeof (GFC_INTEGER_4))
- {
- GFC_UINTEGER_4 ucnt = time (NULL);
- if (ucnt > GFC_INTEGER_4_HUGE)
- cnt = ucnt - GFC_INTEGER_4_HUGE - 1;
- else
- cnt = ucnt;
- mx = GFC_INTEGER_4_HUGE;
- }
- else
- {
- GFC_UINTEGER_8 ucnt = time (NULL);
- if (ucnt > GFC_INTEGER_8_HUGE)
- cnt = ucnt - GFC_INTEGER_8_HUGE - 1;
- else
- cnt = ucnt;
- mx = GFC_INTEGER_8_HUGE;
- }
-#else
- cnt = - GFC_INTEGER_8_HUGE;
- mx = 0;
-#endif
+
if (count != NULL)
*count = cnt;
if (count_rate != NULL)
diff --git a/libgfortran/intrinsics/time_1.h b/libgfortran/intrinsics/time_1.h
index 03e14ed..5ee5d5a 100644
--- a/libgfortran/intrinsics/time_1.h
+++ b/libgfortran/intrinsics/time_1.h
@@ -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
@@ -60,16 +60,38 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
# 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 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__
@@ -78,7 +100,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;
@@ -112,23 +134,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 (RUSAGE_SELF, &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
@@ -137,4 +173,71 @@ __time_1 (long *user_sec, long *user_usec, long *system_sec, long *system_usec)
#endif
+/* POSIX states that CLOCK_REALTIME must be present if clock_gettime
+ is available, others are optional. */
+#ifdef CLOCK_REALTIME
+#define GF_CLOCK_REALTIME CLOCK_REALTIME
+#else
+#define GF_CLOCK_REALTIME 0
+#endif
+
+#ifdef CLOCK_MONOTONIC
+#define GF_CLOCK_MONOTONIC CLOCK_MONOTONIC
+#else
+#define GF_CLOCK_REALTIME GF_CLOCK_REALTIME
+#endif
+
+/* Arguments:
+ clock_id - INPUT, must be either GF_CLOCK_REALTIME or GF_CLOCK_MONOTONIC
+ secs - OUTPUT, seconds
+ nanosecs - OUTPUT, OPTIONAL, nanoseconds
+
+ If clock_id equals GF_CLOCK_REALTIME, the OUTPUT arguments shall be
+ the number of seconds and nanoseconds since the Epoch. If clock_id
+ equals GF_CLOCK_MONOTONIC, and if the target supports it, the
+ OUTPUT arguments represent a monotonically incrementing clock
+ starting from some unspecified time in the past.
+
+ Return value: 0 for success, -1 for error. In case of error, errno
+ is set.
+*/
+static inline int
+gf_gettime (int clock_id __attribute__((unused)), time_t * secs,
+ long * nanosecs)
+{
+#ifdef HAVE_CLOCK_GETTIME
+ struct timespec ts;
+ int err;
+ err = clock_gettime (clock_id, &ts);
+ *secs = ts.tv_sec;
+ if (nanosecs)
+ *nanosecs = ts.tv_nsec;
+ return err;
+#elif HAVE_GETTIMEOFDAY
+ struct timeval tv;
+ int err;
+ err = gettimeofday (&tv, NULL);
+ *secs = tv.tv_sec;
+ if (nanosecs)
+ *nanosecs = tv.tv_usec * 1000;
+ return err;
+#elif HAVE_TIME
+ time_t t, t2;
+ t = time (&t2);
+ *secs = t2;
+ if (nanosecs)
+ *nanosecs = 0;
+ if (t == ((time_t)-1))
+ return -1;
+ return 0;
+#else
+ *secs = 0;
+ if (nanosecs)
+ *nanosecs = 0;
+ errno = ENOSYS;
+ return -1;
+#endif
+}
+
+
#endif /* LIBGFORTRAN_TIME_H */