ruby-changes:52254
From: normal <ko1@a...>
Date: Sun, 19 Aug 2018 05:04:11 +0900 (JST)
Subject: [ruby-changes:52254] normal:r64464 (trunk): thread_sync.c (rb_mutex_sleep): skip interrupt check before sleep
normal 2018-08-19 05:04:07 +0900 (Sun, 19 Aug 2018) New Revision: 64464 https://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=revision&revision=64464 Log: thread_sync.c (rb_mutex_sleep): skip interrupt check before sleep We do not want to risk switching threads before going to sleep because it can cause unexpected wakeups and put us in an unexpected state when used with ConditionVariable. Modified files: trunk/thread.c trunk/thread_sync.c Index: thread_sync.c =================================================================== --- thread_sync.c (revision 64463) +++ thread_sync.c (revision 64464) @@ -438,7 +438,7 @@ rb_mutex_cleanup_keeping_mutexes(const r https://github.com/ruby/ruby/blob/trunk/thread_sync.c#L438 static VALUE rb_mutex_sleep_forever(VALUE time) { - rb_thread_sleep_deadly_allow_spurious_wakeup(); + sleep_forever(GET_THREAD(), SLEEP_DEADLOCKABLE|SLEEP_BEFORE_CHECK_INTS); return Qnil; } @@ -446,7 +446,8 @@ static VALUE https://github.com/ruby/ruby/blob/trunk/thread_sync.c#L446 rb_mutex_wait_for(VALUE time) { struct timespec *t = (struct timespec*)time; - sleep_timespec(GET_THREAD(), *t, 0); /* permit spurious check */ + /* permit spurious check */ + sleep_timespec(GET_THREAD(), *t, SLEEP_BEFORE_CHECK_INTS); return Qnil; } Index: thread.c =================================================================== --- thread.c (revision 64463) +++ thread.c (revision 64464) @@ -94,7 +94,8 @@ static ID id_locals; https://github.com/ruby/ruby/blob/trunk/thread.c#L94 enum SLEEP_FLAGS { SLEEP_DEADLOCKABLE = 0x1, - SLEEP_SPURIOUS_CHECK = 0x2 + SLEEP_SPURIOUS_CHECK = 0x2, + SLEEP_BEFORE_CHECK_INTS = 0x4 }; static void sleep_timespec(rb_thread_t *, struct timespec, unsigned int fl); @@ -1187,7 +1188,9 @@ sleep_forever(rb_thread_t *th, unsigned https://github.com/ruby/ruby/blob/trunk/thread.c#L1188 status = fl & SLEEP_DEADLOCKABLE ? THREAD_STOPPED_FOREVER : THREAD_STOPPED; th->status = status; - RUBY_VM_CHECK_INTS_BLOCKING(th->ec); + if (!(fl & SLEEP_BEFORE_CHECK_INTS)) { + RUBY_VM_CHECK_INTS_BLOCKING(th->ec); + } while (th->status == status) { if (fl & SLEEP_DEADLOCKABLE) { th->vm->sleeper++; @@ -1293,7 +1296,9 @@ sleep_timespec(rb_thread_t *th, struct t https://github.com/ruby/ruby/blob/trunk/thread.c#L1296 getclockofday(&end); timespec_add(&end, &ts); th->status = THREAD_STOPPED; - RUBY_VM_CHECK_INTS_BLOCKING(th->ec); + if (!(fl & SLEEP_BEFORE_CHECK_INTS)) { + RUBY_VM_CHECK_INTS_BLOCKING(th->ec); + } while (th->status == THREAD_STOPPED) { native_sleep(th, &ts); woke = vm_check_ints_blocking(th->ec); -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/