[前][次][番号順一覧][スレッド一覧][生データ]

yarv-diff:379

From: ko1 atdot.net
Date: 2 Sep 2006 22:52:33 +0900
Subject: [yarv-diff:379] r546 - in branches/parallel: . yarvtest

Author: ko1
Date: 2006-09-02 22:52:32 +0900 (Sat, 02 Sep 2006)
New Revision: 546

Modified:
   branches/parallel/ChangeLog
   branches/parallel/compile.c
   branches/parallel/configure.in
   branches/parallel/gc.c
   branches/parallel/re.c
   branches/parallel/regint.h
   branches/parallel/thread.c
   branches/parallel/thread_pthread.h
   branches/parallel/yarvcore.c
   branches/parallel/yarvcore.h
   branches/parallel/yarvtest/test_thread.rb
Log:
Caution: there are some synchronization bugs.

	* compile.c : same change of trunk

	* configure.in : check pthread_spinlock_t and sched_setaffinity

	* re.c : use thread local regs

	* yarvcore.c : ditto

	* regint.h : disable USE_MULTI_THREAD_SYSTEM macro

	* thread.c : check RUBY_MAX_CPU environment variable

	* thread.c, thread_pthread.h : fix parallel behaviour

	* yarvcore.h : ditto

	* gc.c : ditto

	* yarvtest/test_thread.rb : add some tests for above



Modified: branches/parallel/ChangeLog
===================================================================
--- branches/parallel/ChangeLog	2006-09-01 13:06:17 UTC (rev 545)
+++ branches/parallel/ChangeLog	2006-09-02 13:52:32 UTC (rev 546)
@@ -4,6 +4,29 @@
 #  from Mon, 03 May 2004 01:24:19 +0900
 #
 
+2006-09-02(Sat) 22:35:43 +0900  Koichi Sasada  <ko1 atdot.net>
+
+	* compile.c : same change of trunk
+
+	* configure.in : check pthread_spinlock_t and sched_setaffinity
+
+	* re.c : use thread local regs
+
+	* yarvcore.c : ditto
+
+	* regint.h : disable USE_MULTI_THREAD_SYSTEM macro
+
+	* thread.c : check RUBY_MAX_CPU environment variable
+
+	* thread.c, thread_pthread.h : fix parallel behaviour
+
+	* yarvcore.h : ditto
+
+	* gc.c : ditto
+
+	* yarvtest/test_thread.rb : add some tests for above
+
+
 2006-08-31(Thu) 19:09:56 +0900  Koichi Sasada  <ko1 atdot.net>
 
 	* configure.in : check pthread_spinlock_t

Modified: branches/parallel/compile.c
===================================================================
--- branches/parallel/compile.c	2006-09-01 13:06:17 UTC (rev 545)
+++ branches/parallel/compile.c	2006-09-02 13:52:32 UTC (rev 546)
@@ -1483,7 +1483,7 @@
 	if (diobj == niobj) {
 	    REMOVE_ELEM(&iobj->link);
 	}
-	else if (diobj->insn_id == BIN(jump)) {
+	else if (iobj != diobj && diobj->insn_id == BIN(jump)) {
 	    OPERAND_AT(iobj, 0) = OPERAND_AT(diobj, 0);
 	    goto again;
 	}
@@ -3900,25 +3900,27 @@
 	  }
 
 
