Revision: 2926 http://trac.macosforge.org/projects/ruby/changeset/2926 Author: lsansonetti@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; }