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