-#if OPT_BASIC_OPERATIONS
-	  /* TODO: detect by node */
-	  if (recv->last == recv->anchor.next &&
-	      INSN_OF(recv->last) == BIN(putobject) &&
-	      nd_type(node) == NODE_MATCH2) {
-	      ADD_SEQ(ret, val);
-	      ADD_INSN1(ret, nd_line(node), opt_regexpmatch1,
-			OPERAND_AT(recv->last, 0));
+	  if (iseq->compile_data->option->specialized_instruction) {
+	      /* TODO: detect by node */
+	      if (recv->last == recv->anchor.next &&
+		  INSN_OF(recv->last) == BIN(putobject) &&
+		  nd_type(node) == NODE_MATCH2) {
+		  ADD_SEQ(ret, val);
+		  ADD_INSN1(ret, nd_line(node), opt_regexpmatch1,
+			    OPERAND_AT(recv->last, 0));
+	      }
+	      else {
+		  ADD_SEQ(ret, recv);
+		  ADD_SEQ(ret, val);
+		  ADD_INSN(ret, nd_line(node), opt_regexpmatch2);
+	      }
 	  }
 	  else {
 	      ADD_SEQ(ret, recv);
 	      ADD_SEQ(ret, val);
-	      ADD_INSN(ret, nd_line(node), opt_regexpmatch2);
+	      ADD_SEND(ret, nd_line(node), ID2SYM(idEqTilde), INT2FIX(1));
 	  }
-#else
-	  ADD_SEQ(ret, recv);
-	  ADD_SEQ(ret, val);
-	  ADD_SEND(ret, nd_line(node), ID2SYM(idEqTilde), INT2FIX(1));
-#endif
+
 	  if (poped) {
 	      ADD_INSN(ret, nd_line(node), pop);
 	  }

Modified: branches/parallel/configure.in
===================================================================
--- branches/parallel/configure.in	2006-09-01 13:06:17 UTC (rev 545)
+++ branches/parallel/configure.in	2006-09-02 13:52:32 UTC (rev 546)
@@ -782,7 +782,9 @@
     fi
 fi
 
-AC_CHECK_TYPES(pthread_spinlock_t, , , pthread.h)
+AC_CHECK_HEADERS(pthread.h)
+AC_CHECK_TYPES(pthread_spinlock_t)
+AC_CHECK_FUNCS(sched_setaffinity)
 
 if test x"$ac_cv_header_ucontext_h" = xyes; then
     if test x"$rb_with_pthread" = xyes; then

Modified: branches/parallel/gc.c
===================================================================
--- branches/parallel/gc.c	2006-09-01 13:06:17 UTC (rev 545)
+++ branches/parallel/gc.c	2006-09-02 13:52:32 UTC (rev 546)
@@ -489,14 +489,6 @@
 
     locked = rb_thread_global_lock_acquire(th);
 
-    while (th->interrupt_gc_flag) {
-	rb_thread_global_lock_release(th);
-	rb_thread_gc_barrier_stop(th);
-	rb_thread_global_lock_acquire(th);
-    }
-    
-    rb_thread_gc_barrier_start(th);
-    
     for (i=0; i<YARV_VALUE_CACHE_SIZE; i++) {
 	VALUE v = rb_newobj_from_heap();
 	
@@ -505,8 +497,6 @@
     }
     th->value_cache_ptr = &th->value_cache[0];
     rv = rb_newobj_from_heap();
-
-    rb_thread_gc_barrier_end(th);
     
     if (locked) {
 	rb_thread_global_lock_release(th);
@@ -1351,9 +1341,29 @@
 #endif /* __human68k__ or DJGPP */
 #endif /* __GNUC__ */
 
+static int garbage_collect_thread_unsafe(void);
+
 static int
 garbage_collect(void)
 {
+    yarv_thread_t *th = GET_THREAD();
+    int r, locked = rb_thread_global_lock_acquire(th);
+
+    rb_thread_gc_barrier_start(th);
+    if (freelist == 0) {
+	r = garbage_collect_thread_unsafe();
+    }
+    rb_thread_gc_barrier_end(th);
+
+    if (locked) {
+	rb_thread_global_lock_release(th);
+    }
+    return r;
+}
+
+static int
+garbage_collect_thread_unsafe(void)
+{
     struct gc_list *list;
     jmp_buf save_regs_gc_mark;
     yarv_thread_t *th = GET_THREAD();

Modified: branches/parallel/re.c
===================================================================
--- branches/parallel/re.c	2006-09-01 13:06:17 UTC (rev 545)
+++ branches/parallel/re.c	2006-09-02 13:52:32 UTC (rev 546)
@@ -965,12 +965,14 @@
     return pos;
 }
 
+void *rb_thread_get_local_regs(void);
+
 long
 rb_reg_search(VALUE re, VALUE str, long pos, long reverse)
 {
     long result;
     VALUE match;
-    static struct re_registers regs;
+    struct re_registers *regs = rb_thread_get_local_regs();
     long range;
 
     if (pos > RSTRING(str)->len || pos < 0) {
@@ -998,7 +1000,7 @@
 			 ((UChar*)(RSTRING(str)->ptr) + RSTRING(str)->len),
 			 ((UChar*)(RSTRING(str)->ptr) + pos),
 			 ((UChar*)(RSTRING(str)->ptr) + pos + range),
-			 &regs, ONIG_OPTION_NONE);
+			 regs, ONIG_OPTION_NONE);
 
     if (FL_TEST(re, KCODE_FIXED))
 	kcode_reset_option();
@@ -1026,7 +1028,7 @@
 	    FL_UNSET(match, FL_TAINT);
     }
 
-    onig_region_copy(RMATCH(match)->regs, &regs);
+    onig_region_copy(RMATCH(match)->regs, regs);
     RMATCH(match)->str = rb_str_new4(str);
     RMATCH(match)->regexp = re;
     rb_backref_set(match);

Modified: branches/parallel/regint.h
===================================================================
--- branches/parallel/regint.h	2006-09-01 13:06:17 UTC (rev 545)
+++ branches/parallel/regint.h	2006-09-02 13:52:32 UTC (rev 546)
@@ -98,24 +98,20 @@
 #include "version.h"
 #include "rubysig.h"      /* for DEFER_INTS, ENABLE_INTS */
 
-#define USE_MULTI_THREAD_SYSTEM
-#define THREAD_ATOMIC_START          DEFER_INTS
-#define THREAD_ATOMIC_END            ENABLE_INTS
+// #define USE_MULTI_THREAD_SYSTEM
+#define THREAD_ATOMIC_START
+#define THREAD_ATOMIC_END
+//#define THREAD_ATOMIC_START          DEFER_INTS
+//#define THREAD_ATOMIC_END            ENABLE_INTS
 #define THREAD_PASS                  rb_thread_schedule()
-#define CHECK_INTERRUPT do {\
-  if (rb_trap_pending) {\
-    if (! rb_prohibit_interrupt) {\
-      rb_trap_exec();\
-    }\
-  }\
-} while (0)
+#define CHECK_INTERRUPT
 
 #define DEFAULT_WARN_FUNCTION        onig_rb_warn
 #define DEFAULT_VERB_WARN_FUNCTION   onig_rb_warning
 
 #endif /* else NOT_RUBY */
 
