[macruby-changes] [2930] MacRuby/trunk

source_changes at macosforge.org source_changes at macosforge.org
Fri Oct 30 19:34:43 PDT 2009


Revision: 2930
          http://trac.macosforge.org/projects/ruby/changeset/2930
Author:   lsansonetti at apple.com
Date:     2009-10-30 19:34:41 -0700 (Fri, 30 Oct 2009)
Log Message:
-----------
implemented VM cleanup + make sure Threads do not leak resources anymore

Modified Paths:
--------------
    MacRuby/trunk/include/ruby/intern.h
    MacRuby/trunk/thread.c
    MacRuby/trunk/vm.cpp

Modified: MacRuby/trunk/include/ruby/intern.h
===================================================================
--- MacRuby/trunk/include/ruby/intern.h	2009-10-30 19:05:50 UTC (rev 2929)
+++ MacRuby/trunk/include/ruby/intern.h	2009-10-31 02:34:41 UTC (rev 2930)
@@ -612,6 +612,7 @@
 VALUE rb_struct_define_without_accessor(const char *, VALUE, rb_alloc_func_t, ...);
 /* thread.c */
 VALUE rb_thgroup_add(VALUE group, VALUE thread);
+void rb_thread_remove_from_group(VALUE thread);
 typedef void rb_unblock_function_t(void *);
 typedef VALUE rb_blocking_function_t(void *);
 VALUE rb_thread_blocking_region(rb_blocking_function_t *func, void *data1,

Modified: MacRuby/trunk/thread.c
===================================================================
--- MacRuby/trunk/thread.c	2009-10-30 19:05:50 UTC (rev 2929)
+++ MacRuby/trunk/thread.c	2009-10-31 02:34:41 UTC (rev 2930)
@@ -11,15 +11,25 @@
 #include "ruby/node.h"
 #include "vm.h"
 
+VALUE rb_cThread;
+VALUE rb_cThGroup;
+VALUE rb_cMutex;
+
 typedef struct rb_vm_mutex {
     pthread_mutex_t mutex;
     rb_vm_thread_t *thread;
 } rb_vm_mutex_t;
 
-VALUE rb_cThread;
-VALUE rb_cThGroup;
-VALUE rb_cMutex;
+#define GetMutexPtr(obj) ((rb_vm_mutex_t *)DATA_PTR(obj))
 
+typedef struct {
+    bool enclosed;
+    VALUE threads;
+    VALUE mutex;
+} rb_thread_group_t;
+
+#define GetThreadGroupPtr(obj) ((rb_thread_group_t *)DATA_PTR(obj))
+
 #if 0
 static VALUE
 thread_s_new(int argc, VALUE *argv, VALUE klass)
@@ -53,12 +63,21 @@
 
     // Retain the Thread object to avoid a potential GC, the corresponding
     // release is done in rb_vm_thread_run().
-    rb_objc_retain((void *)thread);
+    GC_RETAIN(thread);
 
-    if (pthread_create(&t->thread, NULL, (void *(*)(void *))rb_vm_thread_run,
+    // Prepare attributes for the thread.
+    pthread_attr_t attr;
+    pthread_attr_init(&attr);
+    pthread_attr_setinheritsched(&attr, PTHREAD_INHERIT_SCHED);
+    pthread_attr_setscope(&attr, PTHREAD_SCOPE_SYSTEM);
+    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
+
+    // Launch it.
+    if (pthread_create(&t->thread, &attr, (void *(*)(void *))rb_vm_thread_run,
 		(void *)thread) != 0) {
 	rb_sys_fail("pthread_create() failed");
     }
+    pthread_attr_destroy(&attr);
 
     return thread;
 }
@@ -138,7 +157,14 @@
     if (t->status != THREAD_DEAD) {
 	if (timeout == Qnil) {
 	    // No timeout given: block until the thread finishes.
-	    pthread_assert(pthread_join(t->thread, NULL));
+	    //pthread_assert(pthread_join(t->thread, NULL));
+	    struct timespec ts;
+	    ts.tv_sec = 0;
+	    ts.tv_nsec = 10000000;
+	    while (t->status != THREAD_DEAD) {
+		nanosleep(&ts, NULL);
+		pthread_yield_np();
+	    }
 	}
 	else {
 	    // Timeout given: sleep then check if the thread is dead.
@@ -1083,13 +1109,9 @@
  *  were created.
  */
 
-typedef struct {
-    bool enclosed;
-    VALUE threads;
-} rb_thread_group_t;
+static VALUE mutex_s_alloc(VALUE self, SEL sel);
+static VALUE mutex_initialize(VALUE self, SEL sel);
 
-#define GetThreadGroupPtr(obj) ((rb_thread_group_t *)DATA_PTR(obj))
-
 static VALUE
 thgroup_s_alloc(VALUE self, SEL sel)
 {
@@ -1097,6 +1119,11 @@
 	    sizeof(rb_thread_group_t));
     t->enclosed = false;
     GC_WB(&t->threads, rb_ary_new());
+
+    VALUE mutex = mutex_s_alloc(rb_cMutex, 0);
+    mutex_initialize(mutex, 0);
+    GC_WB(&t->mutex, mutex);
+
     return Data_Wrap_Struct(rb_cThGroup, NULL, NULL, t);
 }
 
@@ -1181,6 +1208,18 @@
  *     tg group now #<Thread:0x401b3c90>
  */
 
+static inline void
+thgroup_lock(rb_thread_group_t *tg)
+{
+    pthread_assert(pthread_mutex_lock(&GetMutexPtr(tg->mutex)->mutex));
+}
+
+static inline void
+thgroup_unlock(rb_thread_group_t *tg)
+{
+    pthread_assert(pthread_mutex_unlock(&GetMutexPtr(tg->mutex)->mutex));
+}
+
 static VALUE
 thgroup_add(VALUE group, SEL sel, VALUE thread)
 {
@@ -1197,10 +1236,14 @@
 	    rb_raise(rb_eThreadError,
 		    "can't move from the enclosed thread group");
 	}
+ 	thgroup_lock(old_tg);
 	rb_ary_delete(old_tg->threads, thread); 
+ 	thgroup_unlock(old_tg);
     }
 
+    thgroup_lock(new_tg);
     rb_ary_push(new_tg->threads, thread);
+    thgroup_unlock(new_tg);
     GC_WB(&t->group, group);
 
     return group;
@@ -1212,6 +1255,21 @@
     return thgroup_add(group, 0, thread);
 }
 
+void
+rb_thread_remove_from_group(VALUE thread)
+{
+    rb_vm_thread_t *t = GetThreadPtr(thread);
+    rb_thread_group_t *tg = GetThreadGroupPtr(t->group);
+    thgroup_lock(tg);
+    if (rb_ary_delete(tg->threads, thread) != thread) {
+	printf("trying to remove a thread (%p) from a group that doesn't "\
+		"contain it\n", (void *)thread);
+	abort();
+    }
+    thgroup_unlock(tg);
+    t->group = Qnil;
+}
+
 /*
  *  Document-class: Mutex
  *
@@ -1251,8 +1309,6 @@
     return Data_Wrap_Struct(rb_cMutex, NULL, NULL, t);
 }
 
-#define GetMutexPtr(obj) ((rb_vm_mutex_t *)DATA_PTR(obj))
-
 static VALUE
 mutex_initialize(VALUE self, SEL sel)
 {

Modified: MacRuby/trunk/vm.cpp
===================================================================
--- MacRuby/trunk/vm.cpp	2009-10-30 19:05:50 UTC (rev 2929)
+++ MacRuby/trunk/vm.cpp	2009-10-31 02:34:41 UTC (rev 2930)
@@ -258,7 +258,6 @@
 
 RoxorCore::~RoxorCore(void)
 {
-    call_all_finalizers();
     // TODO
 }
 
@@ -332,7 +331,17 @@
 
 RoxorVM::~RoxorVM(void)
 {
-    // TODO
+    for (std::map<void *, rb_vm_block_t *>::iterator i = blocks.begin();
+	i != blocks.end();
+	++i) {
+	GC_RELEASE(i->second);
+    }
+    blocks.clear();
+
+    GC_RELEASE(backref);
+    GC_RELEASE(broken_with);
+    GC_RELEASE(last_status);
+    GC_RELEASE(errinfo);
 }
 
 static void
@@ -3630,7 +3639,7 @@
 	s->throw_value = Qnil;
 	s->nested = 1;
 	catch_jmp_bufs[tag] = s;
-	rb_objc_retain((void *)tag);
+	GC_RETAIN(tag);
     }
     else {
 	s = iter->second;
@@ -3654,7 +3663,7 @@
 	s = iter->second;
 	free(s);
 	catch_jmp_bufs.erase(iter);
-	rb_objc_release((void *)tag);
+	GC_RELEASE(tag);
     }
 
     return retval;
@@ -3888,7 +3897,7 @@
     GET_CORE()->register_thread(thread);
 
     // Release the thread now.
-    rb_objc_release((void *)thread);
+    GC_RELEASE(thread);
 
     rb_vm_thread_t *t = GetThreadPtr(thread);
 
@@ -3921,6 +3930,7 @@
 
     pthread_cleanup_pop(0);
 
+    rb_thread_remove_from_group(thread); 
     GET_CORE()->unregister_thread(thread);
     rb_objc_gc_unregister_thread();
 
@@ -4447,7 +4457,11 @@
     printf("functions all=%ld compiled=%ld\n", RoxorCompiler::module->size(),
 	    GET_CORE()->get_functions_compiled());
 #endif
-    
-    delete RoxorCore::shared;
-    RoxorCore::shared = NULL;
+
+
+    // XXX: deleting the core is not safe at this point because there might be
+    // threads still running and trying to unregister.
+//    delete RoxorCore::shared;
+//    RoxorCore::shared = NULL;
+    GET_CORE()->call_all_finalizers();
 }
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/macruby-changes/attachments/20091030/5cf34120/attachment-0001.html>


More information about the macruby-changes mailing list