[前][次][番号順一覧][スレッド一覧][生データ]

yarv-diff:195

From: ko1 atdot.net
Date: 4 Jan 2006 05:19:58 -0000
Subject: [yarv-diff:195] r353 - trunk

Author: ko1
Date: 2006-01-04 14:19:57 +0900 (Wed, 04 Jan 2006)
New Revision: 353

Modified:
   trunk/ChangeLog
   trunk/eval.c
   trunk/eval_intern.h
   trunk/eval_thread.c
   trunk/intern.h
   trunk/signal.c
   trunk/test.rb
   trunk/thread.c
   trunk/thread_pthread.h
   trunk/vm.c
   trunk/yarv.h
   trunk/yarvcore.c
   trunk/yarvcore.h
Log:
	* eval.c (ruby_init), eval_intern.h : use POP_TAG_INIT() at bootstrap

	* eval_thread.c : remove unused functions and comments

	* intern.h : expose rb_make_exception()

	* signal.c : support signal

	* thread.c (yarv_thread_execute_interrupts) : added

	* thread_pthread.h (thread_timer) : set interrupt_flag of
	current runnning threads

	* vm.c (th_invoke_proc) : jump with JUMP_TAG() if some exception
	occurres

	* yarv.h : add yarv_set_current_running_thread_raw() for bootstrap

	* yarvcore.c : add yarv_segv() and segv() method for test

	* yarvcore.c (Init_yarvcore) : set yarv_thread_t#running_thread

	* yarvcore.h : fix yarv_thread_t members



Modified: trunk/ChangeLog
===================================================================
--- trunk/ChangeLog	2006-01-03 14:10:15 UTC (rev 352)
+++ trunk/ChangeLog	2006-01-04 05:19:57 UTC (rev 353)
@@ -4,6 +4,33 @@
 #  from Mon, 03 May 2004 01:24:19 +0900
 #
 
+2006-01-04(Wed) 14:12:47 +0900  Koichi Sasada  <ko1 atdot.net>
+
+	* eval.c (ruby_init), eval_intern.h : use POP_TAG_INIT() at bootstrap
+
+	* eval_thread.c : remove unused functions and comments
+
+	* intern.h : expose rb_make_exception()
+
+	* signal.c : support signal
+
+	* thread.c (yarv_thread_execute_interrupts) : added
+
+	* thread_pthread.h (thread_timer) : set interrupt_flag of
+	current runnning threads
+
+	* vm.c (th_invoke_proc) : jump with JUMP_TAG() if some exception
+	occurres
+
+	* yarv.h : add yarv_set_current_running_thread_raw() for bootstrap
+
+	* yarvcore.c : add yarv_segv() and segv() method for test
+
+	* yarvcore.c (Init_yarvcore) : set yarv_thread_t#running_thread
+
+	* yarvcore.h : fix yarv_thread_t members
+
+
 2006-01-03(Tue) 22:25:04 +0900  Koichi Sasada  <ko1 atdot.net>
 
 	* disasm.c (insn_operand_intern) : fix to add child iseq

Modified: trunk/eval.c
===================================================================
--- trunk/eval.c	2006-01-03 14:10:15 UTC (rev 352)
+++ trunk/eval.c	2006-01-04 05:19:57 UTC (rev 353)
@@ -133,7 +133,7 @@
 #else
   rb_origenviron = environ;
 #endif
-  
+
   Init_yarv();
   Init_stack((void*)&state);
   Init_heap();
@@ -154,7 +154,8 @@
     ruby_prog_init();
     ALLOW_INTS;
   }
-  POP_TAG();
+  POP_TAG_INIT();
+
   if (state) {
     error_print();
     exit(EXIT_FAILURE);

Modified: trunk/eval_intern.h
===================================================================
--- trunk/eval_intern.h	2006-01-03 14:10:15 UTC (rev 352)
+++ trunk/eval_intern.h	2006-01-04 05:19:57 UTC (rev 353)
@@ -203,6 +203,7 @@
 
 #define PUSH_TAG(ptag) TH_PUSH_TAG(GET_THREAD())
 #define POP_TAG()      TH_POP_TAG()
+#define POP_TAG_INIT() } while (0)
 
 #define PUSH_THREAD_TAG() \
   PUSH_TAG(PROT_THREAD)

Modified: trunk/eval_thread.c
===================================================================
--- trunk/eval_thread.c	2006-01-03 14:10:15 UTC (rev 352)
+++ trunk/eval_thread.c	2006-01-04 05:19:57 UTC (rev 353)
@@ -774,18 +774,6 @@
   return 0;
 }
 
