diff options
author | Koichi Sasada <ko1@atdot.net> | 2020-10-14 02:03:21 +0900 |
---|---|---|
committer | Koichi Sasada <ko1@atdot.net> | 2020-10-14 14:02:06 +0900 |
commit | c3ba3fa8d01aa3970dc1f4e3dc0090ae171e9e35 (patch) | |
tree | 7aaff45d1eb07dc41297d1661f528a5449609469 /eval_intern.h | |
parent | d7de342e414b29bea7eff444ae33e44445afb9a5 (diff) |
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.
Notes
Notes:
Merged: https://github.com/ruby/ruby/pull/3654
Diffstat (limited to 'eval_intern.h')
-rw-r--r-- | eval_intern.h | 14 |
1 files changed, 13 insertions, 1 deletions
diff --git a/eval_intern.h b/eval_intern.h index aa07ce30ed..0e5a8ae692 100644 --- a/eval_intern.h +++ b/eval_intern.h @@ -127,14 +127,26 @@ LONG WINAPI rb_w32_stack_overflow_handler(struct _EXCEPTION_POINTERS *); 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) |