Mon Aug 1 16:49:45 CEST 2005 Paolo Molaro <lupus@ximian.com>
authorPaolo Molaro <lupus@oddwiz.org>
Mon, 1 Aug 2005 14:51:35 +0000 (14:51 -0000)
committerPaolo Molaro <lupus@oddwiz.org>
Mon, 1 Aug 2005 14:51:35 +0000 (14:51 -0000)
* include/private/pthread_support.h, pthread_support.c: added
patch to support registering new threads at runtime (from
Michael Meeks <michael.meeks@novell.com>).

svn path=/trunk/mono/; revision=47889

libgc/ChangeLog
libgc/include/private/pthread_support.h
libgc/pthread_support.c

index 89b941970c81d6e814565ab0dc35f5a8eb352246..0463c3e33df039dc3db3f0b8f792744ce83b87d4 100644 (file)
@@ -1,3 +1,10 @@
+
+Mon Aug 1 16:49:45 CEST 2005 Paolo Molaro <lupus@ximian.com>
+
+       * include/private/pthread_support.h, pthread_support.c: added
+       patch to support registering new threads at runtime (from
+       Michael Meeks <michael.meeks@novell.com>).
+
 2005-07-07  Raja R Harinath  <rharinath@novell.com>
 
        * Makefile.am (INCLUDES): Add $(top_builddir)/.. to pick up mono's
