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

ruby-changes:5927

From: mame <ko1@a...>
Date: Thu, 19 Jun 2008 23:19:11 +0900 (JST)
Subject: [ruby-changes:5927] Ruby:r17435 (trunk): * thread.c, thread_win32.c, vm_core.h: try to remove false positive of

mame	2008-06-19 23:18:46 +0900 (Thu, 19 Jun 2008)

  New Revision: 17435

  Modified files:
    trunk/ChangeLog
    trunk/thread.c
    trunk/thread_win32.c
    trunk/vm_core.h

  Log:
    * thread.c, thread_win32.c, vm_core.h: try to remove false positive of
      deadlock detection.


  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi/trunk/ChangeLog?r1=17435&r2=17434&diff_format=u
  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi/trunk/thread_win32.c?r1=17435&r2=17434&diff_format=u
  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi/trunk/thread.c?r1=17435&r2=17434&diff_format=u
  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi/trunk/vm_core.h?r1=17435&r2=17434&diff_format=u

Index: thread_win32.c
===================================================================
--- thread_win32.c	(revision 17434)
+++ thread_win32.c	(revision 17435)
@@ -147,7 +147,7 @@
     int ret;
 
     BLOCKING_REGION(ret = rb_w32_wait_events_blocking(events, num, timeout),
-		    ubf_handle, GET_THREAD(), 1);
+		    ubf_handle, GET_THREAD());
     return ret;
 }
 
@@ -199,7 +199,7 @@
     int ret;
 
     BLOCKING_REGION(ret = rb_w32_sleep(msec),
-		    ubf_handle, GET_THREAD(), 1);
+		    ubf_handle, GET_THREAD());
     return ret;
 }
 
Index: ChangeLog
===================================================================
--- ChangeLog	(revision 17434)
+++ ChangeLog	(revision 17435)
@@ -1,3 +1,8 @@
+Thu Jun 19 23:17:56 2008  Yusuke Endoh  <mame@t...>
+
+	* thread.c, thread_win32.c, vm_core.h: try to remove false positive of
+	  deadlock detection.
+
 Thu Jun 19 21:38:08 2008  Nobuyoshi Nakada  <nobu@r...>
 
 	* ext/extmk.rb (extmake): check if compile before showing message.
Index: vm_core.h
===================================================================
--- vm_core.h	(revision 17434)
+++ vm_core.h	(revision 17435)
@@ -442,6 +442,7 @@
     struct rb_unblock_callback unblock;
     VALUE locking_mutex;
     VALUE keeping_mutexes;
+    int transition_for_lock;
 
     struct rb_vm_tag *tag;
     struct rb_vm_trap_tag *trap_tag;
Index: thread.c
===================================================================
--- thread.c	(revision 17434)
+++ thread.c	(revision 17435)
@@ -96,23 +96,28 @@
   rb_thread_set_current(_th_stored); \
 } while(0)
 
-#define BLOCKING_REGION(exec, ubf, ubfarg, stopped) do { \
+#define BLOCKING_REGION_CORE(exec) do { \
+    GVL_UNLOCK_BEGIN(); {\
+	    exec; \
+    } \
+    GVL_UNLOCK_END(); \
+} while(0);
+
+#define BLOCKING_REGION(exec, ubf, ubfarg) do { \
     rb_thread_t *__th = GET_THREAD(); \
     int __prev_status = __th->status; \
     struct rb_unblock_callback __oldubf; \
     set_unblock_function(__th, ubf, ubfarg, &__oldubf); \
-    if (stopped) __th->status = THREAD_STOPPED; \
+    __th->status = THREAD_STOPPED; \
     thread_debug("enter blocking region (%p)\n", __th); \
-    GVL_UNLOCK_BEGIN(); {\
-	    exec; \
-    } \
-    GVL_UNLOCK_END(); \
+    BLOCKING_REGION_CORE(exec); \
     thread_debug("leave blocking region (%p)\n", __th); \
     remove_signal_thread_list(__th); \
     reset_unblock_function(__th, &__oldubf); \
-    if (stopped && __th->status == THREAD_STOPPED) { \
+    if (__th->status == THREAD_STOPPED) { \
 	__th->status = __prev_status; \
     } \
+    RUBY_VM_CHECK_INTS(); \
 } while(0)
 
 #if THREAD_DEBUG
@@ -396,7 +401,6 @@
 	    rb_thread_interrupt(join_th);
 	    join_th = join_th->join_list_next;
 	}
-	st_delete_wrap(th->vm->living_threads, th->self);
 	if (th != main_th) rb_check_deadlock(th->vm);
 
 	if (!th->root_fiber) {
@@ -816,8 +820,7 @@
 
     BLOCKING_REGION({
 	val = func(data1);
-    }, ubf, data2, 1);
-    RUBY_VM_CHECK_INTS();
+    }, ubf, data2);
 
     return val;
 }
@@ -1641,12 +1644,18 @@
     return ST_CONTINUE;
 }
 
+static int
+vm_living_thread_num(rb_vm_t *vm)
+{
+    return vm->living_threads->num_entries;
+}
+
 int
 rb_thread_alone()
 {
     int num = 1;
     if (GET_THREAD()->vm->living_threads) {
-	num = GET_THREAD()->vm->living_threads->num_entries;
+	num = vm_living_thread_num(GET_THREAD()->vm);
 	thread_debug("rb_thread_alone: %d\n", num);
     }
     return num == 1;
@@ -1912,16 +1921,14 @@
 		    if (except) *except = orig_except;
 		    wait = &wait_100ms;
 		} while (__th->interrupt_flag == 0 && (timeout == 0 || subst(timeout, &wait_100ms)));
