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

ruby-changes:25880

From: tarui <ko1@a...>
Date: Wed, 28 Nov 2012 21:34:25 +0900 (JST)
Subject: [ruby-changes:25880] tarui:r37937 (trunk): * thread.c (thread_join_sleep): check spurious wakeup by itself for

tarui	2012-11-28 21:34:15 +0900 (Wed, 28 Nov 2012)

  New Revision: 37937

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

  Log:
    * thread.c (thread_join_sleep): check spurious wakeup by itself for
    corresponding status change in trap context.
    * vm_core.h (struct rb_thread_struct): add rb_thread_list_t and use as join_list for
    reentry by trap context.
    * thread.c (thread_start_func_2): ditto.
    * thread.c (remove_from_join_list): ditto.
    * thread.c (rb_thread_atfork): ditto.
    * thread.c (thread_join): ditto. & remove trap handler check.
    * thread.c (sleep_forever): add argument : spurious_check.
    * thread.c (sleep_timeval): ditto.
    * thread.c (rb_thread_sleep_forever): set spurious_check.
    * thread.c (rb_thread_sleep_deadly): ditto.
    * thread.c (sleep_for_polling): ditto.
    * thread.c (rb_thread_wait_for): ditto.
    * thread.c (sleep_wait_for_interrupt): bypass spurious_check.

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

Index: ChangeLog
===================================================================
--- ChangeLog	(revision 37936)
+++ ChangeLog	(revision 37937)
@@ -1,3 +1,21 @@
+Wed Nov 28 21:31:21 2012  Masaya Tarui  <tarui@r...>
+
+	* thread.c (thread_join_sleep): check spurious wakeup by itself for
+	corresponding status change in trap context.
+	* vm_core.h (struct rb_thread_struct): add rb_thread_list_t and use as join_list for
+	reentry by trap context.
+	* thread.c (thread_start_func_2): ditto.
+	* thread.c (remove_from_join_list): ditto.
+	* thread.c (rb_thread_atfork): ditto.
+	* thread.c (thread_join): ditto. & remove trap handler check.
+	* thread.c (sleep_forever): add argument : spurious_check.
+	* thread.c (sleep_timeval): ditto.
+	* thread.c (rb_thread_sleep_forever): set spurious_check.
+	* thread.c (rb_thread_sleep_deadly): ditto.
+	* thread.c (sleep_for_polling): ditto.
+	* thread.c (rb_thread_wait_for): ditto.
+	* thread.c (sleep_wait_for_interrupt): bypass spurious_check.
+
 Wed Nov 28 21:23:18 2012  Nobuyoshi Nakada  <nobu@r...>
 
 	* ext/psych/yaml/emitter.c (yaml_emitter_write_indicator): constify.
Index: vm_core.h
===================================================================
--- vm_core.h	(revision 37936)
+++ vm_core.h	(revision 37937)
@@ -457,6 +457,13 @@
 #define ALT_STACK_SIZE (4*1024)
 #endif
 
+struct rb_thread_struct;
+typedef struct rb_thread_list_struct{
+    struct rb_thread_list_struct *next;
+    struct rb_thread_struct *th;
+} rb_thread_list_t;
+
+
 typedef struct rb_thread_struct {
     VALUE self;
     rb_vm_t *vm;
@@ -546,8 +553,7 @@
     /* storage */
     st_table *local_storage;
 
-    struct rb_thread_struct *join_list_next;
-    struct rb_thread_struct *join_list_head;
+    rb_thread_list_t *join_list;
 
     VALUE first_proc;
     VALUE first_args;
Index: thread.c
===================================================================
--- thread.c	(revision 37936)
+++ thread.c	(revision 37937)
@@ -63,9 +63,9 @@
 VALUE rb_cMutex;
 VALUE rb_cThreadShield;
 
-static void sleep_timeval(rb_thread_t *th, struct timeval time);
-static void sleep_wait_for_interrupt(rb_thread_t *th, double sleepsec);
-static void sleep_forever(rb_thread_t *th, int nodeadlock);
+static void sleep_timeval(rb_thread_t *th, struct timeval time, int spurious_check);
+static void sleep_wait_for_interrupt(rb_thread_t *th, double sleepsec, int spurious_check);
+static void sleep_forever(rb_thread_t *th, int nodeadlock, int spurious_check);
 static double timeofday(void);
 static int rb_threadptr_dead(rb_thread_t *th);
 static void rb_check_deadlock(rb_vm_t *vm);
@@ -443,7 +443,7 @@
     int state;
     VALUE args = th->first_args;
     rb_proc_t *proc;
-    rb_thread_t *join_th;
+    rb_thread_list_t *join_list;
     rb_thread_t *main_th;
     VALUE errinfo = Qnil;
 # ifdef USE_SIGALTSTACK
@@ -532,16 +532,16 @@
 	}
 
 	/* wake up joining threads */
