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

yarv-diff:376

From: ko1 atdot.net
Date: 30 Aug 2006 23:17:22 +0900
Subject: [yarv-diff:376] r543 - branches/parallel

Author: ko1
Date: 2006-08-30 23:17:21 +0900 (Wed, 30 Aug 2006)
New Revision: 543

Modified:
   branches/parallel/ChangeLog
   branches/parallel/compile.c
   branches/parallel/eval_intern.h
   branches/parallel/eval_method.h
   branches/parallel/gc.c
   branches/parallel/thread.c
   branches/parallel/thread_pthread.h
   branches/parallel/thread_win32.h
   branches/parallel/vm.c
   branches/parallel/vm_macro.def
   branches/parallel/yarv.h
   branches/parallel/yarvcore.c
   branches/parallel/yarvcore.h
Log:
	* eval_intern.h : parallelize

	* eval_method.h : ditto

	* gc.c : ditto

	* thread.c : ditto

	* thread_pthread.h : ditto

	* thread_win32.h : ditto

	* vm.c : ditto

	* vm_macro.def : ditto

	* yarv.h : ditto

	* yarvcore.c : ditto

	* yarvcore.h : ditto

	* compile.c : dissable LTLT optimization


Modified: branches/parallel/ChangeLog
===================================================================
--- branches/parallel/ChangeLog	2006-08-25 08:18:06 UTC (rev 542)
+++ branches/parallel/ChangeLog	2006-08-30 14:17:21 UTC (rev 543)
@@ -4,6 +4,33 @@
 #  from Mon, 03 May 2004 01:24:19 +0900
 #
 
+2006-08-30(Wed) 23:15:53 +0900  Koichi Sasada  <ko1 atdot.net>
+
+	* eval_intern.h : parallelize
+
+	* eval_method.h : ditto
+
+	* gc.c : ditto
+
+	* thread.c : ditto
+
+	* thread_pthread.h : ditto
+
+	* thread_win32.h : ditto
+
+	* vm.c : ditto
+
+	* vm_macro.def : ditto
+
+	* yarv.h : ditto
+
+	* yarvcore.c : ditto
+
+	* yarvcore.h : ditto
+
+	* compile.c : dissable LTLT optimization
+
+
 2006-08-25(Fri) 17:17:25 +0900  Koichi Sasada  <ko1 atdot.net>
 
 	* thread_pthread.h : 

Modified: branches/parallel/compile.c
===================================================================
--- branches/parallel/compile.c	2006-08-25 08:18:06 UTC (rev 542)
+++ branches/parallel/compile.c	2006-08-30 14:17:21 UTC (rev 543)
@@ -1603,9 +1603,11 @@
 		else if (mid == idLE) {
 		    insn_set_specialized_instruction(iobj, BIN(opt_le));
 		}
+#if 0
 		else if (mid == idLTLT) {
 		    insn_set_specialized_instruction(iobj, BIN(opt_ltlt));
 		}
+#endif
 		else if (mid == idAREF) {
 		    insn_set_specialized_instruction(iobj, BIN(opt_aref));
 		}

Modified: branches/parallel/eval_intern.h
===================================================================
--- branches/parallel/eval_intern.h	2006-08-25 08:18:06 UTC (rev 542)
+++ branches/parallel/eval_intern.h	2006-08-30 14:17:21 UTC (rev 543)
@@ -189,18 +189,22 @@
 #include <sys/stat.h>
 
 #define TH_PUSH_TAG(th) do { \
-  struct yarv_tag _tag; \
-  yarv_thread_t * const _th = th; \
-  _tag.tag = 0; \
-  _tag.prev = _th->tag; \
-  _th->tag = &_tag;
+    struct yarv_tag _tag; \
+    yarv_thread_t * const __th = th; \
+    int __locked = GET_VM()->lock_owner_thread == __th;\
+    _tag.tag = 0; \
+    _tag.prev = __th->tag; \
+    __th->tag = &_tag;
 
 #define TH_POP_TAG() \
-  _th->tag = _tag.prev; \
+  __th->tag = _tag.prev; \
+    if (__locked) { \
+	rb_thread_global_lock_acquire(__th); \
+    } \
 } while (0)
 
 #define TH_POP_TAG2() \
-  _th->tag = _tag.prev
+  __th->tag = _tag.prev
 
 #define PUSH_TAG(ptag) TH_PUSH_TAG(GET_THREAD())
 #define POP_TAG()      TH_POP_TAG()
