From 5732566f4d9a026fef3904f3237a9f7255ba91f2 Mon Sep 17 00:00:00 2001 From: nobu Date: Thu, 6 Nov 2008 13:21:26 +0000 Subject: [PATCH] * thread.c (rb_thread_stop_timer_thread): terminates timer thread immediately. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@20117 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- ChangeLog | 5 +++++ thread.c | 8 ++++---- thread_pthread.c | 32 ++++++++++++++++++-------------- thread_win32.c | 35 +++++++++++++++++++++++++++++------ 4 files changed, 56 insertions(+), 24 deletions(-) diff --git a/ChangeLog b/ChangeLog index 5b14fd272d..144ab66c11 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +Thu Nov 6 22:21:23 2008 Nobuyoshi Nakada + + * thread.c (rb_thread_stop_timer_thread): terminates timer thread + immediately. + Thu Nov 6 21:21:46 2008 Masaki Suketa * ext/win32ole/win32ole.c (fole_s_connect, fole_initialize, diff --git a/thread.c b/thread.c index 7e4e280f06..ca47419644 100644 --- a/thread.c +++ b/thread.c @@ -71,10 +71,10 @@ static void rb_check_deadlock(rb_vm_t *vm); void rb_signal_exec(rb_thread_t *th, int sig); void rb_disable_interrupt(void); +void rb_thread_stop_timer_thread(void); static const VALUE eKillSignal = INT2FIX(0); static const VALUE eTerminateSignal = INT2FIX(1); -static volatile int system_working = 1; inline static void st_delete_wrap(st_table *table, st_data_t key) @@ -318,7 +318,7 @@ rb_thread_terminate_all(void) } POP_TAG(); } - system_working = 0; + rb_thread_stop_timer_thread(); } static void @@ -2322,7 +2322,7 @@ int rb_get_next_signal(void); static void timer_thread_function(void *arg) { - rb_vm_t *vm = arg; /* TODO: fix me for Multi-VM */ + rb_vm_t *vm = GET_VM(); /* TODO: fix me for Multi-VM */ int sig; /* for time slice */ @@ -2356,7 +2356,7 @@ void rb_thread_stop_timer_thread(void) { if (timer_thread_id) { - system_working = 0; + native_stop_timer_thread(); native_thread_join(timer_thread_id); timer_thread_id = 0; } diff --git a/thread_pthread.c b/thread_pthread.c index 0f8214416a..08bacde8e9 100644 --- a/thread_pthread.c +++ b/thread_pthread.c @@ -503,6 +503,8 @@ ubf_select(void *ptr) #define ubf_select 0 #endif +#define PER_NANO 1000000000 + static void native_sleep(rb_thread_t *th, struct timeval *tv) { @@ -513,10 +515,10 @@ native_sleep(rb_thread_t *th, struct timeval *tv) gettimeofday(&tvn, NULL); ts.tv_sec = tvn.tv_sec + tv->tv_sec; ts.tv_nsec = (tvn.tv_usec + tv->tv_usec) * 1000; - if (ts.tv_nsec >= 1000000000){ + if (ts.tv_nsec >= PER_NANO){ ts.tv_sec += 1; - ts.tv_nsec -= 1000000000; - } + ts.tv_nsec -= PER_NANO; + } } thread_debug("native_sleep %ld\n", tv ? tv->tv_sec : -1); @@ -535,7 +537,7 @@ native_sleep(rb_thread_t *th, struct timeval *tv) int r; thread_debug("native_sleep: pthread_cond_wait start\n"); r = pthread_cond_wait(&th->native_thread_data.sleep_cond, - &th->interrupt_lock); + &th->interrupt_lock); if (r) rb_bug("pthread_cond_wait: %d", r); thread_debug("native_sleep: pthread_cond_wait end\n"); } @@ -651,18 +653,18 @@ static pthread_t timer_thread_id; static void * thread_timer(void *dummy) { - while (system_working) { #ifdef HAVE_NANOSLEEP - struct timespec req, rem; - req.tv_sec = 0; - req.tv_nsec = 10 * 1000 * 1000; /* 10 ms */ - nanosleep(&req, &rem); + struct timespec req, rem; + req.tv_sec = 0; + req.tv_nsec = 10 * 1000 * 1000; /* 10 ms */ +#define WAIT_FOR_10MS() nanosleep(&req, &rem) #else - struct timeval tv; - tv.tv_sec = 0; - tv.tv_usec = 10000; /* 10 ms */ - select(0, NULL, NULL, NULL, &tv); + struct timeval tv; + tv.tv_sec = 0; + tv.tv_usec = 10000; /* 10 ms */ +#define WAIT_FOR_10MS() select(0, NULL, NULL, NULL, &tv) #endif + while (WAIT_FOR_10MS() != -1) { #ifndef __CYGWIN__ if (signal_thread_list_anchor.next) { FGLOCK(&signal_thread_list_lock, { @@ -694,7 +696,7 @@ rb_thread_create_timer_thread(void) pthread_attr_setstacksize(&attr, PTHREAD_STACK_MIN + (THREAD_DEBUG ? BUFSIZ : 0)); #endif - err = pthread_create(&timer_thread_id, &attr, thread_timer, GET_VM()); + err = pthread_create(&timer_thread_id, &attr, thread_timer, 0); if (err != 0) { rb_bug("rb_thread_create_timer_thread: return non-zero (%d)", err); } @@ -702,4 +704,6 @@ rb_thread_create_timer_thread(void) rb_disable_interrupt(); /* only timer thread recieve signal */ } +#define native_stop_timer_thread() pthread_kill(timer_thread_id, SIGTERM) + #endif /* THREAD_SYSTEM_DEPENDENT_IMPLEMENTATION */ diff --git a/thread_win32.c b/thread_win32.c index 46780d8ff4..5d6bf9e4bf 100644 --- a/thread_win32.c +++ b/thread_win32.c @@ -451,11 +451,26 @@ native_thread_destroy(rb_thread_t *th) w32_close_handle(intr); } +static void * +get_stack_info(const void *ptr, size_t *maxsize) +{ + MEMORY_BASIC_INFORMATION mi; + DWORD size; + DWORD space; + + if (!VirtualQuery(ptr, &mi, sizeof(mi))) return 0; + size = (char *)mi.BaseAddress - (char *)mi.AllocationBase; + space = size / 5; + if (space > 1024*1024) space = 1024*1024; + *maxsize = size - space; + return (VALUE *)mi.BaseAddress - 1; +} + static unsigned long _stdcall thread_start_func_1(void *th_ptr) { rb_thread_t *th = th_ptr; - VALUE stack_start; + VALUE *stack_start; volatile HANDLE thread_id = th->thread_id; native_thread_init_stack(th); @@ -464,7 +479,9 @@ thread_start_func_1(void *th_ptr) /* run */ thread_debug("thread created (th: %p, thid: %p, event: %p)\n", th, th->thread_id, th->native_thread_data.interrupt_event); - thread_start_func_2(th, &stack_start, 0); + + stack_start = get_stack_info(&stack_start, &th->machine_stack_maxsize); + thread_start_func_2(th, stack_start, rb_ia64_bsp()); w32_close_handle(thread_id); thread_debug("thread deleted (th: %p)\n", th); @@ -531,27 +548,33 @@ ubf_handle(void *ptr) } static HANDLE timer_thread_id = 0; +static HANDLE timer_thread_lock; static unsigned long _stdcall timer_thread_func(void *dummy) { thread_debug("timer_thread\n"); - while (system_working) { - Sleep(WIN32_WAIT_TIMEOUT); + while (WaitForSingleObject(timer_thread_lock, WIN32_WAIT_TIMEOUT) == + WAIT_TIMEOUT) { timer_thread_function(dummy); } thread_debug("timer killed\n"); return 0; } -void +static void rb_thread_create_timer_thread(void) { if (timer_thread_id == 0) { + if (!timer_thread_lock) { + timer_thread_lock = CreateEvent(0, TRUE, FALSE, 0); + } timer_thread_id = w32_create_thread(1024 + (THREAD_DEBUG ? BUFSIZ : 0), - timer_thread_func, GET_VM()); + timer_thread_func, 0); w32_resume_thread(timer_thread_id); } } +#define native_stop_timer_thread() (CloseHandle(timer_thread_lock), timer_thread_lock = 0) + #endif /* THREAD_SYSTEM_DEPENDENT_IMPLEMENTATION */