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

ruby-changes:1799

From: ko1@a...
Date: 28 Aug 2007 01:48:32 +0900
Subject: [ruby-changes:1799] ko1 - Ruby:r13290 (trunk): * thread.c: fix Mutex to be interruptable lock.

ko1	2007-08-28 01:48:14 +0900 (Tue, 28 Aug 2007)

  New Revision: 13290

  Added files:
    trunk/benchmark/bm_vm2_mutex.rb
    trunk/benchmark/bm_vm3_thread_mutex.rb
    trunk/benchmark/bmx_temp.rb
    trunk/test/ruby/test_thread.rb
  Modified files:
    trunk/ChangeLog
    trunk/benchmark/bm_loop_generator.rb
    trunk/benchmark/bm_vm2_case.rb
    trunk/benchmark/run.rb
    trunk/common.mk
    trunk/file.c
    trunk/include/ruby/intern.h
    trunk/prelude.rb
    trunk/process.c
    trunk/thread.c
    trunk/thread_pthread.ci
    trunk/thread_pthread.h
    trunk/thread_win32.ci
    trunk/thread_win32.h
    trunk/version.h
    trunk/vm_core.h

  Log:
    * thread.c: fix Mutex to be interruptable lock.
    * thread_win32.ci, thread_win32.h, thread_pthread.ci, thread_pthread.h:
      prepare native_cond_*() which are based on pthread_cond_*() spec.
    * prelude.rb: fix Mutex#synchronize method.
    * vm_core.h, include/ruby/intern.h: change unblock function interface
      (to pass some user data).
    * file.c, process.c: ditto.
    * benchmark/bm_vm2_mutex.rb: add a benchmark for mutex.
    * benchmark/bm_vm3_thread_mutex.rb: add a benchmark for mutex
      with contension.
    * benchmark/run.rb: fix to remove ENV['RUBYLIB'] for matzruby.
    * test/ruby/test_thread.rb: add a test.
    * common.mk: fix benchmark options.
    


  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi/trunk/benchmark/run.rb?r1=13290&r2=13289
  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi/trunk/benchmark/bmx_temp.rb?r1=13290&r2=13289
  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi/trunk/benchmark/bmx_temp.rb?revision=13290&view=markup
  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi/trunk/version.h?r1=13290&r2=13289
  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi/trunk/thread_win32.ci?r1=13290&r2=13289
  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi/trunk/prelude.rb?r1=13290&r2=13289
  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi/trunk/file.c?r1=13290&r2=13289
  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi/trunk/thread_pthread.ci?r1=13290&r2=13289
  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi/trunk/benchmark/bm_vm2_mutex.rb?r1=13290&r2=13289
  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi/trunk/benchmark/bm_vm2_mutex.rb?revision=13290&view=markup
  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi/trunk/ChangeLog?r1=13290&r2=13289
  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi/trunk/thread_pthread.h?r1=13290&r2=13289
  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi/trunk/thread.c?r1=13290&r2=13289
  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi/trunk/vm_core.h?r1=13290&r2=13289
  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi/trunk/benchmark/bm_vm2_case.rb?r1=13290&r2=13289
  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi/trunk/benchmark/bm_vm2_case.rb?r1=13290&r2=13289
  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi/trunk/test/ruby/test_thread.rb?r1=13290&r2=13289
  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi/trunk/test/ruby/test_thread.rb?revision=13290&view=markup
  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi/trunk/thread_win32.h?r1=13290&r2=13289
  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi/trunk/process.c?r1=13290&r2=13289
  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi/trunk/include/ruby/intern.h?r1=13290&r2=13289
  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi/trunk/benchmark/bm_loop_generator.rb?r1=13290&r2=13289
  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi/trunk/benchmark/bm_loop_generator.rb?r1=13290&r2=13289
  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi/trunk/common.mk?r1=13290&r2=13289
  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi/trunk/benchmark/bm_vm3_thread_mutex.rb?r1=13290&r2=13289
  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi/trunk/benchmark/bm_vm3_thread_mutex.rb?revision=13290&view=markup

Index: prelude.rb
===================================================================
--- prelude.rb	(revision 13289)
+++ prelude.rb	(revision 13290)
@@ -4,9 +4,11 @@
 class Mutex
   def synchronize
     self.lock