-#define THREAD_PASS_LIMIT_COUNT     8
+#define THREAD_PASS_LIMIT_COUNT     2048
 #define xmemset     memset
 #define xmemcpy     memcpy
 #define xmemmove    memmove

Modified: branches/parallel/thread.c
===================================================================
--- branches/parallel/thread.c	2006-09-01 13:06:17 UTC (rev 545)
+++ branches/parallel/thread.c	2006-09-02 13:52:32 UTC (rev 546)
@@ -75,6 +75,15 @@
 static void yarv_set_interrupt_function(yarv_thread_t *th, yarv_interrupt_function_t *func);
 static void yarv_clear_interrupt_function(yarv_thread_t *th);
 
+#define BLOCKING_RANGE(th, func, body) do { \
+  if (rb_thread_blocking_start(th, func) != 0) { \
+      body; \
+      rb_thread_blocking_end(th); \
+  } \
+} while (0)
+
+
+
 #if THREAD_DEBUG
 void thread_debug(const char *fmt, ...);
 #else
@@ -128,6 +137,7 @@
 #endif
 
 
+
 int
 rb_thread_global_lock_acquire(yarv_thread_t *th)
 {
@@ -173,24 +183,26 @@
     return vm->lock_owner_thread == th;
 }
 
-static void
+static int
 rb_thread_blocking_start(yarv_thread_t *th, yarv_interrupt_function_t *func)
 {
     yarv_vm_t *vm = GET_VM();
-    
-  retry:
-    YARV_CHECK_INTS_TH(th);
 
     yarv_set_interrupt_function(th, func);
+    if (th->interrupt_flag) {
+	/* there is possibility that interrupt was occurrd before
+           setting set_interrupt_function */
+	return 0;
+    }
+    
     vm->num_wait_threads++;
+    if (vm->interrupt_gc_flag) {
+	pthread_cond_signal(&vm->gc_barrier_owner_cond);
+    }
+    
     yarv_save_machine_context(th);
-
     rb_thread_global_lock_release(th);
-
-    if (th->interrupt_flag) {
-	rb_thread_global_lock_acquire(th);
-	goto retry;
-    }
+    return 1;
 }
 
 static void
