From ab93e03de3ede2dfecd14654679ea63a059ce255 Mon Sep 17 00:00:00 2001 From: hboehm Date: Sat, 1 Aug 2009 18:01:22 +0000 Subject: [PATCH] 2009-08-01 Hans Boehm (Really Ivan Maidanski) diff100_cvs (diff51 and diff55, partly) * pthread_support.c (GC_allow_register_threads): New API function. * win32_threads.c (GC_allow_register_threads): Ditto. * include/gc.h (GC_allow_register_threads): New API prototype. * include/gc.h (GC_register_my_thread, GC_unregister_my_thread): Update the comments. * pthread_support.c (GC_register_my_thread): Check the collector is in the multi-threaded mode. * win32_threads.c (GC_register_my_thread): Ditto. --- ChangeLog | 12 ++++++++++++ include/gc.h | 17 ++++++++++++++--- pthread_support.c | 11 +++++++++++ win32_threads.c | 15 +++++++++++++++ 4 files changed, 52 insertions(+), 3 deletions(-) diff --git a/ChangeLog b/ChangeLog index 0e335d8e..7ef84a52 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,15 @@ +2009-08-01 Hans Boehm (Really Ivan Maidanski) + diff100_cvs (diff51 and diff55, partly) + + * pthread_support.c (GC_allow_register_threads): New API function. + * win32_threads.c (GC_allow_register_threads): Ditto. + * include/gc.h (GC_allow_register_threads): New API prototype. + * include/gc.h (GC_register_my_thread, GC_unregister_my_thread): + Update the comments. + * pthread_support.c (GC_register_my_thread): Check the collector + is in the multi-threaded mode. + * win32_threads.c (GC_register_my_thread): Ditto. + 2009-07-10 Hans Boehm * finalize.c (GC_finalize_all): Always call GC_invoke_finalizers diff --git a/include/gc.h b/include/gc.h index 9aa3f4bf..89de621a 100644 --- a/include/gc.h +++ b/include/gc.h @@ -912,12 +912,21 @@ typedef void * (GC_CALLBACK * GC_stack_base_func)(struct GC_stack_base *sb, GC_API void * GC_CALL GC_call_with_stack_base(GC_stack_base_func fn, void *arg); +/* Explicitly enable GC_register_my_thread() invocation. */ +/* Done implicitly if a GC thread-creation function is called (or */ +/* DllMain-based thread registration is enabled). Otherwise, it must */ +/* be called from the main (or any previously registered) thread */ +/* between the collector initialization and the first explicit */ +/* registering of a thread (it should be called as late as possible). */ +GC_API void GC_CALL GC_allow_register_threads(void); + /* Register the current thread, with the indicated stack base, as */ /* a new thread whose stack(s) should be traced by the GC. If it */ /* is not implicitly called by the GC, this must be called before a */ /* thread can allocate garbage collected memory, or assign pointers */ /* to the garbage collected heap. Once registered, a thread will be */ /* stopped during garbage collections. */ +/* This call must be previously enabled (see above). */ /* This should never be called from the main thread, where it is */ /* always done implicitly. This is normally done implicitly if GC_ */ /* functions are called to create the thread, e.g. by defining */ @@ -933,9 +942,11 @@ GC_API void * GC_CALL GC_call_with_stack_base(GC_stack_base_func fn, #define GC_UNIMPLEMENTED 3 /* Not yet implemented on this platform. */ GC_API int GC_CALL GC_register_my_thread(struct GC_stack_base *); -/* Unregister the current thread. The thread may no longer allocate */ -/* garbage collected memory or manipulate pointers to the */ -/* garbage collected heap after making this call. */ +/* Unregister the current thread. Only an explicity registered thread */ +/* (i.e. for which GC_register_my_thread() returns GC_SUCCESS) is */ +/* allowed (and required) to call this function. The thread may no */ +/* longer allocate garbage collected memory or manipulate pointers to */ +/* the garbage collected heap after making this call. */ /* Specifically, if it wants to return or otherwise communicate a */ /* pointer to the garbage-collected heap to another thread, it must */ /* do this before calling GC_unregister_my_thread, most probably */ diff --git a/pthread_support.c b/pthread_support.c index 78ede9c3..e01d9704 100644 --- a/pthread_support.c +++ b/pthread_support.c @@ -1038,11 +1038,22 @@ STATIC GC_thread GC_register_my_thread_inner(struct GC_stack_base *sb, return me; } +GC_API void GC_CALL GC_allow_register_threads(void) +{ + /* Check GC is initialized and the current thread is registered. */ + GC_ASSERT(GC_lookup_thread(pthread_self()) != 0); + + GC_need_to_lock = TRUE; /* We are multi-threaded now. */ +} + GC_API int GC_CALL GC_register_my_thread(struct GC_stack_base *sb) { pthread_t my_pthread = pthread_self(); GC_thread me; + if (GC_need_to_lock == FALSE) + ABORT("Threads explicit registering is not previously enabled"); + LOCK(); me = GC_lookup_thread(my_pthread); if (0 == me) { diff --git a/win32_threads.c b/win32_threads.c index 39897165..1ec73b84 100644 --- a/win32_threads.c +++ b/win32_threads.c @@ -594,9 +594,24 @@ STATIC void GC_delete_thread(DWORD id) } } +GC_API void GC_CALL GC_allow_register_threads(void) +{ + /* Check GC is initialized and the current thread is registered. */ + GC_ASSERT(GC_lookup_thread_inner(GetCurrentThreadId()) != 0); + +# if defined(GC_DLL) && !defined(PARALLEL_MARK) && !defined(THREAD_LOCAL_ALLOC) + /* GC_init_parallel() is not called from GC_init_inner(). */ + parallel_initialized = TRUE; +# endif + GC_need_to_lock = TRUE; /* We are multi-threaded now. */ +} + GC_API int GC_CALL GC_register_my_thread(struct GC_stack_base *sb) { DWORD t = GetCurrentThreadId(); + if (GC_need_to_lock == FALSE) + ABORT("Threads explicit registering is not previously enabled"); + /* We lock here, since we want to wait for an ongoing GC. */ LOCK(); if (0 == GC_lookup_thread_inner(t)) { -- 2.40.0