-static int rb_thread_join _((rb_thread_t, double));
-
-static int
-rb_thread_join(th, limit)
-    rb_thread_t th;
-    double limit;
-{
-  UNSUPPORTED(rb_thread_join);
-  return Qtrue;
-}
-
-
 /*
  *  call-seq:
  *     thr.join          => thr
@@ -1051,34 +1039,6 @@
 
 /*
  *  call-seq:
- *     Thread.pass   => nil
- *  
- *  Invokes the thread scheduler to pass execution to another thread.
- *     
- *     a = Thread.new { print "a"; Thread.pass;
- *                      print "b"; Thread.pass;
- *                      print "c" }
- *     b = Thread.new { print "x"; Thread.pass;
- *                      print "y"; Thread.pass;
- *                      print "z" }
- *     a.join
- *     b.join
- *     
- *  <em>produces:</em>
- *     
- *     axbycz
- */
-
-static VALUE
-rb_thread_pass()
-{
-    rb_thread_schedule();
-    return Qnil;
-}
-
-
-/*
- *  call-seq:
  *     Thread.stop   => nil
  *  
  *  Stops execution of the current thread, putting it into a ``sleep'' state,

Modified: trunk/intern.h
===================================================================
--- trunk/intern.h	2006-01-03 14:10:15 UTC (rev 352)
+++ trunk/intern.h	2006-01-04 05:19:57 UTC (rev 353)
@@ -200,6 +200,7 @@
 void ruby_set_current_source(void);
 NORETURN(void rb_exc_raise(VALUE));
 NORETURN(void rb_exc_fatal(VALUE));
+VALUE rb_make_exception(int argc, VALUE *argv);
 VALUE rb_f_exit(int,VALUE*);
 VALUE rb_f_abort(int,VALUE*);
 void rb_remove_method(VALUE, const char*);

Modified: trunk/signal.c
===================================================================
--- trunk/signal.c	2006-01-03 14:10:15 UTC (rev 352)
+++ trunk/signal.c	2006-01-04 05:19:57 UTC (rev 353)
@@ -304,6 +304,12 @@
 rb_atomic_t rb_trap_immediate;
 int rb_prohibit_interrupt = 1;
 
+VALUE
+rb_get_trap_cmd(int sig)
+{
+  return trap_list[sig].cmd;
+}
+
 void
 rb_gc_mark_trap_list(void)
 {
@@ -380,41 +386,6 @@
 #endif
 #endif
 
-static void
-signal_exec(int sig)
-{
-    if (trap_list[sig].cmd == 0) {
-	switch (sig) {
-	  case SIGINT:
-	    rb_thread_interrupt();
-	    break;
-#ifdef SIGHUP
-	  case SIGHUP:
-#endif
-#ifdef SIGQUIT
-	  case SIGQUIT:
-#endif
-#ifdef SIGALRM
-	  case SIGALRM:
-#endif
-#ifdef SIGUSR1
-	  case SIGUSR1:
-#endif
-#ifdef SIGUSR2
-	  case SIGUSR2:
-#endif
-	    rb_thread_signal_raise(signo2signm(sig));
-	    break;
-	}
-    }
-    else if (trap_list[sig].cmd == Qundef) {
-	rb_thread_signal_exit();
-    }
-    else {
-	rb_thread_trap_eval(trap_list[sig].cmd, sig, trap_list[sig].safe);
-    }
-}
-
 #if defined(HAVE_NATIVETHREAD) && defined(HAVE_NATIVETHREAD_KILL)
 static void
 sigsend_to_ruby_thread(int sig)
@@ -437,41 +408,24 @@
 }
 #endif
 
+#include <node.h>
+#include "yarvcore.h"
+
 static RETSIGTYPE
 sighandler(int sig)
 {
-#ifdef _WIN32
-#define IN_MAIN_CONTEXT(f, a) (rb_w32_main_context(a, f) ? (void)0 : f(a))
-#else
-#define IN_MAIN_CONTEXT(f, a) f(a)
-#endif
-    if (sig >= NSIG) {
-	rb_bug("trap_handler: Bad signal %d", sig);
-    }
-
-#if defined(HAVE_NATIVETHREAD) && defined(HAVE_NATIVETHREAD_KILL)
-    if (!is_ruby_native_thread() && !rb_trap_accept_nativethreads[sig]) {
-        sigsend_to_ruby_thread(sig);
-        return;
-    }
-#endif
-
-#if !defined(BSD_SIGNAL) && !defined(POSIX_SIGNAL)
-    if (rb_trap_accept_nativethreads[sig]) {
-        ruby_nativethread_signal(sig, sighandler);
-    } else {
-        ruby_signal(sig, sighandler);
-    }
-#endif
-
-    if (trap_list[sig].cmd == 0 && ATOMIC_TEST(rb_trap_immediate)) {
-	IN_MAIN_CONTEXT(signal_exec, sig);
-	ATOMIC_SET(rb_trap_immediate, 1);
-    }
-    else {
-	ATOMIC_INC(rb_trap_pending);
-	ATOMIC_INC(trap_pending_list[sig]);
-    }
+  yarv_thread_t *th = GET_VM()->main_thread;
+  int next_head = (th->signal_queue.head + 1) % RUBY_SIGNAL_QUEUE_MAX;
+  
+  if(next_head == th->signal_queue.tail){
+    /* signal queue overflow */
+    fprintf(stderr, "Signal Queue overflow. This signal (%d) is ignored.", sig);
+  }
+  else{
+    th->signal_queue.buff[th->signal_queue.head] = sig;
+    th->signal_queue.head = next_head;
+  }
+  th->interrupt_flag = 1;
 }
 
 #ifdef SIGBUS
