Skip to content

Instantly share code, notes, and snippets.

@stephencelis
Created April 19, 2009 15:50
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save stephencelis/98109 to your computer and use it in GitHub Desktop.
Save stephencelis/98109 to your computer and use it in GitHub Desktop.
=== ruby.h
==================================================================
--- ruby.h (/trunk) (revision 16)
+++ ruby.h (/branches/thread-hooks) (revision 16)
@@ -724,6 +724,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 */
=== eval.c
==================================================================
--- eval.c (/trunk) (revision 16)
+++ eval.c (/branches/thread-hooks) (revision 16)
@@ -227,6 +227,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));
@@ -10131,6 +10150,8 @@
thread_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__
@@ -10181,6 +10202,8 @@
VALUE *pos;
int len;
static VALUE tval;
+
+ EXEC_THREADSWITCH_HOOK(RUBY_THREADSWITCH_SAVE,th->thread);
len = ruby_stack_length(&pos);
th->stk_len = 0;
@@ -10313,6 +10336,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 */
@@ -10452,6 +10477,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;
@@ -11631,6 +11691,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);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment