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