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

ruby-changes:8694

From: nobu <ko1@a...>
Date: Thu, 13 Nov 2008 06:09:03 +0900 (JST)
Subject: [ruby-changes:8694] Ruby:r20229 (trunk): * thread.c (rb_barrier_{new,wait,release,destroy}): use Mutex so that

nobu	2008-11-13 06:08:47 +0900 (Thu, 13 Nov 2008)

  New Revision: 20229

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

  Log:
    * thread.c (rb_barrier_{new,wait,release,destroy}): use Mutex so that
      circular requires fail with deadlock.  [ruby-core:19821]

  Modified files:
    trunk/ChangeLog
    trunk/thread.c
    trunk/version.h

Index: ChangeLog
===================================================================
--- ChangeLog	(revision 20228)
+++ ChangeLog	(revision 20229)
@@ -1,3 +1,8 @@
+Thu Nov 13 06:08:44 2008  Nobuyoshi Nakada  <nobu@r...>
+
+	* thread.c (rb_barrier_{new,wait,release,destroy}): use Mutex so that
+	  circular requires fail with deadlock.  [ruby-core:19821]
+
 Wed Nov 12 07:16:01 2008  David Flanagan  <david@think32>
 
 	* ruby.c (set_internal_encoding_once): fix typo in error string
Index: thread.c
===================================================================
--- thread.c	(revision 20228)
+++ thread.c	(revision 20229)
@@ -3032,164 +3032,44 @@
 /*
  * Document-class: Barrier
  */
-typedef struct rb_thread_list_struct rb_thread_list_t;
-
-struct rb_thread_list_struct {
-    rb_thread_t *th;
-    rb_thread_list_t *next;
-};
-
-static void
-thlist_mark(void *ptr)
-{
-    rb_thread_list_t *q = ptr;
-
-    for (; q; q = q->next) {
-	rb_gc_mark(q->th->self);
-    }
-}
-
-static void
-thlist_free(void *ptr)
-{
-    rb_thread_list_t *q = ptr, *next;
-
-    for (; q; q = next) {
-	next = q->next;
-	ruby_xfree(q);
-    }
-}
-
-static int
-thlist_signal(rb_thread_list_t **list, unsigned int maxth, rb_thread_t **woken_thread)
-{
-    int woken = 0;
-    rb_thread_list_t *q;
-
-    while ((q = *list) != NULL) {
-	rb_thread_t *th = q->th;
-
-	*list = q->next;
-	ruby_xfree(q);
-	if (th->status != THREAD_KILLED) {
-	    rb_thread_ready(th);
-	    if (!woken && woken_thread) *woken_thread = th;
-	    if (++woken >= maxth && maxth) break;
-	}
-    }
-    if (!woken && woken_thread) *woken_thread = 0;
-    return woken;
-}
-
-typedef struct {
-    rb_thread_t *owner;
-    rb_thread_list_t *waiting, **tail;
-} rb_barrier_t;
-
-static void
-barrier_mark(void *ptr)
-{
-    rb_barrier_t *b = ptr;
-
-    if (b->owner) rb_gc_mark(b->owner->self);
-    thlist_mark(b->waiting);
-}
-
-static void
-barrier_free(void *ptr)
-{
-    rb_barrier_t *b = ptr;
-
-    b->owner = 0;
-    thlist_free(b->waiting);
-    b->waiting = 0;
-    ruby_xfree(ptr);
-}
-
 static VALUE
 barrier_alloc(VALUE klass)
 {
-    VALUE volatile obj;
-    rb_barrier_t *barrier;
-
-    obj = Data_Make_Struct(klass, rb_barrier_t, barrier_mark, barrier_free, barrier);
-    barrier->owner = GET_THREAD();
-    barrier->waiting = 0;
-    barrier->tail = &barrier->waiting;
-    return obj;
+    return Data_Wrap_Struct(klass, rb_gc_mark, 0, (void *)mutex_alloc(0));
 }
 
 VALUE
 rb_barrier_new(void)
 {
-    return barrier_alloc(rb_cBarrier);
+    VALUE barrier = barrier_alloc(rb_cBarrier);
+    rb_mutex_lock((VALUE)DATA_PTR(barrier));
+    return barrier;
 }
 
