diff options
author | Janne Blomqvist <jb@gcc.gnu.org> | 2011-01-31 22:52:00 +0200 |
---|---|---|
committer | Janne Blomqvist <jb@gcc.gnu.org> | 2011-01-31 22:52:00 +0200 |
commit | b6e7a3d1f97d5a2c611797ba52e75790888f0379 (patch) | |
tree | 218eeedfb68b9af80b02714d695e24e0effb0fbc /libgfortran | |
parent | e1bcd685a28f47ae3b70b5a0f3f005e2d327b580 (diff) | |
download | gcc-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/ChangeLog | 16 | ||||
-rw-r--r-- | libgfortran/config.h.in | 3 | ||||
-rwxr-xr-x | libgfortran/configure | 63 | ||||
-rw-r--r-- | libgfortran/configure.ac | 11 | ||||
-rw-r--r-- | libgfortran/intrinsics/cpu_time.c | 50 | ||||
-rw-r--r-- | libgfortran/intrinsics/date_and_time.c | 42 | ||||
-rw-r--r-- | libgfortran/intrinsics/dtime.c | 7 | ||||
-rw-r--r-- | libgfortran/intrinsics/etime.c | 7 | ||||
-rw-r--r-- | libgfortran/intrinsics/system_clock.c | 111 | ||||
-rw-r--r-- | libgfortran/intrinsics/time_1.h | 121 |
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, <, &nanosecs)) { + values[7] = nanosecs / 1000000; + localtime_r (<, &local_time); gmtime_r (<, &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 */ |