diff --git a/configure.in b/configure.in index 62aaf72..639e1c4 100644 --- a/configure.in +++ b/configure.in @@ -1749,6 +1749,7 @@ AC_CHECK_FUNCS(_setjmpex) # used for AC_ARG_WITH(setjmp-type) AC_CHECK_FUNCS(chroot) AC_CHECK_FUNCS(chsize) AC_CHECK_FUNCS(clock_gettime) +AC_CHECK_FUNCS(mach_absolute_time) AC_CHECK_FUNCS(cosh) AC_CHECK_FUNCS(daemon) AC_CHECK_FUNCS(dl_iterate_phdr) diff --git a/process.c b/process.c index b3a9282..36d8a75 100644 --- a/process.c +++ b/process.c @@ -74,6 +74,9 @@ #ifdef HAVE_SYS_TIMES_H #include #endif +#ifdef HAVE_MACH_ABSOLUTE_TIME +#include +#endif #ifdef HAVE_PWD_H #include @@ -6637,6 +6640,44 @@ rb_proc_times(VALUE obj) #define rb_proc_times rb_f_notimplement #endif +#ifdef HAVE_MACH_ABSOLUTE_TIME + +#if SIZEOF_LONG == 8 +# define UINT64toNUM(x) ULONG2NUM(x) +# define NUMtoUINT64(x) NUM2ULONG(x) +#elif defined(HAVE_LONG_LONG) && SIZEOF_LONG_LONG == 8 +# define UINT64toNUM(x) ULL2NUM(x) +# define NUMtoUINT64(x) NUM2ULL(x) +#endif + +static mach_timebase_info_data_t sTimebaseInfo; + +/* + * call-seq: + * Process.mach_absolute_time() -> number + * + * Returns an absolute number representing the time and is CPU dependent. + */ +static VALUE +rb_mach_absolute_time(VALUE mod) +{ + return UINT64toNUM(mach_absolute_time()); +} + +static VALUE +rb_absolute_to_ns(VALUE mod, VALUE _abs) +{ + uint64_t abs; + uint64_t ns; + + abs = NUMtoUINT64(_abs); + ns = abs * sTimebaseInfo.numer / sTimebaseInfo.denom; + + return UINT64toNUM(ns); +} + +#endif + /* * call-seq: * Process.clock_gettime(clk_id [, unit]) -> number @@ -7107,6 +7148,12 @@ Init_process(void) #endif rb_define_module_function(rb_mProcess, "clock_gettime", rb_clock_gettime, -1); +#ifdef HAVE_MACH_ABSOLUTE_TIME + rb_define_module_function(rb_mProcess, "mach_absolute_time", rb_mach_absolute_time, 0); + rb_define_module_function(rb_mProcess, "absolute_to_ns", rb_absolute_to_ns, 1); + mach_timebase_info(&sTimebaseInfo); +#endif + #if defined(HAVE_TIMES) || defined(_WIN32) rb_cProcessTms = rb_struct_define("Tms", "utime", "stime", "cutime", "cstime", NULL); #endif diff --git a/test/ruby/test_process.rb b/test/ruby/test_process.rb index 2e7f3a4..ef766d8 100644 --- a/test/ruby/test_process.rb +++ b/test/ruby/test_process.rb @@ -1669,4 +1669,15 @@ EOS assert_raise(Errno::EINVAL) { Process.clock_gettime(:foo) } end + def test_mach_absolute_time + x = 3.times.map { Process.mach_absolute_time } + x.each_cons(2) { |l,r| assert_operator(l, :<=, r) } + end if Process.respond_to?(:mach_absolute_time) + + def test_absolute_to_ns + x = 3.times.map { Process.mach_absolute_time } + x.each_cons(2) { |l,r| + assert_operator(Process.absolute_to_ns(r - l), :>, 0) + } + end if Process.respond_to?(:mach_absolute_time) end