From 5f0b8afb97d7830de8f04a7d6a39cde660020c69 Mon Sep 17 00:00:00 2001 From: ko1 Date: Tue, 25 Dec 2007 04:16:06 +0000 Subject: [PATCH] * vm_core.h, thread.c, cont.c: add RUBY_VM_SET_INTERRUPT(), RUBY_VM_SET_TIMER_INTERRUPT(), RUBY_VM_INTERRUPTED(). * thread.c, thread_pthread.c, thread_win32.c: fix to ignore time slice event until sleep. * bootstraptest/test_thread.rb: add a test for time limited join test. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@14654 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- ChangeLog | 10 ++++++++++ bootstraptest/test_thread.rb | 12 +++++++++++- cont.c | 2 +- thread.c | 6 +++--- thread_pthread.c | 16 +++++++++------- thread_win32.c | 15 ++++++++++++--- vm_core.h | 4 ++++ 7 files changed, 50 insertions(+), 15 deletions(-) diff --git a/ChangeLog b/ChangeLog index b6ad69af3f..ed0c9b25f6 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,13 @@ +Tue Dec 25 13:07:56 2007 Koichi Sasada + + * vm_core.h, thread.c, cont.c: add RUBY_VM_SET_INTERRUPT(), + RUBY_VM_SET_TIMER_INTERRUPT(), RUBY_VM_INTERRUPTED(). + + * thread.c, thread_pthread.c, thread_win32.c: fix to ignore time slice + event until sleep. + + * bootstraptest/test_thread.rb: add a test for time limited join test. + Tue Dec 25 12:42:59 2007 Koichi Sasada * vm.c (Init_VM): remove unused code. diff --git a/bootstraptest/test_thread.rb b/bootstraptest/test_thread.rb index 3c1cc5a1c1..b3592e9bd7 100644 --- a/bootstraptest/test_thread.rb +++ b/bootstraptest/test_thread.rb @@ -25,7 +25,17 @@ assert_equal %q{5000}, %q{ Thread.new{ } }.each{|e| - e.join + e.join() + } + } +} +assert_equal %q{5000}, %q{ + 5000.times{|e| + (1..2).map{ + Thread.new{ + } + }.each{|e| + e.join(1000000000) } } } diff --git a/cont.c b/cont.c index c153e5fc59..43b0ea77f2 100644 --- a/cont.c +++ b/cont.c @@ -610,7 +610,7 @@ rb_fiber_start(void) th->thrown_errinfo = vm_make_jump_tag_but_local_jump(state, th->errinfo); } - th->interrupt_flag = 1; + RUBY_VM_SET_INTERRUPT(th); } rb_fiber_terminate(cont); diff --git a/thread.c b/thread.c index ae0c3b3bfb..a96806d773 100644 --- a/thread.c +++ b/thread.c @@ -218,7 +218,7 @@ static void rb_thread_interrupt(rb_thread_t *th) { native_mutex_lock(&th->interrupt_lock); - th->interrupt_flag = 1; + RUBY_VM_SET_INTERRUPT(th); if (th->unblock_function) { (th->unblock_function)(th->unblock_function_arg); } @@ -562,6 +562,7 @@ thread_join_m(int argc, VALUE *argv, VALUE self) if (!NIL_P(limit)) { delay = rb_num2dbl(limit); } + return thread_join(target_th, delay); } @@ -607,7 +608,6 @@ static void sleep_forever(rb_thread_t *th) { native_sleep(th, 0); - RUBY_VM_CHECK_INTS(); } static void @@ -1924,7 +1924,7 @@ timer_thread_function(void) rb_vm_t *vm = GET_VM(); /* TODO: fix me for Multi-VM */ /* for time slice */ - vm->running_thread->interrupt_flag = 1; + RUBY_VM_SET_TIMER_INTERRUPT(vm->running_thread); /* check signal */ if (vm->buffered_signal_size && vm->main_thread->exec_signal == 0) { diff --git a/thread_pthread.c b/thread_pthread.c index a511468949..5a3770520f 100644 --- a/thread_pthread.c +++ b/thread_pthread.c @@ -392,6 +392,7 @@ native_sleep(rb_thread_t *th, struct timeval *tv) int prev_status = th->status; struct timespec ts; struct timeval tvn; + struct timeval tve; if (tv) { gettimeofday(&tvn, NULL); @@ -410,15 +411,14 @@ native_sleep(rb_thread_t *th, struct timeval *tv) GVL_UNLOCK_BEGIN(); { pthread_mutex_lock(&th->interrupt_lock); + th->unblock_function = ubf_pthread_cond_signal; + th->unblock_function_arg = th; - if (th->interrupt_flag) { + if (RUBY_VM_INTERRUPTED(th)) { /* interrupted. return immediate */ thread_debug("native_sleep: interrupted before sleep\n"); } else { - th->unblock_function = ubf_pthread_cond_signal; - th->unblock_function_arg = th; - if (tv == 0) { thread_debug("native_sleep: pthread_cond_wait start\n"); pthread_cond_wait(&th->native_thread_data.sleep_cond, @@ -433,14 +433,16 @@ native_sleep(rb_thread_t *th, struct timeval *tv) &th->interrupt_lock, &ts); thread_debug("native_sleep: pthread_cond_timedwait end (%d)\n", r); } - th->unblock_function = 0; - th->unblock_function_arg = 0; } - pthread_mutex_unlock(&th->interrupt_lock); + th->unblock_function = 0; + th->unblock_function_arg = 0; + pthread_mutex_unlock(&th->interrupt_lock); th->status = prev_status; } GVL_UNLOCK_END(); + RUBY_VM_CHECK_INTS(); + thread_debug("native_sleep done\n"); } diff --git a/thread_win32.c b/thread_win32.c index d8b33e23e0..a7326ebfc5 100644 --- a/thread_win32.c +++ b/thread_win32.c @@ -208,17 +208,26 @@ native_sleep(rb_thread_t *th, struct timeval *tv) { DWORD ret; int status = th->status; + th->status = THREAD_STOPPED; th->unblock_function = ubf_handle; th->unblock_function_arg = th; - thread_debug("native_sleep start (%d)\n", (int)msec); - ret = w32_wait_events(0, 0, msec, th); - thread_debug("native_sleep done (%d)\n", ret); + + if (RUBY_VM_INTERRUPTED(th)) { + /* interrupted. return immediate */ + } + else { + thread_debug("native_sleep start (%d)\n", (int)msec); + ret = w32_wait_events(0, 0, msec, th); + thread_debug("native_sleep done (%d)\n", ret); + } + th->unblock_function = 0; th->unblock_function_arg = 0; th->status = status; } GVL_UNLOCK_END(); + RUBY_VM_CHECK_INTS(); } int diff --git a/vm_core.h b/vm_core.h index 98c57300c1..dbffab1c4f 100644 --- a/vm_core.h +++ b/vm_core.h @@ -634,6 +634,10 @@ extern rb_vm_t *ruby_current_vm; #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_INTERRUPTED(th) ((th)->interrupt_flag & 0x02) + void rb_thread_execute_interrupts(rb_thread_t *); #define RUBY_VM_CHECK_INTS_TH(th) do { \