Improve precision of clock() function on Linux
authorSiddhesh Poyarekar <siddhesh@redhat.com>
Thu, 13 Jun 2013 04:24:35 +0000 (09:54 +0530)
committerSiddhesh Poyarekar <siddhesh@redhat.com>
Thu, 13 Jun 2013 04:24:35 +0000 (09:54 +0530)
Resolves #12515.

Use CLOCK_PROCESS_CPUTIME_ID instead of times to get better precision
in the value returned by clock.

ChangeLog
NEWS
sysdeps/unix/sysv/linux/clock.c

index d08f0a6b2e39c4782d3ff3f6f8f8ea01759bc52d..0452a7c739f054f9b6e85e07d87ca9821beb21d6 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,9 @@
+2013-06-13  Siddhesh Poyarekar  <siddhesh@redhat.com>
+
+       [BZ #12515]
+       * sysdeps/unix/sysv/linux/clock.c (clock): Use result from
+       CLOCK_PROCESS_CPUTIME_ID clock instead of __times.
+
 2013-06-11  Adhemerval Zanella  <azanella@linux.vnet.ibm.com>
 
        [BZ #15605]
diff --git a/NEWS b/NEWS
index 782010d1577615c6ecdbf7d4080a6f8ca31ba46c..354db75cf83cbaadc070228f69a3b314168959ea 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -10,16 +10,16 @@ Version 2.18
 * The following bugs are resolved with this release:
 
   2546, 2560, 5159, 6809, 10060, 10062, 10357, 10686, 11120, 11561, 12387,
-  12723, 13550, 13889, 13951, 13988, 14142, 14176, 14200, 14256, 14280,
-  14293, 14317, 14327, 14478, 14496, 14582, 14686, 14812, 14888, 14894,
-  14908, 14920, 14952, 14964, 14981, 14982, 14985, 14991, 14994, 14996,
-  15000, 15003, 15006, 15007, 15014, 15020, 15023, 15036, 15054, 15055,
-  15062, 15078, 15084, 15085, 15086, 15100, 15160, 15214, 15221, 15232,
-  15234, 15283, 15285, 15287, 15304, 15305, 15307, 15309, 15327, 15330,
-  15335, 15336, 15337, 15339, 15342, 15346, 15359, 15361, 15366, 15380,
-  15381, 15394, 15395, 15405, 15406, 15409, 15416, 15418, 15419, 15423,
-  15424, 15426, 15429, 15441, 15442, 15448, 15465, 15480, 15485, 15488,
-  15490, 15493, 15497, 15506, 15529, 15536, 15553, 15577, 15583.
+  12515, 12723, 13550, 13889, 13951, 13988, 14142, 14176, 14200, 14256,
+  14280, 14293, 14317, 14327, 14478, 14496, 14582, 14686, 14812, 14888,
+  14894, 14908, 14920, 14952, 14964, 14981, 14982, 14985, 14991, 14994,
+  14996, 15000, 15003, 15006, 15007, 15014, 15020, 15023, 15036, 15054,
+  15055, 15062, 15078, 15084, 15085, 15086, 15100, 15160, 15214, 15221,
+  15232, 15234, 15283, 15285, 15287, 15304, 15305, 15307, 15309, 15327,
+  15330, 15335, 15336, 15337, 15339, 15342, 15346, 15359, 15361, 15366,
+  15380, 15381, 15394, 15395, 15405, 15406, 15409, 15416, 15418, 15419,
+  15423, 15424, 15426, 15429, 15441, 15442, 15448, 15465, 15480, 15485,
+  15488, 15490, 15493, 15497, 15506, 15529, 15536, 15553, 15577, 15583.
 
 * CVE-2013-0242 Buffer overrun in regexp matcher has been fixed (Bugzilla
   #15078).
@@ -41,6 +41,8 @@ Version 2.18
 
 * New <math.h> macro named issignaling to check for a signaling NaN (sNaN).
   It is based on draft TS 18661 and currently enabled as a GNU extension.
+
+* Improved precision of the clock() function on Linux.
 \f
 Version 2.17
 
index 5268d33c73a27686f2b3c30fba9af343dfa0ac7d..16036bd1399b74798b4c27e6785e8424969bd638 100644 (file)
@@ -1,4 +1,5 @@
-/* Copyright (C) 1991-2013 Free Software Foundation, Inc.
+/* Return the time used by the program so far (user time + system time).
+   Copyright (C) 1991-2013 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
 
    The GNU C Library is free software; you can redistribute it and/or
 #include <time.h>
 #include <unistd.h>
 
-/* Return the time used by the program so far (user time + system time).  */
+#if CLOCKS_PER_SEC != 1000000l
+# error "CLOCKS_PER_SEC should be 1000000"
+#endif
+
 clock_t
 clock (void)
 {
-  struct tms buf;
-  long clk_tck = __sysconf (_SC_CLK_TCK);
-
-  /* We don't check for errors here.  The only error the kernel
-     returns is EFAULT if the value cannot be written to the struct we
-     pass a pointer to.  Otherwise the kernel returns an `unsigned
-     long' value which is the number of jiffies since system start.
-     But this number can be negative (when read as `long') when the
-     system is up for some time.  Ignoring errors should therefore
-     have no negative impacts but solve the problem.  */
-  __times (&buf);
-
-  return
-    (clk_tck <= CLOCKS_PER_SEC)
-    ? ((unsigned long) buf.tms_utime + buf.tms_stime) * (CLOCKS_PER_SEC
-                                                        / clk_tck)
-    : ((unsigned long) buf.tms_utime + buf.tms_stime) / (clk_tck
-                                                        / CLOCKS_PER_SEC);
+  struct timespec ts;
+
+  /* clock_gettime shouldn't fail here since CLOCK_PROCESS_CPUTIME_ID is
+     supported since 2.6.12.  Check the return value anyway in case the kernel
+     barfs on us for some reason.  */
+  if (__glibc_unlikely (__clock_gettime (CLOCK_PROCESS_CPUTIME_ID, &ts) != 0))
+    return (clock_t) -1;
+
+  return (ts.tv_sec * CLOCKS_PER_SEC
+         + ts.tv_nsec / (1000000000 / CLOCKS_PER_SEC));
 }