@@ -221,7 +225,7 @@
 #define PROT_TOP    INT2FIX(4)	/* 9 */
 
 #define TH_EXEC_TAG() \
-  (FLUSH_REGISTER_WINDOWS, ruby_setjmp(_th->tag->buf))
+  (FLUSH_REGISTER_WINDOWS, ruby_setjmp(__th->tag->buf))
 
 #define EXEC_TAG() \
   TH_EXEC_TAG()

Modified: branches/parallel/eval_method.h
===================================================================
--- branches/parallel/eval_method.h	2006-08-25 08:18:06 UTC (rev 542)
+++ branches/parallel/eval_method.h	2006-08-30 14:17:21 UTC (rev 543)
@@ -269,12 +269,10 @@
 rb_method_node(VALUE klass, ID id)
 {
     NODE *ent = cache_entries[EXPR1(klass, id)];
-    
     if (ent &&
 	ent->nd_mid == id && ent->nd_klass == klass && ent->nd_method) {
 	return ent->nd_method;
     }
-
     return rb_get_method_body(klass, id, 0);
 }
 

Modified: branches/parallel/gc.c
===================================================================
--- branches/parallel/gc.c	2006-08-25 08:18:06 UTC (rev 542)
+++ branches/parallel/gc.c	2006-08-30 14:17:21 UTC (rev 543)
@@ -485,8 +485,18 @@
 {
     int i;
     VALUE rv;
+    int locked;
 
-    // LOCK
+    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();
 	
@@ -495,7 +505,12 @@
     }
     th->value_cache_ptr = &th->value_cache[0];
     rv = rb_newobj_from_heap();
-    // UNLOCK
+
+    rb_thread_gc_barrier_end(th);
+    
+    if (locked) {
+	rb_thread_global_lock_release(th);
+    }
     return rv;
 }
 #endif

Modified: branches/parallel/thread.c
===================================================================
--- branches/parallel/thread.c	2006-08-25 08:18:06 UTC (rev 542)
+++ branches/parallel/thread.c	2006-08-30 14:17:21 UTC (rev 543)
@@ -58,6 +58,7 @@
 
 static VALUE eKillSignal = INT2FIX(0);
 static VALUE eTerminateSignal = INT2FIX(1);
+
 static int system_working = 1;
 
 inline static void
@@ -71,26 +72,9 @@
 #define THREAD_SYSTEM_DEPENDENT_IMPLEMENTATION
 
 static void native_thread_interrupt(yarv_thread_t *th);
-static void yarv_set_interrupt_function(yarv_thread_t *th, yarv_interrupt_function_t *func, int is_return);
+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 GVL_UNLOCK_RANGE(exec) do { \
-    yarv_thread_t *__th = GET_THREAD(); \
-    int __prev_status = __th->status; \
-    yarv_set_interrupt_function(__th, native_thread_interrupt, 0); \
-    __th->status = THREAD_STOPPED; \
-    GVL_UNLOCK_BEGIN(); {\
-	    exec; \
-    } \
-    GVL_UNLOCK_END(); \
-    yarv_remove_signal_thread_list(__th); \
-    yarv_clear_interrupt_function(__th); \
-    if (__th->status == THREAD_STOPPED) { \
-	__th->status = __prev_status; \
-    } \
-    YARV_CHECK_INTS(); \
-} while(0)
-
 #if THREAD_DEBUG
 void thread_debug(const char *fmt, ...);
 #else
@@ -110,7 +94,10 @@
 
 #define DEBUG_OUT() \
   pthread_mutex_lock(&debug_mutex); \
-  printf("%8p - %s", pthread_self(), buf); \
+    { char str[0x20]; time_t t = time(0); \
+	strftime(str, 0x20, "%H%M:%S", localtime(&t)); \
+	printf("%s %016p - %s", str, pthread_self(), buf); \
+    } \
   pthread_mutex_unlock(&debug_mutex);
 
 #else
@@ -141,24 +128,154 @@
 #endif
 
 
