]> granicus.if.org Git - gc/commitdiff
2009-08-01 Hans Boehm <Hans.Boehm@hp.com> (Really Ivan Maidanski)
authorhboehm <hboehm>
Sat, 1 Aug 2009 18:01:22 +0000 (18:01 +0000)
committerIvan Maidanski <ivmai@mail.ru>
Tue, 26 Jul 2011 17:06:45 +0000 (21:06 +0400)
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
include/gc.h
pthread_support.c
win32_threads.c

index 0e335d8e23fc1117fbc918ee0838295c74429408..7ef84a528470fadc66342d2f35508c760da634b6 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,15 @@
+2009-08-01  Hans Boehm <Hans.Boehm@hp.com> (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 <Hans.Boehm@hp.com>
 
        * finalize.c (GC_finalize_all): Always call GC_invoke_finalizers
index 9aa3f4bf70590fb0e45aab620fe985ff9b6a6ae8..89de621afd0b76f24bd2fdd1aed278d26cb9841b 100644 (file)
@@ -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       */
index 78ede9c32a51b7e76591a39222a565c136de08a8..e01d9704bf9b1f41bd7c7e7ddac43f1f5476f811 100644 (file)
@@ -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) {
index 39897165d904c72fb8c6073c7cd9db24a2651eaa..1ec73b845f31f992168697dab6d83275ca6beea3 100644 (file)
@@ -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)) {