From patchwork Mon Jan 31 20:18:45 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Janne Blomqvist X-Patchwork-Id: 81226 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) by ozlabs.org (Postfix) with SMTP id 91832B70F4 for ; Tue, 1 Feb 2011 07:19:14 +1100 (EST) Received: (qmail 26781 invoked by alias); 31 Jan 2011 20:19:12 -0000 Received: (qmail 26718 invoked by uid 22791); 31 Jan 2011 20:19:03 -0000 X-SWARE-Spam-Status: No, hits=-2.0 required=5.0 tests=AWL, BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, FREEMAIL_FROM, RCVD_IN_DNSWL_LOW, TW_BG, TW_FN, TW_LR, TW_PW, TW_TP, TW_WU X-Spam-Check-By: sourceware.org Received: from mail-iw0-f175.google.com (HELO mail-iw0-f175.google.com) (209.85.214.175) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Mon, 31 Jan 2011 20:18:57 +0000 Received: by iwn8 with SMTP id 8so6098432iwn.20 for ; Mon, 31 Jan 2011 12:18:55 -0800 (PST) MIME-Version: 1.0 Received: by 10.231.13.138 with SMTP id c10mr7175427iba.97.1296505125130; Mon, 31 Jan 2011 12:18:45 -0800 (PST) Received: by 10.231.160.68 with HTTP; Mon, 31 Jan 2011 12:18:45 -0800 (PST) Date: Mon, 31 Jan 2011 22:18:45 +0200 Message-ID: Subject: [Patch, libfortran] Use high resolution clock if available, timing cleanup From: Janne Blomqvist To: Fortran List , GCC Patches Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org Hi, the attached patch 1) Does some cleanup for CPU timing functions. 2) Uses clock_gettime() if available, and if so in particular: 2a) enables up to nanosecond resolution for system_clock_8. 2b) SYSTEM_CLOCK uses the monotonic clock, if available, which is a better choice for a wallclock timing function. Regtested on x86_64-unknown-linux-gnu, Ok for trunk? 2011-01-31 Janne Blomqvist * 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. 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 -# endif -# if defined (HAVE_SYS_TIMES_H) -# include -# 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 #include -#undef HAVE_NO_DATE_TIME -#if TIME_WITH_SYS_TIME -# include -# include -#else -# if HAVE_SYS_TIME_H -# include -# else -# ifdef HAVE_TIME_H -# include -# 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 . -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 -#if defined(HAVE_SYS_TIME_H) && defined(HAVE_GETTIMEOFDAY) -# include -#elif defined(HAVE_TIME_H) -# include -# 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 #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 +# endif +# if defined (HAVE_SYS_TIMES_H) +# include +# 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 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 */