@@ -198,19 +210,35 @@
 {
     yarv_vm_t *vm = GET_VM();
     rb_thread_global_lock_acquire(th);
+    yarv_clear_interrupt_function(th);
     vm->num_wait_threads--;
-    yarv_clear_interrupt_function(th);
 }
 
-static int
-set_gc_interrupt_flag(st_data_t key, st_data_t val, st_data_t set)
+void
+rb_thread_gc_barrier_stop(yarv_thread_t *th)
 {
-    VALUE thval = key;
-    yarv_thread_t *th;
-    GetThreadPtr(thval, th);
-    th->interrupt_gc_flag = set;
-    th->interrupt_flag = set;
-    return ST_CONTINUE;
+    yarv_vm_t *vm = GET_VM();
+    int locked;
+    
+    thread_debug("rb_thread_gc_barrier_stop: start\n");
+
+    locked = rb_thread_global_lock_acquire(th);
+    vm->lock_owner_thread = 0;
+    vm->num_wait_threads++;
+    thread_debug("rb_thread_gc_barrier_stop: waiting -> %d\n",
+		 vm->num_wait_threads);
+    {
+	pthread_cond_signal(&vm->gc_barrier_owner_cond);
+	pthread_cond_wait(&vm->gc_barrier_waits_cond,
+			  &vm->global_interpreter_lock);
+    }
+    vm->num_wait_threads--;
+    vm->lock_owner_thread = th;
+
+    if (locked) {
+	rb_thread_global_lock_release(th);
+    }
+    thread_debug("rb_thread_gc_barrier_stop: end\n");
 }
 
 void
@@ -222,13 +250,21 @@
 	/* skip */
     }
     else {
-	st_foreach(vm->living_threads, set_gc_interrupt_flag, 1);
+	while (vm->interrupt_gc_flag) {
+	    rb_thread_global_lock_release(th);
+	    rb_thread_gc_barrier_stop(th);
+	    rb_thread_global_lock_acquire(th);
+	}
+	
+	vm->interrupt_gc_flag = 1;
 	vm->lock_owner_thread = 0;
 	
 	while (vm->living_threads->num_entries != vm->num_wait_threads + 1) {
+	    thread_debug("rb_thread_gc_barrier_start: block start - ltnum: %d, wtnum: %d\n",
+			 vm->living_threads->num_entries, vm->num_wait_threads);
 	    pthread_cond_wait(&vm->gc_barrier_owner_cond,
 			      &vm->global_interpreter_lock);
-	    thread_debug("ltnum: %d, wtnum: %d\n",
+	    thread_debug("rb_thread_gc_barrier_start: block end - ltnum: %d, wtnum: %d\n",
 			 vm->living_threads->num_entries, vm->num_wait_threads);
 	}
     }
@@ -242,35 +278,11 @@
     yarv_vm_t *vm = GET_VM();
     thread_debug("rb_thread_gc_barrier_end: start\n");
 
-    if (vm->living_threads) {
-	st_foreach(vm->living_threads, set_gc_interrupt_flag, 0);
-    }
+    vm->interrupt_gc_flag = 0;
     pthread_cond_broadcast(&vm->gc_barrier_waits_cond);
     thread_debug("rb_thread_gc_barrier_end: end\n");
 }
 
