Feature #15002 ยป 0001-thread.c-sleep_-reduce-the-effect-of-spurious-interr.patch
signal.c | ||
---|---|---|
}
|
||
#endif
|
||
static void
|
||
static int
|
||
signal_exec(VALUE cmd, int safe, int sig)
|
||
{
|
||
rb_execution_context_t *ec = GET_EC();
|
||
... | ... | |
* 3. rb_signal_exec runs on queued signal
|
||
*/
|
||
if (IMMEDIATE_P(cmd))
|
||
return;
|
||
return FALSE;
|
||
ec->interrupt_mask |= TRAP_INTERRUPT_MASK;
|
||
EC_PUSH_TAG(ec);
|
||
... | ... | |
/* XXX: should be replaced with rb_threadptr_pending_interrupt_enque() */
|
||
EC_JUMP_TAG(ec, state);
|
||
}
|
||
return TRUE;
|
||
}
|
||
void
|
||
... | ... | |
}
|
||
}
|
||
void
|
||
/* returns true if a trap handler was run, false otherwise */
|
||
int
|
||
rb_signal_exec(rb_thread_t *th, int sig)
|
||
{
|
||
rb_vm_t *vm = GET_VM();
|
||
... | ... | |
rb_threadptr_signal_exit(th);
|
||
}
|
||
else {
|
||
signal_exec(cmd, safe, sig);
|
||
return signal_exec(cmd, safe, sig);
|
||
}
|
||
return FALSE;
|
||
}
|
||
static sighandler_t
|
thread.c | ||
---|---|---|
}; \
|
||
} while(0)
|
||
/*
|
||
* returns true if this thread was spuriously interrupted, false otherwise
|
||
* (e.g. hit by Thread#run or ran a Ruby-level Signal.trap handler)
|
||
*/
|
||
#define RUBY_VM_CHECK_INTS_BLOCKING(ec) vm_check_ints_blocking(ec)
|
||
static inline void
|
||
static inline int
|
||
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(ec))) return;
|
||
if (LIKELY(!RUBY_VM_INTERRUPTED_ANY(ec))) return FALSE;
|
||
}
|
||
else {
|
||
th->pending_interrupt_queue_checked = 0;
|
||
RUBY_VM_SET_INTERRUPT(ec);
|
||
}
|
||
rb_threadptr_execute_interrupts(th, 1);
|
||
return rb_threadptr_execute_interrupts(th, 1);
|
||
}
|
||
static int
|
||
... | ... | |
{
|
||
enum rb_thread_status prev_status = th->status;
|
||
enum rb_thread_status status;
|
||
int woke;
|
||
status = fl & SLEEP_DEADLOCKABLE ? THREAD_STOPPED_FOREVER : THREAD_STOPPED;
|
||
th->status = status;
|
||
... | ... | |
if (fl & SLEEP_DEADLOCKABLE) {
|
||
th->vm->sleeper--;
|
||
}
|
||
RUBY_VM_CHECK_INTS_BLOCKING(th->ec);
|
||
if (!(fl & SLEEP_SPURIOUS_CHECK))
|
||
woke = vm_check_ints_blocking(th->ec);
|
||
if (woke && !(fl & SLEEP_SPURIOUS_CHECK))
|
||
break;
|
||
}
|
||
th->status = prev_status;
|
||
... | ... | |
{
|
||
struct timespec end;
|
||
enum rb_thread_status prev_status = th->status;
|
||
int woke;
|
||
getclockofday(&end);
|
||
timespec_add(&end, &ts);
|
||
... | ... | |
RUBY_VM_CHECK_INTS_BLOCKING(th->ec);
|
||
while (th->status == THREAD_STOPPED) {
|
||
native_sleep(th, &ts);
|
||
RUBY_VM_CHECK_INTS_BLOCKING(th->ec);
|
||
if (!(fl & SLEEP_SPURIOUS_CHECK))
|
||
woke = vm_check_ints_blocking(th->ec);
|
||
if (woke && !(fl & SLEEP_SPURIOUS_CHECK))
|
||
break;
|
||
if (timespec_update_expire(&ts, &end))
|
||
break;
|
||
... | ... | |
return interrupt & (rb_atomic_t)~ec->interrupt_mask;
|
||
}
|
||
MJIT_FUNC_EXPORTED void
|
||
MJIT_FUNC_EXPORTED int
|
||
rb_threadptr_execute_interrupts(rb_thread_t *th, int blocking_timing)
|
||
{
|
||
rb_atomic_t interrupt;
|
||
int postponed_job_interrupt = 0;
|
||
int ret = FALSE;
|
||
if (th->ec->raised_flag) return;
|
||
if (th->ec->raised_flag) return ret;
|
||
while ((interrupt = threadptr_get_interrupts(th)) != 0) {
|
||
int sig;
|
||
... | ... | |
}
|
||
th->status = THREAD_RUNNABLE;
|
||
while ((sig = rb_get_next_signal()) != 0) {
|
||
rb_signal_exec(th, sig);
|
||
ret |= rb_signal_exec(th, sig);
|
||
}
|
||
th->status = prev_status;
|
||
}
|
||
... | ... | |
if (pending_interrupt && threadptr_pending_interrupt_active_p(th)) {
|
||
VALUE err = rb_threadptr_pending_interrupt_deque(th, blocking_timing ? INTERRUPT_ON_BLOCKING : INTERRUPT_NONE);
|
||
thread_debug("rb_thread_execute_interrupts: %"PRIdVALUE"\n", err);
|
||
ret = TRUE;
|
||
if (err == Qundef) {
|
||
/* no error */
|
||
... | ... | |
rb_thread_schedule_limits(limits_us);
|
||
}
|
||
}
|
||
return ret;
|
||
}
|
||
void
|
vm_core.h | ||
---|---|---|
VALUE rb_exc_set_backtrace(VALUE exc, VALUE bt);
|
||
int rb_signal_buff_size(void);
|
||
void rb_signal_exec(rb_thread_t *th, int sig);
|
||
int rb_signal_exec(rb_thread_t *th, int sig);
|
||
void rb_threadptr_check_signal(rb_thread_t *mth);
|
||
void rb_threadptr_signal_raise(rb_thread_t *th, int sig);
|
||
void rb_threadptr_signal_exit(rb_thread_t *th);
|
||
void rb_threadptr_execute_interrupts(rb_thread_t *, int);
|
||
int rb_threadptr_execute_interrupts(rb_thread_t *, int);
|
||
void rb_threadptr_interrupt(rb_thread_t *th);
|
||
void rb_threadptr_unlock_all_locking_mutexes(rb_thread_t *th);
|
||
void rb_threadptr_pending_interrupt_clear(rb_thread_t *th);
|
||
-
|