[前][次][番号順一覧][スレッド一覧]

ruby-changes:8871

From: yugui <ko1@a...>
Date: Sun, 30 Nov 2008 18:24:03 +0900 (JST)
Subject: [ruby-changes:8871] Ruby:r20407 (ruby_1_9_1): * thread.c, thread_pthread.c, thread_win32.c: merges nobu's commits -

yugui	2008-11-30 18:22:31 +0900 (Sun, 30 Nov 2008)

  New Revision: 20407

  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=rev&revision=20407

  Log:
    * 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.

  Modified files:
    branches/ruby_1_9_1/ChangeLog
    branches/ruby_1_9_1/thread.c
    branches/ruby_1_9_1/thread_pthread.c
    branches/ruby_1_9_1/thread_win32.c

Index: ruby_1_9_1/thread_win32.c
===================================================================
--- ruby_1_9_1/thread_win32.c	(revision 20406)
+++ ruby_1_9_1/thread_win32.c	(revision 20407)
@@ -455,7 +455,6 @@
 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,8 +463,9 @@
     /* 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);
     return 0;
@@ -531,27 +531,42 @@
 }
 
 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 */
Index: ruby_1_9_1/ChangeLog
===================================================================
--- ruby_1_9_1/ChangeLog	(revision 20406)
+++ ruby_1_9_1/ChangeLog	(revision 20407)
@@ -1,3 +1,34 @@
+Sat Nov 29 00:27:33 2008  Yuki Sonoda (Yugui)  <yugui@y...>
+
+	* 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@r...>
 
 	* process.c (rb_fork): stops the timer thread during fork.
Index: ruby_1_9_1/thread_pthread.c
===================================================================
--- ruby_1_9_1/thread_pthread.c	(revision 20406)
+++ ruby_1_9_1/thread_pthread.c	(revision 20407)
@@ -116,7 +116,13 @@
     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
 #ifdef HAVE_SCHED_YIELD
@@ -503,6 +509,8 @@
 #define ubf_select 0
 #endif
 
+#define PER_NANO 1000000000
+
 static void
 native_sleep(rb_thread_t *th, struct timeval *tv)
 {
@@ -513,10 +521,10 @@
 	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 @@
 		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 @@
 }
 
 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 @@
 #endif
 	timer_thread_function(dummy);
     }
+    native_mutex_unlock(&timer_thread_lock);
     return NULL;
 }
 
@@ -694,12 +717,29 @@
 	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 */
Index: ruby_1_9_1/thread.c
===================================================================
--- ruby_1_9_1/thread.c	(revision 20406)
+++ ruby_1_9_1/thread.c	(revision 20407)
@@ -71,6 +71,7 @@
 
 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 @@
 	}
 	POP_TAG();
     }
-    system_working = 0;
+    rb_thread_stop_timer_thread();
 }
 
 static void
@@ -2322,7 +2323,7 @@
 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 @@
 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;
     }

--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

[前][次][番号順一覧][スレッド一覧]