Project

General

Profile

Backport #7134 » mutex_notrap.patch

kosaki (Motohiro KOSAKI), 11/06/2012 04:40 AM

View differences:

vm_core.h (working copy)
void *altstack;
#endif
unsigned long running_time_us;
int trap_enabled;
} rb_thread_t;
/* iseq.c */
......
#define RUBY_VM_SET_TIMER_INTERRUPT(th) ATOMIC_OR((th)->interrupt_flag, 0x01)
#define RUBY_VM_SET_INTERRUPT(th) ATOMIC_OR((th)->interrupt_flag, 0x02)
#define RUBY_VM_SET_FINALIZER_INTERRUPT(th) ATOMIC_OR((th)->interrupt_flag, 0x04)
#define RUBY_VM_INTERRUPTED(th) ((th)->interrupt_flag & 0x02)
#define RUBY_VM_INTERRUPTED(th) ((th)->trap_enabled && ((th)->interrupt_flag & 0x02))
int rb_signal_buff_size(void);
void rb_signal_exec(rb_thread_t *th, int sig);
......
void rb_thread_lock_unlock(rb_thread_lock_t *);
void rb_thread_lock_destroy(rb_thread_lock_t *);
#define THREAD_INTERRUPTED(th) ((th)->trap_enabled && (th)->interrupt_flag)
#define RUBY_VM_CHECK_INTS_BLOCKING(th) do { \
if (UNLIKELY((th)->interrupt_flag)) { \
if (UNLIKELY(THREAD_INTERRUPTED(th))) { \
rb_threadptr_execute_interrupts(th, 1); \
} \
} while (0)
#define RUBY_VM_CHECK_INTS(th) do { \
if (UNLIKELY((th)->interrupt_flag)) { \
if (UNLIKELY(THREAD_INTERRUPTED(th))) { \
rb_threadptr_execute_interrupts(th, 0); \
} \
} while (0)
io.c (working copy)
arg.ptr = ptr + offset;
arg.length = n;
if (fptr->write_lock) {
r = rb_mutex_synchronize(fptr->write_lock, io_binwrite_string, (VALUE)&arg);
r = rb_mutex_synchronize_notrap(fptr->write_lock, io_binwrite_string, (VALUE)&arg);
}
else {
long l = io_writable_length(fptr, n);
thread.c (working copy)
check_ints:
RUBY_VM_CHECK_INTS(th); /* check signal or so */
native_mutex_lock(&th->interrupt_lock);
if (th->interrupt_flag) {
if (THREAD_INTERRUPTED(th)) {
native_mutex_unlock(&th->interrupt_lock);
goto check_ints;
}
......
native_mutex_initialize(&th->interrupt_lock);
th->trap_enabled = 1;
/* kick thread */
st_insert(th->vm->living_threads, thval, (st_data_t) th->thread_id);
err = native_thread_create(th);
......
{
rb_thread_schedule_limits(0);
if (UNLIKELY(GET_THREAD()->interrupt_flag)) {
if (UNLIKELY(THREAD_INTERRUPTED(GET_THREAD()))) {
rb_threadptr_execute_interrupts_common(GET_THREAD(), 0);
}
}
......
return rb_ensure(func, arg, rb_mutex_unlock, mutex);
}
typedef struct {
VALUE mutex;
int old_trap_enabled;
} sync_notrap_t;
/* :nodoc: */
VALUE
rb_mutex_unlock_notrap(VALUE value)
{
sync_notrap_t *arg = (sync_notrap_t*)value;
VALUE ret;
rb_thread_t *th = GET_THREAD();
ret = rb_mutex_unlock(arg->mutex);
th->trap_enabled = arg->old_trap_enabled;
return ret;
}
/*
* :nodoc:
* similar rb_mutex_synchronize(), but also prevent trap
*/
VALUE
rb_mutex_synchronize_notrap(VALUE mutex, VALUE (*func)(VALUE arg), VALUE arg)
{
rb_thread_t *th = GET_THREAD();
sync_notrap_t ensure_arg;
ensure_arg.mutex = mutex;
ensure_arg.old_trap_enabled = th->trap_enabled;
/* mask trap handler for prevent recursive mutex lock */
th->trap_enabled = 0;
rb_mutex_lock(mutex);
return rb_ensure(func, arg, rb_mutex_unlock_notrap, (VALUE)&ensure_arg);
}
/*
* Document-class: ThreadShield
*/
static void
......
th->async_errinfo_queue = rb_ary_tmp_new(0);
th->async_errinfo_queue_checked = 0;
th->async_errinfo_mask_stack = rb_ary_tmp_new(0);
th->trap_enabled = 1;
}
}
internal.h (working copy)
VALUE rb_thread_shield_wait(VALUE self);
VALUE rb_thread_shield_release(VALUE self);
VALUE rb_thread_shield_destroy(VALUE self);
VALUE rb_mutex_synchronize_notrap(VALUE mutex, VALUE (*func)(VALUE arg), VALUE arg);
/* thread_pthread.c, thread_win32.c */
void Init_native_thread(void);
(2-2/2)