From: Yusuke ENDOH Date: 2010-01-12T00:20:03+09:00 Subject: [ruby-dev:40036] Re: Linuxで bm_vm3_thread_mutex.rb が刺さってしまい実行が完了しない 遠藤です。 2010年1月10日20:06 KOSAKI Motohiro : > trunk + fedora12 > の組み合わせにおいて、bm_vm3_thread_mutex.rbの実行が完了しません。調査の結果、本当にデッドロックしているのではなく、デッドロックチェックが過剰に呼ばれすぎているのが原因だと分かりました。 > 要するに微妙なタイミングでレースに負けると毎回デッドロックチェックが走ってしまうのだが、ベンチが合計100万回mutex_lockするベンチなのでレースコンディションが、当初の予想ほどレアではなかったという事です。 > > 添付パッチのように、何回かレースに負けてから初めてデッドロックを疑うようにロジックを変更したところ100倍以上速くなるようです。 IRC で話してしまいましたが、記録としてメールします。 このパッチだと、guess_deadlock が常に 0 になるため、デッドロックの チェックがされなくなってしまいます。 このメールの最後のパッチなら正しく動きますが、高速化の度合いが大分 下がるようです。 # パッチ前が 30 秒 〜 90 秒程度だったのが、25 秒 〜 35 秒程度? しかし試しに rb_check_deadlock の呼び出しを消してみると、なぜか逆に 遅くなるという現象がおきて、なんだか謎めいています。もっと調査が 必要そうです。 けれど、bm_vm3_thread_mutex.rb の実行が終了しないくらい遅いのは困り ますよね。どうしよう。 diff --git a/thread.c b/thread.c index 0ba41c7..cc2eaf8 100644 --- a/thread.c +++ b/thread.c @@ -3160,6 +3160,7 @@ rb_mutex_lock(VALUE self) if (rb_mutex_trylock(self) == Qfalse) { mutex_t *mutex; rb_thread_t *th = GET_THREAD(); + int guess_deadlock = 0; GetMutexPtr(self, mutex); if (mutex->th == GET_THREAD()) { @@ -3188,8 +3189,13 @@ rb_mutex_lock(VALUE self) remove_signal_thread_list(th); reset_unblock_function(th, &oldubf); + if (interrupted == 2) + guess_deadlock++; + else + guess_deadlock = 0; + th->locking_mutex = Qfalse; - if (mutex->th && interrupted == 2) { + if (mutex->th && interrupted == 2 && guess_deadlock > 100) { rb_check_deadlock(th->vm); } if (th->status == THREAD_STOPPED_FOREVER) { -- Yusuke ENDOH