-    yield
-  ensure
-    self.unlock
+    begin
+      yield
+    ensure
+      self.unlock
+    end
   end
 end
 
Index: thread_win32.h
===================================================================
--- thread_win32.h	(revision 13289)
+++ thread_win32.h	(revision 13290)
@@ -24,12 +24,19 @@
 
 typedef HANDLE rb_thread_id_t;
 typedef CRITICAL_SECTION rb_thread_lock_t;
+typedef struct rb_thread_cond_struct rb_thread_cond_t;
 
 int native_mutex_lock(rb_thread_lock_t *);
 int native_mutex_unlock(rb_thread_lock_t *);
 int native_mutex_trylock(rb_thread_lock_t *);
 void native_mutex_initialize(rb_thread_lock_t *);
 
+void native_cond_signal(rb_thread_cond_t *cond);
+void native_cond_broadcast(rb_thread_cond_t *cond);
+void native_cond_wait(rb_thread_cond_t *cond, rb_thread_lock_t *mutex);
+void native_cond_initialize(rb_thread_cond_t *cond);
+void native_cond_destroy(rb_thread_cond_t *cond);
+
 typedef struct native_thread_data_struct {
     HANDLE interrupt_event;
 } native_thread_data_t;
Index: include/ruby/intern.h
===================================================================
--- include/ruby/intern.h	(revision 13289)
+++ include/ruby/intern.h	(revision 13290)
@@ -533,10 +533,10 @@
 VALUE rb_struct_members(VALUE);
 /* thread.c */
 typedef struct rb_thread_struct rb_thread_t;
-typedef void rb_unblock_function_t(rb_thread_t *);
+typedef void rb_unblock_function_t(rb_thread_t *, void *);
 typedef VALUE rb_blocking_function_t(rb_thread_t *th, void *);
-VALUE rb_thread_blocking_region(rb_blocking_function_t *func, void *data,
-				rb_unblock_function_t *ubf);
+VALUE rb_thread_blocking_region(rb_blocking_function_t *func, void *data1,
+				rb_unblock_function_t *ubf, void *data2);
 #define RB_UBF_DFL ((rb_unblock_function_t *)-1)
 VALUE rb_mutex_new(void);
 VALUE rb_mutex_locked_p(VALUE mutex);
Index: ChangeLog
===================================================================
--- ChangeLog	(revision 13289)
+++ ChangeLog	(revision 13290)
@@ -1,3 +1,28 @@
+Tue Aug 28 00:51:22 2007  Koichi Sasada  <ko1@a...>
+
+	* thread.c: fix Mutex to be interruptable lock.
+
+	* thread_win32.ci, thread_win32.h, thread_pthread.ci, thread_pthread.h:
+	  prepare native_cond_*() which are based on pthread_cond_*() spec.
+
+	* prelude.rb: fix Mutex#synchronize method.
+
+	* vm_core.h, include/ruby/intern.h: change unblock function interface
+	  (to pass some user data).
+
+	* file.c, process.c: ditto.
+
+	* benchmark/bm_vm2_mutex.rb: add a benchmark for mutex.
+
+	* benchmark/bm_vm3_thread_mutex.rb: add a benchmark for mutex
+	  with contension.
+
+	* benchmark/run.rb: fix to remove ENV['RUBYLIB'] for matzruby.
+
+	* test/ruby/test_thread.rb: add a test.
+
+	* common.mk: fix benchmark options.
+
 Mon Aug 27 23:14:02 2007  Yukihiro Matsumoto  <matz@r...>
 
 	* string.c (rb_str_rstrip_bang): wrong strip point.  [ruby-dev:31652]
@@ -29,6 +54,7 @@
 
 	* string.c (sym_encoding): return the encoding of a Symbol.
 
+>>>>>>> .r13289
 Mon Aug 27 15:33:10 2007  Nobuyoshi Nakada  <nobu@r...>
 
 	* util.c (IEEE_BIG_ENDIAN): use configured value.  [ruby-dev:31623]
Index: thread_pthread.h
===================================================================
--- thread_pthread.h	(revision 13289)
+++ thread_pthread.h	(revision 13290)
@@ -15,6 +15,7 @@
 #include <pthread.h>
 typedef pthread_t rb_thread_id_t;
 typedef pthread_mutex_t rb_thread_lock_t;
