yarv-diff:327
From: ko1 atdot.net
Date: 4 May 2006 18:34:08 -0000
Subject: [yarv-diff:327] r494 - in trunk: . yarvtest
Author: ko1
Date: 2006-05-05 03:34:07 +0900 (Fri, 05 May 2006)
New Revision: 494
Modified:
trunk/
trunk/ChangeLog
trunk/eval_thread.c
trunk/intern.h
trunk/signal.c
trunk/thread.c
trunk/thread_pthread.h
trunk/thread_win32.h
trunk/yarv.h
trunk/yarvcore.h
trunk/yarvtest/test_thread.rb
Log:
r764@lermite: ko1 | 2006-05-04 18:14:47 +0900
* eval_thread.c : remove rb_thread_interrupt
* intern.h : ditto
* signal.c : change signal transfer route
* thread.c : ditto
* thread_pthread.h : ditto
* thread_win32.h : ditto
* yarv.h : support GET_VM()
* yarvcore.h : change yarv_thread_t/yarv_vm_t structure
* yarvtest/test_thread.rb : decrease threads to test
Property changes on: trunk
___________________________________________________________________
Name: svk:merge
- 81cd9672-7512-7e48-ae48-6936450e977d:/local/yarv/trunk:762
+ 81cd9672-7512-7e48-ae48-6936450e977d:/local/yarv/trunk:764
Modified: trunk/ChangeLog
===================================================================
--- trunk/ChangeLog 2006-05-03 15:34:08 UTC (rev 493)
+++ trunk/ChangeLog 2006-05-04 18:34:07 UTC (rev 494)
@@ -4,6 +4,27 @@
# from Mon, 03 May 2004 01:24:19 +0900
#
+2006-05-04(Thu) 18:11:43 +0900 Koichi Sasada <ko1 atdot.net>
+
+ * eval_thread.c : remove rb_thread_interrupt
+
+ * intern.h : ditto
+
+ * signal.c : change signal transfer route
+
+ * thread.c : ditto
+
+ * thread_pthread.h : ditto
+
+ * thread_win32.h : ditto
+
+ * yarv.h : support GET_VM()
+
+ * yarvcore.h : change yarv_thread_t/yarv_vm_t structure
+
+ * yarvtest/test_thread.rb : decrease threads to test
+
+
2006-05-04(Thu) 00:26:18 +0900 Koichi Sasada <ko1 atdot.net>
* thread_pthread.h : experimental support of thread cache
Modified: trunk/eval_thread.c
===================================================================
--- trunk/eval_thread.c 2006-05-03 15:34:08 UTC (rev 493)
+++ trunk/eval_thread.c 2006-05-04 18:34:07 UTC (rev 494)
@@ -533,12 +533,6 @@
/***/
void
-rb_thread_interrupt()
-{
- rb_interrupt();
-}
-
-void
rb_thread_atfork(void)
{
// TODO
Modified: trunk/intern.h
===================================================================
--- trunk/intern.h 2006-05-03 15:34:08 UTC (rev 493)
+++ trunk/intern.h 2006-05-04 18:34:07 UTC (rev 494)
@@ -270,7 +270,6 @@
VALUE rb_thread_run(VALUE);
VALUE rb_thread_kill(VALUE);
VALUE rb_thread_create(VALUE (*)(ANYARGS), void*);
-void rb_thread_interrupt(void);
void rb_thread_trap_eval(VALUE, int, int);
void rb_thread_signal_raise(void *, const char*); /* should pass literal */
void rb_thread_signal_exit(void *);
Modified: trunk/signal.c
===================================================================
--- trunk/signal.c 2006-05-03 15:34:08 UTC (rev 493)
+++ trunk/signal.c 2006-05-04 18:34:07 UTC (rev 494)
@@ -392,24 +392,61 @@
static RETSIGTYPE
sighandler(int sig)
{
- yarv_thread_t *th = GET_THREAD()->vm->main_thread; // TODO: fix me
- 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.\n", sig);
- }
- else{
- th->signal_queue.buff[th->signal_queue.head] = sig;
- th->signal_queue.head = next_head;
- }
+ yarv_vm_t *vm = GET_VM(); /* fix me for Multi-VM */
+ ATOMIC_INC(vm->signal_buff[sig]);
+ ATOMIC_INC(vm->bufferd_signal_size);
+}
- if(th->status == THREAD_STOPPED){
- native_thread_interrupt(th);
- }
- th->interrupt_flag = 1;
+# ifdef HAVE_SIGPROCMASK
+static sigset_t trap_last_mask;
+# else
+static int trap_last_mask;
+# endif
+
+void
+rb_disable_interrupt(void)
+{
+#ifndef _WIN32
+#ifdef HAVE_SIGPROCMASK
+ sigset_t mask;
+ sigfillset(&mask);
+ sigdelset(&mask, SIGVTALRM);
+ sigprocmask(SIG_SETMASK, &mask, NULL);
+#else
+ int mask;
+ mask = sigblock((~0) ^ (1<<SIGVTALRM));
+ sigsetmask(mask);
+#endif
+ trap_last_mask = mask;
+#endif
}
+static void
+rb_enable_interrupt(void)
+{
+ rb_trap_restore_mask();
+}
+
+int
+rb_get_next_signal(yarv_vm_t *vm)
+{
+ int i, sig = 0;
+
+ for (i=1; i<RUBY_NSIG; i++) {
+ if (vm->signal_buff[i] > 0) {
+ rb_disable_interrupt();
+ {
+ ATOMIC_DEC(vm->signal_buff[i]);
+ ATOMIC_DEC(vm->bufferd_signal_size);
+ }
+ rb_enable_interrupt();
+ sig = i;
+ break;
+ }
+ }
+ return sig;
+}
+
#ifdef SIGBUS
static RETSIGTYPE
sigbus(int sig)
@@ -463,7 +500,7 @@
if (cmd == 0) {
switch (sig) {
case SIGINT:
- rb_thread_interrupt();
+ rb_interrupt();
break;
#ifdef SIGHUP
case SIGHUP:
@@ -522,12 +559,6 @@
VALUE sig, cmd;
};
-# ifdef HAVE_SIGPROCMASK
-static sigset_t trap_last_mask;
-# else
-static int trap_last_mask;
-# endif
-
static VALUE
trap(struct trap_arg *arg)
{
@@ -789,26 +820,7 @@
}
}
-#ifdef HAVE_NATIVETHREAD
static void
-install_nativethread_sighandler(int signum, sighandler_t handler)
-{
- sighandler_t old;
- int old_st;
-
- old_st = rb_trap_accept_nativethreads[signum];
- old = ruby_nativethread_signal(signum, handler);
- if (old != SIG_DFL) {
- if (old_st) {
- ruby_nativethread_signal(signum, old);
- } else {
- ruby_signal(signum, old);
- }
- }
-}
-#endif
-
-static void
init_sigchld(int sig)
{
sighandler_t oldfunc;
Modified: trunk/thread.c
===================================================================
--- trunk/thread.c 2006-05-03 15:34:08 UTC (rev 493)
+++ trunk/thread.c 2006-05-04 18:34:07 UTC (rev 494)
@@ -52,6 +52,8 @@
static int rb_thread_dead(yarv_thread_t *th);
void rb_signal_exec(yarv_thread_t *th, int sig);
+void rb_disable_interrupt();
+
static VALUE eKillSignal = INT2FIX(0);
static VALUE eTerminateSignal = INT2FIX(1);
static int system_working = 1;
@@ -132,6 +134,21 @@
YARV_CHECK_INTS(); \
} while(0)
+
+static void
+rb_thread_interrupt(yarv_thread_t *th)
+{
+ th->interrupt_flag = 1;
+ if (th->status == THREAD_STOPPED) {
+ // (*th->interrupt_function)(th);
+ native_thread_interrupt(th);
+ }
+ else {
+ /* none */
+ }
+}
+
+
static int
terminate_i(st_data_t key, st_data_t val, yarv_thread_t *main_thread)
{
@@ -142,11 +159,7 @@
if (th != main_thread) {
thread_debug("terminate_i: %p\n", th);
th->throwed_errinfo = eTerminateSignal;
- th->interrupt_flag = 1;
-
- if (th->status == THREAD_STOPPED) {
- native_thread_interrupt(th);
- }
+ rb_thread_interrupt(th);
th->status = THREAD_TO_KILL;
}
else {
@@ -174,9 +187,9 @@
}
-
VALUE th_eval_body(yarv_thread_t *th);
+
static void
thread_cleanup_func(void *th_ptr)
{
@@ -185,6 +198,7 @@
th->machine_stack_start = th->machine_stack_end = 0;
}
+
static int
thread_start_func_2(yarv_thread_t *th, VALUE *stack_start)
{
@@ -224,7 +238,7 @@
/* wake up joinning threads */
join_th = th->join_list_head;
while (join_th) {
- native_thread_interrupt(join_th);
+ rb_thread_interrupt(join_th);
join_th = join_th->join_list_next;
}
st_delete_wrap(th->vm->living_threads, th->self);
@@ -233,6 +247,7 @@
return 0;
}
+
static VALUE
yarv_thread_s_new(VALUE klass, VALUE args)
{
@@ -284,7 +299,6 @@
}
sleep_wait_for_interrupt(th, limit - now);
}
-
thread_debug("yarv_thread_join: interrupted (thid: %p)\n",
target_th->thread_id);
}
@@ -607,12 +621,9 @@
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];
- // TODO: signal mask
- th->signal_queue.tail =
- (th->signal_queue.tail + 1) % RUBY_SIGNAL_QUEUE_MAX;
- rb_signal_exec(th, sig);
+ if (th->exec_signal) {
+ rb_signal_exec(th, th->exec_signal);
+ th->exec_signal = 0;
}
/* exception from another thread */
@@ -650,9 +661,7 @@
static void
rb_thread_ready(yarv_thread_t *th)
{
- if (th->status == THREAD_STOPPED) {
- native_thread_interrupt(th);
- }
+ rb_thread_interrupt(th);
}
static VALUE
@@ -763,11 +772,8 @@
thread_debug("rb_thread_kill: %p (%p)\n", th, th->thread_id);
- if (th->status == THREAD_STOPPED) {
- native_thread_interrupt(th);
- }
+ rb_thread_interrupt(th);
th->throwed_errinfo = eKillSignal;
- th->interrupt_flag = 1;
th->status = THREAD_TO_KILL;
return thread;
@@ -1576,12 +1582,17 @@
*
*/
-
static void
timer_function(void)
{
- // TODO: GET_VM() should not be used
- GET_THREAD()->vm->running_thread->interrupt_flag = 1;
+ yarv_vm_t *vm = GET_VM(); /* TODO: fix me for Multi-VM */
+ vm->running_thread->interrupt_flag = 1;
+
+ if (vm->bufferd_signal_size && vm->main_thread->exec_signal == 0) {
+ vm->main_thread->exec_signal = rb_get_next_signal(vm);
+ vm->main_thread->interrupt_flag = 1;
+ rb_thread_interrupt(vm->main_thread);
+ }
}
/*
@@ -1994,5 +2005,8 @@
native_mutex_lock(lp);
}
}
+
+ make_timer_thread();
+ rb_disable_interrupt(); /* only timer thread recieve signal */
}
Modified: trunk/thread_pthread.h
===================================================================
--- trunk/thread_pthread.h 2006-05-03 15:34:08 UTC (rev 493)
+++ trunk/thread_pthread.h 2006-05-04 18:34:07 UTC (rev 494)
@@ -52,9 +52,9 @@
thread_start_func_2(yarv_thread_t *th, VALUE *stack_start));
void static thread_cleanup_func(void *th_ptr);
-static void register_cached_thread_and_wait(volatile yarv_thread_t **th);
+static yarv_thread_t *register_cached_thread_and_wait(void);
-#define USE_THREAD_CACHE 0
+#define USE_THREAD_CACHE 1
static void *
thread_start_func_1(void *th_ptr)
@@ -77,11 +77,10 @@
#if USE_THREAD_CACHE
if (1) {
/* cache thread */
- volatile yarv_thread_t * th = 0;
- register_cached_thread_and_wait(&th);
- if (th != 0) {
- pritnf("!\n");
+ yarv_thread_t *th;
+ if ((th = register_cached_thread_and_wait()) != 0) {
th_ptr = (void *)th;
+ th->thread_id = pthread_self();
goto thread_start;
}
}
@@ -101,33 +100,31 @@
struct cached_thread_entry *cached_thread_root;
-static void
-register_cached_thread_and_wait(volatile yarv_thread_t **th_area)
+static yarv_thread_t *
+register_cached_thread_and_wait(void)
{
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
-
+ volatile yarv_thread_t *th_area = 0;
struct cached_thread_entry *entry =
(struct cached_thread_entry *)malloc(sizeof(struct cached_thread_entry));
struct timespec tm = {
- time(0) + 60, 0,
+ time(0) + 60 /* 60 seconds */, 0,
};
pthread_mutex_lock(&thread_cache_lock);
{
- entry->th_area = th_area;
+ entry->th_area = &th_area;
entry->cond = &cond;
entry->next = cached_thread_root;
cached_thread_root = entry;
- }
-
- pthread_cond_timedwait(&cond, &thread_cache_lock, &tm);
-
- {
- struct cached_thread_entry *e = cached_thread_root;
- struct cached_thread_entry *prev = cached_thread_root;
- if (*th_area == 0) {
+ pthread_cond_timedwait(&cond, &thread_cache_lock, &tm);
+
+ {
+ struct cached_thread_entry *e = cached_thread_root;
+ struct cached_thread_entry *prev = cached_thread_root;
+
while (e) {
if (e == entry) {
if (prev == cached_thread_root) {
@@ -142,12 +139,14 @@
e = e->next;
}
}
+ free(entry);
+ pthread_cond_destroy(&cond);
}
- free(entry);
pthread_mutex_unlock(&thread_cache_lock);
+
+ return (yarv_thread_t *)th_area;
}
-
static int
use_cached_thread(yarv_thread_t *th)
{
@@ -177,24 +176,19 @@
int err = 0;
if (use_cached_thread(th)) {
+ thread_debug("create (use cahced thread): %p\n", th);
}
else {
pthread_attr_t attr;
size_t stack_size = 4 * 1024 - sizeof(int); /* 4KB */
- static int init = 0;
- if (!init) {
- make_timer_thread();
- }
-
thread_debug("create: %p, stack size: %ld\n", th, stack_size);
pthread_attr_init(&attr);
pthread_attr_setstacksize(&attr, stack_size);
- pthread_attr_setdetachstate(&attr, 1);
+ pthread_attr_setinheritsched(&attr, PTHREAD_INHERIT_SCHED);
+ pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
- //
-
err = pthread_create(&th->thread_id, &attr, thread_start_func_1, th);
if (err != 0) {
@@ -327,7 +321,7 @@
#ifdef HAVE_NANOSLEEP
struct timespec req, rem;
req.tv_sec = 0;
- req.tv_nsec = 10 * 1000; /* 10 ms */
+ req.tv_nsec = 10 * 1000 * 1000; /* 10 ms */
nanosleep(&req, &rem);
#else
struct timeval tv;
Modified: trunk/thread_win32.h
===================================================================
--- trunk/thread_win32.h 2006-05-03 15:34:08 UTC (rev 493)
+++ trunk/thread_win32.h 2006-05-04 18:34:07 UTC (rev 494)
@@ -221,12 +221,7 @@
native_thread_create(yarv_thread_t *th)
{
size_t stack_size = 4 * 1024 - sizeof(int); /* 4KB */
- static int init = 0;
- if (!init) {
- make_timer_thread();
- }
-
if ((th->thread_id =
w32_create_thread(stack_size, thread_start_func_1, th))
== 0) {
Modified: trunk/yarv.h
===================================================================
--- trunk/yarv.h 2006-05-03 15:34:08 UTC (rev 493)
+++ trunk/yarv.h 2006-05-04 18:34:07 UTC (rev 494)
@@ -39,6 +39,7 @@
return yarvCurrentThread;
}
+#define GET_VM() theYarvVM
#define GET_THREAD() yarvCurrentThread
static inline void
Modified: trunk/yarvcore.h
===================================================================
--- trunk/yarvcore.h 2006-05-03 15:34:08 UTC (rev 493)
+++ trunk/yarvcore.h 2006-05-04 18:34:07 UTC (rev 494)
@@ -28,6 +28,18 @@
#error "unsupported thread type"
#endif
+#include <signal.h>
+
+#ifndef NSIG
+# ifdef DJGPP
+# define NSIG SIGMAX
+# else
+# define NSIG (_SIGMAX + 1) /* For QNX */
+# endif
+#endif
+
+#define RUBY_NSIG NSIG
+
/*****************/
/* configuration */
/*****************/
@@ -285,7 +297,7 @@
struct yarv_thread_struct;
-typedef struct {
+typedef struct yarv_vm_struct {
VALUE self;
yarv_thread_lock_t global_interpreter_lock;
@@ -301,10 +313,11 @@
int exit_code;
unsigned long trace_flag;
-
/* object management */
VALUE mark_object_ary;
-
+
+ int signal_buff[RUBY_NSIG];
+ int bufferd_signal_size;
} yarv_vm_t;
typedef struct {
@@ -360,8 +373,6 @@
struct yarv_tag *prev;
};
-#define RUBY_SIGNAL_QUEUE_MAX 16
-
typedef struct yarv_thread_struct {
VALUE self;
yarv_vm_t *vm;
@@ -400,18 +411,13 @@
VALUE errinfo;
VALUE throwed_errinfo;
int interrupt_flag;
+ int exec_signal;
struct yarv_tag *tag;
int parse_in_eval;
st_table *local_storage; /* thread local storage */
- struct {
- int buff[RUBY_SIGNAL_QUEUE_MAX];
- int head;
- int tail;
- } signal_queue;
-
struct yarv_thread_struct *join_list_next;
struct yarv_thread_struct *join_list_head;
Modified: trunk/yarvtest/test_thread.rb
===================================================================
--- trunk/yarvtest/test_thread.rb 2006-05-03 15:34:08 UTC (rev 493)
+++ trunk/yarvtest/test_thread.rb 2006-05-04 18:34:07 UTC (rev 494)
@@ -31,7 +31,7 @@
def test_create_many_threads2
ae %q{
- 10000.times{|e|
+ 2000.times{|e|
(1..2).map{
Thread.new{
}
--
ML: yarv-diff quickml.atdot.net
Info: http://www.atdot.net/~ko1/quickml