-	    }, 0, 0, 1);
-	    RUBY_VM_CHECK_INTS();
+	    }, 0, 0);
 	} while (result == 0 && (timeout == 0 || subst(timeout, &wait_100ms)));
     }
 #else
     BLOCKING_REGION({
 	result = select(n, read, write, except, timeout);
 	if (result < 0) lerrno = errno;
-    }, ubf_select, GET_THREAD(), 1);
-    RUBY_VM_CHECK_INTS();
+    }, ubf_select, GET_THREAD());
 #endif
 
     errno = lerrno;
@@ -2482,8 +2489,12 @@
 lock_func(rb_thread_t *th, mutex_t *mutex, int last_thread)
 {
     int interrupted = 0;
+#if 0 /* for debug */
+    native_thread_yield();
+#endif
 
     native_mutex_lock(&mutex->lock);
+    th->transition_for_lock = 0;
     while (mutex->th || (mutex->th = th, 0)) {
 	if (last_thread) {
 	    interrupted = 2;
@@ -2499,7 +2510,13 @@
 	    break;
 	}
     }
+    th->transition_for_lock = 1;
     native_mutex_unlock(&mutex->lock);
+
+#if 0 /* for debug */
+    native_thread_yield();
+#endif
+
     return interrupted;
 }
 
@@ -2535,24 +2552,32 @@
 	    int interrupted;
 	    int prev_status = th->status;
 	    int last_thread = 0;
+	    struct rb_unblock_callback oldubf;
 
-	    th->locking_mutex = self;
+	    set_unblock_function(th, lock_interrupt, mutex, &oldubf);
 	    th->status = THREAD_STOPPED_FOREVER;
 	    th->vm->sleeper++;
-	    if (th->vm->living_threads->num_entries == th->vm->sleeper) {
+	    th->locking_mutex = self;
+	    if (vm_living_thread_num(th->vm) == th->vm->sleeper) {
 		last_thread = 1;
 	    }
 
-	    BLOCKING_REGION({
+	    th->transition_for_lock = 1;
+	    BLOCKING_REGION_CORE({
 		interrupted = lock_func(th, mutex, last_thread);
-	    }, lock_interrupt, mutex, 0);
+	    });
+	    th->transition_for_lock = 0;
+	    remove_signal_thread_list(th);
+	    reset_unblock_function(th, &oldubf);
 
 	    th->locking_mutex = Qfalse;
-	    if (interrupted == 2) {
+	    if (mutex->th && interrupted == 2) {
 		rb_check_deadlock(th->vm);
 		RUBY_VM_SET_TIMER_INTERRUPT(th);
 	    }
-	    th->status = prev_status;
+	    if (th->status == THREAD_STOPPED_FOREVER) {
+		th->status = prev_status;
+	    }
 	    th->vm->sleeper--;
 
 	    if (mutex->th == th) mutex_locked(th, self);
@@ -3414,7 +3439,7 @@
     rb_thread_t *th;
     GetThreadPtr(thval, th);
 
-    if (th->status != THREAD_STOPPED_FOREVER || RUBY_VM_INTERRUPTED(th)) {
+    if (th->status != THREAD_STOPPED_FOREVER || RUBY_VM_INTERRUPTED(th) || th->transition_for_lock) {
 	*found = 1;
     }
     else if (th->locking_mutex) {
@@ -3431,12 +3456,36 @@
     return (*found) ? ST_STOP : ST_CONTINUE;
 }
 
+#if 0 /* for debug */
+static int
+debug_i(st_data_t key, st_data_t val, int *found)
+{
+    VALUE thval = key;
+    rb_thread_t *th;
+    GetThreadPtr(thval, th);
+
+    printf("th:%p %d %d %d", th, th->status, th->interrupt_flag, th->transition_for_lock);
+    if (th->locking_mutex) {
+	mutex_t *mutex;
+	GetMutexPtr(th->locking_mutex, mutex);
+
+	native_mutex_lock(&mutex->lock);
+	printf(" %p %d\n", mutex->th, mutex->cond_notified);
+	native_mutex_unlock(&mutex->lock);
+    }
+    else puts("");
+
+    return ST_CONTINUE;
+}
+#endif
+
 static void
 rb_check_deadlock(rb_vm_t *vm)
 {
     int found = 0;
 
-    if (vm->living_threads->num_entries != vm->sleeper) return;
+    if (vm_living_thread_num(vm) > vm->sleeper) return;
+    if (vm_living_thread_num(vm) < vm->sleeper) rb_bug("sleeper must not be more than vm_living_thread_num(vm)");
 
     st_foreach(vm->living_threads, check_deadlock_i, (st_data_t)&found);
 
@@ -3444,6 +3493,10 @@
 	VALUE argv[2];
 	argv[0] = rb_eFatal;
 	argv[1] = rb_str_new2("deadlock detected");
+#if 0 /* for debug */
+	printf("%d %d %p %p\n", vm->living_threads->num_entries, vm->sleeper, GET_THREAD(), vm->main_thread);
+	st_foreach(vm->living_threads, debug_i, (st_data_t)0);
+#endif
 	rb_thread_raise(2, argv, vm->main_thread);
     }
 }

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

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