+typedef pthread_cond_t rb_thread_cond_t;
 
 void native_mutex_lock(pthread_mutex_t *lock);
 void native_mutex_unlock(pthread_mutex_t *lock);
@@ -23,6 +24,12 @@
 void native_mutex_initialize(pthread_mutex_t *lock);
 void native_mutex_destroy(pthread_mutex_t *lock);
 
+void native_cond_signal(pthread_cond_t *cond);
+void native_cond_broadcast(pthread_cond_t *cond);
+void native_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex);
+void native_cond_initialize(pthread_cond_t *cond);
+void native_cond_destroy(pthread_cond_t *cond);
+
 typedef struct native_thread_data_struct {
     void *signal_thread_list;
     pthread_cond_t sleep_cond;
Index: vm_core.h
===================================================================
--- vm_core.h	(revision 13289)
+++ vm_core.h	(revision 13290)
@@ -427,6 +427,7 @@
 
     int interrupt_flag;
     rb_unblock_function_t *unblock_function;
+    void *unblock_function_arg;
     rb_thread_lock_t interrupt_lock;
 
     struct rb_vm_tag *tag;
Index: thread.c
===================================================================
--- thread.c	(revision 13289)
+++ thread.c	(revision 13290)
@@ -80,7 +80,8 @@
 
 #define THREAD_SYSTEM_DEPENDENT_IMPLEMENTATION
 
-static rb_unblock_function_t* set_unblock_function(rb_thread_t *th, rb_unblock_function_t *func);
+static void set_unblock_function(rb_thread_t *th, rb_unblock_function_t *func, void *ptr,
+				 rb_unblock_function_t **oldfunc, void **oldptr);
 
 #define GVL_UNLOCK_BEGIN() do { \
   rb_thread_t *_th_stored = GET_THREAD(); \
@@ -92,10 +93,12 @@
   rb_thread_set_current(_th_stored); \
 } while(0)
 
-#define BLOCKING_REGION(exec, ubf) do { \
+#define BLOCKING_REGION(exec, ubf, ubfarg) do { \
     rb_thread_t *__th = GET_THREAD(); \
     int __prev_status = __th->status; \
-    rb_unblock_function_t *__oldubf = set_unblock_function(__th, ubf); \
+    rb_unblock_function_t *__oldubf; \
+    void *__oldubfarg; \
+    set_unblock_function(__th, ubf, ubfarg, &__oldubf, &__oldubfarg); \
     __th->status = THREAD_STOPPED; \
     thread_debug("enter blocking region (%p)\n", __th); \
     GVL_UNLOCK_BEGIN(); {\
@@ -104,7 +107,7 @@
     GVL_UNLOCK_END(); \
     thread_debug("leave blocking region (%p)\n", __th); \
     remove_signal_thread_list(__th); \
-    set_unblock_function(__th, __oldubf); \
+    set_unblock_function(__th, __oldubf, __oldubfarg, 0, 0); \
     if (__th->status == THREAD_STOPPED) { \
 	__th->status = __prev_status; \
     } \
@@ -191,11 +194,10 @@
 #endif
 
 
-static rb_unblock_function_t *
-set_unblock_function(rb_thread_t *th, rb_unblock_function_t *func)
+static void
+set_unblock_function(rb_thread_t *th, rb_unblock_function_t *func, void *arg,
+		     rb_unblock_function_t **oldfunc, void **oldarg)
 {
-    rb_unblock_function_t *oldfunc;
-
   check_ints:
     RUBY_VM_CHECK_INTS(); /* check signal or so */
     native_mutex_lock(&th->interrupt_lock);
@@ -204,12 +206,12 @@
 	goto check_ints;
     }
     else {
-	oldfunc = th->unblock_function;
+	if (oldfunc) *oldfunc = th->unblock_function;
+	if (oldarg) *oldarg = th->unblock_function_arg;
 	th->unblock_function = func;
+	th->unblock_function_arg = arg;
     }
     native_mutex_unlock(&th->interrupt_lock);
-
-    return oldfunc;
 }
 
 static void
