aboutsummaryrefslogtreecommitdiffstats
path: root/eval_intern.h
diff options
context:
space:
mode:
authorKoichi Sasada <ko1@atdot.net>2020-10-14 02:03:21 +0900
committerKoichi Sasada <ko1@atdot.net>2020-10-14 14:02:06 +0900
commitc3ba3fa8d01aa3970dc1f4e3dc0090ae171e9e35 (patch)
tree7aaff45d1eb07dc41297d1661f528a5449609469 /eval_intern.h
parentd7de342e414b29bea7eff444ae33e44445afb9a5 (diff)
downloadruby-c3ba3fa8d01aa3970dc1f4e3dc0090ae171e9e35.tar.gz
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.
Diffstat (limited to 'eval_intern.h')
-rw-r--r--eval_intern.h14
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)