-	join_th = th->join_list_head;
-	while (join_th) {
-	    if (join_th == main_th) errinfo = Qnil;
-	    rb_threadptr_interrupt(join_th);
-	    switch (join_th->status) {
+	join_list = th->join_list;
+	while (join_list) {
+	    if (join_list->th == main_th) errinfo = Qnil;
+	    rb_threadptr_interrupt(join_list->th);
+	    switch (join_list->th->status) {
 	      case THREAD_STOPPED: case THREAD_STOPPED_FOREVER:
-		join_th->status = THREAD_RUNNABLE;
+		join_list->th->status = THREAD_RUNNABLE;
 	      default: break;
 	    }
-	    join_th = join_th->join_list_next;
+	    join_list = join_list->next;
 	}
 
 	rb_threadptr_unlock_all_locking_mutexes(th);
@@ -686,14 +686,14 @@
     rb_thread_t *target_th = p->target, *th = p->waiting;
 
     if (target_th->status != THREAD_KILLED) {
-	rb_thread_t **pth = &target_th->join_list_head;
+	rb_thread_list_t **p = &target_th->join_list;
 
-	while (*pth) {
-	    if (*pth == th) {
-		*pth = th->join_list_next;
+	while (*p) {
+	    if ((*p)->th == th) {
+		*p = (*p)->next;
 		break;
 	    }
-	    pth = &(*pth)->join_list_next;
+	    p = &(*p)->next;
 	}
     }
 
@@ -709,7 +709,7 @@
 
     while (target_th->status != THREAD_KILLED) {
 	if (p->forever) {
-	    sleep_forever(th, 1);
+	    sleep_forever(th, 1, 0);
 	}
 	else {
 	    now = timeofday();
@@ -718,7 +718,7 @@
 			     (void *)target_th->thread_id);
 		return Qfalse;
 	    }
-	    sleep_wait_for_interrupt(th, limit - now);
+	    sleep_wait_for_interrupt(th, limit - now, 0);
 	}
 	thread_debug("thread_join: interrupted (thid: %p)\n",
 		     (void *)target_th->thread_id);
@@ -738,10 +738,6 @@
     if (GET_VM()->main_thread == target_th) {
 	rb_raise(rb_eThreadError, "Target thread must not be main thread");
     }
-    /* When running trap handler */
-    if (th->interrupt_mask & TRAP_INTERRUPT_MASK) {
-	rb_raise(rb_eThreadError, "can't be called from trap context");
-    }
 
     arg.target = target_th;
     arg.waiting = th;
@@ -751,8 +747,10 @@
     thread_debug("thread_join (thid: %p)\n", (void *)target_th->thread_id);
 
     if (target_th->status != THREAD_KILLED) {
-	th->join_list_next = target_th->join_list_head;
-	target_th->join_list_head = th;
+	rb_thread_list_t list;
+	list.next = target_th->join_list;
+	list.th = th;
+	target_th->join_list = &list;
 	if (!rb_ensure(thread_join_sleep, (VALUE)&arg,
 		       remove_from_join_list, (VALUE)&arg)) {
 	    return Qnil;
@@ -876,7 +874,7 @@
 }
 
 static void
-sleep_forever(rb_thread_t *th, int deadlockable)
+sleep_forever(rb_thread_t *th, int deadlockable,int spurious_check)
 {
     enum rb_thread_status prev_status = th->status;
     enum rb_thread_status status = deadlockable ? THREAD_STOPPED_FOREVER : THREAD_STOPPED;
@@ -892,7 +890,7 @@
 	    th->vm->sleeper--;
 	}
 	RUBY_VM_CHECK_INTS_BLOCKING(th);
-    } while (th->status == status);
+    } while (spurious_check && th->status == status);
     th->status = prev_status;
 }
 
@@ -913,7 +911,7 @@
 }
 
 static void
-sleep_timeval(rb_thread_t *th, struct timeval tv)
+sleep_timeval(rb_thread_t *th, struct timeval tv,int spurious_check)
 {
     struct timeval to, tvn;
     enum rb_thread_status prev_status = th->status;
@@ -940,7 +938,7 @@
 	    --tv.tv_sec;
 	    tv.tv_usec += 1000000;
 	}
-    } while (th->status == THREAD_STOPPED);
+    } while (spurious_check && th->status == THREAD_STOPPED);
     th->status = prev_status;
 }
 
@@ -948,14 +946,14 @@
 rb_thread_sleep_forever(void)
 {
     thread_debug("rb_thread_sleep_forever\n");
-    sleep_forever(GET_THREAD(), 0);
+    sleep_forever(GET_THREAD(), 0, 1);
 }
 
 static void
 rb_thread_sleep_deadly(void)
 {
     thread_debug("rb_thread_sleep_deadly\n");
-    sleep_forever(GET_THREAD(), 1);
+    sleep_forever(GET_THREAD(), 1, 1);
 }
 
 static double
@@ -976,9 +974,9 @@
 }
 
 static void
-sleep_wait_for_interrupt(rb_thread_t *th, double sleepsec)
+sleep_wait_for_interrupt(rb_thread_t *th, double sleepsec,int spurious_check)
 {
-    sleep_timeval(th, double2timeval(sleepsec));
+    sleep_timeval(th, double2timeval(sleepsec),spurious_check);
 }
 
 static void
@@ -987,14 +985,14 @@
     struct timeval time;
     time.tv_sec = 0;
     time.tv_usec = 100 * 1000;	/* 0.1 sec */
-    sleep_timeval(th, time);
+    sleep_timeval(th, time, 1);
 }
 
 void
 rb_thread_wait_for(struct timeval time)
 {
     rb_thread_t *th = GET_THREAD();
-    sleep_timeval(th, time);
+    sleep_timeval(th, time, 1);
 }
 
 void
@@ -3704,7 +3702,7 @@
 rb_thread_atfork(void)
 {
     rb_thread_atfork_internal(terminate_atfork_i);
-    GET_THREAD()->join_list_head = 0;
+    GET_THREAD()->join_list = NULL;
 
     /* We don't want reproduce CVE-2003-0900. */
     rb_reset_random_seed();

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

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