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/