diff options
author | Paolo Molaro <lupus@oddwiz.org> | 2005-08-01 18:51:35 +0400 |
---|---|---|
committer | Paolo Molaro <lupus@oddwiz.org> | 2005-08-01 18:51:35 +0400 |
commit | 20c942a6d27aa7bdaa4687a45ba8085b73ba8947 (patch) | |
tree | bc5ed66a15d4e7acc2c48a21d1c2955550fc2015 /libgc | |
parent | baa5cb3456a8432a09ce173395327768df88381a (diff) |
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>).
svn path=/trunk/mono/; revision=47889
Diffstat (limited to 'libgc')
-rw-r--r-- | libgc/ChangeLog | 7 | ||||
-rw-r--r-- | libgc/include/private/pthread_support.h | 3 | ||||
-rw-r--r-- | libgc/pthread_support.c | 76 |
3 files changed, 73 insertions, 13 deletions
diff --git a/libgc/ChangeLog b/libgc/ChangeLog index 89b941970c8..0463c3e33df 100644 --- a/libgc/ChangeLog +++ b/libgc/ChangeLog @@ -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 diff --git a/libgc/include/private/pthread_support.h b/libgc/include/private/pthread_support.h index d52e4da90aa..c00ec51fa7b 100644 --- a/libgc/include/private/pthread_support.h +++ b/libgc/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/libgc/pthread_support.c b/libgc/pthread_support.c index bece06f1399..24d81ee5d52 100644 --- a/libgc/pthread_support.c +++ b/libgc/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; @@ -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()); |