@@ -526,6 +480,46 @@
 }
 
 void
+rb_signal_exec(yarv_thread_t *th, int sig)
+{
+  VALUE cmd = rb_get_trap_cmd(sig);
+
+  if (cmd == 0) {
+    switch (sig) {
+    case SIGINT:
+      rb_thread_interrupt();
+      break;
+#ifdef SIGHUP
+    case SIGHUP:
+#endif
+#ifdef SIGQUIT
+    case SIGQUIT:
+#endif
+#ifdef SIGALRM
+    case SIGALRM:
+#endif
+#ifdef SIGUSR1
+    case SIGUSR1:
+#endif
+#ifdef SIGUSR2
+    case SIGUSR2:
+#endif
+      rb_thread_signal_raise(signo2signm(sig));
+      break;
+    }
+  }
+  else if (cmd == Qundef) {
+    rb_thread_signal_exit();
+  }
+  else {
+    yarv_proc_t *proc;
+    VALUE signum = INT2FIX(sig);
+    GetProcVal(cmd, proc);
+    th_invoke_proc(th, proc, 1, &signum);
+  }
+}
+
+void
 rb_trap_exec(void)
 {
 #ifndef MACOS_UNUSE_SIGNAL
@@ -534,7 +528,7 @@
     for (i=0; i<NSIG; i++) {
 	if (trap_pending_list[i]) {
 	    trap_pending_list[i] = 0;
-	    signal_exec(i);
+          rb_signal_exec(GET_THREAD(), i);
 	}
     }
 #endif /* MACOS_UNUSE_SIGNAL */

Modified: trunk/test.rb
===================================================================
--- trunk/test.rb	2006-01-03 14:10:15 UTC (rev 352)
+++ trunk/test.rb	2006-01-04 05:19:57 UTC (rev 353)
@@ -1,19 +1,45 @@
+trap(:SIGINT){
+  p 1
+}
 
-def m
-  m
-end
+segv
 
+__END__
+
 begin
-  m
-rescue SystemStackError
-  retry
+  Process.kill(:SIGINT, $$)
+  loop{}
+rescue => e
+  p e
 end
+p :finish
 
+__END__
+t = Thread.new{
+  begin
+    loop{
+      p :child
+    }
+  rescue
+    p :finish
+  end
+}
+t.raise("foo")
+p t.join
 
 
+__END__
 
+Module.module_eval
+p Kernel.instance_methods.sort
+instance_eval
+
+
+1.instance_eval %{
+  p self
+}
+
 __END__
-
 class A
         class B
           Const = 1

Modified: trunk/thread.c
===================================================================
--- trunk/thread.c	2006-01-03 14:10:15 UTC (rev 352)
+++ trunk/thread.c	2006-01-04 05:19:57 UTC (rev 353)
@@ -212,6 +212,10 @@
   return th->value;
 }
 