-void
-rb_thread_gc_barrier_stop(yarv_thread_t *th)
-{
-    yarv_vm_t *vm = GET_VM();
-
-    thread_debug("rb_thread_gc_barrier_stop: start\n");
-
-    rb_thread_global_lock_acquire(th);
-    vm->lock_owner_thread = 0;
-    vm->num_wait_threads++;
-    thread_debug("rb_thread_gc_barrier_stop: waiting -> %d\n", vm->num_wait_threads);
-    {
-	pthread_cond_signal(&vm->gc_barrier_owner_cond);
-	pthread_cond_wait(&vm->gc_barrier_waits_cond,
-			  &vm->global_interpreter_lock);
-    }
-    vm->num_wait_threads--;
-    vm->lock_owner_thread = th;
-    rb_thread_global_lock_release(th);
-    thread_debug("rb_thread_gc_barrier_stop: end\n");
-}
-
 static void
 yarv_set_interrupt_function(yarv_thread_t *th, yarv_interrupt_function_t *func)
 {
@@ -334,11 +346,19 @@
     }
     
     thread_debug("rb_thread_terminate_all (main thread: %p)\n", th);
-    st_foreach(vm->living_threads, terminate_i, (st_data_t)th);
 
     while (!rb_thread_alone()) {
+	st_foreach(vm->living_threads, terminate_i, (st_data_t)th);
+	if (vm->interrupt_gc_flag) {
+	    rb_thread_gc_barrier_stop(th);
+	}
+	YARV_CHECK_INTS();
 	rb_thread_schedule();
     }
+    
+    rb_thread_global_lock_acquire(th);
+    thread_debug("rb_thread_terminate_all (all terminated)\n", th);
+
     system_working = 0;
 }
 
@@ -351,6 +371,13 @@
     yarv_thread_t *th = th_ptr;
     th->status = THREAD_KILLED;
     th->machine_stack_start = th->machine_stack_end = 0;
+    st_delete_wrap(th->vm->living_threads, th->self);
+
+    if (th->vm->interrupt_gc_flag) {
+	pthread_cond_signal(&th->vm->gc_barrier_owner_cond);
+    }
+    rb_thread_global_lock_release(th);
+    thread_debug("thread terminated: %p\n", th);
 }
 
 
@@ -397,10 +424,7 @@
 	    rb_thread_interrupt(join_th);
 	    join_th = join_th->join_list_next;
 	}
-	st_delete_wrap(th->vm->living_threads, th->self);
     }
-    rb_thread_global_lock_release(th);
-    thread_debug("thread terminated: %p\n", th);
     return 0;
 }
 
@@ -425,10 +449,6 @@
     
     /* kick thread */
     st_insert(target_th->vm->living_threads, thval, (st_data_t) th->thread_id);
-
-    if (th->interrupt_flag && th->interrupt_gc_flag) {
-	target_th->interrupt_flag = target_th->interrupt_gc_flag = 1;
-    }
     
     rb_thread_global_lock_acquire(GET_THREAD());
     native_thread_create(target_th);
@@ -727,6 +747,8 @@
 	th->status = THREAD_RUNNABLE;
 	th->interrupt_flag = 0;
 
+	YARV_CHECK_GC_BARRIER(th);
+	
 	/* signal handling */
 	if (th->exec_signal) {
 	    int sig = th->exec_signal;
@@ -734,10 +756,6 @@
 	    rb_signal_exec(th, sig);
 	}
 
-	if (th->interrupt_gc_flag) {
-	    rb_thread_gc_barrier_stop(th);
-	}
-
 	/* exception from another thread */
 	if (th->throwed_errinfo) {
 	    VALUE err = th->throwed_errinfo;
@@ -764,9 +782,6 @@
 	    }
 	}
 	th->status = status;
