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);
|