+/*
+ * Thread Scheduling
+ */
+
 #if !defined HAVE_PAUSE
 # if defined _WIN32 && !defined __CYGWIN__
 #  define pause() Sleep(INFINITE)
@@ -326,6 +330,103 @@
   }
 }
 
+/*
+ *  call-seq:
+ *     Thread.pass   => nil
+ *  
+ *  Invokes the thread scheduler to pass execution to another thread.
+ *     
+ *     a = Thread.new { print "a"; Thread.pass;
+ *                      print "b"; Thread.pass;
+ *                      print "c" }
+ *     b = Thread.new { print "x"; Thread.pass;
+ *                      print "y"; Thread.pass;
+ *                      print "z" }
+ *     a.join
+ *     b.join
+ *     
+ *  <em>produces:</em>
+ *     
+ *     axbycz
+ */
+
+static VALUE
+yarv_thread_s_pass(VALUE klass)
+{
+  yarv_thraed_schedule();
+  return Qnil;
+}
+
+
+/*
+ *
+ */
+
+void rb_signal_exec(yarv_thread_t *th, int sig);
+
+void
+yarv_thread_execute_interrupts(yarv_thread_t *th)
+{
+  th->interrupt_flag = 0;
+  
+  /* signal handling */
+  while(th->signal_queue.head != th->signal_queue.tail){
+    int sig = th->signal_queue.buff[th->signal_queue.tail];
+    th->signal_queue.tail = (th->signal_queue.tail + 1) % RUBY_SIGNAL_QUEUE_MAX;
+    rb_signal_exec(th, sig);
+  }
+  
+  /* exception from another thread */
+  if(th->throwed_errinfo){
+    VALUE err = th->throwed_errinfo;
+    th->throwed_errinfo = 0;
+    rb_exc_raise(err);
+  }
+  
+  /* thread pass */
+  yarv_thraed_schedule();
+}
+
+static VALUE
+yarv_thread_raise(int argc, VALUE *argv, yarv_thread_t *th)
+{
+  VALUE exc;
+
+  exc = rb_make_exception(argc, argv);
+  th->throwed_errinfo = exc;
+  th->interrupt_flag = 1;
+  return Qnil;
+}
+
+/*
+ *  call-seq:
+ *     thr.raise(exception)
+ *  
+ *  Raises an exception (see <code>Kernel::raise</code>) from <i>thr</i>. The
+ *  caller does not have to be <i>thr</i>.
+ *     
+ *     Thread.abort_on_exception = true
+ *     a = Thread.new { sleep(200) }
+ *     a.raise("Gotcha")
+ *     
+ *  <em>produces:</em>
+ *     
+ *     prog.rb:3: Gotcha (RuntimeError)
+ *     	from prog.rb:2:in `initialize'
+ *     	from prog.rb:2:in `new'
+ *     	from prog.rb:2
+ */
+
+static VALUE
+yarv_thread_raise_m(int argc, VALUE *argv, VALUE self)
+{
+  yarv_thread_t *th;
+  GetThreadVal(self, th);
+  yarv_thread_raise(argc, argv, th);
+  return Qnil;
+}
+
+
 /********************************************************************/
 
 static VALUE
@@ -335,7 +436,7 @@
 
 static VALUE
 yarv_thread_s_main(VALUE klass){
-  return GET_VM()->main_thread;
+  return GET_VM()->main_thread_val;
 }
 
 VALUE
