From 1096d702ed9e4cbc26499fe3749acc7f3609da8f Mon Sep 17 00:00:00 2001 From: ko1 Date: Mon, 6 Nov 2017 07:44:28 +0000 Subject: move rb_thread_t::interrupt_flag and mask to rb_execution_context_t. * vm_core.h (rb_thread_t): move `rb_thread_t::interrupt_flag` and `rb_thread_t::interrupt_mask` to rb_execution_context_t. RUBY_VM_CHECK_INTS() accepts `ec` instead of `th`. * cont.c (rb_fiber_terminate): to propagate interrupt information, add new parameter `need_interrupt`. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@60672 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- cont.c | 26 +++++++++------ eval.c | 2 +- insns.def | 14 ++++---- process.c | 3 +- signal.c | 14 ++++---- thread.c | 99 +++++++++++++++++++++++++++----------------------------- thread_pthread.c | 2 +- thread_sync.c | 6 ++-- thread_win32.c | 4 +-- vm_core.h | 30 +++++++++-------- vm_eval.c | 4 +-- vm_insnhelper.c | 4 +-- vm_trace.c | 20 ++++++------ 13 files changed, 117 insertions(+), 111 deletions(-) diff --git a/cont.c b/cont.c index 889c35cdf0..6f9d76ecd1 100644 --- a/cont.c +++ b/cont.c @@ -1389,7 +1389,7 @@ rb_fiber_new(VALUE (*func)(ANYARGS), VALUE obj) return fiber_init(fiber_alloc(rb_cFiber), rb_proc_new(func, obj)); } -static void rb_fiber_terminate(rb_fiber_t *fib); +static void rb_fiber_terminate(rb_fiber_t *fib, int need_interrupt); void rb_fiber_start(void) @@ -1398,6 +1398,7 @@ rb_fiber_start(void) rb_fiber_t *fib = th->ec->fiber_ptr; rb_proc_t *proc; enum ruby_tag_type state; + int need_interrupt = TRUE; VM_ASSERT(th->ec == ruby_current_execution_context_ptr); VM_ASSERT(FIBER_RESUMED_P(fib)); @@ -1420,20 +1421,22 @@ rb_fiber_start(void) EC_POP_TAG(); if (state) { + VALUE err = th->ec->errinfo; VM_ASSERT(FIBER_RESUMED_P(fib)); if (state == TAG_RAISE || state == TAG_FATAL) { - rb_threadptr_pending_interrupt_enque(th, th->ec->errinfo); + rb_threadptr_pending_interrupt_enque(th, err); } else { - VALUE err = rb_vm_make_jump_tag_but_local_jump(state, th->ec->errinfo); - if (!NIL_P(err)) + err = rb_vm_make_jump_tag_but_local_jump(state, err); + if (!NIL_P(err)) { rb_threadptr_pending_interrupt_enque(th, err); + } } - RUBY_VM_SET_INTERRUPT(th); + need_interrupt = TRUE; } - rb_fiber_terminate(fib); + rb_fiber_terminate(fib, need_interrupt); VM_UNREACHABLE(rb_fiber_start); } @@ -1669,7 +1672,7 @@ fiber_switch(rb_fiber_t *fib, int argc, const VALUE *argv, int is_resume) cont->argc = argc; cont->value = make_passing_arg(argc, argv); value = fiber_store(fib, th); - RUBY_VM_CHECK_INTS(th); + RUBY_VM_CHECK_INTS(th->ec); EXEC_EVENT_HOOK(th->ec, RUBY_EVENT_FIBER_SWITCH, th->self, 0, 0, 0, Qnil); @@ -1704,11 +1707,12 @@ rb_fiber_close(rb_fiber_t *fib) } static void -rb_fiber_terminate(rb_fiber_t *fib) +rb_fiber_terminate(rb_fiber_t *fib, int need_interrupt) { VALUE value = fib->cont.value; - VM_ASSERT(FIBER_RESUMED_P(fib)); + rb_fiber_t *ret_fib; + VM_ASSERT(FIBER_RESUMED_P(fib)); rb_fiber_close(fib); #if FIBER_USE_NATIVE && !defined(_WIN32) @@ -1721,7 +1725,9 @@ rb_fiber_terminate(rb_fiber_t *fib) fib->cont.machine.stack_size = 0; #endif - fiber_switch(return_fiber(), 1, &value, 0); + ret_fib = return_fiber(); + if (need_interrupt) RUBY_VM_SET_INTERRUPT(&ret_fib->cont.saved_ec); + fiber_switch(ret_fib, 1, &value, 0); } VALUE diff --git a/eval.c b/eval.c index 4e8399e7f8..e810ad78d8 100644 --- a/eval.c +++ b/eval.c @@ -171,7 +171,7 @@ ruby_cleanup(volatile int ex) rb_threadptr_check_signal(th); EC_PUSH_TAG(th->ec); if ((state = EXEC_TAG()) == TAG_NONE) { - SAVE_ROOT_JMPBUF(th, { RUBY_VM_CHECK_INTS(th); }); + SAVE_ROOT_JMPBUF(th, { RUBY_VM_CHECK_INTS(th->ec); }); step_0: step++; errs[1] = th->ec->errinfo; diff --git a/insns.def b/insns.def index b254193a4c..6e142ed74b 100644 --- a/insns.def +++ b/insns.def @@ -994,7 +994,7 @@ leave } } - RUBY_VM_CHECK_INTS(rb_ec_thread_ptr(ec)); + RUBY_VM_CHECK_INTS(ec); if (vm_pop_frame(ec, GET_CFP(), GET_EP())) { #if OPT_CALL_THREADED_CODE @@ -1024,7 +1024,7 @@ throw (VALUE throwobj) (VALUE val) { - RUBY_VM_CHECK_INTS(rb_ec_thread_ptr(ec)); + RUBY_VM_CHECK_INTS(ec); val = vm_throw(ec, GET_CFP(), throw_state, throwobj); THROW_EXCEPTION(val); /* unreachable */ @@ -1045,7 +1045,7 @@ jump () () { - RUBY_VM_CHECK_INTS(rb_ec_thread_ptr(ec)); + RUBY_VM_CHECK_INTS(ec); JUMP(dst); } @@ -1061,7 +1061,7 @@ branchif () { if (RTEST(val)) { - RUBY_VM_CHECK_INTS(rb_ec_thread_ptr(ec)); + RUBY_VM_CHECK_INTS(ec); JUMP(dst); } } @@ -1078,7 +1078,7 @@ branchunless () { if (!RTEST(val)) { - RUBY_VM_CHECK_INTS(rb_ec_thread_ptr(ec)); + RUBY_VM_CHECK_INTS(ec); JUMP(dst); } } @@ -1095,7 +1095,7 @@ branchnil () { if (NIL_P(val)) { - RUBY_VM_CHECK_INTS(rb_ec_thread_ptr(ec)); + RUBY_VM_CHECK_INTS(ec); JUMP(dst); } } @@ -1112,7 +1112,7 @@ branchiftype () { if (TYPE(val) == (int)type) { - RUBY_VM_CHECK_INTS(rb_ec_thread_ptr(ec)); + RUBY_VM_CHECK_INTS(ec); JUMP(dst); } } diff --git a/process.c b/process.c index a67e63b89d..c055192ba8 100644 --- a/process.c +++ b/process.c @@ -902,8 +902,7 @@ rb_waitpid(rb_pid_t pid, int *st, int flags) else { while ((result = do_waitpid_nonblocking(pid, st, flags)) < 0 && (errno == EINTR)) { - rb_thread_t *th = GET_THREAD(); - RUBY_VM_CHECK_INTS(th); + RUBY_VM_CHECK_INTS(GET_EC()); } } if (result > 0) { diff --git a/signal.c b/signal.c index 5a8ccf5771..b67317aa6f 100644 --- a/signal.c +++ b/signal.c @@ -987,8 +987,8 @@ sig_do_nothing(int sig) static void signal_exec(VALUE cmd, int safe, int sig) { - rb_thread_t *cur_th = GET_THREAD(); - volatile unsigned long old_interrupt_mask = cur_th->interrupt_mask; + rb_execution_context_t *ec = GET_EC(); + volatile unsigned long old_interrupt_mask = ec->interrupt_mask; enum ruby_tag_type state; /* @@ -1000,19 +1000,19 @@ signal_exec(VALUE cmd, int safe, int sig) if (IMMEDIATE_P(cmd)) return; - cur_th->interrupt_mask |= TRAP_INTERRUPT_MASK; - EC_PUSH_TAG(cur_th->ec); + ec->interrupt_mask |= TRAP_INTERRUPT_MASK; + EC_PUSH_TAG(ec); if ((state = EXEC_TAG()) == TAG_NONE) { VALUE signum = INT2NUM(sig); rb_eval_cmd(cmd, rb_ary_new3(1, signum), safe); } EC_POP_TAG(); - cur_th = GET_THREAD(); - cur_th->interrupt_mask = old_interrupt_mask; + ec = GET_EC(); + ec->interrupt_mask = old_interrupt_mask; if (state) { /* XXX: should be replaced with rb_threadptr_pending_interrupt_enque() */ - EC_JUMP_TAG(cur_th->ec, state); + EC_JUMP_TAG(ec, state); } } diff --git a/thread.c b/thread.c index d91bc957a4..4dcd9eab3b 100644 --- a/thread.c +++ b/thread.c @@ -96,7 +96,7 @@ static void rb_thread_sleep_deadly_allow_spurious_wakeup(void); static double timeofday(void); static int rb_threadptr_dead(rb_thread_t *th); static void rb_check_deadlock(rb_vm_t *vm); -static int rb_threadptr_pending_interrupt_empty_p(rb_thread_t *th); +static int rb_threadptr_pending_interrupt_empty_p(const rb_thread_t *th); #define eKillSignal INT2FIX(0) #define eTerminateSignal INT2FIX(1) @@ -173,17 +173,18 @@ static inline void blocking_region_end(rb_thread_t *th, struct rb_blocking_regio }; \ } while(0) -#define RUBY_VM_CHECK_INTS_BLOCKING(th) vm_check_ints_blocking(th) +#define RUBY_VM_CHECK_INTS_BLOCKING(ec) vm_check_ints_blocking(ec) static inline void -vm_check_ints_blocking(rb_thread_t *th) +vm_check_ints_blocking(rb_execution_context_t *ec) { + rb_thread_t *th = rb_ec_thread_ptr(ec); + if (LIKELY(rb_threadptr_pending_interrupt_empty_p(th))) { - if (LIKELY(!RUBY_VM_INTERRUPTED_ANY(th))) return; + if (LIKELY(!RUBY_VM_INTERRUPTED_ANY(ec))) return; } else { th->pending_interrupt_queue_checked = 0; - - RUBY_VM_SET_INTERRUPT(th); + RUBY_VM_SET_INTERRUPT(ec); } rb_threadptr_execute_interrupts(th, 1); } @@ -381,16 +382,16 @@ unblock_function_set(rb_thread_t *th, rb_unblock_function_t *func, void *arg, in { do { if (fail_if_interrupted) { - if (RUBY_VM_INTERRUPTED_ANY(th)) { + if (RUBY_VM_INTERRUPTED_ANY(th->ec)) { return FALSE; } } else { - RUBY_VM_CHECK_INTS(th); + RUBY_VM_CHECK_INTS(th->ec); } native_mutex_lock(&th->interrupt_lock); - } while (RUBY_VM_INTERRUPTED_ANY(th) && + } while (RUBY_VM_INTERRUPTED_ANY(th->ec) && (native_mutex_unlock(&th->interrupt_lock), TRUE)); VM_ASSERT(th->unblock.func == NULL); @@ -415,10 +416,10 @@ rb_threadptr_interrupt_common(rb_thread_t *th, int trap) { native_mutex_lock(&th->interrupt_lock); if (trap) { - RUBY_VM_SET_TRAP_INTERRUPT(th); + RUBY_VM_SET_TRAP_INTERRUPT(th->ec); } else { - RUBY_VM_SET_INTERRUPT(th); + RUBY_VM_SET_INTERRUPT(th->ec); } if (th->unblock.func != NULL) { (th->unblock.func)(th->unblock.arg); @@ -479,6 +480,7 @@ void rb_thread_terminate_all(void) { rb_thread_t *volatile th = GET_THREAD(); /* main thread */ + rb_execution_context_t * volatile ec = th->ec; rb_vm_t *volatile vm = th->vm; volatile int sleeping = 0; @@ -490,7 +492,7 @@ rb_thread_terminate_all(void) /* unlock all locking mutexes */ rb_threadptr_unlock_all_locking_mutexes(th); - EC_PUSH_TAG(th->ec); + EC_PUSH_TAG(ec); if (EC_EXEC_TAG() == TAG_NONE) { retry: thread_debug("rb_thread_terminate_all (main thread: %p)\n", (void *)th); @@ -503,7 +505,7 @@ rb_thread_terminate_all(void) */ sleeping = 1; native_sleep(th, 0); - RUBY_VM_CHECK_INTS_BLOCKING(th); + RUBY_VM_CHECK_INTS_BLOCKING(ec); sleeping = 0; } } @@ -732,8 +734,6 @@ thread_create_core(VALUE thval, VALUE args, VALUE (*fn)(ANYARGS)) th->pending_interrupt_mask_stack = rb_ary_dup(current_th->pending_interrupt_mask_stack); RBASIC_CLEAR_CLASS(th->pending_interrupt_mask_stack); - th->interrupt_mask = 0; - native_mutex_initialize(&th->interrupt_lock); th->report_on_exception = th->vm->thread_report_on_exception; @@ -1079,7 +1079,7 @@ sleep_forever(rb_thread_t *th, int deadlockable, int spurious_check) enum rb_thread_status status = deadlockable ? THREAD_STOPPED_FOREVER : THREAD_STOPPED; th->status = status; - RUBY_VM_CHECK_INTS_BLOCKING(th); + RUBY_VM_CHECK_INTS_BLOCKING(th->ec); while (th->status == status) { if (deadlockable) { th->vm->sleeper++; @@ -1089,7 +1089,7 @@ sleep_forever(rb_thread_t *th, int deadlockable, int spurious_check) if (deadlockable) { th->vm->sleeper--; } - RUBY_VM_CHECK_INTS_BLOCKING(th); + RUBY_VM_CHECK_INTS_BLOCKING(th->ec); if (!spurious_check) break; } @@ -1134,10 +1134,10 @@ sleep_timeval(rb_thread_t *th, struct timeval tv, int spurious_check) } th->status = THREAD_STOPPED; - RUBY_VM_CHECK_INTS_BLOCKING(th); + RUBY_VM_CHECK_INTS_BLOCKING(th->ec); while (th->status == THREAD_STOPPED) { native_sleep(th, &tv); - RUBY_VM_CHECK_INTS_BLOCKING(th); + RUBY_VM_CHECK_INTS_BLOCKING(th->ec); getclockofday(&tvn); if (to.tv_sec < tvn.tv_sec) break; if (to.tv_sec == tvn.tv_sec && to.tv_usec <= tvn.tv_usec) break; @@ -1217,8 +1217,7 @@ rb_thread_wait_for(struct timeval time) void rb_thread_check_ints(void) { - rb_thread_t *th = GET_THREAD(); - RUBY_VM_CHECK_INTS_BLOCKING(th); + RUBY_VM_CHECK_INTS_BLOCKING(GET_EC()); } /* @@ -1235,7 +1234,7 @@ rb_thread_check_trap_pending(void) int rb_thread_interrupted(VALUE thval) { - return (int)RUBY_VM_INTERRUPTED(rb_thread_ptr(thval)); + return (int)RUBY_VM_INTERRUPTED(rb_thread_ptr(thval)->ec); } void @@ -1264,10 +1263,8 @@ rb_thread_schedule_limits(uint32_t limits_us) void rb_thread_schedule(void) { - rb_thread_t *cur_th = GET_THREAD(); rb_thread_schedule_limits(0); - - RUBY_VM_CHECK_INTS(cur_th); + RUBY_VM_CHECK_INTS(GET_EC()); } /* blocking region */ @@ -1324,7 +1321,7 @@ call_without_gvl(void *(*func)(void *), void *data1, }, ubf, data2, fail_if_interrupted); if (!fail_if_interrupted) { - RUBY_VM_CHECK_INTS_BLOCKING(th); + RUBY_VM_CHECK_INTS_BLOCKING(th->ec); } errno = saved_errno; @@ -1435,22 +1432,21 @@ VALUE rb_thread_io_blocking_region(rb_blocking_function_t *func, void *data1, int fd) { volatile VALUE val = Qundef; /* shouldn't be used */ - rb_vm_t *vm = GET_VM(); - rb_thread_t *volatile th = GET_THREAD(); + rb_execution_context_t * volatile ec = GET_EC(); volatile int saved_errno = 0; enum ruby_tag_type state; struct waiting_fd wfd; wfd.fd = fd; - wfd.th = th; - list_add(&vm->waiting_fds, &wfd.wfd_node); + wfd.th = rb_ec_thread_ptr(ec); + list_add(&rb_ec_vm_ptr(ec)->waiting_fds, &wfd.wfd_node); - EC_PUSH_TAG(th->ec); + EC_PUSH_TAG(ec); if ((state = EXEC_TAG()) == TAG_NONE) { BLOCKING_REGION({ val = func(data1); saved_errno = errno; - }, ubf_select, th, FALSE); + }, ubf_select, rb_ec_thread_ptr(ec), FALSE); } EC_POP_TAG(); @@ -1458,10 +1454,10 @@ rb_thread_io_blocking_region(rb_blocking_function_t *func, void *data1, int fd) list_del(&wfd.wfd_node); if (state) { - EC_JUMP_TAG(th->ec, state); + EC_JUMP_TAG(ec, state); } /* TODO: check func() */ - RUBY_VM_CHECK_INTS_BLOCKING(th); + RUBY_VM_CHECK_INTS_BLOCKING(ec); errno = saved_errno; @@ -1656,7 +1652,7 @@ rb_threadptr_pending_interrupt_check_mask(rb_thread_t *th, VALUE err) } static int -rb_threadptr_pending_interrupt_empty_p(rb_thread_t *th) +rb_threadptr_pending_interrupt_empty_p(const rb_thread_t *th) { return RARRAY_LEN(th->pending_interrupt_queue) == 0; } @@ -1857,7 +1853,8 @@ static VALUE rb_thread_s_handle_interrupt(VALUE self, VALUE mask_arg) { VALUE mask; - rb_thread_t * volatile th = GET_THREAD(); + rb_execution_context_t * volatile ec = GET_EC(); + rb_thread_t * volatile th = rb_ec_thread_ptr(ec); volatile VALUE r = Qnil; enum ruby_tag_type state; @@ -1875,7 +1872,7 @@ rb_thread_s_handle_interrupt(VALUE self, VALUE mask_arg) rb_ary_push(th->pending_interrupt_mask_stack, mask); if (!rb_threadptr_pending_interrupt_empty_p(th)) { th->pending_interrupt_queue_checked = 0; - RUBY_VM_SET_INTERRUPT(th); + RUBY_VM_SET_INTERRUPT(th->ec); } EC_PUSH_TAG(th->ec); @@ -1887,10 +1884,10 @@ rb_thread_s_handle_interrupt(VALUE self, VALUE mask_arg) rb_ary_pop(th->pending_interrupt_mask_stack); if (!rb_threadptr_pending_interrupt_empty_p(th)) { th->pending_interrupt_queue_checked = 0; - RUBY_VM_SET_INTERRUPT(th); + RUBY_VM_SET_INTERRUPT(th->ec); } - RUBY_VM_CHECK_INTS(th); + RUBY_VM_CHECK_INTS(th->ec); if (state) { EC_JUMP_TAG(th->ec, state); @@ -2014,14 +2011,15 @@ rb_threadptr_to_kill(rb_thread_t *th) static inline rb_atomic_t threadptr_get_interrupts(rb_thread_t *th) { + rb_execution_context_t *ec = th->ec; rb_atomic_t interrupt; rb_atomic_t old; do { - interrupt = th->interrupt_flag; - old = ATOMIC_CAS(th->interrupt_flag, interrupt, interrupt & th->interrupt_mask); + interrupt = ec->interrupt_flag; + old = ATOMIC_CAS(ec->interrupt_flag, interrupt, interrupt & ec->interrupt_mask); } while (old != interrupt); - return interrupt & (rb_atomic_t)~th->interrupt_mask; + return interrupt & (rb_atomic_t)~ec->interrupt_mask; } void @@ -2252,7 +2250,7 @@ thread_raise_m(int argc, VALUE *argv, VALUE self) /* To perform Thread.current.raise as Kernel.raise */ if (current_th == target_th) { - RUBY_VM_CHECK_INTS(target_th); + RUBY_VM_CHECK_INTS(target_th->ec); } return Qnil; } @@ -3734,7 +3732,7 @@ do_select(int n, rb_fdset_t *const readfds, rb_fdset_t *const writefds, if (result < 0) lerrno = errno; }, ubf_select, th, FALSE); - RUBY_VM_CHECK_INTS_BLOCKING(th); + RUBY_VM_CHECK_INTS_BLOCKING(th->ec); } while (result < 0 && retryable(errno = lerrno) && do_select_update()); #define fd_term(f) if (f##fds) rb_fd_term(&orig_##f) @@ -3898,7 +3896,7 @@ rb_wait_for_single_fd(int fd, int events, struct timeval *tv) if (result < 0) lerrno = errno; }, ubf_select, th, FALSE); - RUBY_VM_CHECK_INTS_BLOCKING(th); + RUBY_VM_CHECK_INTS_BLOCKING(th->ec); } while (result < 0 && retryable(errno = lerrno) && poll_update()); if (result < 0) return -1; @@ -4041,8 +4039,9 @@ timer_thread_function(void *arg) */ native_mutex_lock(&vm->thread_destruct_lock); /* for time slice */ - if (vm->running_thread) - RUBY_VM_SET_TIMER_INTERRUPT(vm->running_thread); + if (vm->running_thread) { + RUBY_VM_SET_TIMER_INTERRUPT(vm->running_thread->ec); + } native_mutex_unlock(&vm->thread_destruct_lock); /* check signal */ @@ -4890,8 +4889,6 @@ Init_Thread(void) th->pending_interrupt_queue = rb_ary_tmp_new(0); th->pending_interrupt_queue_checked = 0; th->pending_interrupt_mask_stack = rb_ary_tmp_new(0); - - th->interrupt_mask = 0; } } @@ -4922,7 +4919,7 @@ debug_deadlock_check(rb_vm_t *vm, VALUE msg) list_for_each(&vm->living_threads, th, vmlt_node) { rb_str_catf(msg, "* %+"PRIsVALUE"\n rb_thread_t:%p " "native:%"PRI_THREAD_ID" int:%u", - th->self, th, thread_id_str(th), th->interrupt_flag); + th->self, th, thread_id_str(th), th->ec->interrupt_flag); if (th->locking_mutex) { rb_mutex_t *mutex; GetMutexPtr(th->locking_mutex, mutex); @@ -4953,7 +4950,7 @@ rb_check_deadlock(rb_vm_t *vm) if (patrol_thread && patrol_thread != GET_THREAD()) return; list_for_each(&vm->living_threads, th, vmlt_node) { - if (th->status != THREAD_STOPPED_FOREVER || RUBY_VM_INTERRUPTED(th)) { + if (th->status != THREAD_STOPPED_FOREVER || RUBY_VM_INTERRUPTED(th->ec)) { found = 1; } else if (th->locking_mutex) { diff --git a/thread_pthread.c b/thread_pthread.c index 968d7e1f86..686c219ecb 100644 --- a/thread_pthread.c +++ b/thread_pthread.c @@ -1132,7 +1132,7 @@ native_sleep(rb_thread_t *th, struct timeval *timeout_tv) th->unblock.func = ubf_pthread_cond_signal; th->unblock.arg = th; - if (RUBY_VM_INTERRUPTED(th)) { + if (RUBY_VM_INTERRUPTED(th->ec)) { /* interrupted. return immediate */ thread_debug("native_sleep: interrupted before sleep\n"); } diff --git a/thread_sync.c b/thread_sync.c index 3316bcbacf..6eff5e759c 100644 --- a/thread_sync.c +++ b/thread_sync.c @@ -237,7 +237,7 @@ rb_mutex_lock(VALUE self) /* When running trap handler */ if (!FL_TEST_RAW(self, MUTEX_ALLOW_TRAP) && - th->interrupt_mask & TRAP_INTERRUPT_MASK) { + th->ec->interrupt_mask & TRAP_INTERRUPT_MASK) { rb_raise(rb_eThreadError, "can't be called from trap context"); } @@ -280,7 +280,7 @@ rb_mutex_lock(VALUE self) patrol_thread = NULL; th->locking_mutex = Qfalse; - if (mutex->th && timeout && !RUBY_VM_INTERRUPTED(th)) { + if (mutex->th && timeout && !RUBY_VM_INTERRUPTED(th->ec)) { rb_check_deadlock(th->vm); } if (th->status == THREAD_STOPPED_FOREVER) { @@ -290,7 +290,7 @@ rb_mutex_lock(VALUE self) if (mutex->th == th) mutex_locked(th, self); - RUBY_VM_CHECK_INTS_BLOCKING(th); + RUBY_VM_CHECK_INTS_BLOCKING(th->ec); } } return self; diff --git a/thread_win32.c b/thread_win32.c index 2e101b4368..c82bbfce45 100644 --- a/thread_win32.c +++ b/thread_win32.c @@ -167,7 +167,7 @@ w32_wait_events(HANDLE *events, int count, DWORD timeout, rb_thread_t *th) thread_debug(" w32_wait_events events:%p, count:%d, timeout:%ld, th:%p\n", events, count, timeout, th); if (th && (intr = th->native_thread_data.interrupt_event)) { - if (ResetEvent(intr) && (!RUBY_VM_INTERRUPTED(th) || SetEvent(intr))) { + if (ResetEvent(intr) && (!RUBY_VM_INTERRUPTED(th->ec) || SetEvent(intr))) { targets = ALLOCA_N(HANDLE, count + 1); memcpy(targets, events, sizeof(HANDLE) * count); @@ -285,7 +285,7 @@ native_sleep(rb_thread_t *th, struct timeval *tv) th->unblock.arg = th; native_mutex_unlock(&th->interrupt_lock); - if (RUBY_VM_INTERRUPTED(th)) { + if (RUBY_VM_INTERRUPTED(th->ec)) { /* interrupted. return immediate */ } else { diff --git a/vm_core.h b/vm_core.h index 8bbf95f4cd..41b91aff5a 100644 --- a/vm_core.h +++ b/vm_core.h @@ -745,6 +745,10 @@ typedef struct rb_execution_context_struct { int safe_level; int raised_flag; + /* interrupt flags */ + rb_atomic_t interrupt_flag; + unsigned long interrupt_mask; + rb_fiber_t *fiber_ptr; struct rb_thread_struct *thread_ptr; @@ -825,8 +829,7 @@ typedef struct rb_thread_struct { VALUE pending_interrupt_mask_stack; int pending_interrupt_queue_checked; - rb_atomic_t interrupt_flag; - unsigned long interrupt_mask; + /* interrupt management */ rb_nativethread_lock_t interrupt_lock; struct rb_unblock_callback unblock; VALUE locking_mutex; @@ -1652,12 +1655,13 @@ enum { TRAP_INTERRUPT_MASK = 0x08 }; -#define RUBY_VM_SET_TIMER_INTERRUPT(th) ATOMIC_OR((th)->interrupt_flag, TIMER_INTERRUPT_MASK) -#define RUBY_VM_SET_INTERRUPT(th) ATOMIC_OR((th)->interrupt_flag, PENDING_INTERRUPT_MASK) -#define RUBY_VM_SET_POSTPONED_JOB_INTERRUPT(th) ATOMIC_OR((th)->interrupt_flag, POSTPONED_JOB_INTERRUPT_MASK) -#define RUBY_VM_SET_TRAP_INTERRUPT(th) ATOMIC_OR((th)->interrupt_flag, TRAP_INTERRUPT_MASK) -#define RUBY_VM_INTERRUPTED(th) ((th)->interrupt_flag & ~(th)->interrupt_mask & (PENDING_INTERRUPT_MASK|TRAP_INTERRUPT_MASK)) -#define RUBY_VM_INTERRUPTED_ANY(th) ((th)->interrupt_flag & ~(th)->interrupt_mask) +#define RUBY_VM_SET_TIMER_INTERRUPT(ec) ATOMIC_OR((ec)->interrupt_flag, TIMER_INTERRUPT_MASK) +#define RUBY_VM_SET_INTERRUPT(ec) ATOMIC_OR((ec)->interrupt_flag, PENDING_INTERRUPT_MASK) +#define RUBY_VM_SET_POSTPONED_JOB_INTERRUPT(ec) ATOMIC_OR((ec)->interrupt_flag, POSTPONED_JOB_INTERRUPT_MASK) +#define RUBY_VM_SET_TRAP_INTERRUPT(ec) ATOMIC_OR((ec)->interrupt_flag, TRAP_INTERRUPT_MASK) +#define RUBY_VM_INTERRUPTED(ec) ((ec)->interrupt_flag & ~(ec)->interrupt_mask & \ + (PENDING_INTERRUPT_MASK|TRAP_INTERRUPT_MASK)) +#define RUBY_VM_INTERRUPTED_ANY(ec) ((ec)->interrupt_flag & ~(ec)->interrupt_mask) VALUE rb_exc_set_backtrace(VALUE exc, VALUE bt); int rb_signal_buff_size(void); @@ -1676,13 +1680,13 @@ void rb_execution_context_mark(const rb_execution_context_t *ec); void rb_fiber_close(rb_fiber_t *fib); void Init_native_thread(rb_thread_t *th); -#define RUBY_VM_CHECK_INTS(th) ruby_vm_check_ints(th) +#define RUBY_VM_CHECK_INTS(ec) ruby_vm_check_ints(ec) static inline void -ruby_vm_check_ints(rb_thread_t *th) +ruby_vm_check_ints(rb_execution_context_t *ec) { - VM_ASSERT(th->ec == ruby_current_execution_context_ptr); - if (UNLIKELY(RUBY_VM_INTERRUPTED_ANY(th))) { - rb_threadptr_execute_interrupts(th, 0); + VM_ASSERT(ec == ruby_current_execution_context_ptr); + if (UNLIKELY(RUBY_VM_INTERRUPTED_ANY(ec))) { + rb_threadptr_execute_interrupts(rb_ec_thread_ptr(ec), 0); } } diff --git a/vm_eval.c b/vm_eval.c index 9815673287..b11c01a1e3 100644 --- a/vm_eval.c +++ b/vm_eval.c @@ -162,7 +162,7 @@ vm_call0_body(rb_execution_context_t *ec, struct rb_calling_info *calling, const ret = method_missing(calling->recv, ci->mid, calling->argc, argv, ex); goto success; } - RUBY_VM_CHECK_INTS(rb_ec_thread_ptr(ec)); + RUBY_VM_CHECK_INTS(ec); goto again; } case VM_METHOD_TYPE_ALIAS: @@ -197,7 +197,7 @@ vm_call0_body(rb_execution_context_t *ec, struct rb_calling_info *calling, const return Qundef; success: - RUBY_VM_CHECK_INTS(rb_ec_thread_ptr(ec)); + RUBY_VM_CHECK_INTS(ec); return ret; } diff --git a/vm_insnhelper.c b/vm_insnhelper.c index fb2ca371ed..1cb1e5664f 100644 --- a/vm_insnhelper.c +++ b/vm_insnhelper.c @@ -1712,7 +1712,7 @@ vm_call_iseq_setup_tailcall(rb_execution_context_t *ec, rb_control_frame_t *cfp, iseq->body->stack_max); cfp->sp = sp_orig; - RUBY_VM_CHECK_INTS(rb_ec_thread_ptr(ec)); + RUBY_VM_CHECK_INTS(ec); return Qundef; } @@ -3284,7 +3284,7 @@ vm_once_dispatch(ISEQ iseq, IC ic, rb_thread_t *th) } else { /* waiting for finish */ - RUBY_VM_CHECK_INTS(th); + RUBY_VM_CHECK_INTS(th->ec); rb_thread_schedule(); goto again; } diff --git a/vm_trace.c b/vm_trace.c index 745fdab8a1..28be72eb9a 100644 --- a/vm_trace.c +++ b/vm_trace.c @@ -1540,7 +1540,7 @@ postponed_job_register(rb_thread_t *th, rb_vm_t *vm, pjob->func = func; pjob->data = data; - RUBY_VM_SET_POSTPONED_JOB_INTERRUPT(th); + RUBY_VM_SET_POSTPONED_JOB_INTERRUPT(th->ec); return PJRR_SUCESS; } @@ -1576,7 +1576,7 @@ rb_postponed_job_register_one(unsigned int flags, rb_postponed_job_func_t func, for (i=0; ipostponed_job_buffer[i]; if (pjob->func == func) { - RUBY_VM_SET_POSTPONED_JOB_INTERRUPT(th); + RUBY_VM_SET_POSTPONED_JOB_INTERRUPT(th->ec); return 2; } } @@ -1591,16 +1591,16 @@ rb_postponed_job_register_one(unsigned int flags, rb_postponed_job_func_t func, void rb_postponed_job_flush(rb_vm_t *vm) { - rb_thread_t * volatile th = GET_THREAD(); + rb_execution_context_t *ec = GET_EC(); const unsigned long block_mask = POSTPONED_JOB_INTERRUPT_MASK|TRAP_INTERRUPT_MASK; - volatile unsigned long saved_mask = th->interrupt_mask & block_mask; - VALUE volatile saved_errno = th->ec->errinfo; + volatile unsigned long saved_mask = ec->interrupt_mask & block_mask; + VALUE volatile saved_errno = ec->errinfo; - th->ec->errinfo = Qnil; + ec->errinfo = Qnil; /* mask POSTPONED_JOB dispatch */ - th->interrupt_mask |= block_mask; + ec->interrupt_mask |= block_mask; { - EC_PUSH_TAG(th->ec); + EC_PUSH_TAG(ec); if (EXEC_TAG() == TAG_NONE) { int index; while ((index = vm->postponed_job_index) > 0) { @@ -1613,6 +1613,6 @@ rb_postponed_job_flush(rb_vm_t *vm) EC_POP_TAG(); } /* restore POSTPONED_JOB mask */ - th->interrupt_mask &= ~(saved_mask ^ block_mask); - th->ec->errinfo = saved_errno; + ec->interrupt_mask &= ~(saved_mask ^ block_mask); + ec->errinfo = saved_errno; } -- cgit v1.2.3