-
-	/* thread pass */
-	rb_thread_schedule();
     }
 }
 
@@ -1599,9 +1614,9 @@
     FD_SET(fd, &set);
     thread_debug("rb_thread_wait_fd (%d)\n", fd);
     while (result <= 0) {
-	rb_thread_blocking_start(th, interrupt_using_posix_signal);
-	result = select(fd + 1, &set, 0, 0, 0);
-	rb_thread_blocking_end(th);
+	BLOCKING_RANGE(th, interrupt_using_posix_signal, {
+	    result = select(fd + 1, &set, 0, 0, 0);
+	});
     }
     thread_debug("rb_thread_wait_fd done\n", fd);
 }
@@ -1618,9 +1633,9 @@
 
     thread_debug("rb_thread_fd_writable (%d)\n", fd);
     while (result <= 0) {
-	rb_thread_blocking_start(th, interrupt_using_posix_signal);
-	result = select(fd + 1, 0, &set, 0, 0);
-	rb_thread_blocking_end(th);
+	BLOCKING_RANGE(th, interrupt_using_posix_signal, {
+	    result = select(fd + 1, 0, &set, 0, 0);
+	});
     }
     thread_debug("rb_thread_fd_writable done\n");
     return Qtrue;
@@ -1665,13 +1680,16 @@
 #endif
 
     for (;;) {
-	rb_thread_blocking_start(th, interrupt_using_posix_signal);
-	n = select(max, read, write, except, tvp);
-	lerrno = errno;
-	rb_thread_blocking_end(th);
+	n = -1;
+	lerrno = EINTR;
 
+	BLOCKING_RANGE(th, interrupt_using_posix_signal, {
+	    n = select(max, read, write, except, tvp);
+	    lerrno = errno;
+	});
+
 	if (n < 0) {
-	    switch (errno) {
+	    switch (lerrno) {
 	    case EINTR:
 #ifdef ERESTART
 	    case ERESTART:
@@ -1763,11 +1781,9 @@
 {
     char buff[100];
     yarv_thread_t *th = GET_THREAD();
-    rb_thread_blocking_start(th, 0);
-    {
+    BLOCKING_RANGE(th, 0, {
 	fgets(buff, 100, stdin);
-    }
-    rb_thread_blocking_end(th);
+    });
     return rb_str_new2(buff);
 }
 
@@ -2043,9 +2059,10 @@
     }
     if (native_mutex_trylock(&mutex->lock) != 0) {
 	/* can't cancel */
-	rb_thread_blocking_start(th, 0);
-	native_mutex_lock(&mutex->lock);
-	rb_thread_blocking_end(th);
+	BLOCKING_RANGE(th, 0, {
+	    native_mutex_lock(&mutex->lock);
+	    rb_thread_blocking_end(th);
+	});
     }
 
     mutex->th = th;
@@ -2173,6 +2190,32 @@
 
     make_timer_thread();
     atexit(show_func);
+
+#if HAVE_SCHED_SETAFFINITY
+    if (getenv("RUBY_MAX_CPU")) {
+	int i, max;
+	cpu_set_t mask;
+	char *env = getenv("RUBY_MAX_CPU");
+	
+	if (0) {
+	    /* for debug */
+	    sched_getaffinity(0, sizeof(cpu_set_t), &mask);
+	    for (i=0; i<8; i++) {
+		printf("%d: %d\n", i, __CPU_ISSET(i, &mask));
+	    }
+	}
+	max = atoi(env);
+	if (max > 0) {
+	    __CPU_ZERO(&mask);
+	    for (i=0; i<max; i++) {
+		__CPU_SET(i, &mask);
+	    }
+	    if (sched_setaffinity(0, sizeof(cpu_set_t), &mask) != 0) {
+		rb_bug("sched_setaffinity error: %d\n", errno);
+	    }
+	}
+    }
+#endif
     
     rb_disable_interrupt(); /* only timer thread recieve signal */
 }

Modified: branches/parallel/thread_pthread.h
===================================================================
--- branches/parallel/thread_pthread.h	2006-09-01 13:06:17 UTC (rev 545)
+++ branches/parallel/thread_pthread.h	2006-09-02 13:52:32 UTC (rev 546)
@@ -3,6 +3,7 @@
 #define THREAD_PTHREAD_H_INCLUDED
 
 #include <pthread.h>
+
 typedef pthread_t yarv_thread_id_t;
 typedef pthread_mutex_t yarv_thread_lock_t;
 typedef pthread_cond_t yarv_thread_cond_t;
@@ -68,7 +69,7 @@
 
 static void yarv_add_signal_thread_list(yarv_thread_t *th);
 static void yarv_remove_signal_thread_list(yarv_thread_t *th);
-static void rb_thread_blocking_start(yarv_thread_t *th, yarv_interrupt_function_t *func);
+static int rb_thread_blocking_start(yarv_thread_t *th, yarv_interrupt_function_t *func);
 static void rb_thread_blocking_end(yarv_thread_t *th);
 
 static yarv_thread_fglock_t signal_thread_list_lock;
@@ -105,14 +106,14 @@
 	VALUE stack_start;
 	/* ignore self and klass */
 
-	native_cleanup_push(thread_cleanup_func, th);
+//	native_cleanup_push(thread_cleanup_func, th);
 
 	/* run */
 	thread_start_func_2(th, &stack_start);
 
 	/* cleanup */
 	thread_cleanup_func(th);
-	native_cleanup_pop(0);
+//	native_cleanup_pop(0);
     }
 #if USE_THREAD_CACHE
     if (1) {
@@ -275,7 +276,7 @@
 static void
 interrupt_using_pthread_cond_signal(yarv_thread_t *th)
 {
-    thread_debug("interrupt_using_pthread_cond_signal (%p)\n", th);
+    thread_debug("interrupt_using_pthread_cond_signal (thid: %p)\n", th->thread_id);
     pthread_cond_signal(&th->native_thread_data.sleep_cond);
 }
 
@@ -306,10 +307,9 @@
 
     thread_debug("native_sleep %d\n", tv ? tv->tv_sec : -1);
 
-    rb_thread_blocking_start(th, interrupt_using_pthread_cond_signal);
-    {
+    BLOCKING_RANGE(th, interrupt_using_pthread_cond_signal, {
 	pthread_mutex_lock(&th->interrupt_lock);
-	
+
 	if (th->interrupt_flag) {
 	    /* interrupted.  return immediate */
 	    thread_debug("native_sleep: interrupted before sleep\n");
@@ -334,9 +334,8 @@
 	}
 	pthread_mutex_unlock(&th->interrupt_lock);
 
-	th->status = prev_status;
-    }
-    rb_thread_blocking_end(th);
+    });
+    th->status = prev_status;
     thread_debug("native_sleep done\n");
 }
 

Modified: branches/parallel/yarvcore.c
===================================================================
--- branches/parallel/yarvcore.c	2006-09-01 13:06:17 UTC (rev 545)
+++ branches/parallel/yarvcore.c	2006-09-02 13:52:32 UTC (rev 546)
@@ -294,6 +294,7 @@
 	th = ptr;
 	FREE_UNLESS_NULL(th->stack);
 	FREE_UNLESS_NULL(th->top_local_tbl);
+	onig_region_free(&th->regs, 0);
 
 	if (th->local_storage) {
 	    st_free_table(th->local_storage);
@@ -465,6 +466,11 @@
     return val;
 }
 
+void *
+rb_thread_get_local_regs(void)
+{
+  return &GET_THREAD()->regs;
+}
 
 /***************/
 /* YarvEnv     */

Modified: branches/parallel/yarvcore.h
===================================================================
--- branches/parallel/yarvcore.h	2006-09-01 13:06:17 UTC (rev 545)
+++ branches/parallel/yarvcore.h	2006-09-02 13:52:32 UTC (rev 546)
@@ -16,6 +16,7 @@
 #endif
 #include "ruby.h"
 #include "st.h"
+#include "re.h"
 
 #include "debug.h"
 #include "vm_opts.h"
@@ -318,6 +319,7 @@
     struct yarv_thread_struct *running_thread;
     struct yarv_thread_struct *lock_owner_thread;
 
+    int interrupt_gc_flag;
     int num_wait_threads;
     st_table *living_threads;
 
@@ -435,7 +437,6 @@
     int exec_signal;
 
     int interrupt_flag;
-    int interrupt_gc_flag;
     
     yarv_interrupt_function_t *interrupt_function;
     yarv_thread_lock_t interrupt_lock;
@@ -468,6 +469,7 @@
     /* misc */
     int method_missing_reason;
     int abort_on_exception;
+    struct re_registers regs;
 } yarv_thread_t;
 
 typedef struct native_global_lock_struct {
@@ -620,17 +622,32 @@
 NOINLINE(void yarv_set_stack_end(VALUE **stack_end_p));
 NOINLINE(void yarv_save_machine_context(yarv_thread_t *));
 
+
+
+
 extern int rb_thread_pending;
 
 void yarv_thread_execute_interrupts(yarv_thread_t *);
+void rb_thread_gc_barrier_stop(yarv_thread_t *th);
+void rb_thread_gc_barrier_start(yarv_thread_t *th);
+void rb_thread_gc_barrier_end(yarv_thread_t *th);
 
 #define YARV_CHECK_INTS_TH(th) do { \
-  if(th->interrupt_flag){ \
-    /* TODO: trap something event */ \
-    yarv_thread_execute_interrupts(th); \
-  } \
+    if (th->interrupt_flag) { \
+	/* TODO: trap something event */ \
+	yarv_thread_execute_interrupts(th); \
+    } \
+    YARV_CHECK_GC_BARRIER(th); \
 } while (0)
 