@@ -484,13 +585,11 @@
   return ary;
 }
 
-static VALUE
-yarv_thread_s_pass(VALUE klass)
-{
-  yarv_thraed_schedule();
-  return Qnil;
-}
 
+/*
+ * for GC
+ */
+
 void
 yarv_set_stack_end(VALUE **stack_end_p)
 {
@@ -505,6 +604,10 @@
   setjmp(th->machine_regs);
 }
 
+/*
+ * for tests
+ */
+
 static VALUE
 raw_gets(VALUE klass){
   char buff[100];
@@ -526,6 +629,7 @@
   rb_define_singleton_method(cYarvThread, "current", yarv_thread_s_current, 0);
   rb_define_singleton_method(cYarvThread, "pass", yarv_thread_s_pass, 0);
 
+  rb_define_method(cYarvThread, "raise", yarv_thread_raise_m, -1);
   rb_define_method(cYarvThread, "join", yarv_thread_join, -1);
   rb_define_method(cYarvThread, "value", yarv_thread_value, 0);
   rb_define_method(cYarvThread, "[]", rb_thread_aref, 1);

Modified: trunk/thread_pthread.h
===================================================================
--- trunk/thread_pthread.h	2006-01-03 14:10:15 UTC (rev 352)
+++ trunk/thread_pthread.h	2006-01-04 05:19:57 UTC (rev 353)
@@ -100,7 +100,8 @@
     tv.tv_usec = 10000;
     select(0, NULL, NULL, NULL, &tv);
 #endif
-    GET_VM()->interrupt_flag = 1;
+    // TODO: GET_VM() should not be used
+    GET_VM()->running_thread->interrupt_flag = 1;
   }
   return NULL;
 }

Modified: trunk/vm.c
===================================================================
--- trunk/vm.c	2006-01-03 14:10:15 UTC (rev 352)
+++ trunk/vm.c	2006-01-04 05:19:57 UTC (rev 353)
@@ -625,10 +625,15 @@
     }
   }
   else{
+    
   }
   
   th_restore_restored_klass(th, proc->block.lfp, stored_special_cref_stack);
   TH_POP_TAG();
+
+  if(state){
+    JUMP_TAG(state);
+  }
   return val;
 }
 

Modified: trunk/yarv.h
===================================================================
--- trunk/yarv.h	2006-01-03 14:10:15 UTC (rev 352)
+++ trunk/yarv.h	2006-01-04 05:19:57 UTC (rev 353)
@@ -51,11 +51,18 @@
 }
 
 static inline void
-yarv_set_current_running_thread(yarv_thread_t *th)
+yarv_set_current_running_thread_raw(yarv_thread_t *th)
 {
   yarvCurrentThread = th;
 }
 
+static inline void
+yarv_set_current_running_thread(yarv_thread_t *th)
+{
+  yarv_set_current_running_thread_raw(th);
+  th->vm->running_thread = th;
+}
+
 #else
 #error "unsupported thread model"
 #endif

