Project

General

Profile

Feature #15002 ยป 0001-thread.c-sleep_-reduce-the-effect-of-spurious-interr.patch

normalperson (Eric Wong), 08/17/2018 08:07 AM

View differences:

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);
-
    (1-1/1)