+int
+rb_thread_global_lock_acquire(yarv_thread_t *th)
+{
+    yarv_vm_t *vm = th->vm;
+    if (vm->lock_owner_thread == th || rb_thread_alone()) {
+	thread_debug("rb_thread_global_lock_acquire: no need (%s)\n",
+		     vm->lock_owner_thread == th ? "already own" : "alone");
+	return 0;
+    }
+    yarv_save_machine_context(th);
+    thread_debug("rb_thread_global_lock_acquire: try acquire (%p) --> \n",
+		 vm->lock_owner_thread);
+    if (native_mutex_lock(&vm->global_interpreter_lock) != 0) {
+	rb_bug("native_mutex_lock return non-zero");
+    }
+    vm->lock_owner_thread = th;
+    thread_debug("rb_thread_global_lock_acquire: <-- done\n");
+    return 1;
+}
+
+int
+rb_thread_global_lock_release(yarv_thread_t *th)
+{
+    yarv_vm_t *vm = th->vm;
+
+    if (vm->lock_owner_thread != th) {
+	thread_debug("rb_thread_global_lock_release: no need (%s)\n",
+		     vm->lock_owner_thread == 0 ? "not acquired" : "other's");
+	return 0;
+    }
+    thread_debug("rb_thread_global_lock_release: release\n");
+    vm->lock_owner_thread = 0;
+    if (native_mutex_unlock(&vm->global_interpreter_lock) != 0) {
+	rb_bug("native_mutex_unlock return non-zero");
+    }
+    return 1;
+}
+
+static int
+rb_thread_global_lock_acquire_p(yarv_thread_t *th)
+{
+    yarv_vm_t *vm = th->vm;
+    return vm->lock_owner_thread == th;
+}
+
 static void
-yarv_set_interrupt_function(yarv_thread_t *th, yarv_interrupt_function_t *func, int is_return)
+rb_thread_blocking_start(yarv_thread_t *th, yarv_interrupt_function_t *func)
 {
-  check_ints:
-    YARV_CHECK_INTS();
-    native_mutex_lock(&th->interrupt_lock);
+    yarv_vm_t *vm = GET_VM();
+    
+  retry:
+    YARV_CHECK_INTS_TH(th);
+
+    yarv_set_interrupt_function(th, func);
+    vm->num_wait_threads++;
+    yarv_save_machine_context(th);
+
+    rb_thread_global_lock_release(th);
+
     if (th->interrupt_flag) {
-	native_mutex_unlock(&th->interrupt_lock);
-	if (is_return) {
-	    return;
-	}
-	else {
-	    goto check_ints;
-	}
+	rb_thread_global_lock_acquire(th);
+	goto retry;
     }
+}
+
+static void
+rb_thread_blocking_end(yarv_thread_t *th)
+{
+    yarv_vm_t *vm = GET_VM();
+    rb_thread_global_lock_acquire(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)
+{
+    VALUE thval = key;
+    yarv_thread_t *th;
+    GetThreadPtr(thval, th);
+    th->interrupt_gc_flag = set;
+    th->interrupt_flag = set;
+    return ST_CONTINUE;
+}
+
+void
+rb_thread_gc_barrier_start(yarv_thread_t *th)
+{
+    yarv_vm_t *vm = GET_VM();
+    thread_debug("rb_thread_gc_barrier_start: start\n");
+   if (rb_thread_alone() || vm->living_threads == 0) {
+	/* skip */
+    }
     else {
-	th->interrupt_function = func;
+	st_foreach(vm->living_threads, set_gc_interrupt_flag, 1);
+	vm->lock_owner_thread = 0;
+	
+	while (vm->living_threads->num_entries != vm->num_wait_threads + 1) {
+	    pthread_cond_wait(&vm->gc_barrier_owner_cond,
+			      &vm->global_interpreter_lock);
+	    thread_debug("ltnum: %d, wtnum: %d\n",
+			 vm->living_threads->num_entries, vm->num_wait_threads);
+	}
     }
+    vm->lock_owner_thread = th;
+    thread_debug("rb_thread_gc_barrier_start: end\n");
+}
+
+void
+rb_thread_gc_barrier_end(yarv_thread_t *th)
+{
+    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);
+    }
+    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)
+{
+    native_mutex_lock(&th->interrupt_lock);
+    th->interrupt_function = func;
     native_mutex_unlock(&th->interrupt_lock);
 }
 
