% svn diff --diff-cmd diff -x '-u -p'
Index: process.c
===================================================================
--- process.c	(revision 42652)
+++ process.c	(working copy)
@@ -6945,6 +6945,133 @@ rb_clock_gettime(int argc, VALUE *argv)
     return make_clock_result(&ts, unit);
 }
 
+/*
+ *  call-seq:
+ *     Process.clock_getres(clock_id [, unit])   -> number
+ *
+ *  Returns a time resolution returned by POSIX clock_getres() function.
+ *
+ *  +clock_id+ specifies a kind of clock.
+ *  See the document of +Process.clock_gettime+ for details.
+ *
+ *  +clock_id+ can be a symbol as +Process.clock_gettime+.
+ *  However the result may not be accurate.
+ *  For example, +Process.clock_getres(:SUS_GETTIMEOFDAY_BASED_CLOCK_REALTIME, :nanosecond)+
+ *  returns 1000, always.
+ *
+ *  If the given +clock_id+ is not supported, Errno::EINVAL is raised.
+ *
+ *  +unit+ specifies a type of the return value.
+ *  +Process.clock_getres+ accepts +unit+ as +Process.clock_gettime+.
+ *  The default value, +:float_second+, is also same as
+ *  +Process.clock_gettime+.
+ *
+ *  +Process.clock_getres+ also accepts +:hertz+ as +unit+.
+ *  +:hertz+ means a the reciprocal of +:float_second+.
+ *
+ *  +:hertz+ can be used to obtain the exact value of
+ *  the clock ticks per second for times() function and
+ *  CLOCK_PER_SEC for clock() function.
+ *
+ *  +Process.clock_getres(:POSIX_TIMES_BASED_CLOCK_PROCESS_CPUTIME_ID, :hertz)+
+ *  returns the clock ticks per second.
+ *
+ *  +Process.clock_getres(:ISO_C_CLOCK_BASED_CLOCK_PROCESS_CPUTIME_ID, :hertz)+
+ *  returns CLOCK_PER_SEC.
+ *
+ *    p Process.clock_getres(Process::CLOCK_MONOTONIC)
+ *    #=> 1.0e-09
+ *
+ */
+VALUE
+rb_clock_getres(int argc, VALUE *argv)
+{
+    struct timespec ts;
+    VALUE clk_id, unit;
+    int ret;
+    double hertz;
+
+    rb_scan_args(argc, argv, "11", &clk_id, &unit);
+
+    if (SYMBOL_P(clk_id)) {
+#ifdef RUBY_SUS_GETTIMEOFDAY_BASED_CLOCK_REALTIME
+        if (clk_id == RUBY_SUS_GETTIMEOFDAY_BASED_CLOCK_REALTIME) {
+            ts.tv_sec = 0;
+            ts.tv_nsec = 1000;
+            goto success;
+        }
+#endif
+
+#ifdef RUBY_ISO_C_TIME_BASED_CLOCK_REALTIME
+        if (clk_id == RUBY_ISO_C_TIME_BASED_CLOCK_REALTIME) {
+            ts.tv_sec = 1;
+            ts.tv_nsec = 0;
+            goto success;
+        }
+#endif
+
+#ifdef RUBY_SUS_GETRUSAGE_BASED_CLOCK_PROCESS_CPUTIME_ID
+        if (clk_id == RUBY_SUS_GETRUSAGE_BASED_CLOCK_PROCESS_CPUTIME_ID) {
+            ts.tv_sec = 0;
+            ts.tv_nsec = 1000;
+            goto success;
+        }
+#endif
+
+#ifdef RUBY_POSIX_TIMES_BASED_CLOCK_PROCESS_CPUTIME_ID
+        if (clk_id == RUBY_POSIX_TIMES_BASED_CLOCK_PROCESS_CPUTIME_ID) {
+            hertz = get_clk_tck();
+            goto success_hertz;
+        }
+#endif
+
+#ifdef RUBY_ISO_C_CLOCK_BASED_CLOCK_PROCESS_CPUTIME_ID
+        if (clk_id == RUBY_ISO_C_CLOCK_BASED_CLOCK_PROCESS_CPUTIME_ID) {
+            hertz = CLOCKS_PER_SEC;
+            goto success_hertz;
+        }
+#endif
+
+#ifdef RUBY_MACH_ABSOLUTE_TIME_BASED_CLOCK_MONOTONIC
+        /* not yet */
+#endif
+    }
+    else {
+#if defined(HAVE_CLOCK_GETTIME)
+        clockid_t c;
+        c = NUM2CLOCKID(clk_id);
+        ret = clock_getres(c, &ts);
+        if (ret == -1)
+            rb_sys_fail("clock_getres");
+        goto success;
+#endif
+    }
+    /* EINVAL emulates clock_getres behavior when clock_id is invalid. */
+    errno = EINVAL;
+    rb_sys_fail(0);
+
+  success_hertz:
+    if (unit == ID2SYM(rb_intern("hertz"))) {
+        return DBL2NUM(hertz);
+    }
+    else {
+        double ns;
+        ns = 1e9 / hertz;
+        ts.tv_sec = (time_t)(ns*1e-9);
+        ts.tv_nsec = ns - ts.tv_sec*1e9;
+        return make_clock_result(&ts, unit);
+    }
+
+  success:
+    if (unit == ID2SYM(rb_intern("hertz"))) {
+        hertz = 1e9 / (ts.tv_sec * 1e9 + ts.tv_nsec);
+        return DBL2NUM(hertz);
+    }
+    else {
+        return make_clock_result(&ts, unit);
+    }
+}
+
 VALUE rb_mProcess;
 VALUE rb_mProcUID;
 VALUE rb_mProcGID;
@@ -7270,6 +7397,7 @@ Init_process(void)
     rb_define_const(rb_mProcess, "CLOCK_SECOND", CLOCKID2NUM(CLOCK_SECOND));
 #endif
     rb_define_module_function(rb_mProcess, "clock_gettime", rb_clock_gettime, -1);
+    rb_define_module_function(rb_mProcess, "clock_getres", rb_clock_getres, -1);
 
 #if defined(HAVE_TIMES) || defined(_WIN32)
     rb_cProcessTms = rb_struct_define("Tms", "utime", "stime", "cutime", "cstime", NULL);
