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

ruby-changes:14706

From: wyhaines <ko1@a...>
Date: Thu, 4 Feb 2010 01:09:52 +0900 (JST)
Subject: [ruby-changes:14706] Ruby:r26561 (ruby_1_8_6): Backport #1743 ; stops timer thread unless other threads exist.

wyhaines	2010-02-04 01:09:35 +0900 (Thu, 04 Feb 2010)

  New Revision: 26561

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

  Log:
    Backport #1743 [ruby-core:24203]; stops timer thread unless other threads exist.

  Modified files:
    branches/ruby_1_8_6/ChangeLog
    branches/ruby_1_8_6/eval.c
    branches/ruby_1_8_6/version.h

Index: ruby_1_8_6/ChangeLog
===================================================================
--- ruby_1_8_6/ChangeLog	(revision 26560)
+++ ruby_1_8_6/ChangeLog	(revision 26561)
@@ -1,3 +1,7 @@
+Wed Feb 4  01:06:00 2010 Kirk Haines <khaines@r...>
+
+	* eval.c: Backport #1743 [ruby-core:24203]; stops timer thread unless other threads exist.
+
 Wed Jan 28 04:00:00 2010 Kirk Haines <khaines@r...>
 
 	* io.c: Backport #2009 [ruby-core:25173]; (rb_io_fptr_finalize): free fptr to avoid memory leaks.
Index: ruby_1_8_6/version.h
===================================================================
--- ruby_1_8_6/version.h	(revision 26560)
+++ ruby_1_8_6/version.h	(revision 26561)
@@ -1,15 +1,15 @@
 #define RUBY_VERSION "1.8.6"
-#define RUBY_RELEASE_DATE "2010-01-28"
+#define RUBY_RELEASE_DATE "2010-02-04"
 #define RUBY_VERSION_CODE 186
-#define RUBY_RELEASE_CODE 20100128
-#define RUBY_PATCHLEVEL 388
+#define RUBY_RELEASE_CODE 20100204
+#define RUBY_PATCHLEVEL 398
 
 #define RUBY_VERSION_MAJOR 1
 #define RUBY_VERSION_MINOR 8
 #define RUBY_VERSION_TEENY 6
 #define RUBY_RELEASE_YEAR 2010
-#define RUBY_RELEASE_MONTH 1
-#define RUBY_RELEASE_DAY 28
+#define RUBY_RELEASE_MONTH 2
+#define RUBY_RELEASE_DAY 04
 
 #ifdef RUBY_EXTERN
 RUBY_EXTERN const char ruby_version[];
Index: ruby_1_8_6/eval.c
===================================================================
--- ruby_1_8_6/eval.c	(revision 26560)
+++ ruby_1_8_6/eval.c	(revision 26561)
@@ -10569,6 +10569,12 @@
     rb_thread_die(th);
     th->prev->next = th->next;
     th->next->prev = th->prev;
+#if defined(_THREAD_SAFE) || defined(HAVE_SETITIMER)
+    /* if this is the last ruby thread, stop timer signals */
+    if (th->next == th->prev && th->next == main_thread) {
+	rb_thread_stop_timer();
+    }
+#endif
 }
 
 static int
@@ -11955,40 +11961,58 @@
     /* cause EINTR */
 }
 
-static int time_thread_alive_p = 0;
-static pthread_t time_thread;
+#define PER_NANO 1000000000
 
