From 178c1b0922dc727897d81d7cfe9c97d5ffa97fd9 Mon Sep 17 00:00:00 2001 From: Benoit Daloze Date: Sat, 5 Sep 2020 16:26:24 +1200 Subject: Make Mutex per-Fiber instead of per-Thread * Enables Mutex to be used as synchronization between multiple Fibers of the same Thread. * With a Fiber scheduler we can yield to another Fiber on contended Mutex#lock instead of blocking the entire thread. * This also makes the behavior of Mutex consistent across CRuby, JRuby and TruffleRuby. * [Feature #16792] --- thread.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) (limited to 'thread.c') diff --git a/thread.c b/thread.c index d0ebfff882..c4ff5aafde 100644 --- a/thread.c +++ b/thread.c @@ -75,11 +75,13 @@ #include "hrtime.h" #include "internal.h" #include "internal/class.h" +#include "internal/cont.h" #include "internal/error.h" #include "internal/hash.h" #include "internal/io.h" #include "internal/object.h" #include "internal/proc.h" +#include "internal/scheduler.h" #include "internal/signal.h" #include "internal/thread.h" #include "internal/time.h" @@ -548,7 +550,7 @@ rb_threadptr_unlock_all_locking_mutexes(rb_thread_t *th) /* rb_warn("mutex #<%p> remains to be locked by terminated thread", (void *)mutexes); */ mutexes = mutex->next_mutex; - err = rb_mutex_unlock_th(mutex, th); + err = rb_mutex_unlock_th(mutex, th, mutex->fiber); if (err) rb_bug("invalid keeping_mutexes: %s", err); } } @@ -5040,7 +5042,7 @@ rb_thread_shield_wait(VALUE self) if (!mutex) return Qfalse; m = mutex_ptr(mutex); - if (m->th == GET_THREAD()) return Qnil; + if (m->fiber == GET_EC()->fiber_ptr) return Qnil; rb_thread_shield_waiting_inc(self); rb_mutex_lock(mutex); rb_thread_shield_waiting_dec(self); @@ -5540,7 +5542,7 @@ debug_deadlock_check(rb_ractor_t *r, VALUE msg) if (th->locking_mutex) { rb_mutex_t *mutex = mutex_ptr(th->locking_mutex); rb_str_catf(msg, " mutex:%p cond:%"PRIuSIZE, - (void *)mutex->th, rb_mutex_num_waiting(mutex)); + (void *)mutex->fiber, rb_mutex_num_waiting(mutex)); } { @@ -5574,8 +5576,7 @@ rb_check_deadlock(rb_ractor_t *r) } else if (th->locking_mutex) { rb_mutex_t *mutex = mutex_ptr(th->locking_mutex); - - if (mutex->th == th || (!mutex->th && !list_empty(&mutex->waitq))) { + if (mutex->fiber == th->ec->fiber_ptr || (!mutex->fiber && !list_empty(&mutex->waitq))) { found = 1; } } -- cgit v1.2.3