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

yarv-diff:111

From: ko1 atdot.net
Date: 30 Sep 2005 06:08:46 -0000
Subject: [yarv-diff:111] r267 - trunk

Author: ko1
Date: 2005-09-30 15:08:45 +0900 (Fri, 30 Sep 2005)
New Revision: 267

Added:
   trunk/thread.c
   trunk/thread_pthread.h
Modified:
   trunk/ChangeLog
   trunk/common.mk
   trunk/eval.c
   trunk/eval_intern.h
   trunk/eval_thread.c
   trunk/gc.c
   trunk/insns.def
   trunk/test.rb
   trunk/yarv.h
   trunk/yarvcore.c
   trunk/yarvcore.h
Log:
	* thread.c, common.mk : add thread.c

	* thread.c, gc.c, eval_thread.c, yarvcore.c, yarvcore.h : 
	support native thread (on pthread)

	* insns.def : add YARV_CHECK_INTS() check

	* yarv.h : add GET_VM() macro



Modified: trunk/ChangeLog
===================================================================
--- trunk/ChangeLog	2005-09-29 14:01:52 UTC (rev 266)
+++ trunk/ChangeLog	2005-09-30 06:08:45 UTC (rev 267)
@@ -4,6 +4,18 @@
 #  from Mon, 03 May 2004 01:24:19 +0900
 #
 
+2005-09-30(Fri) 14:59:29 +0900  Koichi Sasada  <ko1 atdot.net>
+
+	* thread.c, common.mk : add thread.c
+
+	* thread.c, gc.c, eval_thread.c, yarvcore.c, yarvcore.h : 
+	support native thread (on pthread)
+
+	* insns.def : add YARV_CHECK_INTS() check
+
+	* yarv.h : add GET_VM() macro
+
+
 2005-09-29(Thu) 22:43:08 +0900  Koichi Sasada  <ko1 atdot.net>
 
 	* eval_intern.h, eval_thread.c : move thread_status to eval_intern.h

Modified: trunk/common.mk
===================================================================
--- trunk/common.mk	2005-09-29 14:01:52 UTC (rev 266)
+++ trunk/common.mk	2005-09-30 06:08:45 UTC (rev 267)
@@ -67,6 +67,7 @@
 		vm_dump.$(OBJEXT) \
 		yarvcore.$(OBJEXT) \
 		yarvsubst.$(OBJEXT) \
+		thread.$(OBJEXT) \
 		$(MISSING)
 
 SCRIPT_ARGS   =	--dest-dir="$(DESTDIR)" \
@@ -273,6 +274,12 @@
   {$(VPATH)}node.h {$(VPATH)}env.h {$(VPATH)}util.h \
   {$(VPATH)}rubysig.h {$(VPATH)}st.h {$(VPATH)}dln.h {$(VPATH)}yarv.h
 
+thread.$(OBJEXT): {$(VPATH)}thread.c  {$(VPATH)}eval_intern.h \
+  {$(VPATH)}ruby.h config.h \
+  {$(VPATH)}defines.h {$(VPATH)}intern.h {$(VPATH)}missing.h \
+  {$(VPATH)}node.h {$(VPATH)}env.h {$(VPATH)}util.h \
+  {$(VPATH)}rubysig.h {$(VPATH)}st.h {$(VPATH)}dln.h {$(VPATH)}yarv.h
+
 file.$(OBJEXT): {$(VPATH)}file.c {$(VPATH)}ruby.h config.h \
   {$(VPATH)}defines.h {$(VPATH)}intern.h {$(VPATH)}missing.h \
   {$(VPATH)}rubyio.h {$(VPATH)}rubysig.h {$(VPATH)}util.h \
@@ -373,6 +380,7 @@
 debug.$(OBJEXT): {$(VPATH)}debug.h
 yarvsubst.$(OBJEXT): {$(VPATH)}yarv.h
 
+
 BASERUBY = ruby
 
 INSNS2VMOPT = $(CPPFLAGS) --srcdir=$(srcdir)

Modified: trunk/eval.c
===================================================================
--- trunk/eval.c	2005-09-29 14:01:52 UTC (rev 266)
+++ trunk/eval.c	2005-09-30 06:08:45 UTC (rev 267)
@@ -94,6 +94,9 @@
 #endif
 char **rb_origenviron;
 
+jmp_buf function_call_may_return_twice_jmp_buf;
+int function_call_may_return_twice_false = 0;
+
 void rb_call_inits _((void));
 void Init_stack _((VALUE*));
 void Init_heap _((void));

Modified: trunk/eval_intern.h
===================================================================
--- trunk/eval_intern.h	2005-09-29 14:01:52 UTC (rev 266)
+++ trunk/eval_intern.h	2005-09-30 06:08:45 UTC (rev 267)
@@ -147,8 +147,8 @@
     "%l0", "%l1", "%l2", "%l3", "%l4", "%l5", "%l6", "%l7", \
     "%i0", "%i1", "%i2", "%i3", "%i4", "%i5", "%i7"); })
 #else
-static jmp_buf function_call_may_return_twice_jmp_buf;
-int function_call_may_return_twice_false = 0;
+extern jmp_buf function_call_may_return_twice_jmp_buf;
+extern int function_call_may_return_twice_false;
 #define FUNCTION_CALL_MAY_RETURN_TWICE \
   (function_call_may_return_twice_false ? \
    setjmp(function_call_may_return_twice_jmp_buf) : \
@@ -260,13 +260,6 @@
 #define SCOPE_SET(f)  (scope_vmode=(f))
 #define SCOPE_TEST(f) (scope_vmode&(f))
 
-enum thread_status {
-    THREAD_TO_KILL,
-    THREAD_RUNNABLE,
-    THREAD_STOPPED,
-    THREAD_KILLED,
-};
-
 struct ruby_env {
     struct ruby_env *prev;
     struct FRAME *frame;

Modified: trunk/eval_thread.c
===================================================================
--- trunk/eval_thread.c	2005-09-29 14:01:52 UTC (rev 266)
+++ trunk/eval_thread.c	2005-09-30 06:08:45 UTC (rev 267)
@@ -103,13 +103,6 @@
 /* +infty, for this purpose */
 #define DELAY_INFTY 1E30
 
-#if !defined HAVE_PAUSE
-# if defined _WIN32 && !defined __CYGWIN__
-#  define pause() Sleep(INFINITE)
-# else
-#  define pause() sleep(0x7fffffff)
-# endif
-#endif
 
 #ifdef NFDBITS
 void
@@ -266,7 +259,7 @@
 
     int safe;
 
-    enum thread_status status;
+    enum yarv_thread_status status;
     int wait_for;
     int fd;
     rb_fdset_t readfds;
@@ -306,7 +299,7 @@
 
     int safe;
 
-    enum thread_status status;
+    enum yarv_thread_status status;
     int wait_for;
     int fd;
     rb_fdset_t readfds;
@@ -378,7 +371,7 @@
 
 static const char *
 thread_status_name(status)
-    enum thread_status status;
+    enum yarv_thread_status status;
 {
   switch (status) {
   case THREAD_RUNNABLE:
@@ -765,62 +758,6 @@
   return Qfalse;
 }
 
-void
-rb_thread_wait_for(time)
-    struct timeval time;
-{
-    double date;
-
-    if (rb_thread_critical ||
-	curr_thread == curr_thread->next ||
-	curr_thread->status == THREAD_TO_KILL) {
-	int n;
-	int thr_critical = rb_thread_critical;
-#ifndef linux
-	double d, limit;
-	limit = timeofday()+(double)time.tv_sec+(double)time.tv_usec*1e-6;
-#endif
-	for (;;) {
-	    rb_thread_critical = Qtrue;
-	    TRAP_BEG;
-	    n = select(0, 0, 0, 0, &time);
-	    rb_thread_critical = thr_critical;
-	    TRAP_END;
-	    if (n == 0) return;
-	    if (n < 0) {
-		switch (errno) {
-		  case EINTR:
-#ifdef ERESTART
-		  case ERESTART:
-#endif
-		    return;
-		  default:
-		    rb_sys_fail("sleep");
-		}
-	    }
-#ifndef linux
-	    d = limit - timeofday();
-
-	    time.tv_sec = (int)d;
-	    time.tv_usec = (int)((d - (int)d)*1e6);
-	    if (time.tv_usec < 0) {
-		time.tv_usec += (long)1e6;
-		time.tv_sec -= 1;
-	    }
-	    if (time.tv_sec < 0) return;
-#endif
-	}
-    }
-
-    date = timeofday() + (double)time.tv_sec + (double)time.tv_usec*1e-6;
-    curr_thread->status = THREAD_STOPPED;
-    curr_thread->delay = date;
-    curr_thread->wait_for = WAIT_TIME;
-    rb_thread_schedule();
-}
-
-void rb_thread_sleep_forever _((void));
-
 int
 rb_thread_alone()
 {
@@ -920,7 +857,7 @@
 VALUE
 rb_thread_current()
 {
-  return 0;
+  return GET_THREAD()->self;
 }
 
 
@@ -1163,7 +1100,7 @@
 VALUE
 rb_thread_stop()
 {
-    enum thread_status last_status = THREAD_RUNNABLE;
+    enum yarv_thread_status last_status = THREAD_RUNNABLE;
 
     rb_thread_critical = 0;
     if (curr_thread == curr_thread->next) {
@@ -1204,27 +1141,7 @@
     rb_thread_wait_for(rb_time_timeval(INT2FIX(sec)));
 }
 
-void
-rb_thread_sleep_forever()
-{
-    int thr_critical = rb_thread_critical;
-    if (curr_thread == curr_thread->next ||
-	curr_thread->status == THREAD_TO_KILL) {
-	rb_thread_critical = Qtrue;
-	TRAP_BEG;
-	pause();
-	rb_thread_critical = thr_critical;
-	TRAP_END;
-	return;
-    }
 
-    curr_thread->delay = DELAY_INFTY;
-    curr_thread->wait_for = WAIT_TIME;
-    curr_thread->status = THREAD_STOPPED;
-    rb_thread_schedule();
-}
-
-
 /*
  *  call-seq:
  *     thr.priority   => integer
@@ -1489,34 +1406,6 @@
     /* cause EINTR */
 }
 
-static pthread_t time_thread;
-extern rb_nativethread_t ruby_thid;
-
-static void*
-thread_timer(void *dummy)
-{
-  for (;;) {
-#ifdef HAVE_NANOSLEEP
-    struct timespec req, rem;
-
-    req.tv_sec = 0;
-    req.tv_nsec = 10000000;
-    nanosleep(&req, &rem);
-#else
-    struct timeval tv;
-    tv.tv_sec = 0;
-    tv.tv_usec = 10000;
-    select(0, NULL, NULL, NULL, &tv);
-#endif
-    if (!rb_thread_critical) {
-      rb_thread_pending = 1;
-      if (rb_trap_immediate) {
-        pthread_kill(ruby_thid, SIGVTALRM);
-      }
-    }
-  }
-}
-
 void
 rb_thread_start_timer()
 {
@@ -1567,7 +1456,7 @@
 int rb_thread_tick = THREAD_TICK;
 #endif
 
-NORETURN(static void rb_thread_terminated _((rb_thread_t, int, enum thread_status)));
+NORETURN(static void rb_thread_terminated _((rb_thread_t, int, enum yarv_thread_status)));
 static VALUE rb_thread_yield _((VALUE, rb_thread_t));
 
 static void
@@ -1615,7 +1504,7 @@
 rb_thread_terminated(th, state, status)
     rb_thread_t th;
     int state;
-    enum thread_status status;
+    enum yarv_thread_status status;
 {
     if (state && status != THREAD_TO_KILL && !NIL_P(ruby_errinfo)) {
 	th->flags |= THREAD_RAISED;
@@ -2094,159 +1983,7 @@
     return Qnil;		/* not reached */
 }
 
-VALUE
-rb_thread_local_aref(thread, id)
-    VALUE thread;
-    ID id;
-{
-    rb_thread_t th;
-    VALUE val;
-
-    th = rb_thread_check(thread);
-    if (ruby_safe_level >= 4 && th != curr_thread) {
-	rb_raise(rb_eSecurityError, "Insecure: thread locals");
-    }
-    if (!th->locals) return Qnil;
-    if (st_lookup(th->locals, id, &val)) {
-	return val;
-    }
-    return Qnil;
-}
-
-
 /*
- *  call-seq:
- *      thr[sym]   => obj or nil
- *  
- *  Attribute Reference---Returns the value of a thread-local variable, using
- *  either a symbol or a string name. If the specified variable does not exist,
- *  returns <code>nil</code>.
- *     
- *     a = Thread.new { Thread.current["name"] = "A"; Thread.stop }
- *     b = Thread.new { Thread.current[:name]  = "B"; Thread.stop }
- *     c = Thread.new { Thread.current["name"] = "C"; Thread.stop }
- *     Thread.list.each {|x| puts "#{x.inspect}: #{x[:name]}" }
- *     
- *  <em>produces:</em>
- *     
- *     #<Thread:0x401b3b3c sleep>: C
- *     #<Thread:0x401b3bc8 sleep>: B
- *     #<Thread:0x401b3c68 sleep>: A
- *     #<Thread:0x401bdf4c run>:
- */
-
-static VALUE
-rb_thread_aref(thread, id)
-    VALUE thread, id;
-{
-    return rb_thread_local_aref(thread, rb_to_id(id));
-}
-
-VALUE
-rb_thread_local_aset(thread, id, val)
-    VALUE thread;
-    ID id;
-    VALUE val;
-{
-    rb_thread_t th = rb_thread_check(thread);
-
-    if (ruby_safe_level >= 4 && th != curr_thread) {
-	rb_raise(rb_eSecurityError, "Insecure: can't modify thread locals");
-    }
-    if (OBJ_FROZEN(thread)) rb_error_frozen("thread locals");
-
-    if (!th->locals) {
-	th->locals = st_init_numtable();
-    }
-    if (NIL_P(val)) {
-	st_delete(th->locals, (st_data_t*)&id, 0);
-	return Qnil;
-    }
-    st_insert(th->locals, id, val);
-
-    return val;
-}
-
-
-/*
- *  call-seq:
- *      thr[sym] = obj   => obj
- *  
- *  Attribute Assignment---Sets or creates the value of a thread-local variable,
- *  using either a symbol or a string. See also <code>Thread#[]</code>.
- */
-
-static VALUE
-rb_thread_aset(thread, id, val)
-    VALUE thread, id, val;
-{
-    return rb_thread_local_aset(thread, rb_to_id(id), val);
-}
-
-
-/*
- *  call-seq:
- *     thr.key?(sym)   => true or false
- *  
- *  Returns <code>true</code> if the given string (or symbol) exists as a
- *  thread-local variable.
- *     
- *     me = Thread.current
- *     me[:oliver] = "a"
- *     me.key?(:oliver)    #=> true
- *     me.key?(:stanley)   #=> false
- */
-
-static VALUE
-rb_thread_key_p(thread, id)
-    VALUE thread, id;
-{
-    rb_thread_t th = rb_thread_check(thread);
-
-    if (!th->locals) return Qfalse;
-    if (st_lookup(th->locals, rb_to_id(id), 0))
-	return Qtrue;
-    return Qfalse;
-}
-
-static int
-thread_keys_i(key, value, ary)
-    ID key;
-    VALUE value, ary;
-{
-    rb_ary_push(ary, ID2SYM(key));
-    return ST_CONTINUE;
-}
-
-
-/*
- *  call-seq:
- *     thr.keys   => array
- *  
- *  Returns an an array of the names of the thread-local variables (as Symbols).
- *     
- *     thr = Thread.new do
- *       Thread.current[:cat] = 'meow'
- *       Thread.current["dog"] = 'woof'
- *     end
- *     thr.join   #=> #<Thread:0x401b3f10 dead>
- *     thr.keys   #=> [:dog, :cat]
- */
-
-static VALUE
-rb_thread_keys(thread)
-    VALUE thread;
-{
-    rb_thread_t th = rb_thread_check(thread);
-    VALUE ary = rb_ary_new();
-
-    if (th->locals) {
-	st_foreach(th->locals, thread_keys_i, ary);
-    }
-    return ary;
-}
-
-/*
  * call-seq:
  *   thr.inspect   => string
  *
@@ -2577,6 +2314,9 @@
 void
 Init_Thread()
 {
+  recursive_key = rb_intern("__recursive_key__");
+  return;
+  /*
     VALUE cThGroup;
 
     rb_eThreadError = rb_define_class("ThreadError", rb_eStandardError);
@@ -2622,11 +2362,6 @@
     rb_define_method(rb_cThread, "safe_level", rb_thread_safe_level, 0);
     rb_define_method(rb_cThread, "group", rb_thread_group, 0);
 
-    rb_define_method(rb_cThread, "[]", rb_thread_aref, 1);
-    rb_define_method(rb_cThread, "[]=", rb_thread_aset, 2);
-    rb_define_method(rb_cThread, "key?", rb_thread_key_p, 1);
-    rb_define_method(rb_cThread, "keys", rb_thread_keys, 0);
-
     rb_define_method(rb_cThread, "inspect", rb_thread_inspect, 0);
 
     rb_cCont = rb_define_class("Continuation", rb_cObject);
@@ -2646,7 +2381,7 @@
     rb_define_const(cThGroup, "Default", thgroup_default);
     rb_global_variable(&thgroup_default);
 
-    recursive_key = rb_intern("__recursive_key__");
+   */
 }
 
 static VALUE

Modified: trunk/gc.c
===================================================================
--- trunk/gc.c	2005-09-29 14:01:52 UTC (rev 266)
+++ trunk/gc.c	2005-09-30 06:08:45 UTC (rev 267)
@@ -18,6 +18,7 @@
 #include "node.h"
 #include "env.h"
 #include "re.h"
+#include "yarvcore.h"
 #include <stdio.h>
 #include <setjmp.h>
 #include <sys/types.h>
@@ -420,16 +421,10 @@
 # define STACK_LEVEL_MAX 655300
 #endif
 
-NOINLINE(static void set_stack_end(VALUE **stack_end_p));
+NOINLINE(void yarv_set_stack_end(VALUE **stack_end_p));
 
-static void
-set_stack_end(VALUE **stack_end_p)
-{
-    VALUE stack_end;
-    *stack_end_p = &stack_end;
-}
-#define SET_STACK_END    VALUE *stack_end; set_stack_end(&stack_end)
-#define STACK_END        (stack_end)
+#define YARV_SET_STACK_END yarv_set_stack_end(&th->machine_stack_end)
+#define STACK_END        (th->machine_stack_end)
 
 #if defined(sparc) || defined(__sparc__)
 # define STACK_LENGTH  (rb_gc_stack_start - STACK_END + 0x80)
@@ -448,13 +443,13 @@
 #else
 static int grow_direction;
 static int
-stack_grow_direction(addr)
-    VALUE *addr;
+stack_grow_direction(VALUE *addr)
 {
-    SET_STACK_END;
+  yarv_thread_t *th = GET_THREAD();
+  YARV_SET_STACK_END;
 
-    if (STACK_END > addr) return grow_direction = 1;
-    return grow_direction = -1;
+  if (STACK_END > addr) return grow_direction = 1;
+  return grow_direction = -1;
 }
 # define stack_growup_p(x) ((grow_direction ? grow_direction : stack_grow_direction(x)) > 0)
 # define STACK_UPPER(x, a, b) (stack_growup_p(x) ? a : b)
@@ -463,25 +458,26 @@
 #define GC_WATER_MARK 512
 
 #define CHECK_STACK(ret) do {\
-    SET_STACK_END;\
+    YARV_SET_STACK_END;\
     (ret) = (STACK_LENGTH > STACK_LEVEL_MAX + GC_WATER_MARK);\
 } while (0)
 
 int
 ruby_stack_length(VALUE **p)
 {
-    SET_STACK_END;
-    if (p) *p = STACK_UPPER(STACK_END, rb_gc_stack_start, STACK_END);
-    return STACK_LENGTH;
+  yarv_thread_t *th = GET_THREAD();
+  YARV_SET_STACK_END;
+  if (p) *p = STACK_UPPER(STACK_END, rb_gc_stack_start, STACK_END);
+  return STACK_LENGTH;
 }
 
 int
 ruby_stack_check(void)
 {
-    int ret;
-
-    CHECK_STACK(ret);
-    return ret;
+  int ret;
+  yarv_thread_t *th = GET_THREAD();
+  CHECK_STACK(ret);
+  return ret;
 }
 
 #define MARK_STACK_MAX 1024
@@ -1250,120 +1246,132 @@
 static int
 garbage_collect(void)
 {
-    struct gc_list *list;
-    struct FRAME * volatile frame; /* gcc 2.7.2.3 -O2 bug??  */
-    jmp_buf save_regs_gc_mark;
-    SET_STACK_END;
+  struct gc_list *list;
+  struct FRAME * volatile frame; /* gcc 2.7.2.3 -O2 bug??  */
+  jmp_buf save_regs_gc_mark;
+  yarv_thread_t *th = GET_THREAD();
 
-    if (!heaps) return Qfalse;
-#ifdef HAVE_NATIVETHREAD
-    if (!is_ruby_native_thread()) {
-	rb_bug("cross-thread violation on rb_gc()");
+  YARV_SET_STACK_END;
+
+  if (!heaps) return Qfalse;
+
+  if (dont_gc || during_gc) {
+    if (!freelist) {
+      add_heap();
     }
-#endif
-    if (dont_gc || during_gc) {
-	if (!freelist) {
-	    add_heap();
-	}
-	return Qfalse;
-    }
-    if (during_gc) return Qfalse;
-    during_gc++;
+    return Qfalse;
+  }
+  if (during_gc) return Qfalse;
+  during_gc++;
 
-    init_mark_stack();
+  init_mark_stack();
 
-    /* mark frame stack */
-    for (frame = ruby_frame; frame; frame = frame->prev) {
-	rb_gc_mark_frame(frame);
-	if (frame->tmp) {
-	    struct FRAME *tmp = frame->tmp;
-	    while (tmp) {
-		rb_gc_mark_frame(tmp);
-		tmp = tmp->prev;
-	    }
-	}
+  /* mark frame stack */
+  for (frame = ruby_frame; frame; frame = frame->prev) {
+    rb_gc_mark_frame(frame);
+    if (frame->tmp) {
+      struct FRAME *tmp = frame->tmp;
+      while (tmp) {
+        rb_gc_mark_frame(tmp);
+        tmp = tmp->prev;
+      }
     }
-    gc_mark((VALUE)ruby_scope, 0);
-    gc_mark((VALUE)ruby_dyna_vars, 0);
-    if (finalizer_table) {
-	mark_tbl(finalizer_table, 0);
-    }
+  }
+  gc_mark((VALUE)ruby_scope, 0);
+  gc_mark((VALUE)ruby_dyna_vars, 0);
+  if (finalizer_table) {
+    mark_tbl(finalizer_table, 0);
+  }
 
-    FLUSH_REGISTER_WINDOWS;
-    /* This assumes that all registers are saved into the jmp_buf (and stack) */
-    setjmp(save_regs_gc_mark);
-    mark_locations_array((VALUE*)save_regs_gc_mark, sizeof(save_regs_gc_mark) / sizeof(VALUE *));
+  FLUSH_REGISTER_WINDOWS;
+  /* This assumes that all registers are saved into the jmp_buf (and stack) */
+  setjmp(save_regs_gc_mark);
+  mark_locations_array((VALUE*)save_regs_gc_mark, sizeof(save_regs_gc_mark) / sizeof(VALUE *));
+  
 #if STACK_GROW_DIRECTION < 0
-    rb_gc_mark_locations((VALUE*)STACK_END, rb_gc_stack_start);
+  rb_gc_mark_locations(th->machine_stack_end, th->machine_stack_start);
 #elif STACK_GROW_DIRECTION > 0
-    rb_gc_mark_locations(rb_gc_stack_start, (VALUE*)STACK_END + 1);
+  rb_gc_mark_locations(th->machin_stack_start, th->machine_stack_end);
 #else
-    if ((VALUE*)STACK_END < rb_gc_stack_start)
-	rb_gc_mark_locations((VALUE*)STACK_END, rb_gc_stack_start);
-    else
-	rb_gc_mark_locations(rb_gc_stack_start, (VALUE*)STACK_END + 1);
+  if ((VALUE*)STACK_END < rb_gc_stack_start)
+    rb_gc_mark_locations(th->machine_stack_end, th->machin_stack_start);
+  else
+    rb_gc_mark_locations(th->machin_stack_start, th->machine_stack_end + 1);
 #endif
 #ifdef __ia64__
-    /* mark backing store (flushed register window on the stack) */
-    /* the basic idea from guile GC code                         */
-    {
-	ucontext_t ctx;
-	VALUE *top, *bot;
+  /* mark backing store (flushed register window on the stack) */
+  /* the basic idea from guile GC code                         */
+  {
+    ucontext_t ctx;
+    VALUE *top, *bot;
 #if defined(HAVE_UNWIND_H) && defined(HAVE__UNW_CREATECONTEXTFORSELF)
-	_Unwind_Context *unwctx = _UNW_createContextForSelf();
+    _Unwind_Context *unwctx = _UNW_createContextForSelf();
 #endif
 
-	getcontext(&ctx);
-	mark_locations_array((VALUE*)&ctx.uc_mcontext,
-			     ((size_t)(sizeof(VALUE)-1 + sizeof ctx.uc_mcontext)/sizeof(VALUE)));
+    getcontext(&ctx);
+    mark_locations_array((VALUE*)&ctx.uc_mcontext,
+                         ((size_t)(sizeof(VALUE)-1 + sizeof ctx.uc_mcontext)/sizeof(VALUE)));
 #if defined(HAVE_UNWIND_H) && defined(HAVE__UNW_CREATECONTEXTFORSELF)
-	_UNW_currentContext(unwctx);
-	bot = (VALUE*)(long)_UNW_getAR(unwctx, _UNW_AR_BSP);
-	top = (VALUE*)(long)_UNW_getAR(unwctx, _UNW_AR_BSPSTORE);
-	_UNW_destroyContext(unwctx);
+    _UNW_currentContext(unwctx);
+    bot = (VALUE*)(long)_UNW_getAR(unwctx, _UNW_AR_BSP);
+    top = (VALUE*)(long)_UNW_getAR(unwctx, _UNW_AR_BSPSTORE);
+    _UNW_destroyContext(unwctx);
 #else
-	bot = (VALUE*)__libc_ia64_register_backing_store_base;
-	top = (VALUE*)ctx.uc_mcontext.IA64_BSPSTORE;
+    bot = (VALUE*)__libc_ia64_register_backing_store_base;
+    top = (VALUE*)ctx.uc_mcontext.IA64_BSPSTORE;
 #endif
-	rb_gc_mark_locations(bot, top);
-    }
+    rb_gc_mark_locations(bot, top);
+  }
 #endif
 #if defined(__human68k__) || defined(__mc68000__)
-    rb_gc_mark_locations((VALUE*)((char*)STACK_END + 2),
-			 (VALUE*)((char*)rb_gc_stack_start + 2));
+  rb_gc_mark_locations((VALUE*)((char*)STACK_END + 2),
+                       (VALUE*)((char*)rb_gc_stack_start + 2));
 #endif
-    rb_gc_mark_threads();
+  rb_gc_mark_threads();
 
-    /* mark protected global variables */
-    for (list = global_List; list; list = list->next) {
-	rb_gc_mark_maybe(*list->varptr);
-    }
-    rb_mark_end_proc();
-    rb_gc_mark_global_tbl();
+  /* mark protected global variables */
+  for (list = global_List; list; list = list->next) {
+    rb_gc_mark_maybe(*list->varptr);
+  }
+  rb_mark_end_proc();
+  rb_gc_mark_global_tbl();
 
-    rb_mark_tbl(rb_class_tbl);
-    rb_gc_mark_trap_list();
+  rb_mark_tbl(rb_class_tbl);
+  rb_gc_mark_trap_list();
 
-    /* mark generic instance variables for special constants */
-    rb_mark_generic_ivar_tbl();
+  /* mark generic instance variables for special constants */
+  rb_mark_generic_ivar_tbl();
 
-    rb_gc_mark_parser();
+  rb_gc_mark_parser();
 
-    /* gc_mark objects whose marking are not completed*/
-    while (!MARK_STACK_EMPTY){
-	if (mark_stack_overflow){
-	    gc_mark_all();
-	}
-	else {
-	    gc_mark_rest();
-	}
+  /* gc_mark objects whose marking are not completed*/
+  while (!MARK_STACK_EMPTY){
+    if (mark_stack_overflow){
+      gc_mark_all();
     }
-    gc_sweep();
+    else {
+      gc_mark_rest();
+    }
+  }
+  gc_sweep();
 
-    return Qtrue;
+  return Qtrue;
 }
 
 void
+yarv_machine_stack_mark(yarv_thread_t *th)
+{
+#if STACK_GROW_DIRECTION < 0
+  rb_gc_mark_locations(th->machine_stack_end, th->machine_stack_start);
+#elif STACK_GROW_DIRECTION > 0
+  rb_gc_mark_locations(th->machin_stack_start, th->machine_stack_end);
+#else
+#error "TODO"
+#endif
+}
+
+
+void
 rb_gc(void)
 {
     garbage_collect();

Modified: trunk/insns.def
===================================================================
--- trunk/insns.def	2005-09-29 14:01:52 UTC (rev 266)
+++ trunk/insns.def	2005-09-30 06:08:45 UTC (rev 267)
@@ -1364,6 +1364,7 @@
 (VALUE val)
 (VALUE val)
 {
+  YARV_CHECK_INTS();
   POP_CONTROL_STACK_FRAME(th);
   RESTORE_REGS();
 }

Modified: trunk/test.rb
===================================================================
--- trunk/test.rb	2005-09-29 14:01:52 UTC (rev 266)
+++ trunk/test.rb	2005-09-30 06:08:45 UTC (rev 267)
@@ -1,9 +1,13 @@
 
-p YARVCore::VM::Thread.new{
-  
+10.times{|e|
+  Thread.new(e){|le|
+    10000.times{|i|
+      p [le, i]
+    }
+  }
 }
+sleep 10
 
-
 __END__
 
 require 'test_req'

Added: trunk/thread.c
===================================================================
--- trunk/thread.c	2005-09-29 14:01:52 UTC (rev 266)
+++ trunk/thread.c	2005-09-30 06:08:45 UTC (rev 267)
@@ -0,0 +1,497 @@
+/*
+ * YARVCore::VM::Thread
+ */
+
+/*
+  YARV Thread Desgin
+
+  mode 1: Userlevel Thread
+    Same as traditional ruby thread.
+
+  mode 2: Native Thread with Giant VM lock
+    Using pthread (or Windows thread) and Ruby threads run concurrent.
+
+  mode 3: Native Thread with fine grain lock
+    Using pthread and Ruby threads run concurrent or parallel.
+
+------------------------------------------------------------------------
+
+  mode 2:
+    A thread has mutex (GIL: Global Interpreter Lock) can run.  When
+    thread scheduling, running thread release GIL.  If running thread
+    try blocking operation, this thread must release GIL and another
+    thread can continue this flow.  After blocking operation, thread
+    must check interrupt (CHECK_INTS).
+
+    Every VM can run parallel.
+
+    Ruby threads are scheduled by OS thread scheduler.
+
+------------------------------------------------------------------------
+
+  mode 3:
+    Every threads run concurrent and to access shared object exclusive
+    access control is needed.  For example, to access String object or
+    Array object, fine grain lock must be locked every time.
+ */
+
+
+/* for pthread (mode 2) */
+
+#include "eval_intern.h"
+
+#define THREAD_DEBUG 0
+
+#if THREAD_DEBUG
+#define thead_debug printf
+#else
+#define thead_debug if(0)printf
+#endif
+
+
+/********************************************************************************/
+
+void
+static thread_cleanup_func(void *th_ptr)
+{
+  yarv_thread_t *th = th_ptr;
+  rb_hash_delete(GET_VM()->living_threads, th->self);
+  th->status = THREAD_KILLED;
+  th->machine_stack_start = th->machine_stack_end = 0;
+}
+
+VALUE th_eval_body(yarv_thread_t *th);
+
+NOINLINE(static int
+         thread_start_func_2(yarv_thread_t *th, VALUE *stack_start));
+
+static int
+thread_start_func_2(yarv_thread_t *th, VALUE *stack_start)
+{
+  VALUE args = th->first_args;
+  yarv_proc_t *proc;
+  GetProcVal(th->first_proc, proc);
+
+  th->machine_stack_start = stack_start;
+  
+  thead_debug("start: %p\n", th);
+  GIL_LOCK_BEGIN();
+  yarv_set_current_running_thread(th);
+  thead_debug("get_lock, start: %p\n", th);
+  th->value = th_invoke_proc(th, proc, RARRAY(args)->len, RARRAY(args)->ptr);
+  th->status = THREAD_KILLED;
+  thead_debug("end: %p\n", th);
+  rb_hash_delete(GET_VM()->living_threads, th->self);
+
+  GIL_LOCK_END();
+
+  return 0;
+}
+
+static void *
+thread_start_func_1(void *th_ptr)
+{
+  yarv_thread_t *th = th_ptr;
+  VALUE stack_start;
+  /* ignore self and klass */
+  
+  native_cleanup_push(thread_cleanup_func, th);
+
+  /* run */
+  thread_start_func_2(th, &stack_start);
+  thread_cleanup_func(th);
+  native_cleanup_pop(0);
+  return 0;
+}
+
+#if HAVE_PTHREAD_H
+int
+native_thread_crteate(yarv_thread_t *th)
+{
+  pthread_attr_t attr;
+  size_t stack_size = 16 * 1024;
+  int err;
+
+  thead_debug("create: %p, stack size: %d\n", th, stack_size);
+
+  pthread_attr_init(&attr);
+  pthread_attr_setstacksize(&attr, stack_size);
+  err = pthread_create(&th->thread_id, &attr, thread_start_func_1, th);
+  if(err != 0){
+    th->status = THREAD_KILLED;
+    rb_raise(rb_eThreadError, "can't create Thread (%d)", err);
+  }
+  return err;
+}
+#else
+#error "unsupported"
+#endif
+
+static VALUE
+yarv_thread_s_new(VALUE klass, VALUE args)
+{
+  yarv_thread_t *th;
+  VALUE thval;
+  
+  /* create thread object */
+  thval= rb_class_new_instance(0, 0, cYarvThread);
+  GetThreadVal(thval, th);
+  rb_hash_aset(GET_VM()->living_threads, thval, Qtrue);
+  
+  /* setup thread environment */
+  th->first_args = args;
+  th->first_proc = rb_block_proc();
+
+  /* kick thread */
+  native_thread_crteate(th);
+  return thval;
+}
+
+static VALUE
+yarv_thread_join(int argc, VALUE *argv, VALUE self)
+{
+  yarv_thread_t *th;
+  int err;
+  GetThreadVal(self, th);
+
+  if(th->status == THREAD_KILLED){
+    return self;
+  }
+  
+  GIL_UNLOCK_BEGIN();
+  err = native_thread_join(th->thread_id, 0);
+  GIL_UNLOCK_END();
+
+  switch(err){
+  case EDEADLK:
+    rb_raise(rb_eThreadError, "can't join current thread (cause dead lock)");
+  }
+  return self;
+}
+
+static VALUE
+yarv_thread_value(VALUE self)
+{
+  yarv_thread_t *th;
+  yarv_thread_join(0, 0, self);
+  GetThreadVal(self, th);
+  return th->value;
+}
+
+#if !defined HAVE_PAUSE
+# if defined _WIN32 && !defined __CYGWIN__
+#  define pause() Sleep(INFINITE)
+# else
+#  define pause() sleep(0x7fffffff)
+# endif
+#endif
+
+void
+rb_thread_sleep_forever()
+{
+  GIL_UNLOCK_BEGIN();
+  pause();
+  GIL_UNLOCK_END();
+}
+
+static double
+timeofday(void)
+{
+    struct timeval tv;
+    gettimeofday(&tv, NULL);
+    return (double)tv.tv_sec + (double)tv.tv_usec * 1e-6;
+}
+
+static void
+sleep_timeval(struct timeval time)
+{
+#ifndef linux
+  double d, limit;
+  limit = timeofday()+(double)time.tv_sec+(double)time.tv_usec*1e-6;
+#endif
+  for (;;) {
+    int n = select(0, 0, 0, 0, &time);
+    if (n == 0) return;
+    if (n < 0) {
+      switch (errno) {
+      case EINTR:
+#ifdef ERESTART
+      case ERESTART:
+#endif
+        return;
+      default:
+        rb_sys_fail("sleep");
+      }
+    }
+#ifndef linux
+    d = limit - timeofday();
+
+    time.tv_sec = (int)d;
+    time.tv_usec = (int)((d - (int)d)*1e6);
+    if (time.tv_usec < 0) {
+      time.tv_usec += (long)1e6;
+      time.tv_sec -= 1;
+    }
+    if (time.tv_sec < 0) return;
+#endif
+  }
+}
+
+void
+rb_thread_wait_for(struct timeval time)
+{
+  double date;
+  
+  CSL_UNLOCK_BEGIN();
+  GIL_UNLOCK_BEGIN();
+  sleep_timeval(time);
+  GIL_UNLOCK_END();
+  CSL_UNLOCK_END();
+}
+
+static VALUE
+yarv_thread_s_current(VALUE klass){
+  return GET_THREAD()->self;
+}
+
+static VALUE
+yarv_thread_s_main(VALUE klass){
+  return GET_VM()->main_thread;
+}
+
+
+VALUE
+rb_thread_local_aref(VALUE thread, ID id)
+{
+  yarv_thread_t *th;
+  VALUE val;
+
+  GetThreadVal(thread, th);
+  if(ruby_safe_level >= 4 && th != GET_THREAD()){
+    rb_raise(rb_eSecurityError, "Insecure: thread locals");
+  }
+  if(!th->local_storage){
+    return Qnil;
+  }
+  if(st_lookup(th->local_storage, id, &val)){
+    return val;
+  }
+  return Qnil;
+}
+
+
+/*
+ *  call-seq:
+ *      thr[sym]   => obj or nil
+ *  
+ *  Attribute Reference---Returns the value of a thread-local variable, using
+ *  either a symbol or a string name. If the specified variable does not exist,
+ *  returns <code>nil</code>.
+ *     
+ *     a = Thread.new { Thread.current["name"] = "A"; Thread.stop }
+ *     b = Thread.new { Thread.current[:name]  = "B"; Thread.stop }
+ *     c = Thread.new { Thread.current["name"] = "C"; Thread.stop }
+ *     Thread.list.each {|x| puts "#{x.inspect}: #{x[:name]}" }
+ *     
+ *  <em>produces:</em>
+ *     
+ *     #<Thread:0x401b3b3c sleep>: C
+ *     #<Thread:0x401b3bc8 sleep>: B
+ *     #<Thread:0x401b3c68 sleep>: A
+ *     #<Thread:0x401bdf4c run>:
+ */
+
+static VALUE
+rb_thread_aref(VALUE thread, VALUE id)
+{
+  return rb_thread_local_aref(thread, rb_to_id(id));
+}
+
+VALUE
+rb_thread_local_aset(VALUE thread, ID id, VALUE val)
+{
+  yarv_thread_t *th;
+  GetThreadVal(thread, th);
+  
+  if(ruby_safe_level >= 4 && th != GET_THREAD()){
+    rb_raise(rb_eSecurityError, "Insecure: can't modify thread locals");
+  }
+  if(OBJ_FROZEN(thread)){
+    rb_error_frozen("thread locals");
+  }
+  if(!th->local_storage){
+    th->local_storage = st_init_numtable();
+  }
+  if(NIL_P(val)){
+    st_delete(th->local_storage, (st_data_t*)&id, 0);
+    return Qnil;
+  }
+  st_insert(th->local_storage, id, val);
+  return val;
+}
+
+/*
+ *  call-seq:
+ *      thr[sym] = obj   => obj
+ *  
+ *  Attribute Assignment---Sets or creates the value of a thread-local variable,
+ *  using either a symbol or a string. See also <code>Thread#[]</code>.
+ */
+
+static VALUE
+rb_thread_aset(VALUE thread, ID id, VALUE val)
+{
+  return rb_thread_local_aset(thread, rb_to_id(id), val);
+}
+
+
+/*
+ *  call-seq:
+ *     thr.key?(sym)   => true or false
+ *  
+ *  Returns <code>true</code> if the given string (or symbol) exists as a
+ *  thread-local variable.
+ *     
+ *     me = Thread.current
+ *     me[:oliver] = "a"
+ *     me.key?(:oliver)    #=> true
+ *     me.key?(:stanley)   #=> false
+ */
+
+static VALUE
+rb_thread_key_p(VALUE thread, ID id)
+{
+  yarv_thread_t *th;
+  GetThreadVal(thread, th);
+  
+  if(!th->local_storage){
+    return Qfalse;
+  }
+  if(st_lookup(th->local_storage, rb_to_id(id), 0)){
+    return Qtrue;
+  }
+  return Qfalse;
+}
+
+static int
+thread_keys_i(ID key, VALUE value, VALUE ary)
+{
+  rb_ary_push(ary, ID2SYM(key));
+  return ST_CONTINUE;
+}
+
+
+/*
+ *  call-seq:
+ *     thr.keys   => array
+ *  
+ *  Returns an an array of the names of the thread-local variables (as Symbols).
+ *     
+ *     thr = Thread.new do
+ *       Thread.current[:cat] = 'meow'
+ *       Thread.current["dog"] = 'woof'
+ *     end
+ *     thr.join   #=> #<Thread:0x401b3f10 dead>
+ *     thr.keys   #=> [:dog, :cat]
+ */
+
+static VALUE
+rb_thread_keys(thread)
+    VALUE thread;
+{
+  yarv_thread_t *th;
+  GetThreadVal(thread, th);
+  VALUE ary = rb_ary_new();
+
+  if(th->local_storage){
+    st_foreach(th->local_storage, thread_keys_i, ary);
+  }
+  return ary;
+}
+
+void
+yarv_thraed_schedule()
+{
+  if(GET_VM()->thread_critical == 0){
+    yarv_thread_t *th = GET_THREAD(); 
+    yarv_save_machine_context(th);
+    native_mutex_unlock(&GET_VM()->global_interpreter_lock);
+    native_mutex_lock(&GET_VM()->global_interpreter_lock);
+    yarv_set_current_running_thread(th);
+  }
+}
+
+static VALUE
+yarv_thread_s_pass(VALUE klass)
+{
+  yarv_thraed_schedule();
+  return Qnil;
+}
+
+void
+yarv_set_stack_end(VALUE **stack_end_p)
+{
+    VALUE stack_end;
+    *stack_end_p = &stack_end;
+}
+
+void
+yarv_save_machine_context(yarv_thread_t *th)
+{
+  yarv_set_stack_end(&th->machine_stack_end);
+  setjmp(th->machine_regs);
+}
+
+static pthread_t time_thread;
+
+static void*
+thread_timer(void *dummy)
+{
+  for (;;) {
+#ifdef HAVE_NANOSLEEP
+    struct timespec req, rem;
+
+    req.tv_sec = 0;
+    req.tv_nsec = 10000000;
+    nanosleep(&req, &rem);
+#else
+    struct timeval tv;
+    tv.tv_sec = 0;
+    tv.tv_usec = 10000;
+    select(0, NULL, NULL, NULL, &tv);
+#endif
+    theYarvVM->interrupt_flag = 1;
+  }
+}
+
+void
+Init_yarvthread(){
+  rb_define_singleton_method(cYarvThread, "new", yarv_thread_s_new, -2);
+  rb_define_singleton_method(cYarvThread, "start", yarv_thread_s_new, -2);
+  rb_define_singleton_method(cYarvThread, "fork", yarv_thread_s_new, -2);
+
+  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, "join", yarv_thread_join, -1);
+  rb_define_method(cYarvThread, "value", yarv_thread_value, 0);
+  rb_define_method(cYarvThread, "[]", rb_thread_aref, 1);
+  rb_define_method(cYarvThread, "[]=", rb_thread_aset, 2);
+  rb_define_method(cYarvThread, "key?", rb_thread_key_p, 1);
+  rb_define_method(cYarvThread, "keys", rb_thread_keys, 0);
+
+  if(time_thread == 0){
+    pthread_create(&time_thread, 0, thread_timer, 0);
+  }
+
+  {
+    /* main thread setting */
+    {
+      /* acquire global interpreter lock */
+      yarv_thread_lock_t *lp = &GET_VM()->global_interpreter_lock;
+      yarv_thread_lock_initialize(*lp);
+      native_mutex_lock(lp);
+    }
+  }
+}
+


Property changes on: trunk/thread.c
___________________________________________________________________
Name: svn:executable
   + *

Added: trunk/thread_pthread.h
===================================================================
--- trunk/thread_pthread.h	2005-09-29 14:01:52 UTC (rev 266)
+++ trunk/thread_pthread.h	2005-09-30 06:08:45 UTC (rev 267)
@@ -0,0 +1,19 @@
+
+#ifndef THREAD_PTHREAD_H_INCLUDED
+#define THREAD_PTHREAD_H_INCLUDED
+
+#include <pthread.h>
+typedef pthread_t yarv_thread_id_t;
+typedef pthread_mutex_t yarv_thread_lock_t;
+
+#define native_mutex_lock   pthread_mutex_lock
+#define native_mutex_unlock pthread_mutex_unlock
+#define native_thread_join  pthread_join
+
+#define yarv_thread_lock_initialize(lock) \
+  ((lock) = PTHREAD_MUTEX_INITIALIZER)
+
+#define native_cleanup_push pthread_cleanup_push
+#define native_cleanup_pop  pthread_cleanup_pop
+
+#endif /* THREAD_PTHREAD_H_INCLUDED */


Property changes on: trunk/thread_pthread.h
___________________________________________________________________
Name: svn:executable
   + *

Modified: trunk/yarv.h
===================================================================
--- trunk/yarv.h	2005-09-29 14:01:52 UTC (rev 266)
+++ trunk/yarv.h	2005-09-30 06:08:45 UTC (rev 267)
@@ -21,13 +21,47 @@
 #define SET_YARV_STOP() 
 #endif
 
-VALUE yarv_get_current_running_vm_value _(());
-VALUE yarv_get_current_running_thread_value _(());
 
-yarv_vm_t *yarv_get_current_running_vm _(());
-yarv_thread_t *yarv_get_current_running_thread _(());
+#if YARV_THREAD_MODEL == 2
+extern yarv_thread_t *yarvCurrentThread;
+extern yarv_vm_t *theYarvVM;
 
+static inline VALUE
+yarv_get_current_running_vm_value()
+{
+  return theYarvVM->self;
+}
+
+static inline VALUE
+yarv_get_current_running_thread_value()
+{
+  return yarvCurrentThread->self;
+}
+
+static inline yarv_vm_t *
+yarv_get_current_running_vm()
+{
+  return theYarvVM;
+}
+
+static inline yarv_thread_t *
+yarv_get_current_running_thread()
+{
+  return yarvCurrentThread;
+}
+
+static inline void
+yarv_set_current_running_thread(yarv_thread_t *th)
+{
+  yarvCurrentThread = th;
+}
+
+#else
+#error "unsupported thread model"
+#endif
+
 #define GET_THREAD() yarv_get_current_running_thread()
+#define GET_VM()     yarv_get_current_running_vm()
 
 struct yarv_yield_data{
   yarv_thread_t *th;

Modified: trunk/yarvcore.c
===================================================================
--- trunk/yarvcore.c	2005-09-29 14:01:52 UTC (rev 266)
+++ trunk/yarvcore.c	2005-09-30 06:08:45 UTC (rev 267)
@@ -59,7 +59,8 @@
 #define va_init_list(a,b) va_start(a)
 #endif
 
-#if 0
+#define MARK_FREE_DEBUG 0
+#if MARK_FREE_DEBUG
 #define MARK_REPORT(msg) printf("mark: %s\n", msg)
 #define FREE_REPORT(msg) printf("free: %s\n", msg)
 #define GC_INFO printf
@@ -81,41 +82,11 @@
 void yarv_setup(void *p1, void *p2, void *p3, void *p4,
                 void *p5, void *p6, void *p7, void *p8);
 
-static yarv_thread_t *yarvCurrentRunningThread = 0;
-static yarv_vm_t *theYarvVM = 0;
+yarv_thread_t *yarvCurrentThread = 0;
+yarv_vm_t *theYarvVM = 0;
 static VALUE yarvVMArray = Qnil;
 
 VALUE
-yarv_get_current_running_vm_value()
-{
-  return theYarvVM->self;
-}
-
-VALUE
-yarv_get_current_running_thread_value()
-{
-  return yarvCurrentRunningThread->self;
-}
-
-yarv_vm_t *
-yarv_get_current_running_vm()
-{
-  return theYarvVM;
-}
-
-yarv_thread_t *
-yarv_get_current_running_thread()
-{
-  return yarvCurrentRunningThread;
-}
-
-void
-yarv_set_current_running_thread(yarv_thread_t *th)
-{
-  yarvCurrentRunningThread = th;
-}
-
-VALUE
 th_invoke_yield(yarv_thread_t *th, int argc, VALUE *argv);
 
 /* rb_yield_values */
@@ -207,7 +178,7 @@
   argv[4] = ISEQ_TYPE_TOP;
   iseq = rb_class_new_instance(5, argv, cYarvISeq);
 
-  vm_eval(yarv_get_current_running_vm_value(), iseq);
+  vm_eval(GET_VM()->self, iseq);
   return 0;
 }
 
@@ -275,7 +246,7 @@
 {
   VALUE vm;
   VALUE ret;
-  vm = yarv_get_current_running_vm_value();
+  vm = GET_VM()->self;
   ret = vm_eval(vm, iseq);
   return ret;
 }
@@ -533,7 +504,7 @@
   MARK_REPORT("-> vm");
   if(ptr){
     vmobj = ptr;
-    rb_gc_mark(vmobj->main_thread);
+    rb_gc_mark(vmobj->living_threads);
   }
   MARK_REPORT("<- vm");
 }
@@ -576,11 +547,16 @@
     th = ptr;
     FREE_UNLESS_NULL(th->stack);
     FREE_UNLESS_NULL(th->top_local_tbl);
+    if(th->local_storage){
+      st_free_table(th->local_storage);
+    }
     ruby_xfree(ptr);
   }
   FREE_REPORT("<- thread");
 }
 
+void yarv_machine_stack_mark(yarv_thread_t *th);
+
 static void thread_mark(void *ptr){
   yarv_thread_t *th;
   MARK_REPORT("-> thread");
@@ -601,8 +577,16 @@
     
     /* mark ruby objects */
     MARK_UNLESS_NULL(th->vm_value);
-    MARK_UNLESS_NULL(th->stat_insn_usage);
     MARK_UNLESS_NULL(th->klass_nest_stack);
+    MARK_UNLESS_NULL(th->first_proc);
+    MARK_UNLESS_NULL(th->first_args);
+    MARK_UNLESS_NULL(th->stat_insn_usage);
+    
+    if(GET_THREAD() != th &&
+       th->machine_stack_start &&
+       th->machine_stack_end){
+      yarv_machine_stack_mark(th);
+    }
   }
   MARK_REPORT("<- thread");
 }
@@ -634,6 +618,8 @@
   th->cfp->dfp = th->stack;
   th->cfp->self = Qnil;
   th->cfp->magic = 0;
+
+  th->status = THREAD_RUNNABLE;
 }
 
 static VALUE
@@ -641,8 +627,7 @@
 {
   yarv_thread_t *th;
   yarv_vm_t *vm;
-  VALUE vmval = yarv_get_current_running_vm_value();
-
+  VALUE vmval = GET_VM()->self;
   GetThreadVal(self, th);
   GetVMVal(vmval, vm);
 
@@ -785,6 +770,8 @@
 // VALUE yarv_Hash_each();
 VALUE insns_name_array();
 
+VALUE Init_yarvthread();
+
 char yarv_version[0x20];
 char *yarv_options = ""
 #if   OPT_DIRECT_THREADED_CODE
@@ -865,12 +852,11 @@
 
   /* declare YARVCore::VM::Thread */
   cYarvThread = rb_define_class_under(cYarvVM, "Thread", rb_cObject);
+  rb_define_global_const("Thread", cYarvThread);
   rb_define_alloc_func(cYarvThread, thread_alloc);
   rb_define_method(cYarvThread, "initialize", thread_init, 0);
   rb_define_method(cYarvThread, "eval",       thread_eval, 1);
   
-  // rb_define_singleton_method(cYarvThread, "new", rb_thread_s_new, -2);
-  
   /* declare YARVCore::VM::Env */
   cYarvEnv = rb_define_class_under(cYarvVM, "Env", rb_cObject);
   rb_define_alloc_func(cYarvEnv, env_alloc);
@@ -954,10 +940,16 @@
     thread_free(GET_THREAD());
     yarv_set_current_running_thread(th);
 
+    extern VALUE *rb_gc_stack_start;
+    th->machine_stack_start = rb_gc_stack_start;
+    Init_yarvthread();
+
+    vm->living_threads = rb_hash_new();
+    rb_hash_aset(vm->living_threads, th->self, Qtrue);
+    
     /*
      * set toplevel binding
      */
-
   }
 }
 

Modified: trunk/yarvcore.h
===================================================================
--- trunk/yarvcore.h	2005-09-29 14:01:52 UTC (rev 266)
+++ trunk/yarvcore.h	2005-09-30 06:08:45 UTC (rev 267)
@@ -6,17 +6,19 @@
 #ifndef _YARVCORE_H_INCLUDED_
 #define _YARVCORE_H_INCLUDED_
 
+#define YARV_THREAD_MODEL 2
+
+#include <setjmp.h>
+
 #include "debug.h"
 #include "vm_opts.h"
+#include "st.h"
 
-#ifdef HAVE_PTHREAD_H
-#include <pthread.h>
-typedef pthread_t yarv_thread_id_t;
-typedef pthread_mutex_t yarv_thread_lock_t;
+#if defined(HAVE_PTHREAD_H)
+#include "thread_pthread.h"
 #else
-typedef int yarv_thread_id_t;
-typedef 
-#endif /* _SAFE_THREAD */
+#error "unsupported thread type"
+#endif
 
 /*****************/
 /* configuration */
@@ -262,11 +264,13 @@
   Data_Get_Struct(obj, yarv_vm_t, tobj)
 
 typedef struct{
-  VALUE main_thread;
   VALUE self;
   
-  /* this data structure should include all
-     runtime information (e.g. method table, object management table, ...) */
+  yarv_thread_lock_t global_interpreter_lock;
+  int thread_critical;
+  VALUE main_thread;
+  VALUE living_threads;
+  int interrupt_flag;
 } yarv_vm_t;
 
 typedef struct{
@@ -293,6 +297,13 @@
 #define GetThreadVal(obj, tobj) \
   Data_Get_Struct(obj, yarv_thread_t, tobj)
 
+enum yarv_thread_status{
+    THREAD_TO_KILL,
+    THREAD_RUNNABLE,
+    THREAD_STOPPED,
+    THREAD_KILLED,
+};
+
 typedef struct{
   VALUE self;
   VALUE vm_value;
@@ -312,9 +323,6 @@
   /* klass/module nest information stack */
   VALUE klass_nest_stack; /* Array */
 
-  /* other information */
-  VALUE stat_insn_usage;
-
   /* passed via parse.y, eval.c (rb_scope_setup_local_tbl) */
   ID *top_local_tbl;
 
@@ -322,13 +330,24 @@
   ID *base_local_tbl;
   int base_local_size;
   yarv_block_t *base_block;
-
+  
   /* thread control */
-  yarv_thread_id_t *thread_id;
+  yarv_thread_id_t thread_id;
   VALUE value;
-  int status;
-  yarv_thread_lock_t global_interpreter_lock;
+  enum yarv_thread_status status;
+
+  VALUE first_proc;
+  VALUE first_args;
+
+  /* for GC */
+  VALUE  *machine_stack_start;
+  VALUE  *machine_stack_end;
+  jmp_buf machine_regs;
   
+  /* other information */
+  st_table *local_storage; /* thread local storage */
+  VALUE stat_insn_usage;
+  
 } yarv_thread_t;
 
 /** node -> yarv instruction sequence object */
@@ -349,7 +368,7 @@
 
 
 /* each thread has this size stack : 2MB */
-#define YARV_THREAD_STACK_SIZE 0x20000
+#define YARV_THREAD_STACK_SIZE (128 * 1024)
 
 
 /* from ruby 1.9 variable.c */
@@ -434,6 +453,48 @@
 
 #include "yarv.h"
 
+#define GIL_LOCK_BEGIN() do { \
+  native_mutex_lock(&GET_VM()->global_interpreter_lock)
+
+#define GIL_LOCK_END() \
+  native_mutex_unlock(&GET_VM()->global_interpreter_lock); \
+} while(0)
+
+#define GIL_UNLOCK_BEGIN() do { \
+  yarv_thread_t *_th_stored = GET_THREAD(); \
+  yarv_save_machine_context(_th_stored); \
+  native_mutex_unlock(&GET_VM()->global_interpreter_lock)
+
+#define GIL_UNLOCK_END() \
+  native_mutex_lock(&GET_VM()->global_interpreter_lock); \
+  yarv_set_current_running_thread(_th_stored); \
+} while(0)
+
+#define CSL_UNLOCK_BEGIN() do { \
+  int _thread_critical = GET_VM()->thread_critical; \
+  GET_VM()->thread_critical = 0
+
+#define CSL_UNLOCK_END() \
+  GET_VM()->thread_critical = _thread_critical; \
+} while(0)
+
+NOINLINE(void yarv_set_stack_end(VALUE **stack_end_p));
+NOINLINE(void yarv_save_machine_context(yarv_thread_t *));
+
+extern int rb_thread_pending;
+
+void yarv_thraed_schedule();
+
+#define YARV_CHECK_INTS() do { \
+  if(theYarvVM->interrupt_flag){ \
+    theYarvVM->interrupt_flag = 0; \
+    /* TODO: trap something event */ \
+    yarv_thraed_schedule(); \
+  } \
+} while (0)
+
+
+
 #endif	// _YARVCORE_H_INCLUDED_
 
 


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

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