Bug #4770 » 0001-interrupt-flag.patch
| atomic.h | ||
|---|---|---|
|
#ifndef RUBY_ATOMIC_H
|
||
|
#define RUBY_ATOMIC_H
|
||
|
#ifdef _WIN32
|
||
|
#pragma intrinsic(_InterlockedOr)
|
||
|
typedef LONG rb_atomic_t;
|
||
|
# define ATOMIC_SET(var, val) InterlockedExchange(&(var), (val))
|
||
|
# define ATOMIC_INC(var) InterlockedIncrement(&(var))
|
||
|
# define ATOMIC_DEC(var) InterlockedDecrement(&(var))
|
||
|
# define ATOMIC_OR(var, val) _InterlockedOr(&(var), (val))
|
||
|
# define ATOMIC_EXCHANGE(var, val) InterlockedExchange(&(var), (val))
|
||
|
#elif defined HAVE_GCC_ATOMIC_BUILTINS
|
||
|
/* @shyouhei hack to support atomic operations in case of gcc. Gcc
|
||
|
* has its own pseudo-insns to support them. See info, or
|
||
|
* http://gcc.gnu.org/onlinedocs/gcc/Atomic-Builtins.html */
|
||
|
typedef unsigned int rb_atomic_t; /* Anything OK */
|
||
|
# define ATOMIC_SET(var, val) __sync_lock_test_and_set(&(var), (val))
|
||
|
# define ATOMIC_INC(var) __sync_fetch_and_add(&(var), 1)
|
||
|
# define ATOMIC_DEC(var) __sync_fetch_and_sub(&(var), 1)
|
||
|
# define ATOMIC_OR(var, val) __sync_or_and_fetch(&(var), (val))
|
||
|
# define ATOMIC_EXCHANGE(var, val) __sync_lock_test_and_set(&(var), (val))
|
||
|
#else
|
||
|
typedef int rb_atomic_t;
|
||
|
extern rb_atomic_t ruby_atomic_exchange(rb_atomic_t *ptr, rb_atomic_t val);
|
||
|
# define ATOMIC_SET(var, val) ((var) = (val))
|
||
|
# define ATOMIC_INC(var) (++(var))
|
||
|
# define ATOMIC_DEC(var) (--(var))
|
||
|
# define ATOMIC_OR(var, val) ((var) |= (val))
|
||
|
# define ATOMIC_EXCHANGE(var, val) ruby_atomic_exchange(&(var), (val))
|
||
|
#endif
|
||
|
#endif /* RUBY_ATOMIC_H */
|
||
| common.mk | ||
|---|---|---|
|
gc.$(OBJEXT): {$(VPATH)}gc.c $(RUBY_H_INCLUDES) {$(VPATH)}re.h \
|
||
|
{$(VPATH)}regex.h $(ENCODING_H_INCLUDES) $(VM_CORE_H_INCLUDES) \
|
||
|
{$(VPATH)}gc.h {$(VPATH)}io.h {$(VPATH)}eval_intern.h {$(VPATH)}util.h \
|
||
|
{$(VPATH)}debug.h
|
||
|
{$(VPATH)}debug.h {$(VPATH)}atomic.h
|
||
|
hash.$(OBJEXT): {$(VPATH)}hash.c $(RUBY_H_INCLUDES) {$(VPATH)}util.h
|
||
|
inits.$(OBJEXT): {$(VPATH)}inits.c $(RUBY_H_INCLUDES)
|
||
|
io.$(OBJEXT): {$(VPATH)}io.c $(RUBY_H_INCLUDES) {$(VPATH)}io.h \
|
||
| ... | ... | |
|
safe.$(OBJEXT): {$(VPATH)}safe.c $(RUBY_H_INCLUDES) \
|
||
|
$(VM_CORE_H_INCLUDES) {$(VPATH)}debug.h
|
||
|
signal.$(OBJEXT): {$(VPATH)}signal.c $(RUBY_H_INCLUDES) \
|
||
|
$(VM_CORE_H_INCLUDES) {$(VPATH)}debug.h
|
||
|
$(VM_CORE_H_INCLUDES) {$(VPATH)}debug.h {$(VPATH)}atomic.h
|
||
|
sprintf.$(OBJEXT): {$(VPATH)}sprintf.c $(RUBY_H_INCLUDES) {$(VPATH)}re.h \
|
||
|
{$(VPATH)}regex.h {$(VPATH)}vsnprintf.c $(ENCODING_H_INCLUDES)
|
||
|
st.$(OBJEXT): {$(VPATH)}st.c {$(VPATH)}config.h {$(VPATH)}defines.h \
|
||
| ... | ... | |
|
struct.$(OBJEXT): {$(VPATH)}struct.c $(RUBY_H_INCLUDES)
|
||
|
thread.$(OBJEXT): {$(VPATH)}thread.c {$(VPATH)}eval_intern.h \
|
||
|
$(RUBY_H_INCLUDES) {$(VPATH)}gc.h $(VM_CORE_H_INCLUDES) \
|
||
|
{$(VPATH)}debug.h {$(VPATH)}thread_$(THREAD_MODEL).c
|
||
|
{$(VPATH)}debug.h {$(VPATH)}thread_$(THREAD_MODEL).c {$(VPATH)}atomic.h
|
||
|
transcode.$(OBJEXT): {$(VPATH)}transcode.c $(RUBY_H_INCLUDES) \
|
||
|
$(ENCODING_H_INCLUDES) {$(VPATH)}transcode_data.h
|
||
|
cont.$(OBJEXT): {$(VPATH)}cont.c $(RUBY_H_INCLUDES) \
|
||
|
$(VM_CORE_H_INCLUDES) {$(VPATH)}gc.h {$(VPATH)}eval_intern.h \
|
||
|
{$(VPATH)}debug.h
|
||
|
{$(VPATH)}debug.h {$(VPATH)}atomic.h
|
||
|
time.$(OBJEXT): {$(VPATH)}time.c $(RUBY_H_INCLUDES) \
|
||
|
$(ENCODING_H_INCLUDES) {$(VPATH)}timev.h
|
||
|
util.$(OBJEXT): {$(VPATH)}util.c $(RUBY_H_INCLUDES) {$(VPATH)}util.h
|
||
| signal.c | ||
|---|---|---|
|
#include <signal.h>
|
||
|
#include <stdio.h>
|
||
|
#include <errno.h>
|
||
|
#include "atomic.h"
|
||
|
#ifdef _WIN32
|
||
|
typedef LONG rb_atomic_t;
|
||
|
# define ATOMIC_TEST(var) InterlockedExchange(&(var), 0)
|
||
|
# define ATOMIC_SET(var, val) InterlockedExchange(&(var), (val))
|
||
|
# define ATOMIC_INC(var) InterlockedIncrement(&(var))
|
||
|
# define ATOMIC_DEC(var) InterlockedDecrement(&(var))
|
||
|
#elif defined HAVE_GCC_ATOMIC_BUILTINS
|
||
|
/* @shyouhei hack to support atomic operations in case of gcc. Gcc
|
||
|
* has its own pseudo-insns to support them. See info, or
|
||
|
* http://gcc.gnu.org/onlinedocs/gcc/Atomic-Builtins.html */
|
||
|
typedef unsigned int rb_atomic_t; /* Anything OK */
|
||
|
# define ATOMIC_TEST(var) __sync_lock_test_and_set(&(var), 0)
|
||
|
# define ATOMIC_SET(var, val) __sync_lock_test_and_set(&(var), (val))
|
||
|
# define ATOMIC_INC(var) __sync_fetch_and_add(&(var), 1)
|
||
|
# define ATOMIC_DEC(var) __sync_fetch_and_sub(&(var), 1)
|
||
|
#else
|
||
|
typedef int rb_atomic_t;
|
||
|
# define ATOMIC_TEST(var) ((var) ? ((var) = 0, 1) : 0)
|
||
|
# define ATOMIC_SET(var, val) ((var) = (val))
|
||
|
# define ATOMIC_INC(var) (++(var))
|
||
|
# define ATOMIC_DEC(var) (--(var))
|
||
|
#if !defined(_WIN32) && !defined(HAVE_GCC_ATOMIC_BUILTINS)
|
||
|
rb_atomic_t ruby_atomic_exchange(rb_atomic_t *ptr, rb_atomic_t val)
|
||
|
{
|
||
|
rb_atomic_t old = *ptr;
|
||
|
*ptr = val;
|
||
|
return old;
|
||
|
}
|
||
|
#endif
|
||
|
#if defined(__BEOS__) || defined(__HAIKU__)
|
||
| thread.c | ||
|---|---|---|
|
static void
|
||
|
rb_threadptr_execute_interrupts_rec(rb_thread_t *th, int sched_depth)
|
||
|
{
|
||
|
rb_atomic_t interrupt;
|
||
|
if (GET_VM()->main_thread == th) {
|
||
|
while (rb_signal_buff_size() && !th->exec_signal) native_thread_yield();
|
||
|
}
|
||
|
if (th->raised_flag) return;
|
||
|
while (th->interrupt_flag) {
|
||
|
while ((interrupt = ATOMIC_EXCHANGE(th->interrupt_flag, 0)) != 0) {
|
||
|
enum rb_thread_status status = th->status;
|
||
|
int timer_interrupt = th->interrupt_flag & 0x01;
|
||
|
int finalizer_interrupt = th->interrupt_flag & 0x04;
|
||
|
int timer_interrupt = interrupt & 0x01;
|
||
|
int finalizer_interrupt = interrupt & 0x04;
|
||
|
th->status = THREAD_RUNNABLE;
|
||
|
th->interrupt_flag = 0;
|
||
|
/* signal handling */
|
||
|
if (th->exec_signal) {
|
||
| vm_core.h | ||
|---|---|---|
|
#include "vm_opts.h"
|
||
|
#include "id.h"
|
||
|
#include "method.h"
|
||
|
#include "atomic.h"
|
||
|
#if defined(_WIN32)
|
||
|
#include "thread_win32.h"
|
||
| ... | ... | |
|
VALUE thrown_errinfo;
|
||
|
int exec_signal;
|
||
|
int interrupt_flag;
|
||
|
rb_atomic_t interrupt_flag;
|
||
|
rb_thread_lock_t interrupt_lock;
|
||
|
struct rb_unblock_callback unblock;
|
||
|
VALUE locking_mutex;
|
||
| ... | ... | |
|
#error "unsupported thread model"
|
||
|
#endif
|
||
|
#define RUBY_VM_SET_INTERRUPT(th) ((th)->interrupt_flag |= 0x02)
|
||
|
#define RUBY_VM_SET_TIMER_INTERRUPT(th) ((th)->interrupt_flag |= 0x01)
|
||
|
#define RUBY_VM_SET_FINALIZER_INTERRUPT(th) ((th)->interrupt_flag |= 0x04)
|
||
|
#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)
|
||
|
int rb_signal_buff_size(void);
|
||