@@ -218,7 +220,7 @@
     native_mutex_lock(&th->interrupt_lock);
     th->interrupt_flag = 1;
     if (th->unblock_function) {
-	(th->unblock_function)(th);
+	(th->unblock_function)(th, th->unblock_function_arg);
     }
     else {
 	/* none */
@@ -661,8 +663,8 @@
 
 VALUE
 rb_thread_blocking_region(
-    rb_blocking_function_t *func, void *data,
-    rb_unblock_function_t *ubf)
+    rb_blocking_function_t *func, void *data1,
+    rb_unblock_function_t *ubf, void *data2)
 {
     VALUE val;
     rb_thread_t *th = GET_THREAD();
@@ -670,9 +672,10 @@
     if (ubf == RB_UBF_DFL) {
 	ubf = ubf_select;
     }
+
     BLOCKING_REGION({
-	val = func(th, data);
-    }, ubf);
+	val = func(th, data1);
+    }, ubf, data2);
 
     return val;
 }
@@ -1747,14 +1750,14 @@
 		    if (except) *except = orig_except;
 		    wait = &wait_100ms;
 		} while (__th->interrupt_flag == 0 && (timeout == 0 || subst(timeout, &wait_100ms)));
-	    }, 0);
+	    }, 0, 0);
 	} while (result == 0 && (timeout == 0 || subst(timeout, &wait_100ms)));
     }
 #else
     BLOCKING_REGION({
 	result = select(n, read, write, except, timeout);
 	if (result < 0) lerrno = errno;
-    }, ubf_select);
+    }, ubf_select, 0);
 #endif
 
     errno = lerrno;
@@ -2146,11 +2149,13 @@
  */
 
 typedef struct mutex_struct {
-    rb_thread_t *th;
     rb_thread_lock_t lock;
+    rb_thread_cond_t cond;
+    rb_thread_t volatile *th;
+    volatile int cond_waiting;
 } mutex_t;
 
-#define GetMutexVal(obj, tobj) \
+#define GetMutexPtr(obj, tobj) \
   Data_Get_Struct(obj, mutex_t, tobj)
 
 static void
@@ -2169,10 +2174,8 @@
 {
     if (ptr) {
 	mutex_t *mutex = ptr;
-	if (mutex->th) {
-	    native_mutex_unlock(&mutex->lock);
-	}
 	native_mutex_destroy(&mutex->lock);
+	native_cond_destroy(&mutex->cond);
     }
     ruby_xfree(ptr);
 }
@@ -2184,8 +2187,8 @@
     mutex_t *mutex;
 
     obj = Data_Make_Struct(klass, mutex_t, mutex_mark, mutex_free, mutex);
-    mutex->th = 0;
     native_mutex_initialize(&mutex->lock);
+    native_cond_initialize(&mutex->cond);
     return obj;
 }
 
@@ -2217,7 +2220,7 @@
 rb_mutex_locked_p(VALUE self)
 {
     mutex_t *mutex;
-    GetMutexVal(self, mutex);
+    GetMutexPtr(self, mutex);
     return mutex->th ? Qtrue : Qfalse;
 }
 
@@ -2229,24 +2232,69 @@
  * lock was granted.
  */
 VALUE
