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

ruby-changes:7431

From: nobu <ko1@a...>
Date: Sat, 30 Aug 2008 20:06:52 +0900 (JST)
Subject: [ruby-changes:7431] Ruby:r18950 (mvm): * vm_core.h (struct rb_thread_struct): added signal and message

nobu	2008-08-30 20:06:36 +0900 (Sat, 30 Aug 2008)

  New Revision: 18950

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

  Log:
    * vm_core.h (struct rb_thread_struct): added signal and message
      queues.
    
    * thread.c (rb_queue_initialize, rb_queue_destroy, rb_queue_push),
      (rb_queue_shift): new functions.
    
    * thread.c (rb_thread_execute_interrupts): uses signal queue.
     
    * thread.c (ruby_vm_send_signal): extracted from vm_send_signal.
    
    * vm.c (vm_free): unlock and destroys global_vm_lock.
    
    * vm.c (th_init2, thread_free): initializes and destroys signal and
      message queues.

  Modified files:
    branches/mvm/ChangeLog
    branches/mvm/thread.c
    branches/mvm/vm.c
    branches/mvm/vm_core.h

Index: mvm/ChangeLog
===================================================================
--- mvm/ChangeLog	(revision 18949)
+++ mvm/ChangeLog	(revision 18950)
@@ -1,3 +1,20 @@
+Sat Aug 30 20:06:24 2008  Nobuyoshi Nakada  <nobu@r...>
+
+	* vm_core.h (struct rb_thread_struct): added signal and message
+	  queues.
+
+	* thread.c (rb_queue_initialize, rb_queue_destroy, rb_queue_push),
+	  (rb_queue_shift): new functions.
+
+	* thread.c (rb_thread_execute_interrupts): uses signal queue.
+
+	* thread.c (ruby_vm_send_signal): extracted from vm_send_signal.
+
+	* vm.c (vm_free): unlock and destroys global_vm_lock.
+
+	* vm.c (th_init2, thread_free): initializes and destroys signal and
+	  message queues.
+
 Sat Aug 30 16:38:23 2008    <nobu@r...>
 
 	* vm_core.h (struct rb_vm_struct): replaced signal staff with trap
Index: mvm/vm_core.h
===================================================================
--- mvm/vm_core.h	(revision 18949)
+++ mvm/vm_core.h	(revision 18950)
@@ -426,6 +426,21 @@
 
 struct rb_mutex_struct;
 
+typedef struct rb_queue_element {
+    struct rb_queue_element *next;
+    void *value;
+} rb_queue_element_t;
+
+typedef struct rb_queue {
+    rb_thread_lock_t lock;
+    rb_queue_element_t *head, **tail;
+} rb_queue_t;
+
+void rb_queue_initialize(rb_queue_t *);
+void rb_queue_destroy(rb_queue_t *);
+int rb_queue_push(rb_queue_t *, void *);
+int rb_queue_shift(rb_queue_t *, void **);
+
 struct rb_thread_struct
 {
     VALUE self;
@@ -468,10 +483,14 @@
 
     VALUE errinfo;
     VALUE thrown_errinfo;
-    int exec_signal;
 
+    struct {
+	rb_queue_t signal, message;
+    } queue;
+
     int interrupt_flag;
     rb_thread_lock_t interrupt_lock;
+
     struct rb_unblock_callback unblock;
     VALUE locking_mutex;
     struct rb_mutex_struct *keeping_mutexes;
Index: mvm/thread.c
===================================================================
--- mvm/thread.c	(revision 18949)
+++ mvm/thread.c	(revision 18950)
@@ -961,6 +961,59 @@
     return val;
 }
 
+void
+rb_queue_initialize(rb_queue_t *que)
+{
+    ruby_native_thread_lock_initialize(&que->lock);
+    que->head = 0;
+    que->tail = &que->head;
+}
+
+void
+rb_queue_destroy(rb_queue_t *que)
+{
+    rb_queue_element_t *e, *n;
+    ruby_native_thread_lock(&que->lock);
+    for (e = que->head; e; e = n) {
+	n = e->next;
+	free(e);
+    }
+    que->head = 0;
+    que->tail = 0;
+    ruby_native_thread_unlock(&que->lock);
+    native_mutex_destroy(&que->lock);
+}
+
+int
+rb_queue_push(rb_queue_t *que, void *value)
+{
+    rb_queue_element_t *e = malloc(sizeof(rb_queue_element_t));
+    if (!e) return Qfalse;
+    e->value = value;
+    e->next = 0;
+    ruby_native_thread_lock(&que->lock);
+    *que->tail = e;
+    que->tail = &e->next;
+    ruby_native_thread_unlock(&que->lock);
+    return Qtrue;
+}
+
+int
+rb_queue_shift(rb_queue_t *que, void **value)
+{
+    rb_queue_element_t *e;
+
+    if (!que->head) return Qfalse;
+    ruby_native_thread_lock(&que->lock);
+    if ((e = que->head) != 0 && !(que->head = e->next)) {
+	que->tail = &que->head;
+    }
+    ruby_native_thread_unlock(&que->lock);
+    if (!e) return 0;
+    *value = e->value;
+    return Qtrue;
+}
+
 /*
  *  call-seq:
  *     Thread.pass   => nil
@@ -1001,14 +1054,14 @@
 	enum rb_thread_status status = th->status;
 	int timer_interrupt = th->interrupt_flag & 0x01;
 	int finalizer_interrupt = th->interrupt_flag & 0x04;
+	void *exec_signal;
 
 	th->status = THREAD_RUNNABLE;
 	th->interrupt_flag = 0;
 
 	/* signal handling */
