[前][次][番号順一覧][スレッド一覧]

ruby-changes:25804

From: kosaki <ko1@a...>
Date: Mon, 26 Nov 2012 19:57:49 +0900 (JST)
Subject: [ruby-changes:25804] kosaki:r37861 (trunk): * ruby_atomic.h (ATOMIC_CAS): new macro for compare-and-exchange.

kosaki	2012-11-26 19:57:39 +0900 (Mon, 26 Nov 2012)

  New Revision: 37861

  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=rev&revision=37861

  Log:
    * ruby_atomic.h (ATOMIC_CAS): new macro for compare-and-exchange.
    
    * vm_core.h (struct rb_thread_struct): add interrupt_mask member.
    * thread.c (thread_create_core, Init_Thread): initialize
      th->thread_mask.
    
    * vm_core.h (RUBY_VM_INTERRUPTED_ANY): new macro for avoiding
      bare th->interrupt_flag.
    * vm_core.h (RUBY_VM_INTERRUPTED, RUBY_VM_INTERRUPTED): check
      th->interrupt_mask.
    * thread.c (set_unblock_function, rb_thread_schedule): replace
      th->interrupt_flag with RUBY_VM_INTERRUPTED_ANY()
    
    * signal.c (signal_exec): set up thread->interrupt_mask for
      preventing recursive trap handler.
    * vm_core.h (RUBY_VM_CHECK_INTS, RUBY_VM_CHECK_INTS_BLOCKING): ditto.
    
    * thread.c (rb_threadptr_execute_interrupts):
      don't process interrupt if it is masked.
      [Bug #6009] [ruby-core:42524]

  Modified files:
    trunk/ChangeLog
    trunk/ruby_atomic.h
    trunk/signal.c
    trunk/thread.c
    trunk/vm_core.h

Index: ChangeLog
===================================================================
--- ChangeLog	(revision 37860)
+++ ChangeLog	(revision 37861)
@@ -1,3 +1,26 @@
+Mon Nov 26 19:45:18 2012  KOSAKI Motohiro  <kosaki.motohiro@g...>
+
+	* ruby_atomic.h (ATOMIC_CAS): new macro for compare-and-exchange.
+
+	* vm_core.h (struct rb_thread_struct): add interrupt_mask member.
+	* thread.c (thread_create_core, Init_Thread): initialize
+	  th->thread_mask.
+
+	* vm_core.h (RUBY_VM_INTERRUPTED_ANY): new macro for avoiding
+	  bare th->interrupt_flag.
+	* vm_core.h (RUBY_VM_INTERRUPTED, RUBY_VM_INTERRUPTED): check
+	  th->interrupt_mask.
+	* thread.c (set_unblock_function, rb_thread_schedule): replace
+	  th->interrupt_flag with RUBY_VM_INTERRUPTED_ANY()
+
+	* signal.c (signal_exec): set up thread->interrupt_mask for
+	  preventing recursive trap handler.
+	* vm_core.h (RUBY_VM_CHECK_INTS, RUBY_VM_CHECK_INTS_BLOCKING): ditto.
+
+	* thread.c (rb_threadptr_execute_interrupts):
+	  don't process interrupt if it is masked.
+	  [Bug #6009] [ruby-core:42524]
+
 Mon Nov 26 19:43:42 2012  Koichi Sasada  <ko1@a...>
 
 	* iseq.c (make_compile_option_value): add trace_instruction option.
Index: vm_core.h
===================================================================
--- vm_core.h	(revision 37860)
+++ vm_core.h	(revision 37861)
@@ -521,6 +521,7 @@
     VALUE async_errinfo_mask_stack;
 
     rb_atomic_t interrupt_flag;
+    unsigned long interrupt_mask;
     rb_thread_lock_t interrupt_lock;
     struct rb_unblock_callback unblock;
     VALUE locking_mutex;
@@ -861,7 +862,8 @@
 #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_SET_TRAP_INTERRUPT(th)		ATOMIC_OR((th)->interrupt_flag, 0x08)
-#define RUBY_VM_INTERRUPTED(th) ((th)->interrupt_flag & 0x0A)
+#define RUBY_VM_INTERRUPTED(th) ((th)->interrupt_flag & 0x0A & ~(th)->interrupt_mask)
+#define RUBY_VM_INTERRUPTED_ANY(th) ((th)->interrupt_flag & ~(th)->interrupt_mask)
 
 int rb_signal_buff_size(void);
 void rb_signal_exec(rb_thread_t *th, int sig);
@@ -879,13 +881,13 @@
 void rb_thread_lock_destroy(rb_thread_lock_t *);
 
 #define RUBY_VM_CHECK_INTS_BLOCKING(th) do { \
-    if (UNLIKELY((th)->interrupt_flag)) { \
+    if (UNLIKELY(RUBY_VM_INTERRUPTED_ANY(th))) { \
 	rb_threadptr_execute_interrupts(th, 1); \
     } \
 } while (0)
 
 #define RUBY_VM_CHECK_INTS(th) do { \
-    if (UNLIKELY((th)->interrupt_flag)) { \
+    if (UNLIKELY(RUBY_VM_INTERRUPTED_ANY(th))) {	\
 	rb_threadptr_execute_interrupts(th, 0); \
     } \
 } while (0)
Index: ruby_atomic.h
===================================================================
--- ruby_atomic.h	(revision 37860)
+++ ruby_atomic.h	(revision 37861)
@@ -13,6 +13,7 @@
 # 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))
+# define ATOMIC_CAS(var, oldval, newval) __sync_val_compare_and_swap(&(var), (oldval), (newval))
 
 # define ATOMIC_SIZE_ADD(var, val) __sync_fetch_and_add(&(var), (val))
 # define ATOMIC_SIZE_SUB(var, val) __sync_fetch_and_sub(&(var), (val))
@@ -48,7 +49,7 @@
 # define ATOMIC_OR(var, val) _InterlockedOr(&(var), (val))
 #endif
 # define ATOMIC_EXCHANGE(var, val) InterlockedExchange(&(var), (val))
-
+# define ATOMIC_CAS(var, oldval, newval) InterlockedCompareExchange(&(var), (newval), (oldval))
 # ifdef _M_AMD64
 #  define ATOMIC_SIZE_ADD(var, val) InterlockedExchangeAdd64(&(var), (val))
 #  define ATOMIC_SIZE_SUB(var, val) InterlockedExchangeAdd64(&(var), -(val))
Index: thread.c
===================================================================
--- thread.c	(revision 37860)
+++ thread.c	(revision 37861)
@@ -267,7 +267,7 @@
   check_ints:
     RUBY_VM_CHECK_INTS(th); /* check signal or so */
     native_mutex_lock(&th->interrupt_lock);
-    if (th->interrupt_flag) {
+    if (RUBY_VM_INTERRUPTED_ANY(th)) {
 	native_mutex_unlock(&th->interrupt_lock);
 	goto check_ints;
     }
@@ -582,6 +582,7 @@
     RBASIC(th->async_errinfo_mask_stack)->klass = 0;
 
     th->in_trap = 0;
+    th->interrupt_mask = 0;
 
     native_mutex_initialize(&th->interrupt_lock);
 
@@ -1054,10 +1055,11 @@
 void
 rb_thread_schedule(void)
 {
+    rb_thread_t *cur_th = GET_THREAD();
     rb_thread_schedule_limits(0);
 
-    if (UNLIKELY(GET_THREAD()->interrupt_flag)) {
-	rb_threadptr_execute_interrupts(GET_THREAD(), 0);
+    if (UNLIKELY(RUBY_VM_INTERRUPTED_ANY(cur_th))) {
+	rb_threadptr_execute_interrupts(cur_th, 0);
     }
 }
 
@@ -1725,18 +1727,32 @@
 void
 rb_threadptr_execute_interrupts(rb_thread_t *th, int blocking_timing)
 {
-    rb_atomic_t interrupt;
-
     if (th->raised_flag) return;
 
-    while ((interrupt = ATOMIC_EXCHANGE(th->interrupt_flag, 0)) != 0) {
+    while (1) {
 	enum rb_thread_status status = th->status;
-	int timer_interrupt = interrupt & 0x01;
-	int async_errinfo_interrupt = interrupt & 0x02;
-	int finalizer_interrupt = interrupt & 0x04;
-	int trap_interrupt = interrupt & 0x08;
+	rb_atomic_t interrupt;
+	rb_atomic_t old;
 	int sig;
+	int timer_interrupt;
+	int async_errinfo_interrupt;
+	int finalizer_interrupt;
+	int trap_interrupt;
 
+	do {
+	    interrupt = th->interrupt_flag;
+	    old = ATOMIC_CAS(th->interrupt_flag, interrupt, interrupt & th->interrupt_mask);
+	} while (old != interrupt);
+
+	interrupt &= ~th->interrupt_mask;
+	if (!interrupt)
+	    return;
+
+	timer_interrupt = interrupt & 0x01;
+	async_errinfo_interrupt = interrupt & 0x02;
+	finalizer_interrupt = interrupt & 0x04;
+	trap_interrupt = interrupt & 0x08;
+
 	th->status = THREAD_RUNNABLE;
 
 	/* signal handling */
@@ -4798,6 +4814,7 @@
 	    th->async_errinfo_mask_stack = rb_ary_tmp_new(0);
 
 	    th->in_trap = 0;
+	    th->interrupt_mask = 0;
 	}
     }
 
Index: signal.c
===================================================================
--- signal.c	(revision 37860)
+++ signal.c	(revision 37861)
@@ -625,9 +625,11 @@
 {
     rb_thread_t *cur_th = GET_THREAD();
     volatile int old_in_trap = cur_th->in_trap;
+    volatile unsigned long old_interrupt_mask = cur_th->interrupt_mask;
     int state;
 
     cur_th->in_trap = 1;
+    cur_th->interrupt_mask |= 0x08;
     TH_PUSH_TAG(cur_th);
     if ((state = EXEC_TAG()) == 0) {
 	VALUE signum = INT2NUM(sig);
@@ -635,6 +637,7 @@
     }
     TH_POP_TAG();
     cur_th = GET_THREAD();
+    cur_th->interrupt_mask = old_interrupt_mask;
     cur_th->in_trap = old_in_trap;
 
     if (state) {

--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

[前][次][番号順一覧][スレッド一覧]