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/