[前][次][番号順一覧][スレッド一覧]

ruby-changes:52326

From: normal <ko1@a...>
Date: Sat, 25 Aug 2018 15:58:42 +0900 (JST)
Subject: [ruby-changes:52326] normal:r64533 (trunk): thread.c: use rb_hrtime_t scalar for high-resolution time operations

normal	2018-08-25 15:58:35 +0900 (Sat, 25 Aug 2018)

  New Revision: 64533

  https://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=revision&revision=64533

  Log:
    thread.c: use rb_hrtime_t scalar for high-resolution time operations
    
    Relying on "struct timespec" was too annoying API-wise and
    used more stack space.  "double" was a bit wacky w.r.t rounding
    in the past, so now we'll switch to using a 64-bit type.
    
    Unsigned 64-bit integer is able to give us over nearly 585
    years of range with nanoseconds.  This range is good enough
    for the Linux kernel internal time representation, so it
    ought to be good enough for us.
    
    This reduces the stack usage of functions while GVL is held
    (and thus subject to marking) on x86-64 Linux (with ppoll):
    
    rb_wait_for_single_fd    120 => 104
    do_select                120 => 88
    
    [ruby-core:88582] [Misc #15014]

  Added files:
    trunk/hrtime.h
  Modified files:
    trunk/common.mk
    trunk/thread.c
    trunk/thread_pthread.c
    trunk/thread_sync.c
    trunk/thread_win32.c
Index: thread_win32.c
===================================================================
--- thread_win32.c	(revision 64532)
+++ thread_win32.c	(revision 64533)
@@ -276,11 +276,16 @@ rb_w32_Sleep(unsigned long msec) https://github.com/ruby/ruby/blob/trunk/thread_win32.c#L276
     return ret;
 }
 
+static DWORD
+hrtime2msec(rb_hrtime_t hrt)
+{
+    return (DWORD)hrt / (DWORD)RB_HRTIME_PER_MSEC;
+}
+
 static void