-static int
-rb_barrier_signal(rb_barrier_t *barrier, unsigned int maxth)
-{
-    int n = thlist_signal(&barrier->waiting, maxth, &barrier->owner);
-    if (!barrier->waiting) barrier->tail = &barrier->waiting;
-    return n;
-}
-
 VALUE
 rb_barrier_wait(VALUE self)
 {
-    rb_barrier_t *barrier;
-    rb_thread_list_t *q;
-    rb_thread_t *th = GET_THREAD();
+    VALUE mutex = (VALUE)DATA_PTR(self);
 
-    Data_Get_Struct(self, rb_barrier_t, barrier);
-    if (!barrier->tail) return Qfalse;
-    if (!barrier->owner || barrier->owner->status == THREAD_KILLED) {
-	barrier->owner = 0;
-	if (rb_barrier_signal(barrier, 1)) return Qfalse;
-	barrier->owner = th;
-	return Qtrue;
-    }
-    else if (barrier->owner == th) {
-	return Qfalse;
-    }
-    else {
-	*barrier->tail = q = ALLOC(rb_thread_list_t);
-	q->th = th;
-	q->next = 0;
-	barrier->tail = &q->next;
-	rb_thread_sleep_forever();
-	if (!barrier->tail) return Qfalse;
-	return barrier->owner == th ? Qtrue : Qfalse;
-    }
+    if (!mutex) return Qfalse;
+    rb_mutex_lock(mutex);
+    if (DATA_PTR(self)) return Qtrue;
+    rb_mutex_unlock(mutex);
+    return Qfalse;
 }
 
-static rb_barrier_t *
-rb_barrier_owned_ptr(VALUE self)
-{
-    rb_barrier_t *barrier;
-
-    Data_Get_Struct(self, rb_barrier_t, barrier);
-    if (barrier->owner != GET_THREAD()) {
-	rb_raise(rb_eThreadError, "not owned");
-    }
-    return barrier;
-}
-
 VALUE
 rb_barrier_release(VALUE self)
 {
-    rb_barrier_t *barrier = rb_barrier_owned_ptr(self);
-    unsigned int n = rb_barrier_signal(barrier, 0);
-    return n ? UINT2NUM(n) : Qfalse;
+    return rb_mutex_unlock((VALUE)DATA_PTR(self));
 }
 
 VALUE
 rb_barrier_destroy(VALUE self)
 {
-    rb_barrier_t *barrier = rb_barrier_owned_ptr(self);
-    int n = thlist_signal(&barrier->waiting, 0, 0);
-    barrier->owner = 0;
-    barrier->tail = 0;
-    return n ? UINT2NUM(n) : Qfalse;
+    VALUE mutex = (VALUE)DATA_PTR(self);
+    DATA_PTR(self) = 0;
+    return rb_mutex_unlock(mutex);
 }
 
 /* variables for recursive traversals */
Index: version.h
===================================================================
--- version.h	(revision 20228)
+++ version.h	(revision 20229)
@@ -1,7 +1,7 @@
 #define RUBY_VERSION "1.9.0"
-#define RUBY_RELEASE_DATE "2008-11-12"
+#define RUBY_RELEASE_DATE "2008-11-13"
 #define RUBY_VERSION_CODE 190
-#define RUBY_RELEASE_CODE 20081112
+#define RUBY_RELEASE_CODE 20081113
 #define RUBY_PATCHLEVEL 0
 
 #define RUBY_VERSION_MAJOR 1
@@ -9,7 +9,7 @@
 #define RUBY_VERSION_TEENY 0
 #define RUBY_RELEASE_YEAR 2008
 #define RUBY_RELEASE_MONTH 11
-#define RUBY_RELEASE_DAY 12
+#define RUBY_RELEASE_DAY 13
 
 #ifdef RUBY_EXTERN
 RUBY_EXTERN const char ruby_version[];

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

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