@@ -174,14 +291,15 @@
 rb_thread_interrupt(yarv_thread_t *th)
 {
     native_mutex_lock(&th->interrupt_lock);
-    th->interrupt_flag = 1;
-
-    if (th->interrupt_function) {
-	(th->interrupt_function)(th);
+    {
+	th->interrupt_flag = 1;
+	if (th->interrupt_function) {
+	    (th->interrupt_function)(th);
+	}
+	else {
+	    /* none */
+	}
     }
-    else {
-	/* none */
-    }
     native_mutex_unlock(&th->interrupt_lock);
 }
 
@@ -195,9 +313,9 @@
 
     if (th != main_thread) {
 	thread_debug("terminate_i: %p\n", th);
-	rb_thread_interrupt(th);
 	th->throwed_errinfo = eTerminateSignal;
 	th->status = THREAD_TO_KILL;
+	rb_thread_interrupt(th);
     }
     else {
 	thread_debug("terminate_i: main thread (%p)\n", th);
@@ -211,9 +329,10 @@
     yarv_thread_t *th = GET_THREAD(); /* main thread */
     yarv_vm_t *vm = th->vm;
     if (vm->main_thread != th) {
-	rb_bug("rb_thread_terminate_all: called by child thread (%p, %p)", vm->main_thread, th);
+	rb_bug("rb_thread_terminate_all: called by child thread (%p, %p)",
+	       vm->main_thread, th);
     }
-
+    
     thread_debug("rb_thread_terminate_all (main thread: %p)\n", th);
     st_foreach(vm->living_threads, terminate_i, (st_data_t)th);
 
@@ -247,10 +366,10 @@
 
     thread_debug("thread start: %p\n", th);
 
-    native_mutex_lock(&th->vm->global_interpreter_lock);
+    rb_thread_global_lock_acquire(th);
+    yarv_set_current_running_thread(th);
     {
 	thread_debug("thread start (get lock): %p\n", th);
-	yarv_set_current_running_thread(th);
 
 	TH_PUSH_TAG(th);
 	if ((state = EXEC_TAG()) == 0) {
@@ -266,6 +385,8 @@
 	}
 	TH_POP_TAG();
 
+	rb_thread_global_lock_acquire(th);
+
 	th->status = THREAD_KILLED;
 	thread_debug("thread end: %p\n", th);
 	st_delete_wrap(th->vm->living_threads, th->self);
@@ -278,7 +399,8 @@
 	}
 	st_delete_wrap(th->vm->living_threads, th->self);
     }
-    native_mutex_unlock(&th->vm->global_interpreter_lock);
+    rb_thread_global_lock_release(th);
+    thread_debug("thread terminated: %p\n", th);
     return 0;
 }
 
@@ -287,22 +409,29 @@
 static VALUE
 yarv_thread_s_new(VALUE klass, VALUE args)
 {
-    yarv_thread_t *th;
+    yarv_thread_t *target_th;
+    yarv_thread_t *th = GET_THREAD();
     VALUE thval;
 
     /* create thread object */
     thval = yarv_thread_alloc(cYarvThread);
-    GetThreadPtr(thval, th);
+    GetThreadPtr(thval, target_th);
     
     /* setup thread environment */
-    th->first_args = args;
-    th->first_proc = rb_block_proc();
+    target_th->first_args = args;
+    target_th->first_proc = rb_block_proc();
+
+    native_mutex_initialize(&target_th->interrupt_lock);
     
-    native_mutex_initialize(&th->interrupt_lock);
+    /* kick thread */
+    st_insert(target_th->vm->living_threads, thval, (st_data_t) th->thread_id);
 
-    /* kick thread */
-    st_insert(th->vm->living_threads, thval, (st_data_t) th->thread_id);
-    native_thread_create(th);
+    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);
     return thval;
 }
 
@@ -459,7 +588,6 @@
 sleep_forever(yarv_thread_t *th)
 {
     native_sleep(th, 0);
-    YARV_CHECK_INTS();
 }
 
 static void
@@ -525,11 +653,12 @@
 void
 rb_thread_schedule()
 {
+    /* parallel version doesn't need scheduler */
     thread_debug("rb_thread_schedule\n");
     if (!rb_thread_alone()) {
 	yarv_thread_t *th = GET_THREAD();
-
 	thread_debug("rb_thread_schedule/switch start\n");
+#if 0
 
 	yarv_save_machine_context(th);
 	native_mutex_unlock(&th->vm->global_interpreter_lock);
@@ -542,6 +671,11 @@
 	thread_debug("rb_thread_schedule/switch done\n");
 
 	YARV_CHECK_INTS();
+#else
+	rb_thread_global_lock_release(th);
+	native_thread_yield();
+	rb_thread_global_lock_acquire(th);
+#endif
     }
 }
 
