[macruby-changes] [2926] MacRuby/trunk

source_changes at macosforge.org source_changes at macosforge.org
Thu Oct 29 23:34:13 PDT 2009


Revision: 2926
          http://trac.macosforge.org/projects/ruby/changeset/2926
Author:   lsansonetti at apple.com
Date:     2009-10-29 23:34:13 -0700 (Thu, 29 Oct 2009)
Log Message:
-----------
unregister VM objects created from GCD pthreads

Modified Paths:
--------------
    MacRuby/trunk/eval.c
    MacRuby/trunk/gcd.c
    MacRuby/trunk/vm.cpp
    MacRuby/trunk/vm.h

Modified: MacRuby/trunk/eval.c
===================================================================
--- MacRuby/trunk/eval.c	2009-10-30 04:12:21 UTC (rev 2925)
+++ MacRuby/trunk/eval.c	2009-10-30 06:34:13 UTC (rev 2926)
@@ -38,6 +38,7 @@
 void Init_ext(void);
 void Init_PreGC(void);
 void Init_PreVM(void);
+void Init_PreGCD(void);
 
 bool ruby_dlog_enabled = false;
 FILE *ruby_dlog_file = NULL;
@@ -73,6 +74,7 @@
 
     Init_PreGC();
     Init_PreVM();
+    Init_PreGCD();
 
     rb_call_inits();
     ruby_prog_init();

Modified: MacRuby/trunk/gcd.c
===================================================================
--- MacRuby/trunk/gcd.c	2009-10-30 04:12:21 UTC (rev 2925)
+++ MacRuby/trunk/gcd.c	2009-10-30 06:34:13 UTC (rev 2926)
@@ -846,7 +846,41 @@
     }
 }
 
+// GCD callbacks that will let us know when a POSIX thread is started / ended.
+// We can appropriately create/delete a RoxorVM object based on that.
+static void (*old_dispatch_begin_thread_4GC)(void) = NULL;
+static void (*old_dispatch_end_thread_4GC)(void) = NULL;
+extern void (*dispatch_begin_thread_4GC)(void);
+extern void (*dispatch_end_thread_4GC)(void);
+
+static void
+rb_dispatch_begin_thread(void)
+{
+    if (old_dispatch_begin_thread_4GC != NULL) {
+	(*old_dispatch_begin_thread_4GC)();
+    }
+    rb_vm_register_current_alien_thread();
+}
+
+static void
+rb_dispatch_end_thread(void)
+{
+    if (old_dispatch_end_thread_4GC != NULL) {
+	(*old_dispatch_end_thread_4GC)();
+    }
+    rb_vm_unregister_current_alien_thread();
+}
+
 void
+Init_PreGCD(void)
+{
+    old_dispatch_begin_thread_4GC = dispatch_begin_thread_4GC;
+    old_dispatch_end_thread_4GC = dispatch_end_thread_4GC;
+    dispatch_begin_thread_4GC = rb_dispatch_begin_thread;
+    dispatch_end_thread_4GC = rb_dispatch_end_thread;
+}
+
+void
 Init_Dispatch(void)
 {
     high_priority_id = rb_intern("high");
@@ -928,6 +962,12 @@
 #else
 
 void
+Init_PreGCD(void)
+{
+    // Do nothing...
+}
+
+void
 Init_Dispatch(void)
 {
     // Do nothing...

Modified: MacRuby/trunk/vm.cpp
===================================================================
--- MacRuby/trunk/vm.cpp	2009-10-30 04:12:21 UTC (rev 2925)
+++ MacRuby/trunk/vm.cpp	2009-10-30 06:34:13 UTC (rev 2926)
@@ -4374,13 +4374,54 @@
     rb_vm_thread_pre_init(t, NULL, 0, NULL, (void *)this);
     t->thread = pthread_self();
 
-    VALUE main = Data_Wrap_Struct(rb_cThread, NULL, NULL, t);
-    GET_CORE()->register_thread(main);
-    this->set_thread(main);
+    VALUE thread = Data_Wrap_Struct(rb_cThread, NULL, NULL, t);
+    GET_CORE()->register_thread(thread);
+    this->set_thread(thread);
 }
 
 extern "C"
 void
+rb_vm_register_current_alien_thread(void)
+{
+    // This callback is not used, we prefer to create RoxorVM objects
+    // lazily (in RoxorVM::current()), for performance reasons, because the
+    // callback is called *a lot* and most of the time from various parts of
+    // the system which will never ask us to execute Ruby code.
+#if 0
+    if (GET_CORE()->get_running()) {
+	printf("registered alien thread %p\n", pthread_self());
+	RoxorVM *vm = new RoxorVM();
+	vm->setup_from_current_thread();
+    }
+#endif
+}
+
+extern "C"
+void
+rb_vm_unregister_current_alien_thread(void)
+{
+    // Check if the current pthread has been registered.
+    GET_CORE()->lock();
+    pthread_t self = pthread_self();
+    VALUE ary = GET_CORE()->get_threads();
+    bool need_to_unregister = false;
+    for (int i = 0; i < RARRAY_LEN(ary); i++) {
+	VALUE t = RARRAY_AT(ary, i);
+	if (GetThreadPtr(t)->thread == self) {
+	    need_to_unregister = true;
+	}
+    }
+    GET_CORE()->unlock();
+
+    // If yes, appropriately unregister it.
+    if (need_to_unregister) {
+	//printf("unregistered alien thread %p\n", pthread_self());
+	GET_CORE()->unregister_thread(GET_VM()->get_thread());
+    }
+}
+
+extern "C"
+void
 Init_PostVM(void)
 {
     // Create and register the main thread.

Modified: MacRuby/trunk/vm.h
===================================================================
--- MacRuby/trunk/vm.h	2009-10-30 04:12:21 UTC (rev 2925)
+++ MacRuby/trunk/vm.h	2009-10-30 06:34:13 UTC (rev 2926)
@@ -394,6 +394,9 @@
 void rb_vm_thread_cancel(rb_vm_thread_t *t);
 void rb_vm_thread_raise(rb_vm_thread_t *t, VALUE exc);
 
+void rb_vm_register_current_alien_thread(void);
+void rb_vm_unregister_current_alien_thread(void);
+
 bool rb_vm_abort_on_exception(void);
 void rb_vm_set_abort_on_exception(bool flag);
 
@@ -811,7 +814,6 @@
 		    // create a new VM object just for this thread.
 		    // XXX the VM object is never detroyed.
 		    RoxorVM *new_vm = new RoxorVM();
-		    pthread_setspecific(vm_thread_key, (void *)new_vm);
 		    new_vm->setup_from_current_thread();
 		    return new_vm;
 		}
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/macruby-changes/attachments/20091029/7baa1506/attachment.html>


More information about the macruby-changes mailing list