diff -ur ../ruby-1.8.6-p368.org/eval.c ./eval.c --- ../ruby-1.8.6-p368.org/eval.c 2009-03-23 18:26:03.000000000 +0900 +++ ./eval.c 2009-06-11 23:08:09.000000000 +0900 @@ -220,6 +220,25 @@ #include + +typedef struct threadswitch_hook { + rb_threadswitch_hook_func_t func; + struct threadswitch_hook *next; +} rb_threadswitch_hook_t; + +static rb_threadswitch_hook_t *threadswitch_hooks; + +#define EXEC_THREADSWITCH_HOOK(event, thread) \ + do { \ + rb_threadswitch_hook_t *hook = threadswitch_hooks; \ + \ + while (hook) { \ + (*hook->func)(event, thread); \ + hook = hook->next; \ + } \ + } while (0) + + VALUE rb_cProc; VALUE rb_cBinding; static VALUE proc_invoke _((VALUE,VALUE,VALUE,VALUE)); @@ -10232,6 +10251,8 @@ stack_free(th) rb_thread_t th; { + EXEC_THREADSWITCH_HOOK(RUBY_THREADSWITCH_FREE,th->thread); + if (th->stk_ptr) free(th->stk_ptr); th->stk_ptr = 0; #ifdef __ia64 @@ -10291,6 +10312,8 @@ VALUE *pos; size_t len; static VALUE tval; + + EXEC_THREADSWITCH_HOOK(RUBY_THREADSWITCH_SAVE,th->thread); len = ruby_stack_length(&pos); th->stk_len = 0; @@ -10485,6 +10508,8 @@ #define STACK_PAD_SIZE 1024 volatile VALUE space[STACK_PAD_SIZE], *sp = space; + EXEC_THREADSWITCH_HOOK(RUBY_THREADSWITCH_RESTORE,th->thread); + #if !STACK_GROW_DIRECTION if (space < rb_gc_stack_start) { /* Stack grows downward */ @@ -10614,6 +10639,41 @@ rb_thread_main_jump(e, RESTORE_RAISE); } +void * +rb_add_threadswitch_hook(func) + rb_threadswitch_hook_func_t func; +{ + rb_threadswitch_hook_t *hook; + rb_thread_t th; + + hook = ALLOC(rb_threadswitch_hook_t); + hook->func = func; + hook->next = threadswitch_hooks; + threadswitch_hooks = hook; + + FOREACH_THREAD(th) { + (*func)(RUBY_THREADSWITCH_INIT, th->thread); + } END_FOREACH(th); + + return hook; +} + +void +rb_remove_threadswitch_hook(handle) + void *handle; +{ + rb_threadswitch_hook_t **hook_p, *hook; + + for (hook_p = &threadswitch_hooks; *hook_p; hook_p = &hook->next) { + hook = *hook_p; + if (hook == (rb_threadswitch_hook_t*)handle) { + *hook_p = hook->next; + xfree(hook); + return; + } + } +} + static void copy_fds(dst, src, max) fd_set *dst, *src; @@ -11869,6 +11929,8 @@ THREAD_ALLOC(th); th->thread = Data_Wrap_Struct(klass, thread_mark, thread_free, th); + EXEC_THREADSWITCH_HOOK(RUBY_THREADSWITCH_INIT,th->thread); + for (vars = th->dyna_vars; vars; vars = vars->next) { if (FL_TEST(vars, DVAR_DONT_RECYCLE)) break; FL_SET(vars, DVAR_DONT_RECYCLE); Only in .: eval.c.orig diff -ur ../ruby-1.8.6-p368.org/ruby.h ./ruby.h --- ../ruby-1.8.6-p368.org/ruby.h 2008-07-10 13:52:35.000000000 +0900 +++ ./ruby.h 2009-06-11 23:08:09.000000000 +0900 @@ -749,6 +749,19 @@ void ruby_native_thread_kill _((int)); #endif + +typedef unsigned int rb_threadswitch_event_t; + +#define RUBY_THREADSWITCH_INIT 0x01 +#define RUBY_THREADSWITCH_FREE 0x02 +#define RUBY_THREADSWITCH_SAVE 0x04 +#define RUBY_THREADSWITCH_RESTORE 0x08 + +typedef void (*rb_threadswitch_hook_func_t) _((rb_threadswitch_event_t,VALUE)); + +void *rb_add_threadswitch_hook _((rb_threadswitch_hook_func_t func)); +void rb_remove_threadswitch_hook _((void *handle)); + #if defined(__cplusplus) #if 0 { /* satisfy cc-mode */ Only in .: ruby.h.orig