-rb_mutex_try_lock(VALUE self)
+rb_mutex_trylock(VALUE self)
 {
     mutex_t *mutex;
-    GetMutexVal(self, mutex);
+    VALUE locked = Qfalse;
+    GetMutexPtr(self, mutex);
 
     if (mutex->th == GET_THREAD()) {
 	rb_raise(rb_eThreadError, "deadlock; recursive locking");
     }
 
-    if (native_mutex_trylock(&mutex->lock) != EBUSY) {
+    native_mutex_lock(&mutex->lock);
+    if (mutex->th == 0) {
 	mutex->th = GET_THREAD();
-	return Qtrue;
+	locked = Qtrue;
     }
-    else {
-	return Qfalse;
+    native_mutex_unlock(&mutex->lock);
+
+    return locked;
+}
+
+static VALUE
+lock_func(rb_thread_t *th, void *ptr)
+{
+    int locked = 0;
+    mutex_t *mutex = (mutex_t *)ptr;
+
+    while (locked == 0) {
+	native_mutex_lock(&mutex->lock);
+
+	if (mutex->th == 0) {
+	    mutex->th = th;
+	    locked = 1;
+	}
+	else {
+	    mutex->cond_waiting++;
+	    native_cond_wait(&mutex->cond, &mutex->lock);
+
+	    if (th->interrupt_flag) {
+		locked = 1;
+	    }
+	    else if (mutex->th == 0) {
+		mutex->th = th;
+		locked = 1;
+	    }
+	}
+
+	native_mutex_unlock(&mutex->lock);
     }
+    return Qnil;
 }
 
+static void
+lock_interrupt(rb_thread_t *th, void *ptr)
+{
+    mutex_t *mutex = (mutex_t *)ptr;
+    native_mutex_lock(&mutex->lock);
+    if (mutex->cond_waiting > 0) {
+	native_cond_broadcast(&mutex->cond);
+	mutex->cond_waiting = 0;
+    }
+    native_mutex_unlock(&mutex->lock);
+}
+
 /*
  * call-seq:
  *    mutex.lock  => true or false
@@ -2257,21 +2305,17 @@
 VALUE
 rb_mutex_lock(VALUE self)
 {
-    mutex_t *mutex;
-    GetMutexVal(self, mutex);
+    if (rb_mutex_trylock(self) == Qfalse) {
+	mutex_t *mutex;
+	rb_thread_t *th = GET_THREAD();
+	GetMutexPtr(self, mutex);
 
-    if (mutex->th == GET_THREAD()) {
-	rb_raise(rb_eThreadError, "deadlock; recursive locking");
+	while (mutex->th != th) {
+	    rb_thread_blocking_region(lock_func, mutex, lock_interrupt, mutex);
+	    RUBY_VM_CHECK_INTS();
+	}
     }
 
-    if (native_mutex_trylock(&mutex->lock) != 0) {
-	/* can't cancel */
-	GVL_UNLOCK_BEGIN();
-	native_mutex_lock(&mutex->lock);
-	GVL_UNLOCK_END();
-    }
-
-    mutex->th = GET_THREAD();
     return self;
 }
 
@@ -2286,14 +2330,22 @@
 rb_mutex_unlock(VALUE self)
 {
     mutex_t *mutex;
-    GetMutexVal(self, mutex);
+    GetMutexPtr(self, mutex);
 
     if (mutex->th != GET_THREAD()) {
 	rb_raise(rb_eThreadError,
 		 "Attempt to unlock a mutex which is locked by another thread");
     }
+
+    native_mutex_lock(&mutex->lock);
     mutex->th = 0;
+    if (mutex->cond_waiting > 0) {
+	/* waiting thread */
+	native_cond_signal(&mutex->cond);
+	mutex->cond_waiting--;
+    }
     native_mutex_unlock(&mutex->lock);
+
     return self;
 }
 
@@ -2963,7 +3015,7 @@
     rb_define_alloc_func(rb_cMutex, mutex_alloc);
     rb_define_method(rb_cMutex, "initialize", mutex_initialize, 0);
     rb_define_method(rb_cMutex, "locked?", rb_mutex_locked_p, 0);
-    rb_define_method(rb_cMutex, "try_lock", rb_mutex_try_lock, 0);
+    rb_define_method(rb_cMutex, "try_lock", rb_mutex_trylock, 0);
     rb_define_method(rb_cMutex, "lock", rb_mutex_lock, 0);
     rb_define_method(rb_cMutex, "unlock", rb_mutex_unlock, 0);
     rb_define_method(rb_cMutex, "sleep", mutex_sleep, -1);
Index: common.mk
===================================================================
--- common.mk	(revision 13289)
+++ common.mk	(revision 13290)
@@ -655,10 +655,10 @@
 	$(MINIRUBY) $(srcdir)/tool/parse.rb $(srcdir)/test.rb
 
 benchmark: $(PROGRAM) PHONY
