diff -ur ../ruby-1.8.7-p160.mp_patched/eval.c ./eval.c
--- ../ruby-1.8.7-p160.mp_patched/eval.c	2009-03-23 18:28:31.000000000 +0900
+++ ./eval.c	2009-04-18 00:19:27.000000000 +0900
@@ -217,6 +217,25 @@
 
 #include <sys/stat.h>
 
+
+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));
@@ -10515,6 +10534,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
@@ -10574,6 +10595,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;
@@ -10768,6 +10791,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 */
@@ -10897,6 +10922,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;
@@ -12143,6 +12203,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);
diff -ur ../ruby-1.8.7-p160.mp_patched/ruby.h ./ruby.h
--- ../ruby-1.8.7-p160.mp_patched/ruby.h	2008-07-10 13:54:53.000000000 +0900
+++ ./ruby.h	2009-04-18 00:16:34.000000000 +0900
@@ -766,6 +766,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 */
