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

ruby-changes:19414

From: kosaki <ko1@a...>
Date: Sat, 7 May 2011 02:39:44 +0900 (JST)
Subject: [ruby-changes:19414] Ruby:r31454 (trunk): mutex: deadlock check timeout use monotonic time.

kosaki	2011-05-07 02:39:32 +0900 (Sat, 07 May 2011)

  New Revision: 31454

  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=rev&revision=31454

  Log:
    mutex: deadlock check timeout use monotonic time.
    
    * thread_pthread.c (native_cond_timeout): new internal api.
      it calculate a proper time for argument of native_cond_timedwait().
    * thread_win32.c (native_cond_timeout): ditto.
    
    * thread_pthread.c (thread_timer): use native_cond_timeout()
      instead of get_ts.
    * thread.c (lock_func): ditto.
    
    * thread_pthread.c (get_ts): removed. use native_cond_timeout().
    * thread.c (init_lock_timeout): ditto.

  Modified files:
    trunk/ChangeLog
    trunk/thread.c
    trunk/thread_pthread.c
    trunk/thread_win32.c

Index: thread_win32.c
===================================================================
--- thread_win32.c	(revision 31453)
+++ thread_win32.c	(revision 31454)
@@ -489,6 +489,29 @@
     return __cond_timedwait(cond, mutex, timeout_ms);
 }
 
+static struct timespec
+native_cond_timeout(rb_thread_cond_t *cond, struct timespec timeout_rel)
+{
+    int ret;
+    struct timeval tv;
+    struct timespec timeout;
+
+    ret = gettimeofday(&tv, 0);
+    if (ret != 0)
+	rb_sys_fail(0);
+    timeout.tv_sec = tv.tv_sec;
+    timeout.tv_nsec = tv.tv_usec * 1000;
+
+    timeout.tv_sec += timeout_rel.tv_sec;
+    timeout.tv_nsec += timeout_rel.tv_nsec;
+    if (timeout.tv_nsec >= 1000*1000*1000) {
+	timeout.tv_sec++;
+	timeout.tv_nsec -= 1000*1000*1000;
+    }
+    return timeout;
+}
+
+
 static void
 native_cond_initialize(rb_thread_cond_t *cond, int flags)
 {
Index: ChangeLog
===================================================================
--- ChangeLog	(revision 31453)
+++ ChangeLog	(revision 31454)
@@ -1,3 +1,18 @@
+Sat May  7 02:29:41 2011  KOSAKI Motohiro  <kosaki.motohiro@g...>
+
+	  mutex: deadlock check timeout use monotonic time.
+
+	* thread_pthread.c (native_cond_timeout): new internal api.
+	  it calculate a proper time for argument of native_cond_timedwait().
+	* thread_win32.c (native_cond_timeout): ditto.
+
+	* thread_pthread.c (thread_timer): use native_cond_timeout()
+	  instead of get_ts.
+	* thread.c (lock_func): ditto.
+
+	* thread_pthread.c (get_ts): removed. use native_cond_timeout().
+	* thread.c (init_lock_timeout): ditto.
+
 Sat May  7 01:54:21 2011  KOSAKI Motohiro  <kosaki.motohiro@g...>
 
 	* thread_pthread.c (get_ts): add monotonic clock capability.
Index: thread_pthread.c
===================================================================
--- thread_pthread.c	(revision 31453)
+++ thread_pthread.c	(revision 31454)
@@ -295,6 +295,41 @@
     return r;
 }
 
+static struct timespec
+native_cond_timeout(rb_thread_cond_t *cond, struct timespec timeout_rel)
+{
+    int ret;
+    struct timeval tv;
+    struct timespec timeout;
+
+#if USE_MONOTONIC_COND
+    if (cond->clockid == CLOCK_MONOTONIC) {
+	ret = clock_gettime(cond->clockid, &timeout);
+	if (ret != 0)
+	    rb_sys_fail("clock_gettime()");
+	goto out;
+    }
+#endif
+
+    if (cond->clockid != CLOCK_REALTIME)
+	rb_bug("unsupported clockid %d", cond->clockid);
+
+    ret = gettimeofday(&tv, 0);
+    if (ret != 0)
+	rb_sys_fail(0);
+    timeout.tv_sec = tv.tv_sec;
+    timeout.tv_nsec = tv.tv_usec * 1000;
+
+  out:
+    timeout.tv_sec += timeout_rel.tv_sec;
+    timeout.tv_nsec += timeout_rel.tv_nsec;
+    if (timeout.tv_nsec >= 1000*1000*1000) {
+	timeout.tv_sec++;
+	timeout.tv_nsec -= 1000*1000*1000;
+    }
+    return timeout;
+}
+
 #define native_cleanup_push pthread_cleanup_push
 #define native_cleanup_pop  pthread_cleanup_pop
 #ifdef HAVE_SCHED_YIELD