-native_sleep(rb_thread_t *th, struct timespec *ts)
+native_sleep(rb_thread_t *th, rb_hrtime_t *rel)
 {
-    const volatile DWORD msec = (ts) ?
-	(DWORD)(ts->tv_sec * 1000 + ts->tv_nsec / 1000000) : INFINITE;
+    const volatile DWORD msec = rel ? hrtime2msec(*rel) : INFINITE;
 
     GVL_UNLOCK_BEGIN(th);
     {
Index: thread_sync.c
===================================================================
--- thread_sync.c	(revision 64532)
+++ thread_sync.c	(revision 64533)
@@ -248,8 +248,8 @@ do_mutex_lock(VALUE self, int interrupti https://github.com/ruby/ruby/blob/trunk/thread_sync.c#L248
 
 	while (mutex->th != th) {
 	    enum rb_thread_status prev_status = th->status;
-	    struct timespec *timeout = 0;
-	    struct timespec ts = { 0, 100000000 }; /* 100ms */
+	    rb_hrtime_t *timeout = 0;
+	    rb_hrtime_t rel = rb_msec2hrtime(100);
 
 	    th->status = THREAD_STOPPED_FOREVER;
 	    th->locking_mutex = self;
@@ -261,7 +261,7 @@ do_mutex_lock(VALUE self, int interrupti https://github.com/ruby/ruby/blob/trunk/thread_sync.c#L261
 	     */
 	    if ((vm_living_thread_num(th->vm) == th->vm->sleeper) &&
 		!patrol_thread) {
-		timeout = &ts;
+		timeout = &rel;
 		patrol_thread = th;
 	    }
 
@@ -458,8 +458,9 @@ rb_mutex_sleep_forever(VALUE time) https://github.com/ruby/ruby/blob/trunk/thread_sync.c#L458
 static VALUE
 rb_mutex_wait_for(VALUE time)
 {
-    struct timespec *t = (struct timespec*)time;
-    sleep_timespec(GET_THREAD(), *t, 0); /* permit spurious check */
+    rb_hrtime_t *rel = (rb_hrtime_t *)time;
+    /* permit spurious check */
+    sleep_hrtime(GET_THREAD(), *rel, 0);
     return Qnil;
 }
 
@@ -472,16 +473,17 @@ rb_mutex_sleep(VALUE self, VALUE timeout https://github.com/ruby/ruby/blob/trunk/thread_sync.c#L473
     if (!NIL_P(timeout)) {
         t = rb_time_interval(timeout);
     }
+
     rb_mutex_unlock(self);
     beg = time(0);
     if (NIL_P(timeout)) {
 	rb_ensure(rb_mutex_sleep_forever, Qnil, mutex_lock_uninterruptible, self);
     }
     else {
-        struct timespec ts;
-        VALUE tsp = (VALUE)timespec_for(&ts, &t);
+        rb_hrtime_t rel = rb_timeval2hrtime(&t);
 
-        rb_ensure(rb_mutex_wait_for, tsp, mutex_lock_uninterruptible, self);
+        rb_ensure(rb_mutex_wait_for, (VALUE)&rel,
+                  mutex_lock_uninterruptible, self);
     }
     RUBY_VM_CHECK_INTS_BLOCKING(GET_EC());
     end = time(0) - beg;
Index: thread_pthread.c
===================================================================
--- thread_pthread.c	(revision 64532)
+++ thread_pthread.c	(revision 64533)
@@ -123,9 +123,9 @@ static void clear_thread_cache_altstack( https://github.com/ruby/ruby/blob/trunk/thread_pthread.c#L123
 static void ubf_wakeup_all_threads(void);
 static int ubf_threads_empty(void);
 static int native_cond_timedwait(rb_nativethread_cond_t *, pthread_mutex_t *,
-                                 const struct timespec *);
-static const struct timespec *sigwait_timeout(rb_thread_t *, int sigwait_fd,
-                                              const struct timespec *,
+                                 const rb_hrtime_t *abs);
+static const rb_hrtime_t *sigwait_timeout(rb_thread_t *, int sigwait_fd,
+                                              const rb_hrtime_t *,
                                               int *drained_p);
 static void ubf_timer_disarm(void);
 static void threadptr_trap_interrupt(rb_thread_t *);
@@ -159,8 +159,7 @@ static const void *const condattr_monoto https://github.com/ruby/ruby/blob/trunk/thread_pthread.c#L159
 #define TIME_QUANTUM_USEC (TIME_QUANTUM_MSEC * 1000)
 #define TIME_QUANTUM_NSEC (TIME_QUANTUM_USEC * 1000)
 
-static struct timespec native_cond_timeout(rb_nativethread_cond_t *,
-                                           struct timespec rel);
+static rb_hrtime_t native_cond_timeout(rb_nativethread_cond_t *, rb_hrtime_t);
 
 /*
  * Designate the next gvl.timer thread, favor the last thread in
@@ -186,19 +185,17 @@ designate_timer_thread(rb_vm_t *vm) https://github.com/ruby/ruby/blob/trunk/thread_pthread.c#L185
 static void
 do_gvl_timer(rb_vm_t *vm, rb_thread_t *th)
 {
-    static struct timespec ts;
+    static rb_hrtime_t abs;
     native_thread_data_t *nd = &th->native_thread_data;
 
     /* take over wakeups from UBF_TIMER */
     ubf_timer_disarm();
 
     if (vm->gvl.timer_err == ETIMEDOUT) {
-        ts.tv_sec = 0;
-        ts.tv_nsec = TIME_QUANTUM_NSEC;
-        ts = native_cond_timeout(&nd->cond.gvlq, ts);
+        abs = native_cond_timeout(&nd->cond.gvlq, TIME_QUANTUM_NSEC);
     }
     vm->gvl.timer = th;
-    vm->gvl.timer_err = native_cond_timedwait(&nd->cond.gvlq, &vm->gvl.lock, &ts);
+    vm->gvl.timer_err = native_cond_timedwait(&nd->cond.gvlq, &vm->gvl.lock, &abs);
     vm->gvl.timer = 0;
 
     ubf_wakeup_all_threads();
@@ -499,9 +496,11 @@ rb_native_cond_wait(rb_nativethread_cond https://github.com/ruby/ruby/blob/trunk/thread_pthread.c#L496
 }
 
 static int
-native_cond_timedwait(rb_nativethread_cond_t *cond, pthread_mutex_t *mutex, const struct timespec *ts)
+native_cond_timedwait(rb_nativethread_cond_t *cond, pthread_mutex_t *mutex,
+                      const rb_hrtime_t *abs)
 {
     int r;
+    struct timespec ts;
 
     /*
      * An old Linux may return EINTR. Even though POSIX says
@@ -510,7 +509,7 @@ native_cond_timedwait(rb_nativethread_co https://github.com/ruby/ruby/blob/trunk/thread_pthread.c#L509
      * Let's hide it from arch generic code.
      */
     do {
-	r = pthread_cond_timedwait(cond, mutex, ts);
+	r = pthread_cond_timedwait(cond, mutex, rb_hrtime2timespec(&ts, abs));
     } while (r == EINTR);
 
     if (r != 0 && r != ETIMEDOUT) {
@@ -520,20 +519,18 @@ native_cond_timedwait(rb_nativethread_co https://github.com/ruby/ruby/blob/trunk/thread_pthread.c#L519
     return r;
 }
 
-static struct timespec
-native_cond_timeout(rb_nativethread_cond_t *cond, struct timespec timeout_rel)
+static rb_hrtime_t
+native_cond_timeout(rb_nativethread_cond_t *cond, const rb_hrtime_t rel)
 {
-    struct timespec abs;
-
     if (condattr_monotonic) {
-        getclockofday(&abs);
+        return rb_hrtime_add(rb_hrtime_now(), rel);
     }
     else {
-        rb_timespec_now(&abs);
-    }
-    timespec_add(&abs, &timeout_rel);
+        struct timespec ts;
 
-    return abs;
+        rb_timespec_now(&ts);
+        return rb_hrtime_add(rb_timespec2hrtime(&ts), rel);
+    }
 }
 
 #define native_cleanup_push pthread_cleanup_push
@@ -1056,13 +1053,13 @@ thread_cache_reset(void) https://github.com/ruby/ruby/blob/trunk/thread_pthread.c#L1053
  * worst case network latency across the globe) without wasting memory
  */
 #ifndef THREAD_CACHE_TIME
-#  define THREAD_CACHE_TIME 3
+#  define THREAD_CACHE_TIME ((rb_hrtime_t)3 * RB_HRTIME_PER_SEC)
 #endif
 
 static rb_thread_t *
 register_cached_thread_and_wait(void *altstack)
 {
-    struct timespec end = { THREAD_CACHE_TIME, 0 };
+    rb_hrtime_t end = THREAD_CACHE_TIME;
     struct cached_thread_entry entry;
 
     rb_native_cond_initialize(&entry.cond);
@@ -1218,28 +1215,20 @@ ubf_pthread_cond_signal(void *ptr) https://github.com/ruby/ruby/blob/trunk/thread_pthread.c#L1215
 }
 
 static void
-native_cond_sleep(rb_thread_t *th, struct timespec *timeout_rel)
+native_cond_sleep(rb_thread_t *th, rb_hrtime_t *rel)
 {
-    struct timespec timeout;
     rb_nativethread_lock_t *lock = &th->interrupt_lock;
     rb_nativethread_cond_t *cond = &th->native_thread_data.cond.intr;
 
-    if (timeout_rel) {
-	/* Solaris cond_timedwait() return EINVAL if an argument is greater than
-	 * current_time + 100,000,000.  So cut up to 100,000,000.  This is
-	 * considered as a kind of spurious wakeup.  The caller to native_sleep
-	 * should care about spurious wakeup.
-	 *
-	 * See also [Bug #1341] [ruby-core:29702]
-	 * http://download.oracle.com/docs/cd/E19683-01/816-0216/6m6ngupgv/index.html
-	 */
-	if (timeout_rel->tv_sec > 100000000) {
-	    timeout_rel->tv_sec = 100000000;
-	    timeout_rel->tv_nsec = 0;
-	}
-
-	timeout = native_cond_timeout(cond, *timeout_rel);
-    }
+    /* Solaris cond_timedwait() return EINVAL if an argument is greater than
+     * current_time + 100,000,000.  So cut up to 100,000,000.  This is
+     * considered as a kind of spurious wakeup.  The caller to native_sleep
+     * should care about spurious wakeup.
+     *
+     * See also [Bug #1341] [ruby-core:29702]
+     * http://download.oracle.com/docs/cd/E19683-01/816-0216/6m6ngupgv/index.html
+     */
+    const rb_hrtime_t max = (rb_hrtime_t)100000000 * RB_HRTIME_PER_SEC;
 
     GVL_UNLOCK_BEGIN(th);
     {
@@ -1252,10 +1241,19 @@ native_cond_sleep(rb_thread_t *th, struc https://github.com/ruby/ruby/blob/trunk/thread_pthread.c#L1241
 	    thread_debug("native_sleep: interrupted before sleep\n");
 	}
 	else {
-	    if (!timeout_rel)
+	    if (!rel) {
 		rb_native_cond_wait(cond, lock);
-	    else
-		native_cond_timedwait(cond, lock, &timeout);
+	    }
+            else {
+                rb_hrtime_t end;
+
+                if (*rel > max) {
+                    *rel = max;
+                }
+
+                end = native_cond_timeout(cond, *rel);
+		native_cond_timedwait(cond, lock, &end);
+            }
 	}
 	th->unblock.func = 0;
 
@@ -1970,15 +1968,12 @@ rb_sigwait_sleep(rb_thread_t *th, int si https://github.com/ruby/ruby/blob/trunk/thread_pthread.c#L1968
         check_signals_nogvl(th, sigwait_fd);
     }
     else {
-        struct timespec end, diff;
-        const struct timespec *to;
+        rb_hrtime_t rel, end;
         int n = 0;
 
         if (ts) {
-            getclockofday(&end);
-            timespec_add(&end, ts);
-            diff = *ts;
-            ts = &diff;
+            rel = rb_timespec2hrtime(ts);
+            end = rb_hrtime_add(rb_hrtime_now(), rel);
         }
         /*
          * tricky: this needs to return on spurious wakeup (no auto-retry).
@@ -1986,21 +1981,23 @@ rb_sigwait_sleep(rb_thread_t *th, int si https://github.com/ruby/ruby/blob/trunk/thread_pthread.c#L1981
          * wakeups, so we care about the result of consume_communication_pipe
          */
         for (;;) {
-            to = sigwait_timeout(th, sigwait_fd, ts, &n);
+            const rb_hrtime_t *sto = sigwait_timeout(th, sigwait_fd, &rel, &n);
+            struct timespec tmp;
+
             if (n) return;
-            n = ppoll(&pfd, 1, to, 0);
+            n = ppoll(&pfd, 1, rb_hrtime2timespec(&tmp, sto), 0);
             if (check_signals_nogvl(th, sigwait_fd))
                 return;
             if (n || (th && RUBY_VM_INTERRUPTED(th->ec)))
                 return;
-            if (ts && timespec_update_expire(&diff, &end))
+            if (ts && hrtime_update_expire(&rel, end))
                 return;
         }
     }
 }
 
 static void
-native_sleep(rb_thread_t *th, struct timespec *timeout_rel)
+native_sleep(rb_thread_t *th, rb_hrtime_t *rel)
 {
     int sigwait_fd = rb_sigwait_fd_get(th);
 
@@ -2012,7 +2009,8 @@ native_sleep(rb_thread_t *th, struct tim https://github.com/ruby/ruby/blob/trunk/thread_pthread.c#L2009
         GVL_UNLOCK_BEGIN(th);
 
         if (!RUBY_VM_INTERRUPTED(th->ec)) {
-            rb_sigwait_sleep(th, sigwait_fd, timeout_rel);
+            struct timespec ts;
+            rb_sigwait_sleep(th, sigwait_fd, rb_hrtime2timespec(&ts, rel));
         }
         else {
             check_signals_nogvl(th, sigwait_fd);
@@ -2023,7 +2021,7 @@ native_sleep(rb_thread_t *th, struct tim https://github.com/ruby/ruby/blob/trunk/thread_pthread.c#L2021
         rb_sigwait_fd_migrate(th->vm);
     }
     else {
-        native_cond_sleep(th, timeout_rel);
+        native_cond_sleep(th, rel);
     }
 }
 
Index: thread.c
===================================================================
--- thread.c	(revision 64532)
+++ thread.c	(revision 64533)
@@ -74,6 +74,7 @@ https://github.com/ruby/ruby/blob/trunk/thread.c#L74
 #include "internal.h"
 #include "iseq.h"
 #include "vm_core.h"
+#include "hrtime.h"
 
 #ifndef USE_NATIVE_THREAD_PRIORITY
 #define USE_NATIVE_THREAD_PRIORITY 0
@@ -97,18 +98,14 @@ enum SLEEP_FLAGS { https://github.com/ruby/ruby/blob/trunk/thread.c#L98
     SLEEP_SPURIOUS_CHECK = 0x2
 };
 
-static void sleep_timespec(rb_thread_t *, struct timespec, unsigned int fl);
+static void sleep_hrtime(rb_thread_t *, rb_hrtime_t, unsigned int fl);
 static void sleep_forever(rb_thread_t *th, unsigned int fl);
 static void rb_thread_sleep_deadly_allow_spurious_wakeup(void);
 static int rb_threadptr_dead(rb_thread_t *th);
 static void rb_check_deadlock(rb_vm_t *vm);
 static int rb_threadptr_pending_interrupt_empty_p(const rb_thread_t *th);
 static const char *thread_status_name(rb_thread_t *th, int detail);
-static void timespec_add(struct timespec *, const struct timespec *);
-static void timespec_sub(struct timespec *, const struct timespec *);
-static int timespec_cmp(const struct timespec *a, const struct timespec *b);
-static int timespec_update_expire(struct timespec *, const struct timespec *);
-static void getclockofday(struct timespec *);
+static int hrtime_update_expire(rb_hrtime_t *, const rb_hrtime_t);
 NORETURN(static void async_bug_fd(const char *mesg, int errno_arg, int fd));
 static int consume_communication_pipe(int fd);
 static int check_signals_nogvl(rb_thread_t *, int sigwait_fd);
@@ -229,40 +226,17 @@ vm_living_thread_num(const rb_vm_t *vm) https://github.com/ruby/ruby/blob/trunk/thread.c#L226
 #  endif
 #endif
 
-static struct timespec *
-timespec_for(struct timespec *ts, const struct timeval *tv)
-{
-    if (tv) {
-        ts->tv_sec = tv->tv_sec;
-        ts->tv_nsec = tv->tv_usec * 1000;
-        return ts;
-    }
-    return 0;
-}
-
-static struct timeval *
-timeval_for(struct timeval *tv, const struct timespec *ts)
-{
-    if (tv && ts) {
-        tv->tv_sec = ts->tv_sec;
-        tv->tv_usec = (int32_t)(ts->tv_nsec / 1000); /* 10**6 < 2**(32-1) */
-        return tv;
-    }
-    return 0;
-}
-
 static void
-timeout_prepare(struct timespec **tsp,
-            struct timespec *ts, struct timespec *end,
-            const struct timeval *timeout)
+timeout_prepare(rb_hrtime_t **to, rb_hrtime_t *rel, rb_hrtime_t *end,
+                const struct timeval *timeout)
 {
     if (timeout) {
-        getclockofday(end);
-        timespec_add(end, timespec_for(ts, timeout));
-        *tsp = ts;
+        *rel = rb_timeval2hrtime(timeout);
+        *end = rb_hrtime_add(rb_hrtime_now(), *rel);
+        *to = rel;
     }
     else {
-	*tsp = 0;
+        *to = 0;
     }
 }
 
@@ -596,13 +570,13 @@ rb_thread_terminate_all(void) https://github.com/ruby/ruby/blob/trunk/thread.c#L570
 	terminate_all(vm, th);
 
 	while (vm_living_thread_num(vm) > 1) {
-	    struct timespec ts = { 1, 0 };
+            rb_hrtime_t rel = RB_HRTIME_PER_SEC;
 	    /*
 	     * Thread exiting routine in thread_start_func_2 notify
 	     * me when the last sub-thread exit.
 	     */
 	    sleeping = 1;
-	    native_sleep(th, &ts);
+	    native_sleep(th, &rel);
 	    RUBY_VM_CHECK_INTS_BLOCKING(ec);
 	    sleeping = 0;
 	}
@@ -931,7 +905,7 @@ rb_thread_create(VALUE (*fn)(ANYARGS), v https://github.com/ruby/ruby/blob/trunk/thread.c#L905
 
 struct join_arg {
     rb_thread_t *target, *waiting;
-    struct timespec *limit;
+    rb_hrtime_t *limit;
 };
 
 static VALUE
@@ -960,11 +934,10 @@ thread_join_sleep(VALUE arg) https://github.com/ruby/ruby/blob/trunk/thread.c#L934
 {
     struct join_arg *p = (struct join_arg *)arg;
     rb_thread_t *target_th = p->target, *th = p->waiting;
-    struct timespec end;
+    rb_hrtime_t end;
 
     if (p->limit) {
-        getclockofday(&end);
-        timespec_add(&end, p->limit);
+        end = rb_hrtime_add(*p->limit, rb_hrtime_now());
     }
 
     while (target_th->status != THREAD_KILLED) {
@@ -976,7 +949,7 @@ thread_join_sleep(VALUE arg) https://github.com/ruby/ruby/blob/trunk/thread.c#L949
 	    th->vm->sleeper--;
 	}
 	else {
-            if (timespec_update_expire(p->limit, &end)) {
+            if (hrtime_update_expire(p->limit, end)) {
 		thread_debug("thread_join: timeout (thid: %"PRI_THREAD_ID")\n",
 			     thread_id_str(target_th));
 		return Qfalse;
@@ -993,7 +966,7 @@ thread_join_sleep(VALUE arg) https://github.com/ruby/ruby/blob/trunk/thread.c#L966
 }
 
 static VALUE
-thread_join(rb_thread_t *target_th, struct timespec *ts)
+thread_join(rb_thread_t *target_th, rb_hrtime_t *rel)
 {
     rb_thread_t *th = GET_THREAD();
     struct join_arg arg;
@@ -1007,7 +980,7 @@ thread_join(rb_thread_t *target_th, stru https://github.com/ruby/ruby/blob/trunk/thread.c#L980
 
     arg.target = target_th;
     arg.waiting = th;
-    arg.limit = ts;
+    arg.limit = rel;
 
     thread_debug("thread_join (thid: %"PRI_THREAD_ID", status: %s)\n",
 		 thread_id_str(target_th), thread_status_name(target_th, TRUE));
@@ -1052,7 +1025,7 @@ thread_join(rb_thread_t *target_th, stru https://github.com/ruby/ruby/blob/trunk/thread.c#L1025
     return target_th->self;
 }
 
-static struct timespec *double2timespec(struct timespec *, double);
+static rb_hrtime_t *double2hrtime(rb_hrtime_t *, double);
 
 /*
  *  call-seq:
@@ -1097,8 +1070,7 @@ static VALUE https://github.com/ruby/ruby/blob/trunk/thread.c#L1070
 thread_join_m(int argc, VALUE *argv, VALUE self)
 {
     VALUE limit;
-    struct timespec timespec;
-    struct timespec *ts = 0;
+    rb_hrtime_t rel, *to = 0;
 
     rb_scan_args(argc, argv, "01", &limit);
 
@@ -1109,17 +1081,14 @@ thread_join_m(int argc, VALUE *argv, VAL https://github.com/ruby/ruby/blob/trunk/thread.c#L1081
     switch (TYPE(limit)) {
       case T_NIL: break;
       case T_FIXNUM:
-        timespec.tv_sec = NUM2TIMET(limit);
-        if (timespec.tv_sec < 0)
-            timespec.tv_sec = 0;
-        timespec.tv_nsec = 0;
-        ts = &timespec;
+        rel = rb_sec2hrtime(NUM2TIMET(limit));
+        to = &rel;
         break;
       default:
-        ts = double2timespec(&timespec, rb_num2dbl(limit));
+        to = double2hrtime(&rel, rb_num2dbl(limit));
     }
 
-    return thread_join(rb_thread_ptr(self), ts);
+    return thread_join(rb_thread_ptr(self), to);
 }
 
 /*
@@ -1158,8 +1127,8 @@ thread_value(VALUE self) https://github.com/ruby/ruby/blob/trunk/thread.c#L1127
 #define TIMESPEC_SEC_MAX TIMET_MAX
 #define TIMESPEC_SEC_MIN TIMET_MIN
 
-static struct timespec *
-double2timespec(struct timespec *ts, double d)
+static rb_hrtime_t *
+double2hrtime(rb_hrtime_t *hrt, double d)
 {
     /* assume timespec.tv_sec has same signedness as time_t */
     const double TIMESPEC_SEC_MAX_PLUS_ONE = TIMET_MAX_PLUS_ONE;
@@ -1168,18 +1137,31 @@ double2timespec(struct timespec *ts, dou https://github.com/ruby/ruby/blob/trunk/thread.c#L1137
         return NULL;
     }
     else if (d <= 0) {
-        ts->tv_sec = 0;
-        ts->tv_nsec = 0;
+        *hrt = 0;
     }
     else {
-        ts->tv_sec = (time_t)d;
-        ts->tv_nsec = (long)((d - (time_t)d) * 1e9);
-        if (ts->tv_nsec < 0) {
-            ts->tv_nsec += (long)1e9;
-            ts->tv_sec -= 1;
-        }
+        *hrt = (rb_hrtime_t)(d * (double)RB_HRTIME_PER_SEC);
     }
-    return ts;
+    return hrt;
+}
+
+static void
+getclockofday(struct timespec *ts)
+{
+#if defined(HAVE_CLOCK_GETTIME) && defined(CLOCK_MONOTONIC)
+    if (clock_gettime(CLOCK_MONOTONIC, ts) == 0)
+        return;
+#endif
+    rb_timespec_now(ts);
+}
+
+rb_hrtime_t
+rb_hrtime_now(void)
+{
+    struct timespec ts;
+
+    getclockofday(&ts);
+    return rb_timespec2hrtime(&ts);
 }
 
 static void
@@ -1208,102 +1190,39 @@ sleep_forever(rb_thread_t *th, unsigned https://github.com/ruby/ruby/blob/trunk/thread.c#L1190
     th->status = prev_status;
 (... truncated)

--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

[前][次][番号順一覧][スレッド一覧]