From: Paolo Molaro Date: Mon, 1 Aug 2005 14:51:35 +0000 (+0000) Subject: Mon Aug 1 16:49:45 CEST 2005 Paolo Molaro X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=493f35d8b32ed9f98e7f7105c1ff6a749024ab2e;p=gc Mon Aug 1 16:49:45 CEST 2005 Paolo Molaro * include/private/pthread_support.h, pthread_support.c: added patch to support registering new threads at runtime (from Michael Meeks ). svn path=/trunk/mono/; revision=47889 --- diff --git a/ChangeLog b/ChangeLog index 2f93568d..1ddd8dba 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ + +Mon Aug 1 16:49:45 CEST 2005 Paolo Molaro + + * include/private/pthread_support.h, pthread_support.c: added + patch to support registering new threads at runtime (from + Michael Meeks ). + 2005-07-07 Raja R Harinath * Makefile.am (INCLUDES): Add $(top_builddir)/.. to pick up mono's diff --git a/include/private/pthread_support.h b/include/private/pthread_support.h index d52e4da9..c00ec51f 100644 --- a/include/private/pthread_support.h +++ b/include/private/pthread_support.h @@ -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; diff --git a/pthread_support.c b/pthread_support.c index ae66ece9..78505cb7 100644 --- a/pthread_support.c +++ b/pthread_support.c @@ -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; @@ -1160,15 +1174,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 @@ -1191,7 +1204,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; @@ -1199,7 +1212,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, */ @@ -1211,19 +1224,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());