-	if (th->exec_signal) {
-	    int sig = th->exec_signal;
-	    th->exec_signal = 0;
+	while (rb_queue_shift(&th->queue.signal, &exec_signal)) {
+	    int sig = (int)(VALUE)exec_signal;
 	    rb_signal_exec(th, sig);
 	}
 
@@ -2256,20 +2309,28 @@
     return Qtrue;
 }
 
+int
+ruby_vm_send_signal(rb_vm_t *vm, int sig)
+{
+    rb_thread_t *mth;
+    enum rb_thread_status prev_status;
+
+    if (sig <= 0 || sig >= RUBY_NSIG) return -1;
+    mth = vm->main_thread;
+    prev_status = mth->status;
+    thread_debug("main_thread: %s, sig: %d\n",
+		 thread_status_name(prev_status), sig);
+    rb_queue_push(&mth->queue.signal, (void *)(VALUE)sig);
+    if (mth->status != THREAD_KILLED) mth->status = THREAD_RUNNABLE;
+    rb_thread_interrupt(mth);
+    mth->status = prev_status;
+    return sig;
+}
+
 static int
 vm_send_signal(rb_vm_t *vm, void *sig)
 {
-    if (vm->main_thread->exec_signal == 0) {
-	rb_thread_t *mth = vm->main_thread;
-	enum rb_thread_status prev_status = mth->status;
-	mth->exec_signal = (VALUE)sig;
-	thread_debug("main_thread: %s, sig: %d\n",
-		     thread_status_name(prev_status),
-		     vm->main_thread->exec_signal);
-	if (mth->status != THREAD_KILLED) mth->status = THREAD_RUNNABLE;
-	rb_thread_interrupt(mth);
-	mth->status = prev_status;
-    }
+    ruby_vm_send_signal(vm, (int)(VALUE)sig);
     return Qtrue;
 }
 
Index: mvm/vm.c
===================================================================
--- mvm/vm.c	(revision 18949)
+++ mvm/vm.c	(revision 18950)
@@ -1345,6 +1345,7 @@
 static struct {
     rb_thread_lock_t lock;
     st_table *list;
+    rb_vm_t *main;
 } vm_manager = {RB_THREAD_LOCK_INITIALIZER};
 
 static void
@@ -1401,6 +1402,8 @@
 	st_free_table(vmobj->living_threads);
 	vmobj->living_threads = 0;
 	vm_del(vmobj);
+	ruby_native_thread_unlock(&vmobj->global_vm_lock);
+	ruby_native_thread_lock_destroy(&vmobj->global_vm_lock);
 	ruby_xfree(ptr);
     }
     RUBY_FREE_LEAVE("vm");
@@ -1476,13 +1479,6 @@
     vm->specific_storage.ptr = calloc(vm->specific_storage.len, sizeof(VALUE));
 }
 
-int
-ruby_vm_send_signal(rb_vm_t *vm, int sig)
-{
-    if (sig <= 0 || sig >= RUBY_NSIG) return -1;
-    return sig;
-}
-
 /* Thread */
 
 #define USE_THREAD_DATA_RECYCLE 1
@@ -1565,7 +1561,10 @@
 	}
 #endif
 
-	if (th->vm->main_thread == th) {
+	rb_queue_destroy(&th->queue.message);
+	rb_queue_destroy(&th->queue.signal);
+
+	if (th->vm->main_thread == th && th->vm == vm_manager.main) {
 	    RUBY_GC_INFO("main thread\n");
 	}
 	else {
@@ -1653,6 +1652,9 @@
 {
     th->self = self;
 
+    rb_queue_initialize(&th->queue.signal);
+    rb_queue_initialize(&th->queue.message);
+
     /* allocate thread stack */
     th->stack_size = RUBY_VM_THREAD_STACK_SIZE;
     th->stack = thread_recycle_stack(th->stack_size);
@@ -1984,6 +1986,7 @@
     vm_init2(vm);
     th->vm = vm;
 
+    vm_manager.main = vm;
     vm_manager.list = st_init_numtable();
     vm_add(vm);
 

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

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