+static struct timespec *
+get_ts(struct timespec *to, long ns)
+{
+    struct timeval tv;
+
+#ifdef CLOCK_MONOTONIC
+    if (clock_gettime(CLOCK_MONOTONIC, to) != 0)
+#endif
+    {
+	gettimeofday(&tv, NULL);
+	to->tv_sec = tv.tv_sec;
+	to->tv_nsec = tv.tv_usec * 1000;
+    }
+    if ((to->tv_nsec += ns) >= PER_NANO) {
+	to->tv_sec += to->tv_nsec / PER_NANO;
+	to->tv_nsec %= PER_NANO;
+    }
+    return to;
+}
+
+static struct timer_thread {
+    pthread_cond_t cond;
+    pthread_mutex_t lock;
+    pthread_t thread;
+} time_thread = {PTHREAD_COND_INITIALIZER, PTHREAD_MUTEX_INITIALIZER};
+
+#define safe_mutex_lock(lock) \
+    (pthread_mutex_lock(lock), \
+     pthread_cleanup_push((void (*)_((void *)))pthread_mutex_unlock, lock))
+
 static void*
 thread_timer(dummy)
     void *dummy;
 {
-#ifdef _THREAD_SAFE
-#define test_cancel() pthread_testcancel()
-#else
-#define test_cancel() /* void */
-#endif
+    struct timer_thread *running = ((void **)dummy)[0];
+    pthread_cond_t *start = ((void **)dummy)[1];
+    struct timespec to;
+    int err;
 
     sigset_t all_signals;
 
     sigfillset(&all_signals);
     pthread_sigmask(SIG_BLOCK, &all_signals, 0);
 
-    for (;;) {
-#ifdef HAVE_NANOSLEEP
-	struct timespec req, rem;
+    safe_mutex_lock(&running->lock);
+    pthread_cond_signal(start);
 
-	test_cancel();
-	req.tv_sec = 0;
-	req.tv_nsec = 10000000;
-	nanosleep(&req, &rem);
-#else
-	struct timeval tv;
-
-	test_cancel();
-	tv.tv_sec = 0;
-	tv.tv_usec = 10000;
-	select(0, NULL, NULL, NULL, &tv);
-#endif
+#define WAIT_FOR_10MS() \
+    pthread_cond_timedwait(&running->cond, &running->lock, get_ts(&to, PER_NANO/100))
+    while ((err = WAIT_FOR_10MS()) == EINTR || err == ETIMEDOUT) {
 	if (!rb_thread_critical) {
 	    rb_thread_pending = 1;
 	    if (rb_trap_immediate) {
@@ -11996,17 +12020,39 @@
 	    }
 	}
     }
-#undef test_cancel
+
+    pthread_cleanup_pop(1);
+
+    return NULL;
 }
 
 void
 rb_thread_start_timer()
 {
+    void *args[2];
+    static pthread_cond_t start = PTHREAD_COND_INITIALIZER;
+
+    if (!thread_init) return;
+    args[0] = &time_thread;
+    args[1] = &start;
+    safe_mutex_lock(&time_thread.lock);
+    if (pthread_create(&time_thread.thread, 0, thread_timer, args) == 0) {
+	thread_init = 1;
+	pthread_atfork(0, 0, rb_thread_stop_timer);
+	pthread_cond_wait(&start, &time_thread.lock);
+    }
+    pthread_cleanup_pop(1);
 }
 
 void
 rb_thread_stop_timer()
 {
+    if (!thread_init) return;
+    safe_mutex_lock(&time_thread.lock);
+    pthread_cond_signal(&time_thread.cond);
+    pthread_cleanup_pop(1);
+    pthread_join(time_thread.thread, NULL);
+    thread_init = 0;
 }
 
 void
@@ -12047,11 +12093,12 @@
 {
     struct itimerval tval;
 
-    if (!thread_init) return;
+    if (thread_init) return;
     tval.it_interval.tv_sec = 0;
     tval.it_interval.tv_usec = 10000;
     tval.it_value = tval.it_interval;
     setitimer(ITIMER_VIRTUAL, &tval, NULL);
+    thread_init = 1;
 }
 
 void
@@ -12064,6 +12111,7 @@
     tval.it_interval.tv_usec = 0;
     tval.it_value = tval.it_interval;
     setitimer(ITIMER_VIRTUAL, &tval, NULL);
+    thread_init = 0;
 }
 
 void
@@ -12098,7 +12146,6 @@
     }
 
     if (!thread_init) {
-	thread_init = 1;
 #if defined(HAVE_SETITIMER) || defined(_THREAD_SAFE)
 #if defined(POSIX_SIGNAL)
 	posix_signal(SIGVTALRM, catch_timer);
@@ -12106,14 +12153,8 @@
 	signal(SIGVTALRM, catch_timer);
 #endif
 
-#ifdef _THREAD_SAFE
-	pthread_create(&time_thread, 0, thread_timer, 0);
-        time_thread_alive_p = 1;
-        pthread_atfork(0, 0, rb_child_atfork);
-#else
 	rb_thread_start_timer();
 #endif
-#endif
     }
 
     if (THREAD_SAVE_CONTEXT(curr_thread)) {

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

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