+#define YARV_CHECK_GC_BARRIER(th) do { \
+    if (th->vm->interrupt_gc_flag) { \
+	rb_thread_gc_barrier_stop(th); \
+    } \
+} while (0)
+
+
+
 #define YARV_CHECK_INTS() \
   YARV_CHECK_INTS_TH(GET_THREAD())
 

Modified: branches/parallel/yarvtest/test_thread.rb
===================================================================
--- branches/parallel/yarvtest/test_thread.rb	2006-09-01 13:06:17 UTC (rev 545)
+++ branches/parallel/yarvtest/test_thread.rb	2006-09-02 13:52:32 UTC (rev 546)
@@ -15,6 +15,33 @@
     }
   end
 
+  def test_thread_with_gc
+    ae %q{
+      flag = false
+      Thread.new{
+        flag = true
+        loop{''}
+      }
+      sleep 0.1 until flag
+    }
+  end
+
+  def test_threads_with_gc
+    ae %q{
+      GC.stress = true
+      (1..10).map{
+        Thread.new{
+          100.times{|e|
+            "#{e}"
+          }
+        }
+      }.each{|t|
+        t.join
+      }
+      :ok
+    }
+  end
+  
   def test_create_many_threads1
     ae %q{
       v = 0
@@ -103,7 +130,7 @@
     }
   end
 
-  def test_status
+  def _test_status
     ae %q{
       t = Thread.new{
         loop{}
@@ -151,12 +178,13 @@
     }
     ae %q{
       thg = ThreadGroup.new
-
+      flag = false
       t = Thread.new{
         thg.add Thread.current
+        flag = true
         sleep
       }
-      sleep 0.1
+      sleep 0.1 until flag
       [thg.list.size, ThreadGroup::Default.list.size]
     }
   end


--
ML: yarv-diff quickml.atdot.net
Info: http://www.atdot.net/~ko1/quickml

[前][次][番号順一覧][スレッド一覧][生データ]