@@ -917,49 +952,23 @@
 static rb_thread_cond_t timer_thread_cond;
 static pthread_mutex_t timer_thread_lock = PTHREAD_MUTEX_INITIALIZER;
 
-static struct timespec *
-get_ts(struct timespec *ts, unsigned long nsec)
-{
-    int ret;
-    struct timeval tv;
-
-#if USE_MONOTONIC_COND
-    if (timer_thread_cond.clockid == CLOCK_MONOTONIC) {
-	ret = clock_gettime(CLOCK_MONOTONIC, ts);
-	if (ret != 0)
-	    rb_sys_fail("clock_gettime(CLOCK_MONOTONIC)");
-	goto out;
-    }
-#endif
-
-    if (timer_thread_cond.clockid != CLOCK_REALTIME)
-	rb_bug("unsupported clockid %d", timer_thread_cond.clockid);
-
-    ret = gettimeofday(&tv, 0);
-    if (ret != 0)
-	rb_sys_fail(0);
-    ts->tv_sec = tv.tv_sec;
-    ts->tv_nsec = tv.tv_usec * 1000;
-
-  out:
-    ts->tv_nsec += nsec;
-    if (ts->tv_nsec >= PER_NANO) {
-	ts->tv_sec++;
-	ts->tv_nsec -= PER_NANO;
-    }
-    return ts;
-}
-
 static void *
 thread_timer(void *dummy)
 {
-    struct timespec ts;
+    struct timespec timeout_10ms;
 
+    timeout_10ms.tv_sec = 0;
+    timeout_10ms.tv_nsec = 10 * 1000 * 1000;
+
     native_mutex_lock(&timer_thread_lock);
     native_cond_broadcast(&timer_thread_cond);
-#define WAIT_FOR_10MS() native_cond_timedwait(&timer_thread_cond, &timer_thread_lock, get_ts(&ts, PER_NANO/100))
     while (system_working > 0) {
-	int err = WAIT_FOR_10MS();
+	int err;
+	struct timespec timeout;
+
+	timeout = native_cond_timeout(&timer_thread_cond, timeout_10ms);
+	err = native_cond_timedwait(&timer_thread_cond, &timer_thread_lock,
+				    &timeout);
 	if (err == ETIMEDOUT);
 	else if (err == 0 || err == EINTR) {
 	    if (rb_signal_buff_size() == 0) break;
Index: thread.c
===================================================================
--- thread.c	(revision 31453)
+++ thread.c	(revision 31454)
@@ -3336,7 +3336,7 @@
 
     obj = TypedData_Make_Struct(klass, mutex_t, &mutex_data_type, mutex);
     native_mutex_initialize(&mutex->lock);
-    native_cond_initialize(&mutex->cond, 0);
+    native_cond_initialize(&mutex->cond, RB_CONDATTR_CLOCK_MONOTONIC);
     return obj;
 }
 
@@ -3410,26 +3410,6 @@
     return locked;
 }
 
-static struct timespec init_lock_timeout(int timeout_ms)
-{
-    struct timespec ts;
-    struct timeval tv;
-    int ret;
-
-    ret = gettimeofday(&tv, NULL);
-    if (ret < 0)
-	rb_sys_fail(0);
-
-    ts.tv_sec = tv.tv_sec;
-    ts.tv_nsec = tv.tv_usec * 1000 + timeout_ms * 1000 * 1000;
-    if (ts.tv_nsec >= 1000000000) {
-	ts.tv_sec++;
-	ts.tv_nsec -= 1000000000;
-    }
-
-    return ts;
-}
-
 static int
 lock_func(rb_thread_t *th, mutex_t *mutex, int timeout_ms)
 {
@@ -3438,9 +3418,6 @@
     native_mutex_lock(&mutex->lock);
     th->transition_for_lock = 0;
     for (;;) {
-	struct timespec ts;
-	int ret;
-
 	if (!mutex->th) {
 	    mutex->th = th;
 	    break;
@@ -3448,8 +3425,14 @@
 
 	mutex->cond_waiting++;
 	if (timeout_ms) {
-	    ts = init_lock_timeout(timeout_ms);
-	    ret = native_cond_timedwait(&mutex->cond, &mutex->lock, &ts);
+	    int ret;
+	    struct timespec timeout_rel;
+	    struct timespec timeout;
+
+	    timeout_rel.tv_sec = 0;
+	    timeout_rel.tv_nsec = timeout_ms * 1000 * 1000;
+	    timeout = native_cond_timeout(&mutex->cond, timeout_rel);
+	    ret = native_cond_timedwait(&mutex->cond, &mutex->lock, &timeout);
 	    if (ret == ETIMEDOUT) {
 		interrupted = 2;
 		break;

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

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