[前][次][番号順一覧][スレッド一覧]

ruby-changes:63341

From: Koichi <ko1@a...>
Date: Wed, 14 Oct 2020 14:02:39 +0900 (JST)
Subject: [ruby-changes:63341] c3ba3fa8d0 (master): support exception when lock_rec > 0

https://git.ruby-lang.org/ruby.git/commit/?id=c3ba3fa8d0

From c3ba3fa8d01aa3970dc1f4e3dc0090ae171e9e35 Mon Sep 17 00:00:00 2001
From: Koichi Sasada <ko1@a...>
Date: Wed, 14 Oct 2020 02:03:21 +0900
Subject: support exception when lock_rec > 0

If a ractor getting a VM lock (monitor) raises an exception,
unlock can be skipped. To release VM lock correctly on exception
(or other jumps with JUMP_TAG), EC_POP_TAG() releases VM lock.

diff --git a/eval_intern.h b/eval_intern.h
index aa07ce3..0e5a8ae 100644
--- a/eval_intern.h
+++ b/eval_intern.h
@@ -127,14 +127,26 @@ LONG WINAPI rb_w32_stack_overflow_handler(struct _EXCEPTION_POINTERS *); https://github.com/ruby/ruby/blob/trunk/eval_intern.h#L127
       rb_fiber_start(); \
   } while (0)
 
+void rb_ec_vm_lock_rec_release(rb_execution_context_t *ec, int lock_rec);
+
+static inline void
+rb_ec_vm_lock_rec_check(rb_execution_context_t *ec, int lock_rec)
+{
+    if (rb_ec_vm_lock_rec(ec) != lock_rec) {
+        rb_ec_vm_lock_rec_release(ec, lock_rec);
+    }
+}
+
 #define EC_PUSH_TAG(ec) do { \
   rb_execution_context_t * const _ec = (ec); \
   struct rb_vm_tag _tag; \
   _tag.state = TAG_NONE; \
   _tag.tag = Qundef; \
-  _tag.prev = _ec->tag;
+  _tag.prev = _ec->tag; \
+  _tag.lock_rec = rb_ec_vm_lock_rec(_ec); \
 
 #define EC_POP_TAG() \
+  rb_ec_vm_lock_rec_check(_ec, _tag.lock_rec); \
   _ec->tag = _tag.prev; \
 } while (0)
 
diff --git a/vm_core.h b/vm_core.h
index 44f85ff..f783bd5 100644
--- a/vm_core.h
+++ b/vm_core.h
@@ -794,6 +794,7 @@ struct rb_vm_tag { https://github.com/ruby/ruby/blob/trunk/vm_core.h#L794
     rb_jmpbuf_t buf;
     struct rb_vm_tag *prev;
     enum ruby_tag_type state;
+    int lock_rec;
 };
 
 STATIC_ASSERT(rb_vm_tag_buf_offset, offsetof(struct rb_vm_tag, buf) > 0);
@@ -1797,6 +1798,19 @@ rb_current_vm(void) https://github.com/ruby/ruby/blob/trunk/vm_core.h#L1798
     return ruby_current_vm_ptr;
 }
 
+static inline int
+rb_ec_vm_lock_rec(rb_execution_context_t *ec)
+{
+    rb_vm_t *vm = rb_ec_vm_ptr(ec);
+
+    if (vm->ractor.sync.lock_owner != rb_ec_ractor_ptr(ec)) {
+        return 0;
+    }
+    else {
+        return vm->ractor.sync.lock_rec;
+    }
+}
+
 #else
 #error "unsupported thread model"
 #endif
diff --git a/vm_sync.c b/vm_sync.c
index e3d0ffe..6b17ce8 100644
--- a/vm_sync.c
+++ b/vm_sync.c
@@ -246,3 +246,25 @@ rb_vm_barrier(void) https://github.com/ruby/ruby/blob/trunk/vm_sync.c#L246
         }
     }
 }
+
+void
+rb_ec_vm_lock_rec_release(rb_execution_context_t *ec, int recorded_lock_rec)
+{
+    int current_lock_rec = rb_ec_vm_lock_rec(ec);
+    unsigned int lev;
+
+    bp();
+
+    if (recorded_lock_rec > current_lock_rec) {
+        for (; recorded_lock_rec > current_lock_rec; current_lock_rec++) {
+            RB_VM_LOCK_ENTER_LEV(&lev);
+        }
+    }
+    else {
+        for (; recorded_lock_rec < current_lock_rec; current_lock_rec--) {
+            RB_VM_LOCK_LEAVE_LEV(&lev);
+        }
+    }
+
+    VM_ASSERT(recorded_lock_rec == rb_ec_vm_lock_rec(ec));
+}
-- 
cgit v0.10.2


--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

[前][次][番号順一覧][スレッド一覧]