diff options
author | yugui <yugui@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2008-11-30 09:22:31 +0000 |
---|---|---|
committer | yugui <yugui@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2008-11-30 09:22:31 +0000 |
commit | 2015069a204e8ba13709f94aed5e4341ea297728 (patch) | |
tree | e2671d3edc017889d4821db6c8d1a69c3e181abf | |
parent | d22b7e6ddbd5c616d90c82cb86fd5797cd2d5a61 (diff) |
* thread.c, thread_pthread.c, thread_win32.c: merges nobu's commits -
r20117, r20123, r20124, r20127, r20132-r20134, r20138, r20140, r20141
and r20160 - from trunk into ruby_1_9_1.
* thread_pthread.c (thread_timer): checks working flags again.
* thread_pthread.c (rb_thread_create_timer_thread): do not wait never
coming signal if failed to create tiemr thread.
* thread_pthread.c (native_cond_timedwait): returns error code.
* thread_pthread.c (thread_timer, rb_thread_create_timer_thread):
handshakes properly.
* thread_pthread.c (thread_timer): initializes mutex each time.
* thread_win32.c (thread_start_func_1): use already gotten stack info.
* thread.c (thread_timer): pthread_cond_timedwait returns ETIMEDOUT
when timed out.
* thread_pthread.c (thread_timer): uses pthread_cond_timedwait always
instead of pthread_kill.
* thread.c (thread_timer): uses timedwait on cygwin.
* thread.c (rb_thread_stop_timer_thread): terminates timer thread
immediately.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/branches/ruby_1_9_1@20407 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
-rw-r--r-- | ChangeLog | 31 | ||||
-rw-r--r-- | thread.c | 8 | ||||
-rw-r--r-- | thread_pthread.c | 74 | ||||
-rw-r--r-- | thread_win32.c | 27 |
4 files changed, 113 insertions, 27 deletions
@@ -1,3 +1,34 @@ +Sat Nov 29 00:27:33 2008 Yuki Sonoda (Yugui) <yugui@yugui.jp> + + * thread.c, thread_pthread.c, thread_win32.c: merges nobu's commits - + r20117, r20123, r20124, r20127, r20132-r20134, r20138, r20140, r20141 + and r20160 - from trunk into ruby_1_9_1. + + * thread_pthread.c (thread_timer): checks working flags again. + + * thread_pthread.c (rb_thread_create_timer_thread): do not wait never + coming signal if failed to create tiemr thread. + + * thread_pthread.c (native_cond_timedwait): returns error code. + + * thread_pthread.c (thread_timer, rb_thread_create_timer_thread): + handshakes properly. + + * thread_pthread.c (thread_timer): initializes mutex each time. + + * thread_win32.c (thread_start_func_1): use already gotten stack info. + + * thread.c (thread_timer): pthread_cond_timedwait returns ETIMEDOUT + when timed out. + + * thread_pthread.c (thread_timer): uses pthread_cond_timedwait always + instead of pthread_kill. + + * thread.c (thread_timer): uses timedwait on cygwin. + + * thread.c (rb_thread_stop_timer_thread): terminates timer thread + immediately. + Tue Nov 25 00:08:22 2008 Nobuyoshi Nakada <nobu@ruby-lang.org> * process.c (rb_fork): stops the timer thread during fork. @@ -71,6 +71,7 @@ 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); @@ -318,7 +319,7 @@ rb_thread_terminate_all(void) } POP_TAG(); } - system_working = 0; + rb_thread_stop_timer_thread(); } static void @@ -2322,7 +2323,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 */ @@ -2355,8 +2356,7 @@ timer_thread_function(void *arg) void rb_thread_stop_timer_thread(void) { - if (timer_thread_id) { - system_working = 0; + if (timer_thread_id && 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..7ddfcea7b0 100644 --- a/thread_pthread.c +++ b/thread_pthread.c @@ -116,6 +116,12 @@ native_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex) pthread_cond_wait(cond, mutex); } +static int +native_cond_timedwait(pthread_cond_t *cond, pthread_mutex_t *mutex, struct timespec *ts) +{ + return pthread_cond_timedwait(cond, mutex, ts); +} + #define native_cleanup_push pthread_cleanup_push #define native_cleanup_pop pthread_cleanup_pop @@ -503,6 +509,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 +521,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 +543,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"); } @@ -647,22 +655,36 @@ remove_signal_thread_list(rb_thread_t *th) } static pthread_t timer_thread_id; +static pthread_cond_t timer_thread_cond = PTHREAD_COND_INITIALIZER; +static pthread_mutex_t timer_thread_lock = PTHREAD_MUTEX_INITIALIZER; + +static struct timespec * +get_ts(struct timespec *ts, unsigned long nsec) +{ + struct timeval tv; + gettimeofday(&tv, 0); + ts->tv_sec = tv.tv_sec; + ts->tv_nsec = tv.tv_usec * 1000 + nsec; + if (ts->tv_nsec >= PER_NANO) { + ts->tv_sec++; + ts->tv_nsec -= PER_NANO; + } + return ts; +} 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); -#else - struct timeval tv; - tv.tv_sec = 0; - tv.tv_usec = 10000; /* 10 ms */ - select(0, NULL, NULL, NULL, &tv); -#endif + struct timespec ts; + int err; + + native_mutex_lock(&timer_thread_lock); + native_cond_broadcast(&timer_thread_cond); +#define WAIT_FOR_10MS() native_cond_timedwait(&timer_thread_cond, &timer_thread_lock, get_ts(&ts, PER_NANO/100)) + while (system_working > 0 && (err = WAIT_FOR_10MS()) != 0 && err != EINTR) { + if (err != ETIMEDOUT) { + rb_bug("thread_timer/timedwait: %d", err); + } #ifndef __CYGWIN__ if (signal_thread_list_anchor.next) { FGLOCK(&signal_thread_list_lock, { @@ -677,6 +699,7 @@ thread_timer(void *dummy) #endif timer_thread_function(dummy); } + native_mutex_unlock(&timer_thread_lock); return NULL; } @@ -694,12 +717,29 @@ 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()); + native_mutex_lock(&timer_thread_lock); + err = pthread_create(&timer_thread_id, &attr, thread_timer, 0); if (err != 0) { + native_mutex_unlock(&timer_thread_lock); rb_bug("rb_thread_create_timer_thread: return non-zero (%d)", err); } + native_cond_wait(&timer_thread_cond, &timer_thread_lock); + native_mutex_unlock(&timer_thread_lock); } rb_disable_interrupt(); /* only timer thread recieve signal */ } +static int +native_stop_timer_thread(void) +{ + int stopped; + native_mutex_lock(&timer_thread_lock); + stopped = --system_working <= 0; + if (stopped) { + native_cond_signal(&timer_thread_cond); + } + native_mutex_unlock(&timer_thread_lock); + return stopped; +} + #endif /* THREAD_SYSTEM_DEPENDENT_IMPLEMENTATION */ diff --git a/thread_win32.c b/thread_win32.c index 46780d8ff4..0befbff4ae 100644 --- a/thread_win32.c +++ b/thread_win32.c @@ -455,7 +455,6 @@ static unsigned long _stdcall thread_start_func_1(void *th_ptr) { rb_thread_t *th = th_ptr; - VALUE stack_start; volatile HANDLE thread_id = th->thread_id; native_thread_init_stack(th); @@ -464,7 +463,8 @@ 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); + + thread_start_func_2(th, th->machine_stack_start, rb_ia64_bsp()); w32_close_handle(thread_id); thread_debug("thread deleted (th: %p)\n", th); @@ -531,27 +531,42 @@ 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); } } +static int +native_stop_timer_thread(void) +{ + int stopped = --system_working <= 0; + if (stopped) { + CloseHandle(timer_thread_lock); + timer_thread_lock = 0; + } + return stopped; +} + #endif /* THREAD_SYSTEM_DEPENDENT_IMPLEMENTATION */ |