diff options
-rw-r--r-- | libgfortran/ChangeLog | 14 | ||||
-rw-r--r-- | libgfortran/intrinsics/date_and_time.c | 6 | ||||
-rw-r--r-- | libgfortran/intrinsics/system_clock.c | 73 | ||||
-rw-r--r-- | libgfortran/intrinsics/time_1.h | 67 |
4 files changed, 98 insertions, 62 deletions
diff --git a/libgfortran/ChangeLog b/libgfortran/ChangeLog index 47ab730..fbeb87d 100644 --- a/libgfortran/ChangeLog +++ b/libgfortran/ChangeLog @@ -1,3 +1,17 @@ +2011-02-05 Janne Blomqvist <jb@gcc.gnu.org> + + PR libfortran/47571 + * intrinsics/time_1.h (GF_CLOCK_MONOTONIC): Move to system_clock.c. + (weak_gettime): Likewise. + (gf_gettime): Change API, move weak_gettime() usage to + system_clock.c + * intrinsics/system_clock.c (GTHREAD_USE_WEAK): Define. + (gf_gettime_mono): New function. + (system_clock_4): Use gf_gettime_mono(). + (system_clock_8): Likewise. + * intrinsics/date_and_time.c (date_and_time): Update gf_gettime() + usage. + 2011-02-02 Janne Blomqvist <jb@gcc.gnu.org> PR libfortran/47571 diff --git a/libgfortran/intrinsics/date_and_time.c b/libgfortran/intrinsics/date_and_time.c index 714df14..c58d114 100644 --- a/libgfortran/intrinsics/date_and_time.c +++ b/libgfortran/intrinsics/date_and_time.c @@ -162,11 +162,11 @@ date_and_time (char *__date, char *__time, char *__zone, struct tm local_time; struct tm UTC_time; - long nanosecs; + long usecs; - if (!gf_gettime(GF_CLOCK_REALTIME, <, &nanosecs)) + if (!gf_gettime (<, &usecs)) { - values[7] = nanosecs / 1000000; + values[7] = usecs / 1000; localtime_r (<, &local_time); gmtime_r (<, &UTC_time); diff --git a/libgfortran/intrinsics/system_clock.c b/libgfortran/intrinsics/system_clock.c index 3715562..3a44dd9 100644 --- a/libgfortran/intrinsics/system_clock.c +++ b/libgfortran/intrinsics/system_clock.c @@ -29,6 +29,75 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see #include "time_1.h" +#ifdef HAVE_CLOCK_GETTIME +/* POSIX states that CLOCK_REALTIME must be present if clock_gettime + is available, others are optional. */ +#ifdef CLOCK_MONOTONIC +#define GF_CLOCK_MONOTONIC CLOCK_MONOTONIC +#else +#define GF_CLOCK_MONOTONIC CLOCK_REALTIME +#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. + + 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 + targets. */ +#ifndef GTHREAD_USE_WEAK +#define GTHREAD_USE_WEAK 1 +#endif + +#if SUPPORTS_WEAK && GTHREAD_USE_WEAK +static int weak_gettime (clockid_t, struct timespec *) + __attribute__((__weakref__("clock_gettime"))); +#else +static inline int weak_gettime (clockid_t clk_id, struct timespec *res) +{ + return clock_gettime (clk_id, res); +} +#endif +#endif + + +/* High resolution monotonic clock, falling back to the realtime clock + if the target does not support such a clock. + + Arguments: + secs - OUTPUT, seconds + nanosecs - OUTPUT, nanoseconds + + If the target supports a monotonic clock, the OUTPUT arguments + represent a monotonically incrementing clock starting from some + unspecified time in the past. + + If a monotonic clock is not available, falls back to the realtime + clock which is not monotonic. + + Return value: 0 for success, -1 for error. In case of error, errno + is set. +*/ +static inline int +gf_gettime_mono (time_t * secs, long * nanosecs) +{ + int err; +#ifdef HAVE_CLOCK_GETTIME + if (weak_gettime) + { + struct timespec ts; + err = weak_gettime (GF_CLOCK_MONOTONIC, &ts); + *secs = ts.tv_sec; + *nanosecs = ts.tv_nsec; + return err; + } +#endif + err = gf_gettime (secs, nanosecs); + *nanosecs *= 1000; + return err; +} + extern void system_clock_4 (GFC_INTEGER_4 *, GFC_INTEGER_4 *, GFC_INTEGER_4 *); export_proto(system_clock_4); @@ -56,7 +125,7 @@ system_clock_4(GFC_INTEGER_4 *count, GFC_INTEGER_4 *count_rate, if (sizeof (secs) < sizeof (GFC_INTEGER_4)) internal_error (NULL, "secs too small"); - if (gf_gettime (GF_CLOCK_MONOTONIC, &secs, &nanosecs) == 0) + if (gf_gettime_mono (&secs, &nanosecs) == 0) { GFC_UINTEGER_4 ucnt = (GFC_UINTEGER_4) secs * TCK; ucnt += (nanosecs + 500000000 / TCK) / (1000000000 / TCK); @@ -103,7 +172,7 @@ system_clock_8 (GFC_INTEGER_8 *count, GFC_INTEGER_8 *count_rate, if (sizeof (secs) < sizeof (GFC_INTEGER_4)) internal_error (NULL, "secs too small"); - if (gf_gettime (GF_CLOCK_MONOTONIC, &secs, &nanosecs) == 0) + if (gf_gettime_mono (&secs, &nanosecs) == 0) { GFC_UINTEGER_8 ucnt = (GFC_UINTEGER_8) secs * TCK; ucnt += (nanosecs + 500000000 / TCK) / (1000000000 / TCK); diff --git a/libgfortran/intrinsics/time_1.h b/libgfortran/intrinsics/time_1.h index 86e4331..073595a 100644 --- a/libgfortran/intrinsics/time_1.h +++ b/libgfortran/intrinsics/time_1.h @@ -175,87 +175,40 @@ gf_cputime (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_MONOTONIC GF_CLOCK_REALTIME -#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. */ -#ifdef HAVE_CLOCK_GETTIME -#ifdef SUPPORTS_WEAK -static int weak_gettime (clockid_t, struct timespec *) - __attribute__((__weakref__("clock_gettime"))); -#else -static inline int weak_gettime (clockid_t clk_id, struct timespec *res) -{ - return clock_gettime (clk_id, res); -} -#endif -#endif +/* Realtime clock with microsecond resolution, falling back to less + precise functions if the target does not support gettimeofday(). -/* Arguments: - clock_id - INPUT, must be either GF_CLOCK_REALTIME or GF_CLOCK_MONOTONIC + Arguments: secs - OUTPUT, seconds - nanosecs - OUTPUT, OPTIONAL, nanoseconds + usecs - OUTPUT, microseconds - 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. + The OUTPUT arguments shall represent the number of seconds and + nanoseconds since the Epoch. 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) +gf_gettime (time_t * secs, long * usecs) { -#ifdef HAVE_CLOCK_GETTIME - if (weak_gettime) - { - struct timespec ts; - int err; - err = weak_gettime (clock_id, &ts); - *secs = ts.tv_sec; - if (nanosecs) - *nanosecs = ts.tv_nsec; - return err; - } -#endif #ifdef HAVE_GETTIMEOFDAY struct timeval tv; int err; err = gettimeofday (&tv, NULL); *secs = tv.tv_sec; - if (nanosecs) - *nanosecs = tv.tv_usec * 1000; + *usecs = tv.tv_usec; return err; #elif HAVE_TIME time_t t, t2; t = time (&t2); *secs = t2; - if (nanosecs) - *nanosecs = 0; + *usecs = 0; if (t == ((time_t)-1)) return -1; return 0; #else *secs = 0; - if (nanosecs) - *nanosecs = 0; + *usecs = 0; errno = ENOSYS; return -1; #endif |