-	$(RUNRUBY) $(srcdir)/benchmark/run.rb $(OPT) $(ITEMS) --ruby=./$(PROGRAM) --matzruby=$(MATZRUBY) --opts=-I$(srcdir)/lib
+	$(RUNRUBY) $(srcdir)/benchmark/run.rb $(OPT) $(ITEMS) --ruby=`./$(PROGRAM)  -I$(srcdir)/lib' --matzruby=$(MATZRUBY)
 
 benchmark-each: $(PROGRAM) PHONY
-	$(RUNRUBY) $(srcdir)/benchmark/run.rb bm_$(ITEM) $(OPT) --ruby=./$(PROGRAM) --matzruby=$(MATZRUBY) --opts=-I$(srcdir)/lib
+	$(RUNRUBY) $(srcdir)/benchmark/run.rb bm_$(ITEM) $(OPT) --ruby='./$(PROGRAM) -I$(srcdir)/lib' --matzruby=$(MATZRUBY)
 
 tbench: $(PROGRAM) PHONY
 	$(RUNRUBY) $(srcdir)/benchmark/run.rb bmx $(OPT) --ruby=./$(PROGRAM) --matzruby=$(MATZRUBY) --opts=-I$(srcdir)/lib
Index: process.c
===================================================================
--- process.c	(revision 13289)
+++ process.c	(revision 13290)
@@ -606,8 +606,8 @@
     arg.st = st;
     arg.flags = flags;
   retry:
-    result = (rb_pid_t)rb_thread_blocking_region(rb_waitpid_blocking,
-						 &arg, RB_UBF_DFL);
+    result = (rb_pid_t)rb_thread_blocking_region(rb_waitpid_blocking, &arg,
+						 RB_UBF_DFL, 0);
     if (result < 0) {
 #if 0
 	if (errno == EINTR) {
Index: thread_pthread.ci
===================================================================
--- thread_pthread.ci	(revision 13289)
+++ thread_pthread.ci	(revision 13290)
@@ -39,7 +39,7 @@
 	    return EBUSY;
 	}
 	else {
-	    rb_bug("native_mutex_unlock return non-zero: %d", r);
+	    rb_bug("native_mutex_trylock return non-zero: %d", r);
 	}
     }
     return 0;
@@ -63,6 +63,43 @@
     }
 }
 
+void
+native_cond_initialize(pthread_cond_t *cond)
+{
+    int r = pthread_cond_init(cond, 0);
+    if (r != 0) {
+	rb_bug("native_cond_initialize return non-zero: %d", r);
+    }
+}
+
+void
+native_cond_destroy(pthread_cond_t *cond)
+{
+    int r = pthread_cond_destroy(cond);
+    if (r != 0) {
+	rb_bug("native_cond_destroy return non-zero: %d", r);
+    }
+}
+
+void
+native_cond_signal(pthread_cond_t *cond)
+{
+    pthread_cond_signal(cond);
+}
+
+void
+native_cond_broadcast(pthread_cond_t *cond)
+{
+    pthread_cond_broadcast(cond);
+}
+
+void
+native_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex)
+{
+    pthread_cond_wait(cond, mutex);
+}
+
+
 #define native_cleanup_push pthread_cleanup_push
 #define native_cleanup_pop  pthread_cleanup_pop
 #define native_thread_yield() sched_yield()
@@ -309,7 +346,7 @@
 }
 
 static void
-ubf_pthread_cond_signal(rb_thread_t *th)
+ubf_pthread_cond_signal(rb_thread_t *th, void *ptr)
 {
     thread_debug("ubf_pthread_cond_signal (%p)\n", th);
     pthread_cond_signal(&th->native_thread_data.sleep_cond);
@@ -326,7 +363,7 @@
 }
 
 static void
-ubf_select(rb_thread_t *th)
+ubf_select(rb_thread_t *th, void *ptr)
 {
     add_signal_thread_list(th);
     ubf_select_each(th);
Index: version.h
===================================================================
--- version.h	(revision 13289)
+++ version.h	(revision 13290)
@@ -1,7 +1,7 @@
 #define RUBY_VERSION "1.9.0"
-#define RUBY_RELEASE_DATE "2007-08-27"
+#define RUBY_RELEASE_DATE "2007-08-28"
 #define RUBY_VERSION_CODE 190
-#define RUBY_RELEASE_CODE 20070827
+#define RUBY_RELEASE_CODE 20070828
 #define RUBY_PATCHLEVEL 0
 
 #define RUBY_VERSION_MAJOR 1
@@ -9,7 +9,7 @@
 #define RUBY_VERSION_TEENY 0
 #define RUBY_RELEASE_YEAR 2007
 #define RUBY_RELEASE_MONTH 8
-#define RUBY_RELEASE_DAY 27
+#define RUBY_RELEASE_DAY 28
 
 #ifdef RUBY_EXTERN
 RUBY_EXTERN const char ruby_version[];
Index: benchmark/bm_vm3_thread_mutex.rb
===================================================================
--- benchmark/bm_vm3_thread_mutex.rb	(revision 0)
+++ benchmark/bm_vm3_thread_mutex.rb	(revision 13290)
@@ -0,0 +1,18 @@
+require 'thread'
+m = Mutex.new
+r = 0
+max = 1000
+(1..max).map{
+  Thread.new{
+    i=0
+    while i<max
+      i+=1
+      m.synchronize{
+        r += 1
+      }
+    end
+  }
+}.each{|e|
+  e.join
+}
+raise r.to_s if r != max * max

Property changes on: benchmark/bm_vm3_thread_mutex.rb
___________________________________________________________________
Name: svn:eol-style
   + LF

Index: benchmark/bm_vm2_mutex.rb
===================================================================
--- benchmark/bm_vm2_mutex.rb	(revision 0)
+++ benchmark/bm_vm2_mutex.rb	(revision 13290)
@@ -0,0 +1,9 @@
+require 'thread'
+
+m = Mutex.new
+
+i=0
+while i<6000000 # benchmark loop 2
+  i+=1
+  m.synchronize{}
+end

Property changes on: benchmark/bm_vm2_mutex.rb
___________________________________________________________________
Name: svn:eol-style
   + LF

Index: benchmark/run.rb
===================================================================
--- benchmark/run.rb	(revision 13289)
+++ benchmark/run.rb	(revision 13290)
@@ -68,7 +68,11 @@
 
 def matzruby_exec file
   print 'matz'
-  benchmark file, $matzruby_program
+  rubylib = ENV['RUBYLIB']
+  ENV['RUBYLIB'] = ''
+  r = benchmark file, $matzruby_program
+  ENV['RUBYLIB'] = rubylib
+  r
 end
 
 if $0 == __FILE__
Index: benchmark/bm_vm2_case.rb
===================================================================
--- benchmark/bm_vm2_case.rb	(revision 13289)
+++ benchmark/bm_vm2_case.rb	(revision 13290)
@@ -1,14 +1,14 @@
-i=0
-while i<6000000 # while loop 2
-  case :foo
-  when :bar
-    raise
-  when :baz
-    raise
-  when :boo
-    raise
-  when :foo
-    i+=1
-  end
-end
-
+i=0
+while i<6000000 # while loop 2
+  case :foo
+  when :bar
+    raise
+  when :baz
+    raise
+  when :boo
+    raise
+  when :foo
+    i+=1
+  end
+end
+

Property changes on: benchmark/bm_vm2_case.rb
___________________________________________________________________
Name: svn:eol-style
   + LF

Index: benchmark/bm_loop_generator.rb
===================================================================
--- benchmark/bm_loop_generator.rb	(revision 13289)
+++ benchmark/bm_loop_generator.rb	(revision 13290)
@@ -1,14 +1,14 @@
-max = 600000
-
-if defined? Fiber
-  gen = (1..max).each
-  loop do
-    gen.next
-  end
-else
-  require 'generator'
-  gen = Generator.new((0..max))
-  while gen.next?
-    gen.next
-  end
-end
+max = 600000
+
+if defined? Fiber
+  gen = (1..max).each
+  loop do
+    gen.next
+  end
+else
+  require 'generator'
+  gen = Generator.new((0..max))
+  while gen.next?
+    gen.next
+  end
+end

Property changes on: benchmark/bm_loop_generator.rb
___________________________________________________________________
Name: svn:eol-style
   + LF

Index: benchmark/bmx_temp.rb
===================================================================

Property changes on: benchmark/bmx_temp.rb
___________________________________________________________________
Name: svn:eol-style
   + LF

Index: test/ruby/test_thread.rb
===================================================================
--- test/ruby/test_thread.rb	(revision 0)
+++ test/ruby/test_thread.rb	(revision 13290)
@@ -0,0 +1,24 @@
+require 'test/unit'
+
+class TestThread < Test::Unit::TestCase
+  def test_mutex_synchronize
+    m = Mutex.new
+    r = 0
+    max = 100
+    (1..max).map{
+      Thread.new{
+        i=0
+        while i<max*max
+          i+=1
+          m.synchronize{
+            r += 1
+          }
+        end
+      }
+    }.each{|e|
+      e.join
+    }
+    assert_equal(max * max * max, r)
+  end
+end
+

Property changes on: test/ruby/test_thread.rb
___________________________________________________________________
Name: svn:eol-style
   + LF

Index: thread_win32.ci
===================================================================
--- thread_win32.ci	(revision 13289)
+++ thread_win32.ci	(revision 13290)
@@ -122,7 +122,7 @@
     return ret;
 }
 
-static void ubf_handle(rb_thread_t *th);
+static void ubf_handle(rb_thread_t *th, void *ptr);
 #define ubf_select ubf_handle
 
 int
@@ -136,7 +136,7 @@
 {
     int ret;
 
-    BLOCKING_REGION(ret = rb_w32_wait_events_blocking(events, num, timeout), ubf_handle);
+    BLOCKING_REGION(ret = rb_w32_wait_events_blocking(events, num, timeout), ubf_handle, 0);
     return ret;
 }
 
@@ -187,7 +187,7 @@
 {
     int ret;
 
-    BLOCKING_REGION(ret = rb_w32_sleep(msec), ubf_handle);
+    BLOCKING_REGION(ret = rb_w32_sleep(msec), ubf_handle, 0);
     return ret;
 }
 
@@ -309,7 +309,88 @@
 #endif
 }
 
+struct cond_event_entry {
+    struct cond_event_entry* next;
+    HANDLE event;
+};
 
+struct rb_thread_cond_struct {
+    struct cond_event_entry *next;
+    struct cond_event_entry *last;
+};
+
+void
+native_cond_signal(rb_thread_cond_t *cond)
+{
+    /* cond is guarded by mutex */
+    struct cond_event_entry *e = cond->next;
+
+    if (e) {
+	cond->next = e->next;
+	SetEvent(e->event);
+    }
+    else {
+	rb_bug("native_cond_signal: no pending threads");
+    }
+}
+
+void
+native_cond_broadcast(rb_thread_cond_t *cond)
+{
+    /* cond is guarded by mutex */
+    struct cond_event_entry *e = cond->next;
+    cond->next = 0;
+
+    while (e) {
+	SetEvent(e->event);
+	e = e->next;
+    }
+}
+
+void
+native_cond_wait(rb_thread_cond_t *cond, rb_thread_lock_t *mutex)
+{
+    DWORD r;
+    struct cond_event_entry entry;
+
+    entry.next = 0;
+    entry.event = CreateEvent(0, FALSE, FALSE, 0);
+
+    /* cond is guarded by mutex */
+    if (cond->next) {
+	cond->last->next = &entry;
+	cond->last = &entry;
+    }
+    else {
+	cond->next = &entry;
+	cond->last = &entry;
+    }
+
+    native_mutex_unlock(mutex);
+    {
+	r = WaitForSingleObject(entry.event, INFINITE);
+	if (r != WAIT_OBJECT_0) {
+	    rb_bug("native_cond_wait: WaitForSingleObject returns %d", r);
+	}
+    }
+    native_mutex_lock(mutex);
+
+    w32_close_handle(entry.event);
+}
+
+void
+native_cond_initialize(rb_thread_cond_t *cond)
+{
+    cond->next = 0;
+    cond->last = 0;
+}
+
+void
+native_cond_destroy(rb_thread_cond_t *cond)
+{
+    /* */
+}
+
 static void
 native_thread_destroy(rb_thread_t *th)
 {
@@ -384,7 +465,7 @@
 }
 
 static void
-ubf_handle(rb_thread_t *th)
+ubf_handle(rb_thread_t *th, void *ptr)
 {
     thread_debug("ubf_handle: %p\n", th);
     w32_set_event(th->native_thread_data.interrupt_event);
Index: file.c
===================================================================
--- file.c	(revision 13289)
+++ file.c	(revision 13290)
@@ -3148,7 +3148,7 @@
     if (fptr->mode & FMODE_WRITABLE) {
 	rb_io_flush(obj);
     }
-    while ((int)rb_thread_blocking_region(rb_thread_flock, op, RB_UBF_DFL) < 0) {
+    while ((int)rb_thread_blocking_region(rb_thread_flock, op, RB_UBF_DFL, 0) < 0) {
 	switch (errno) {
 	  case EAGAIN:
 	  case EACCES:

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

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