@@ -554,20 +688,6 @@
 }
 
 
-VALUE
-rb_thread_run_parallel(VALUE(*func)(yarv_thread_t *th, void *), void *data)
-{
-    VALUE val;
-    yarv_thread_t *th = GET_THREAD();
-    
-    GVL_UNLOCK_RANGE({
-	val = func(th, data);
-    });
-    
-    return val;
-}
-
-
 /*
  *  call-seq:
  *     Thread.pass   => nil
@@ -614,6 +734,10 @@
 	    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;
@@ -1369,9 +1493,12 @@
 int
 rb_thread_alone()
 {
+    /* rb_thread_alone() is thread safe, because if thread_alone()
+       is true, any other threads doesn't interrupt */
+
     int num = 1;
-    if (GET_THREAD()->vm->living_threads) {
-	num = GET_THREAD()->vm->living_threads->num_entries;
+    if (GET_VM()->living_threads) {
+	num = GET_VM()->living_threads->num_entries;
 	thread_debug("rb_thread_alone: %d\n", num);
     }
     return num == 1;
@@ -1466,12 +1593,15 @@
 {
     fd_set set;
     int result = 0;
+    yarv_thread_t *th = GET_THREAD();
 
     FD_ZERO(&set);
     FD_SET(fd, &set);
     thread_debug("rb_thread_wait_fd (%d)\n", fd);
     while (result <= 0) {
-	GVL_UNLOCK_RANGE(result = select(fd + 1, &set, 0, 0, 0));
+	rb_thread_blocking_start(th, interrupt_using_posix_signal);
+	result = select(fd + 1, &set, 0, 0, 0);
+	rb_thread_blocking_end(th);
     }
     thread_debug("rb_thread_wait_fd done\n", fd);
 }
@@ -1481,13 +1611,16 @@
 {
     fd_set set;
     int result = 0;
+    yarv_thread_t *th = GET_THREAD();
 
     FD_ZERO(&set);
     FD_SET(fd, &set);
 
     thread_debug("rb_thread_fd_writable (%d)\n", fd);
     while (result <= 0) {
-	GVL_UNLOCK_RANGE(result = select(fd + 1, 0, &set, 0, 0));
+	rb_thread_blocking_start(th, interrupt_using_posix_signal);
+	result = select(fd + 1, 0, &set, 0, 0);
+	rb_thread_blocking_end(th);
     }
     thread_debug("rb_thread_fd_writable done\n");
     return Qtrue;
@@ -1499,6 +1632,8 @@
 {
     struct timeval *tvp = timeout;
     int lerrno, n;
+    yarv_thread_t *th = GET_THREAD();
+
 #ifndef linux
     double limit;
     struct timeval tv;
@@ -1530,9 +1665,10 @@
 #endif
 
     for (;;) {
-	GVL_UNLOCK_RANGE(n = select(max, read, write, except, tvp);
-			 lerrno = errno;
-	    );
+	rb_thread_blocking_start(th, interrupt_using_posix_signal);
+	n = select(max, read, write, except, tvp);
+	lerrno = errno;
+	rb_thread_blocking_end(th);
 
 	if (n < 0) {
 	    switch (errno) {
@@ -1599,7 +1735,6 @@
 timer_function(void)
 {
     yarv_vm_t *vm = GET_VM(); /* TODO: fix me for Multi-VM */
-    vm->running_thread->interrupt_flag = 1;
     
     if (vm->bufferd_signal_size && vm->main_thread->exec_signal == 0) {
 	vm->main_thread->exec_signal = rb_get_next_signal(vm);
@@ -1608,7 +1743,7 @@
 	rb_thread_interrupt(vm->main_thread);
     }
 
-#if 1
+#if 0
     /* prove profiling */
     if ((vm->main_thread->cfp->magic & 0x0f) == 0x05) {
 	prof_in_c++;
@@ -1627,11 +1762,12 @@
 raw_gets(VALUE klass)
 {
     char buff[100];
-    GVL_UNLOCK_BEGIN();
+    yarv_thread_t *th = GET_THREAD();
+    rb_thread_blocking_start(th, 0);
     {
 	fgets(buff, 100, stdin);
     }
-    GVL_UNLOCK_END();
+    rb_thread_blocking_end(th);
     return rb_str_new2(buff);
 }
 
@@ -1899,20 +2035,20 @@
 mutex_lock(VALUE self)
 {
     mutex_t *mutex;
+    yarv_thread_t *th = GET_THREAD();
     GetMutexVal(self, mutex);
 
-    if (mutex->th == GET_THREAD()) {
+    if (mutex->th == th) {
 	rb_raise(rb_eThreadError, "deadlock; recursive locking");
     }
-
     if (native_mutex_trylock(&mutex->lock) != 0) {
 	/* can't cancel */
-	GVL_UNLOCK_BEGIN();
+	rb_thread_blocking_start(th, 0);
 	native_mutex_lock(&mutex->lock);
-	GVL_UNLOCK_END();
+	rb_thread_blocking_end(th);
     }
 
-    mutex->th = GET_THREAD();
+    mutex->th = th;
     return self;
 }
 
@@ -2027,10 +2163,11 @@
 	/* main thread setting */
 	{
 	    /* acquire global interpreter lock */
-	    yarv_thread_lock_t *lp = &GET_THREAD()->vm->global_interpreter_lock;
-	    native_mutex_initialize(lp);
-	    native_mutex_lock(lp);
+	    native_mutex_initialize(&GET_THREAD()->vm->global_interpreter_lock);
 	    native_mutex_initialize(&GET_THREAD()->interrupt_lock);
+
+	    pthread_cond_init(&GET_VM()->gc_barrier_owner_cond, 0);
+	    pthread_cond_init(&GET_VM()->gc_barrier_waits_cond, 0);
 	}
     }
 

Modified: branches/parallel/thread_pthread.h
===================================================================
--- branches/parallel/thread_pthread.h	2006-08-25 08:18:06 UTC (rev 542)
+++ branches/parallel/thread_pthread.h	2006-08-30 14:17:21 UTC (rev 543)
@@ -6,6 +6,7 @@
 typedef pthread_t yarv_thread_id_t;
 typedef pthread_mutex_t yarv_thread_lock_t;
 typedef pthread_spinlock_t yarv_thread_fglock_t;
+typedef pthread_cond_t yarv_thread_cond_t;
 
 #define native_mutex_lock   pthread_mutex_lock
 #define native_mutex_unlock pthread_mutex_unlock
@@ -29,40 +30,10 @@
 #define FGLOCK_RANGE(lock, body) \
   { FGLOCK(lock); { body; } FGUNLOCK(lock); }
 
-
-#if 0
-typedef struct native_global_lock_struct {
-    native_thread_lock_t lock;
-    yarv_thread_t *th;
-} native_global_lock_t;
-
-static inline void
-yarv_aquire_global_lock(yarv_thread_t *th, native_global_lock_t &glock)
-{
-    if (glock->th == th || rb_thread_alone()) {
-	return;
-    }
-    yarv_save_machine_context(th);
-    native_mutex_lock(&lock->lock);
-    lock->th = th;
-}
-
-static inline void
-yarv_release_global_lock(yarv_thread_t *th, native_global_lock_t &glock)
-{
-    if (glock->th != th) {
-	return;
-    }
-    glock->th = 0;
-    native_mutex_unlock(&lock->lock);
-}
-
-#endif
-
-#define GL_LOCK_RANGE(th_, lock_, body) { \
-    yarv_aquire_global_lock(th_, lock_); \
+#define GL_LOCK_RANGE(th_, body) { \
+    rb_thread_global_lock_acquire(th_); \
     { body; } ; \
-    yarv_free_global_lock(th_, lock_, body); \
+    rb_thread_global_lock_release(th_); \
 }
 
 #endif /* THREAD_PTHREAD_H_INCLUDED */
@@ -89,6 +60,8 @@
 
 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 void rb_thread_blocking_end(yarv_thread_t *th);
 
 static yarv_thread_fglock_t signal_thread_list_lock;
 
@@ -251,7 +224,6 @@
 	    stack_size = PTHREAD_STACK_MIN * 2;
 	}
 	
-	thread_debug("create: %p, stack size: %ld\n", th, stack_size);
 
 	pthread_attr_init(&attr);
 	pthread_attr_setstacksize(&attr, stack_size);
@@ -259,6 +231,8 @@
 	pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
 
 	err = pthread_create(&th->thread_id, &attr, thread_start_func_1, th);
+	thread_debug("create: %p (tid: %016p), stack size: %ld\n",
+		     th, th->thread_id, stack_size);
 
 	if (err != 0) {
 	    th->status = THREAD_KILLED;
@@ -298,7 +272,7 @@
 }
 
 static void
-native_thread_send_interrupt_signal(yarv_thread_t *th)
+interrupt_using_posix_signal(yarv_thread_t *th)
 {
     thread_debug("native_thread_send_interrupt_signal (%p)\n", th->thread_id);
     if (th) {
@@ -323,7 +297,8 @@
     pthread_cond_init(&th->native_thread_data.sleep_cond, 0);
 
     thread_debug("native_sleep %d\n", tv ? tv->tv_sec : -1);
-    GVL_UNLOCK_BEGIN();
+
+    rb_thread_blocking_start(th, interrupt_using_pthread_cond_signal);
     {
 	pthread_mutex_lock(&th->interrupt_lock);
 	
@@ -353,7 +328,7 @@
 
 	th->status = prev_status;
     }
-    GVL_UNLOCK_END();
+    rb_thread_blocking_end(th);
     thread_debug("native_sleep done\n");
 }
 
@@ -474,7 +449,7 @@
 make_timer_thread()
 {
     if (!time_thread) {
-	size_t stack_size = PTHREAD_STACK_MIN;
+	size_t stack_size = PTHREAD_STACK_MIN * 2;
 	pthread_attr_t attr;
 	
 	pthread_attr_init(&attr);

Modified: branches/parallel/thread_win32.h
===================================================================
--- branches/parallel/thread_win32.h	2006-08-25 08:18:06 UTC (rev 542)
+++ branches/parallel/thread_win32.h	2006-08-30 14:17:21 UTC (rev 543)
@@ -231,8 +231,6 @@
     thread_start_func_2(th, &stack_start);
     thread_cleanup_func(th);
 
-    // native_mutex_unlock(&GET_VM()->global_interpreter_lock);
-
     thread_debug("close handle - intr: %p, thid: %p\n",
 		 th->native_thread_data.interrupt_event, th->thread_id);
     CloseHandle(th->native_thread_data.interrupt_event);

Modified: branches/parallel/vm.c
===================================================================
--- branches/parallel/vm.c	2006-08-25 08:18:06 UTC (rev 542)
+++ branches/parallel/vm.c	2006-08-30 14:17:21 UTC (rev 543)
@@ -1238,7 +1238,7 @@
 	else {
 	    int count = ic ? nd_line(ic) : 0;
 	    mn = rb_method_node(klass, id);
-	    
+
 	    if (count < 0x10) {
 		ic = NEW_INLINE_CACHE_ENTRY();
 		ic->ic_klass = klass;
@@ -1550,8 +1550,12 @@
     int state;
     VALUE result, err;
     VALUE initial = 0;
-    int locked = 0;
+
+    /* free lock */
+    rb_thread_global_lock_release(th);
     
+    /* eval body */
+    
     TH_PUSH_TAG(th);
     if ((state = EXEC_TAG()) == 0) {
       vm_loop_start:
@@ -1571,6 +1575,7 @@
 	VALUE *escape_dfp = NULL;
 	VALUE type;
 
+	rb_thread_global_lock_release(th);
 	err = th->errinfo;
 
 	if (state == TAG_RAISE) {
@@ -1748,5 +1753,6 @@
   finish_vme:
     TH_POP_TAG();
 
+    rb_thread_global_lock_acquire(th);
     return result;
 }

Modified: branches/parallel/vm_macro.def
===================================================================
--- branches/parallel/vm_macro.def	2006-08-25 08:18:06 UTC (rev 542)
+++ branches/parallel/vm_macro.def	2006-08-30 14:17:21 UTC (rev 543)
@@ -61,7 +61,10 @@
     
     reg_cfp->sp -= num + 1;
 
-    val = call_cfunc(mn->nd_cfnc, recv, mn->nd_argc, num, reg_cfp->sp + 1);
+    GL_LOCK_RANGE(
+	th, 
+	val = call_cfunc(mn->nd_cfnc, recv, mn->nd_argc, num, reg_cfp->sp + 1);
+	);
     
     if (reg_cfp != th->cfp + 1) {
 	SDR2(reg_cfp);

Modified: branches/parallel/yarv.h
===================================================================
--- branches/parallel/yarv.h	2006-08-25 08:18:06 UTC (rev 542)
+++ branches/parallel/yarv.h	2006-08-30 14:17:21 UTC (rev 543)
@@ -22,8 +22,8 @@
 #endif
 
 
+/**********************************************************/
 #if YARV_THREAD_MODEL == 2
-
 extern yarv_thread_t *yarvCurrentThread;
 extern yarv_vm_t *theYarvVM;
 
@@ -55,6 +55,21 @@
     th->vm->running_thread = th;
 }
 
+/**********************************************************/
+#elif YARV_THREAD_MODEL == 3
+extern __thread yarv_thread_t *yarvCurrentThread;
+extern yarv_vm_t *theYarvVM;
+
+#define GET_VM()     theYarvVM
+#define GET_THREAD() yarvCurrentThread
+
+static inline void
+yarv_set_current_running_thread(yarv_thread_t *th)
+{
+    yarvCurrentThread = th;
+}
+
+/**********************************************************/
 #else
 #error "unsupported thread model"
 #endif

Modified: branches/parallel/yarvcore.c
===================================================================
--- branches/parallel/yarvcore.c	2006-08-25 08:18:06 UTC (rev 542)
+++ branches/parallel/yarvcore.c	2006-08-30 14:17:21 UTC (rev 543)
@@ -77,12 +77,11 @@
 /* YARVCore */
 /************/
 
-yarv_thread_t *yarvCurrentThread = 0;
+__thread yarv_thread_t *yarvCurrentThread = 0;
 yarv_vm_t *theYarvVM = 0;
 static VALUE yarvVMArray = Qnil;
 
 RUBY_EXTERN int rb_thread_critical;
-RUBY_EXTERN int ruby_nerrs;
 RUBY_EXTERN NODE *ruby_eval_tree;
 
 VALUE
@@ -1037,5 +1036,5 @@
     th->vm = vm;
     th->machine_stack_start = rb_gc_stack_start;
 
-    yarv_set_current_running_thread_raw(th);
+    yarv_set_current_running_thread(th);
 }

Modified: branches/parallel/yarvcore.h
===================================================================
--- branches/parallel/yarvcore.h	2006-08-25 08:18:06 UTC (rev 542)
+++ branches/parallel/yarvcore.h	2006-08-30 14:17:21 UTC (rev 543)
@@ -6,7 +6,7 @@
 #ifndef _YARVCORE_H_INCLUDED_
 #define _YARVCORE_H_INCLUDED_
 
-#define YARV_THREAD_MODEL 2
+#define YARV_THREAD_MODEL 3
 
 #include <setjmp.h>
 
@@ -311,12 +311,17 @@
     VALUE self;
 
     yarv_thread_lock_t global_interpreter_lock;
-
+    yarv_thread_cond_t gc_barrier_owner_cond;
+    yarv_thread_cond_t gc_barrier_waits_cond;
+    
     struct yarv_thread_struct *main_thread;
     struct yarv_thread_struct *running_thread;
+    struct yarv_thread_struct *lock_owner_thread;
 
+    int num_wait_threads;
+    st_table *living_threads;
+
     VALUE main_thread_val;
-    st_table *living_threads;
     VALUE thgroup_default;
 
     int thread_abort_on_exception;
@@ -430,6 +435,8 @@
     int exec_signal;
 
     int interrupt_flag;
+    int interrupt_gc_flag;
+    
     yarv_interrupt_function_t *interrupt_function;
     yarv_thread_lock_t interrupt_lock;
 
@@ -463,6 +470,11 @@
     int abort_on_exception;
 } yarv_thread_t;
 
+typedef struct native_global_lock_struct {
+    yarv_thread_lock_t lock;
+    yarv_thread_t *th;
+} native_global_lock_t;
+
 /** node -> yarv instruction sequence object */
 VALUE iseq_compile(VALUE self, NODE *node);
 
@@ -605,16 +617,6 @@
 
 #include "yarv.h"
 
-#define GVL_UNLOCK_BEGIN() do { \
-  yarv_thread_t *_th_stored = GET_THREAD(); \
-  yarv_save_machine_context(_th_stored); \
-  native_mutex_unlock(&_th_stored->vm->global_interpreter_lock)
-
-#define GVL_UNLOCK_END() \
-  native_mutex_lock(&_th_stored->vm->global_interpreter_lock); \
-  yarv_set_current_running_thread(_th_stored); \
-} while(0)
-
 NOINLINE(void yarv_set_stack_end(VALUE **stack_end_p));
 NOINLINE(void yarv_save_machine_context(yarv_thread_t *));
 


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

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