Modified: trunk/yarvcore.c
===================================================================
--- trunk/yarvcore.c	2006-01-03 14:10:15 UTC (rev 352)
+++ trunk/yarvcore.c	2006-01-04 05:19:57 UTC (rev 353)
@@ -743,6 +743,7 @@
 {
   VALUE val;
   th_set_top_stack(th, iseq);
+  
   if(!rb_const_defined(rb_cObject, rb_intern("TOPLEVEL_BINDING"))){
     rb_define_global_const("TOPLEVEL_BINDING", rb_f_binding(Qnil));
   }
@@ -954,9 +955,20 @@
 
 /********************************************************************/
 
-static VALUE yarv_once(){
+static VALUE
+yarv_once()
+{
   return rb_yield(Qnil);
 }
+
+static VALUE
+yarv_segv()
+{
+  volatile int *a = 0;
+  *a = 0;
+  return Qnil;
+}
+
 static VALUE cfunc(){
   rb_funcall(Qnil, rb_intern("rfunc"), 0, 0);
   rb_funcall(Qnil, rb_intern("rfunc"), 0, 0);
@@ -1088,6 +1100,7 @@
   /* YARV test functions */
   
   rb_define_global_function("once", yarv_once, 0);
+  rb_define_global_function("segv", yarv_segv, 0);
   rb_define_global_function("cfunc", cfunc, 0);
   rb_define_global_function("yarv_caller", yarv_caller, 1);
   rb_define_global_function("SDR", sdr, 0);
@@ -1155,8 +1168,11 @@
     rb_ary_push(yarvVMArray, vm->self);
 
     /* create main thread */
-    vm->main_thread = rb_class_new_instance(0, 0, cYarvThread);
-    GetThreadVal(vm->main_thread, th);
+    vm->main_thread_val = rb_class_new_instance(0, 0, cYarvThread);
+    GetThreadVal(vm->main_thread_val, th);
+
+    vm->main_thread = th;
+    vm->running_thread = th;
     
     thread_free(GET_THREAD());
     yarv_set_current_running_thread(th);
@@ -1166,9 +1182,6 @@
     
     vm->living_threads = st_init_numtable();
     st_insert(vm->living_threads, th->self, (st_data_t)th->thread_id);
-    /*
-     * set toplevel binding
-     */
   }
 }
 
@@ -1188,6 +1201,6 @@
   /* initialize main thread */
   yarv_thread_t *th = ALLOC(yarv_thread_t);
   th_init2(th);
-  yarv_set_current_running_thread(th);
+  yarv_set_current_running_thread_raw(th);
 }
 

Modified: trunk/yarvcore.h
===================================================================
--- trunk/yarvcore.h	2006-01-03 14:10:15 UTC (rev 352)
+++ trunk/yarvcore.h	2006-01-04 05:19:57 UTC (rev 353)
@@ -279,17 +279,21 @@
 #define GetVMVal(obj, tobj) \
   Data_Get_Struct(obj, yarv_vm_t, tobj)
 
+struct yarv_thread_struct;
+
 typedef struct{
   VALUE self;
-  
+
   yarv_thread_lock_t global_interpreter_lock;
   unsigned long thread_critical;
-  VALUE main_thread;
+
+  struct yarv_thread_struct *main_thread;
+  struct yarv_thread_struct *running_thread;
+
+  VALUE main_thread_val;
   st_table *living_threads;
 
   int exit_code;
-  
-  unsigned long interrupt_flag;
   unsigned long trace_flag;
 } yarv_vm_t;
 
@@ -340,7 +344,9 @@
   struct yarv_tag *prev;
 };
 
-typedef struct yarv_thread{
+#define RUBY_SIGNAL_QUEUE_MAX 16
+
+typedef struct yarv_thread_struct{
   VALUE self;
   yarv_vm_t *vm;
   
@@ -369,13 +375,21 @@
   /* thread control */
   yarv_thread_id_t thread_id;
   enum yarv_thread_status status;
-  int interrupt_flag;
-  struct yarv_tag *tag;
   
   VALUE value;
-  VALUE errinfo;
   VALUE wait_thread_value;
 
+  VALUE errinfo;
+  VALUE throwed_errinfo;
+  int interrupt_flag;
+  struct yarv_tag *tag;
+
+  struct{
+    int buff[RUBY_SIGNAL_QUEUE_MAX];
+    int head;
+    int tail;
+  } signal_queue;
+
   VALUE first_proc;
   VALUE first_args;
 
@@ -563,12 +577,10 @@
 
 
 #define YARV_CHECK_INTS_TH(th) do { \
-  if(th->vm->interrupt_flag || \
-     th->interrupt_flag){ \
+  if(th->interrupt_flag){ \
     th->interrupt_flag = 0; \
-    th->vm->interrupt_flag = 0; \
     /* TODO: trap something event */ \
-    yarv_thraed_schedule(); \
+    yarv_thread_execute_interrupts(th); \
   } \
 } while (0)
 


-- 
ML: yarv-diff quickml.atdot.net
Info: http://www.atdot.net/~ko1/quickml

[前][次][番号順一覧][スレッド一覧][生データ]