[#43610] Re: [ruby-list:48149] Re: requireが配列を取れたら便利だと思うんだけど.. — Hiroshi Nakamura <nakahiro@...>

cnVieS1saXN0GyRCJCskaTt9JEMkRk1oJF4kNyQ/ISMkRyRiQjMkKyRKJD0kJiEjGyhCCgoyMDEx

12 messages 2011/06/02

[#43643] DateTime.new! and DateTime.jd — Aaron Patterson <aaron.patterson@...>

こんにちは、アーロンです。

25 messages 2011/06/07
[#43647] Re: DateTime.new! and DateTime.jd — Tadayoshi Funaba <tadf@...> 2011/06/07

blocker はお前だろ。

[#43648] Re: DateTime.new! and DateTime.jd — Yukihiro Matsumoto <matz@...> 2011/06/07

まつもと ゆきひろです

[#43651] Re: DateTime.new! and DateTime.jd — Tadayoshi Funaba <tadf@...> 2011/06/07

> うーん、ただでさえ日英のコミュニケーション障壁があるのに、よ

[#43653] Re: DateTime.new! and DateTime.jd — Aaron Patterson <aaron.patterson@...> 2011/06/07

2011/6/7 Tadayoshi Funaba <tadf@dotrb.org>:

[#43657] Re: DateTime.new! and DateTime.jd — Tadayoshi Funaba <tadf@...> 2011/06/07

皆さんってのに俺は入ってないみたいだな。

[#43661] Re: DateTime.new! and DateTime.jd — Yukihiro Matsumoto <matz@...> 2011/06/07

まつもと ゆきひろです

[#43662] Re: DateTime.new! and DateTime.jd — Tadayoshi Funaba <tadf@...> 2011/06/07

> Aaronが言ってる「リリース」は1.9.3のことだと思いますよ。

[#43645] Re: [ruby-core:36778] Re: 1.8.7 release next month — Urabe Shyouhei <shyouhei@...>

Moving to ruby-dev to understand strategies of backporting the Tk

13 messages 2011/06/07

[#43787] [Ruby 1.9 - Feature #4878][Open] CMath に frexp, ldexp, hypot の3関数は不要ではないか — Kenta Murata <muraken@...>

24 messages 2011/06/13
[#43788] Re: [Ruby 1.9 - Feature #4878][Open] CMath に frexp, ldexp, hypot の3関数は不要ではないか — Yukihiro Matsumoto <matz@...> 2011/06/13

まつもと ゆきひろです

[#43789] Re: [Ruby 1.9 - Feature #4878][Open] CMath に frexp, ldexp, hypot の3関数は不要ではないか — Tadayoshi Funaba <tadf@...> 2011/06/13

もう結論が出てしまったようですが、これは、元々 lib/complex.rb にあった

[#43794] Re: [Ruby 1.9 - Feature #4878][Open] CMath に frexp, ldexp, hypot の3関数は不要ではないか — Kenta Murata <muraken@...> 2011/06/13

=E3=82=80=E3=82=89=E3=81=9F=E3=81=A7=E3=81=99=E3=80=82

[#43795] Re: [Ruby 1.9 - Feature #4878][Open] CMath に frexp, ldexp, hypot の3関数は不要ではないか — Tadayoshi Funaba <tadf@...> 2011/06/13

> complex.rb をロードすると Math が CMath 相当に置き換わりますから、

[#43797] Re: [Ruby 1.9 - Feature #4878][Open] CMath に frexp, ldexp, hypot の3関数は不要ではないか — Kenta Murata <muraken@...> 2011/06/14

=E3=82=80=E3=82=89=E3=81=9F=E3=81=A7=E3=81=99=E3=80=82

[#43799] Re: [Ruby 1.9 - Feature #4878][Open] CMath に frexp, ldexp, hypot の3関数は不要ではないか — Yukihiro Matsumoto <matz@...> 2011/06/14

まつもと ゆきひろです

[#43800] Re: [Ruby 1.9 - Feature #4878][Open] CMath に frexp, ldexp, hypot の3関数は不要ではないか — Kenta Murata <muraken@...> 2011/06/14

=E3=82=80=E3=82=89=E3=81=9F=E3=81=A7=E3=81=99=E3=80=82

[#43803] Re: [Ruby 1.9 - Feature #4878][Open] CMath に frexp, ldexp, hypot の3関数は不要ではないか — Tadayoshi Funaba <tadf@...> 2011/06/14

> これに相当する事をやっているのが complex.rb なので、

[#43806] Re: [Ruby 1.9 - Feature #4878][Open] CMath に frexp, ldexp, hypot の3関数は不要ではないか — Yusuke ENDOH <mame@...> 2011/06/14

遠藤です。

[#43807] Re: [Ruby 1.9 - Feature #4878][Open] CMath に frexp, ldexp, hypot の3関数は不要ではないか — Tadayoshi Funaba <tadf@...> 2011/06/14

> 定義域を増やすだけにしよう、ということですよね。賛成です。

[#43809] Re: [Ruby 1.9 - Feature #4878][Open] CMath に frexp, ldexp, hypot の3関数は不要ではないか — Yusuke ENDOH <mame@...> 2011/06/14

2011年6月14日22:17 Tadayoshi Funaba <tadf@dotrb.org>:

[#43810] Re: [Ruby 1.9 - Feature #4878][Open] CMath に frexp, ldexp, hypot の3関数は不要ではないか — Tadayoshi Funaba <tadf@...> 2011/06/14

> 互換性がないという点では同じ話だと思うのですが……。

[#43811] Re: [Ruby 1.9 - Feature #4878][Open] CMath に frexp, ldexp, hypot の3関数は不要ではないか — Yusuke ENDOH <mame@...> 2011/06/14

2011年6月14日23:02 Tadayoshi Funaba <tadf@dotrb.org>:

[#43812] Re: [Ruby 1.9 - Feature #4878][Open] CMath に frexp, ldexp, hypot の3関数は不要ではないか — Tadayoshi Funaba <tadf@...> 2011/06/14

> いやあ、5 月末の feature freeze 時点では -2 を返していたはずなんですが、

[#43852] [Ruby 1.9 - Bug #4909][Open] trapハンドラは再入されてはいけないのではないか? — Motohiro KOSAKI <kosaki.motohiro@...>

11 messages 2011/06/20

[ruby-dev:43834] new deadlock detection

From: SASADA Koichi <ko1@...>
Date: 2011-06-16 18:05:26 UTC
List: ruby-dev #43834
 ささだです.

 デッドロック検出をする方法を新しく実装してみました.test-all が通った
ので,添付してお送りします.

方針:
- sleeper の増減を,「スレッドを起こす人」にさせるようにした.
- デッドロックの検出を,living thread num と sleeper の比較
  だけで済むようにした.


利点:
- deadlock 検出のコードが随分と綺麗になった.


まずそうなところ:
- THREAD_INTERRUPTED という状態を用意したので,意図しない
  影響が出るかもしれない.
- rb_threadptr_interrupt で th->status を変えているが,
 race がおきそう...(この関数は GVL 外からも呼ばれる可能性がある).

→ スレッドの状態遷移について,
   しっかりとドキュメント化する必要がある

微妙なところ:
- あまり速くはならなかった,というか若干遅くなった
 (現在のが十分速い,という)

                        前      後
vm4_thread_mutex1       0.486   0.516
vm4_thread_mutex2       0.484   0.519
vm4_thread_mutex3       0.720   0.746

(シンプルになったんで,速くなるかなぁ,と期待したんだけど.polling のほ
うが速いってことか?)

 1.9.3 には怖くて入れられないような気がしますが,今後はこっちのほうが,
見通しが良くていいんでないか,という気がします.今のは難しいなぁ,とか.

-- 
// SASADA Koichi at atdot dot net

Attachments (1)

new_deadloc.patch (6.67 KB, text/x-diff)
Index: vm_core.h
===================================================================
--- vm_core.h	(revision 32131)
+++ vm_core.h	(working copy)
@@ -359,6 +359,7 @@ enum rb_thread_status {
     THREAD_RUNNABLE,
     THREAD_STOPPED,
     THREAD_STOPPED_FOREVER,
+    THREAD_INTERRUPTED,
     THREAD_KILLED
 };
 
Index: thread.c
===================================================================
--- thread.c	(revision 32131)
+++ thread.c	(working copy)
@@ -300,6 +300,12 @@ rb_threadptr_interrupt(rb_thread_t *th)
     else {
 	/* none */
     }
+
+    if (th->status == THREAD_STOPPED_FOREVER) {
+	th->vm->sleeper--;
+    }
+    th->status = THREAD_INTERRUPTED;
+
     native_mutex_unlock(&th->interrupt_lock);
 }
 
@@ -846,9 +852,7 @@ sleep_forever(rb_thread_t *th, int deadl
 	    rb_check_deadlock(th->vm);
 	}
 	native_sleep(th, 0);
-	if (deadlockable) {
-	    th->vm->sleeper--;
-	}
+
 	RUBY_VM_CHECK_INTS();
     } while (th->status == THREAD_STOPPED_FOREVER);
     th->status = prev_status;
@@ -1317,7 +1321,7 @@ rb_threadptr_execute_interrupts_rec(rb_t
 		rb_exc_raise(err);
 	    }
 	}
-	th->status = status;
+	// th->status = status;
 
 	if (finalizer_interrupt) {
 	    rb_gc_finalize_deferred();
@@ -1899,6 +1903,8 @@ thread_status_name(enum rb_thread_status
       case THREAD_STOPPED:
       case THREAD_STOPPED_FOREVER:
 	return "sleep";
+      case THREAD_INTERRUPTED:
+	return "interrupted";
       case THREAD_TO_KILL:
 	return "aborting";
       case THREAD_KILLED:
@@ -2965,7 +2971,7 @@ rb_threadptr_check_signal(rb_thread_t *m
 	thread_debug("main_thread: %s, sig: %d\n",
 		     thread_status_name(prev_status), sig);
 	mth->exec_signal = sig;
-	if (mth->status != THREAD_KILLED) mth->status = THREAD_RUNNABLE;
+	// if (mth->status != THREAD_KILLED) mth->status = THREAD_RUNNABLE;
 	rb_threadptr_interrupt(mth);
 	mth->status = prev_status;
     }
@@ -3448,12 +3454,26 @@ rb_mutex_trylock(VALUE self)
     return locked;
 }
 
+static void
+lock_interrupt(void *ptr)
+{
+    rb_mutex_t *mutex = (rb_mutex_t *)ptr;
+
+    native_mutex_lock(&mutex->lock);
+    {
+	if (mutex->cond_waiting > 0) {
+	    native_cond_broadcast(&mutex->cond);
+	}
+    }
+    native_mutex_unlock(&mutex->lock);
+}
+
 static int
-lock_func(rb_thread_t *th, rb_mutex_t *mutex, int timeout_ms)
+lock_func(rb_thread_t *th, rb_mutex_t *mutex)
 {
     int interrupted = 0;
-    int err = 0;
 
+    native_mutex_lock(&mutex->lock);
     mutex->cond_waiting++;
     for (;;) {
 	if (!mutex->th) {
@@ -3464,40 +3484,15 @@ lock_func(rb_thread_t *th, rb_mutex_t *m
 	    interrupted = 1;
 	    break;
 	}
-	if (err == ETIMEDOUT) {
-	    interrupted = 2;
-	    break;
-	}
 
-	if (timeout_ms) {
-	    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);
-	    err = native_cond_timedwait(&mutex->cond, &mutex->lock, &timeout);
-	}
-	else {
 	    native_cond_wait(&mutex->cond, &mutex->lock);
-	    err = 0;
-	}
     }
     mutex->cond_waiting--;
+    native_mutex_unlock(&mutex->lock);
 
     return interrupted;
 }
 
-static void
-lock_interrupt(void *ptr)
-{
-    rb_mutex_t *mutex = (rb_mutex_t *)ptr;
-    native_mutex_lock(&mutex->lock);
-    if (mutex->cond_waiting > 0)
-	native_cond_broadcast(&mutex->cond);
-    native_mutex_unlock(&mutex->lock);
-}
-
 /*
  * call-seq:
  *    mutex.lock  -> self
@@ -3519,40 +3514,29 @@ rb_mutex_lock(VALUE self)
 	}
 
 	while (mutex->th != th) {
-	    int interrupted;
 	    enum rb_thread_status prev_status = th->status;
-	    int timeout_ms = 0;
 	    struct rb_unblock_callback oldubf;
+	    int interrupted;
 
 	    set_unblock_function(th, lock_interrupt, mutex, &oldubf);
 	    th->status = THREAD_STOPPED_FOREVER;
 	    th->locking_mutex = self;
-
-	    native_mutex_lock(&mutex->lock);
 	    th->vm->sleeper++;
-	    /*
-	     * Carefully! while some contended threads are in lock_func(),
-	     * vm->sleepr is unstable value. we have to avoid both deadlock
-	     * and busy loop.
-	     */
-	    if (vm_living_thread_num(th->vm) == th->vm->sleeper) {
-		timeout_ms = 100;
-	    }
+
+	    rb_check_deadlock(th->vm);
+
 	    GVL_UNLOCK_BEGIN();
-	    interrupted = lock_func(th, mutex, timeout_ms);
-	    native_mutex_unlock(&mutex->lock);
+	    {
+		interrupted = lock_func(th, mutex);
+	    }
 	    GVL_UNLOCK_END();
-
 	    reset_unblock_function(th, &oldubf);
 
 	    th->locking_mutex = Qfalse;
-	    if (mutex->th && interrupted == 2) {
-		rb_check_deadlock(th->vm);
-	    }
+
 	    if (th->status == THREAD_STOPPED_FOREVER) {
 		th->status = prev_status;
 	    }
-	    th->vm->sleeper--;
 
 	    if (mutex->th == th) mutex_locked(th, self);
 
@@ -3580,9 +3564,11 @@ rb_mutex_unlock_th(rb_mutex_t *mutex, rb
     }
     else {
 	mutex->th = 0;
-	if (mutex->cond_waiting > 0)
+	if (mutex->cond_waiting > 0) {
+	    th->vm->sleeper--;
 	    native_cond_signal(&mutex->cond);
     }
+    }
 
     native_mutex_unlock(&mutex->lock);
 
@@ -4710,65 +4696,16 @@ ruby_native_thread_p(void)
     return th != 0;
 }
 
-static int
-check_deadlock_i(st_data_t key, st_data_t val, int *found)
-{
-    VALUE thval = key;
-    rb_thread_t *th;
-    GetThreadPtr(thval, th);
-
-    if (th->status != THREAD_STOPPED_FOREVER || RUBY_VM_INTERRUPTED(th)) {
-	*found = 1;
-    }
-    else if (th->locking_mutex) {
-	rb_mutex_t *mutex;
-	GetMutexPtr(th->locking_mutex, mutex);
-
-	native_mutex_lock(&mutex->lock);
-	if (mutex->th == th || (!mutex->th && mutex->cond_waiting)) {
-	    *found = 1;
-	}
-	native_mutex_unlock(&mutex->lock);
-    }
-
-    return (*found) ? ST_STOP : ST_CONTINUE;
-}
-
-#ifdef DEBUG_DEADLOCK_CHECK
-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", th, th->status, th->interrupt_flag);
-    if (th->locking_mutex) {
-	rb_mutex_t *mutex;
-	GetMutexPtr(th->locking_mutex, mutex);
-
-	native_mutex_lock(&mutex->lock);
-	printf(" %p %d\n", mutex->th, mutex->cond_waiting);
-	native_mutex_unlock(&mutex->lock);
-    }
-    else
-	puts("");
-
-    return ST_CONTINUE;
-}
-#endif
-
 static void
 rb_check_deadlock(rb_vm_t *vm)
 {
-    int found = 0;
+    int tnum = vm_living_thread_num(vm);
 
-    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)");
+    if (tnum > vm->sleeper) return;
+    if (tnum < 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);
-
-    if (!found) {
+    /* deadlock */
+    {
 	VALUE argv[2];
 	argv[0] = rb_eFatal;
 	argv[1] = rb_str_new2("deadlock detected");

In This Thread

Prev Next