index d52e4da90aa0983d3e032b5effb065e145e9e25e..c00ec51fa7bb98297a543d4d46b733a8f3b36284 100644 (file)
@@ -33,6 +33,7 @@ typedef struct GC_Thread_Rep {
 #      define FINISHED 1       /* Thread has exited.   */
 #      define DETACHED 2       /* Thread is intended to be detached.   */
 #      define MAIN_THREAD 4    /* True for the original thread only.   */
+#       define FOREIGN_THREAD 8 /* Will not be de-registered by us      */
     short thread_blocked;      /* Protected by GC lock.                */
                                /* Treated as a boolean value.  If set, */
                                /* thread will acquire GC lock before   */
@@ -91,6 +92,8 @@ extern GC_bool GC_thr_initialized;
 
 GC_thread GC_lookup_thread(pthread_t id);
 
+void *GC_thread_deregister_foreign (void *data);
+
 void GC_stop_init();
 
 extern GC_bool GC_in_thread_creation;
index bece06f139923c2a99e5eb4c66a8bee22ee5e6d1..24d81ee5d52130577c06a81e9f05b35f3cca4f47 100644 (file)
@@ -221,6 +221,20 @@ static void return_freelists(ptr_t *fl, ptr_t *gfl)
 /* we arrange for those to fault asap.)                                        */
 static ptr_t size_zero_object = (ptr_t)(&size_zero_object);
 
+void GC_delete_thread(pthread_t id);
+
+void *GC_thread_deregister_foreign (void *data)
+{
+    GC_thread me = (GC_thread)data;
+ /*   GC_fprintf1( "\n\n\n\n --- Deregister %x ---\n\n\n\n\n", me->flags ); */
+    if (me -> flags & FOREIGN_THREAD) {
+       LOCK();
+ /*    GC_fprintf0( "\n\n\n\n --- FOO ---\n\n\n\n\n" ); */
+       GC_delete_thread(me->id);
+       UNLOCK();
+    }
+}
+
 /* Each thread structure must be initialized.  */
 /* This call must be made from the new thread. */
 /* Caller holds allocation lock.               */
@@ -229,7 +243,7 @@ void GC_init_thread_local(GC_thread p)
     int i;
 
     if (!keys_initialized) {
-       if (0 != GC_key_create(&GC_thread_key, 0)) {
+       if (0 != GC_key_create(&GC_thread_key, GC_thread_deregister_foreign)) {
            ABORT("Failed to create key for local allocator");
         }
        keys_initialized = TRUE;
@@ -1201,15 +1215,14 @@ WRAP_FUNC(pthread_detach)(pthread_t thread)
 
 GC_bool GC_in_thread_creation = FALSE;
 
-void * GC_start_routine(void * arg)
+typedef void *(*ThreadStartFn)(void *);
+void * GC_start_routine_head(void * arg, void *base_addr,
+                            ThreadStartFn *start, void **start_arg )
 {
-    int dummy;
     struct start_info * si = arg;
     void * result;
     GC_thread me;
     pthread_t my_pthread;
-    void *(*start)(void *);
-    void *start_arg;
 
     my_pthread = pthread_self();
 #   ifdef DEBUG_THREADS
@@ -1232,7 +1245,7 @@ void * GC_start_routine(void * arg)
     /* one for the main thread.  There is a strong argument that that's        */
     /* a kernel bug, but a pervasive one.                              */
 #   ifdef STACK_GROWS_DOWN
-      me -> stack_end = (ptr_t)(((word)(&dummy) + (GC_page_size - 1))
+      me -> stack_end = (ptr_t)(((word)(base_addr) + (GC_page_size - 1))
                                & ~(GC_page_size - 1));
 #        ifndef GC_DARWIN_THREADS
         me -> stop_info.stack_ptr = me -> stack_end - 0x10;
@@ -1240,7 +1253,7 @@ void * GC_start_routine(void * arg)
        /* Needs to be plausible, since an asynchronous stack mark      */
        /* should not crash.                                            */
 #   else
-      me -> stack_end = (ptr_t)((word)(&dummy) & ~(GC_page_size - 1));
+      me -> stack_end = (ptr_t)((word)(base_addr) & ~(GC_page_size - 1));
       me -> stop_info.stack_ptr = me -> stack_end + 0x10;
 #   endif
     /* This is dubious, since we may be more than a page into the stack, */
@@ -1252,19 +1265,56 @@ void * GC_start_routine(void * arg)
       /* from /proc, but the hook to do so isn't there yet.            */
 #   endif /* IA64 */
     UNLOCK();
-    start = si -> start_routine;
-#   ifdef DEBUG_THREADS
-       GC_printf1("start_routine = 0x%lx\n", start);
-#   endif
-    start_arg = si -> arg;
+
+    if (start) *start = si -> start_routine;
+    if (start_arg) *start_arg = si -> arg;
+
     sem_post(&(si -> registered));     /* Last action on si.   */
                                        /* OK to deallocate.    */
-    pthread_cleanup_push(GC_thread_exit_proc, 0);
 #   if defined(THREAD_LOCAL_ALLOC) && !defined(DBG_HDRS_ALL)
        LOCK();
         GC_init_thread_local(me);
        UNLOCK();
 #   endif
+
+    return me;
+}
+
+int GC_thread_register_foreign (void *base_addr)
+{
+    struct start_info si = { 0, }; /* stacked for legibility & locking */
+    GC_thread me;
+
+    GC_printf1( "GC_thread_register_foreign %p\n", &si );
+
+    si.flags = FOREIGN_THREAD;
+
+    if (!parallel_initialized) GC_init_parallel();
+    LOCK();
+    if (!GC_thr_initialized) GC_thr_init();
+
+    UNLOCK();
+
+    me = GC_start_routine_head(&si, base_addr, NULL, NULL);
+
+    return me != NULL;
+}
+
+void * GC_start_routine(void * arg)
+{
+    int dummy;
+    struct start_info * si = arg;
+    void * result;
+    GC_thread me;
+    ThreadStartFn start;
+    void *start_arg;
+
+    me = GC_start_routine_head (arg, &dummy, &start, &start_arg);
+
+    pthread_cleanup_push(GC_thread_exit_proc, 0);
+#   ifdef DEBUG_THREADS
+       GC_printf1("start_routine = 0x%lx\n", start);
+#   endif
     result = (*start)(start_arg);
 #if DEBUG_THREADS
         GC_printf1("Finishing thread 0x%x\n", pthread_self());