Fix Mutex#unlock with a scheduler and thread contention
* It would hit "[BUG] unexpected THREAD_STOPPED" before.
This commit is contained in:
parent
deffb63021
commit
264889ec3d
@ -47,6 +47,29 @@ class TestFiberMutex < Test::Unit::TestCase
|
|||||||
thread.join
|
thread.join
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def test_mutex_thread
|
||||||
|
mutex = Mutex.new
|
||||||
|
mutex.lock
|
||||||
|
|
||||||
|
thread = Thread.new do
|
||||||
|
scheduler = Scheduler.new
|
||||||
|
Thread.current.scheduler = scheduler
|
||||||
|
|
||||||
|
Fiber.schedule do
|
||||||
|
mutex.lock
|
||||||
|
sleep 0.1
|
||||||
|
mutex.unlock
|
||||||
|
end
|
||||||
|
|
||||||
|
scheduler.run
|
||||||
|
end
|
||||||
|
|
||||||
|
sleep 0.1
|
||||||
|
mutex.unlock
|
||||||
|
|
||||||
|
thread.join
|
||||||
|
end
|
||||||
|
|
||||||
def test_condition_variable
|
def test_condition_variable
|
||||||
mutex = Mutex.new
|
mutex = Mutex.new
|
||||||
condition = ConditionVariable.new
|
condition = ConditionVariable.new
|
||||||
|
@ -402,20 +402,20 @@ rb_mutex_unlock_th(rb_mutex_t *mutex, rb_thread_t *th, rb_fiber_t *fiber)
|
|||||||
|
|
||||||
if (cur->th->scheduler != Qnil) {
|
if (cur->th->scheduler != Qnil) {
|
||||||
rb_scheduler_unblock(cur->th->scheduler, cur->self, rb_fiberptr_self(cur->fiber));
|
rb_scheduler_unblock(cur->th->scheduler, cur->self, rb_fiberptr_self(cur->fiber));
|
||||||
|
} else {
|
||||||
|
switch (cur->th->status) {
|
||||||
|
case THREAD_RUNNABLE: /* from someone else calling Thread#run */
|
||||||
|
case THREAD_STOPPED_FOREVER: /* likely (rb_mutex_lock) */
|
||||||
|
rb_threadptr_interrupt(cur->th);
|
||||||
|
goto found;
|
||||||
|
case THREAD_STOPPED: /* probably impossible */
|
||||||
|
rb_bug("unexpected THREAD_STOPPED");
|
||||||
|
case THREAD_KILLED:
|
||||||
|
/* not sure about this, possible in exit GC? */
|
||||||
|
rb_bug("unexpected THREAD_KILLED");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (cur->th->status) {
|
|
||||||
case THREAD_RUNNABLE: /* from someone else calling Thread#run */
|
|
||||||
case THREAD_STOPPED_FOREVER: /* likely (rb_mutex_lock) */
|
|
||||||
rb_threadptr_interrupt(cur->th);
|
|
||||||
goto found;
|
|
||||||
case THREAD_STOPPED: /* probably impossible */
|
|
||||||
rb_bug("unexpected THREAD_STOPPED");
|
|
||||||
case THREAD_KILLED:
|
|
||||||
/* not sure about this, possible in exit GC? */
|
|
||||||
rb_bug("unexpected THREAD_KILLED");
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
found:
|
found:
|
||||||
while (*th_mutex != mutex) {
|
while (*th_mutex != mutex) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user