]> granicus.if.org Git - gc/commitdiff
2011-05-11 Ivan Maidanski <ivmai@mail.ru>
authorivmai <ivmai>
Wed, 11 May 2011 07:19:46 +0000 (07:19 +0000)
committerIvan Maidanski <ivmai@mail.ru>
Tue, 26 Jul 2011 17:06:58 +0000 (21:06 +0400)
* pthread_support.c (GC_unregister_my_thread_inner): Don't call
GC_remove_specific.
* include/private/thread_local_alloc.h (GC_remove_specific):
Remove (since it is empty for all targets).
* pthread_support.c (GC_record_stack_base): New inline function.
* win32_threads.c (GC_record_stack_base): Ditto.
* pthread_support.c (GC_register_my_thread_inner): Invoke
GC_record_stack_base.
* win32_threads.c (GC_register_my_thread_inner): Ditto.
* pthread_support.c (GC_register_my_thread): If thread is FINISHED
then call GC_record_stack_base, clear FINISHED, initialize
thread-local list and return success.
* win32_threads.c (GC_register_my_thread): Ditto.
* include/gc.h (GC_register_my_thread): Update documentation.
* include/private/thread_local_alloc.h (GC_thread_key): Ditto.

ChangeLog
include/gc.h
include/private/thread_local_alloc.h
pthread_support.c
win32_threads.c

index 457a1d761c6101f7e781646fce6b9404c202a2b1..8820d38d1fdcc5d610e51f9de82f418e64d3a891 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,21 @@
+2011-05-11  Ivan Maidanski  <ivmai@mail.ru>
+
+       * pthread_support.c (GC_unregister_my_thread_inner): Don't call
+       GC_remove_specific.
+       * include/private/thread_local_alloc.h (GC_remove_specific):
+       Remove (since it is empty for all targets).
+       * pthread_support.c (GC_record_stack_base): New inline function.
+       * win32_threads.c (GC_record_stack_base): Ditto.
+       * pthread_support.c (GC_register_my_thread_inner): Invoke
+       GC_record_stack_base.
+       * win32_threads.c (GC_register_my_thread_inner): Ditto.
+       * pthread_support.c (GC_register_my_thread): If thread is FINISHED
+       then call GC_record_stack_base, clear FINISHED, initialize
+       thread-local list and return success.
+       * win32_threads.c (GC_register_my_thread): Ditto.
+       * include/gc.h (GC_register_my_thread): Update documentation.
+       * include/private/thread_local_alloc.h (GC_thread_key): Ditto.
+
 2011-05-10  Ivan Maidanski  <ivmai@mail.ru>
 
        * thread_local_alloc.c (GC_malloc, GC_malloc_atomic): Join
index e94a943e62e3e91b7961b0f88d0ea8e6d78c084b..8c996cbc6dc758e62293b6a4928dec4a5839f02e 100644 (file)
@@ -1044,7 +1044,10 @@ GC_API void * GC_CALL GC_call_with_stack_base(GC_stack_base_func /* fn */,
   /* always done implicitly.  This is normally done implicitly if GC_   */
   /* functions are called to create the thread, e.g. by including gc.h  */
   /* (which redefines some system functions) before calling the system  */
-  /* thread creation function.                                          */
+  /* thread creation function.  Nonetheless, thread cleanup routines    */
+  /* (eg., pthread key destructor) typically require manual thread      */
+  /* registering (and unregistering) if pointers to GC-allocated        */
+  /* objects are manipulated inside.                                    */
   /* It is also always done implicitly on some platforms if             */
   /* GC_use_threads_discovery() is called at start-up.  Except for the  */
   /* latter case, the explicit call is normally required for threads    */
index 20995a8c5533ede0eb1e8bb8c68de506feb10625..93f943d2a0d9655d50d50ac5ad87c1f4988a70f8 100644 (file)
@@ -97,13 +97,11 @@ typedef struct thread_local_freelists {
 #   define GC_getspecific pthread_getspecific
 #   define GC_setspecific pthread_setspecific
 #   define GC_key_create pthread_key_create
-#   define GC_remove_specific(key)  /* No need for cleanup on exit. */
     typedef pthread_key_t GC_key_t;
 # elif defined(USE_COMPILER_TLS) || defined(USE_WIN32_COMPILER_TLS)
 #   define GC_getspecific(x) (x)
 #   define GC_setspecific(key, v) ((key) = (v), 0)
 #   define GC_key_create(key, d) 0
-#   define GC_remove_specific(key)  /* No need for cleanup on exit. */
     typedef void * GC_key_t;
 # elif defined(USE_WIN32_SPECIFIC)
 #   ifndef WIN32_LEAN_AND_MEAN
@@ -120,7 +118,6 @@ typedef struct thread_local_freelists {
 #   endif
 #   define GC_key_create(key, d)  \
         ((d) != 0 || (*(key) = TlsAlloc()) == TLS_OUT_OF_INDEXES ? -1 : 0)
-#   define GC_remove_specific(key)  /* No need for cleanup on thread exit. */
         /* Need TlsFree on process exit/detach ? */
     typedef DWORD GC_key_t;
 # elif defined(USE_CUSTOM_SPECIFIC)
@@ -152,12 +149,9 @@ extern
   __declspec(thread)
 #endif
 GC_key_t GC_thread_key;
-
-/* This is set up by the thread_local_alloc implementation.  But the    */
-/* thread support layer calls GC_remove_specific(GC_thread_key)         */
-/* before a thread exits.                                               */
-/* And the thread support layer makes sure that GC_thread_key is traced,*/
-/* if necessary.                                                        */
+/* This is set up by the thread_local_alloc implementation.  No need    */
+/* for cleanup on thread exit.  But the thread support layer makes sure */
+/* that GC_thread_key is traced, if necessary.                          */
 
 #endif /* THREAD_LOCAL_ALLOC */
 
index a6a5a5a3529644eff32a11ec25b2480224737839..af16a57d2c5bce27f429a443cc1e7952c12ca0ec 100644 (file)
@@ -1183,9 +1183,6 @@ STATIC void GC_unregister_my_thread_inner(GC_thread me)
     } else {
         me -> flags |= FINISHED;
     }
-#   if defined(THREAD_LOCAL_ALLOC)
-      GC_remove_specific(GC_thread_key);
-#   endif
 }
 
 GC_API int GC_CALL GC_unregister_my_thread(void)
@@ -1344,6 +1341,20 @@ GC_API int WRAP_FUNC(pthread_detach)(pthread_t thread)
 GC_INNER GC_bool GC_in_thread_creation = FALSE;
                                 /* Protected by allocation lock. */
 
+GC_INLINE void GC_record_stack_base(GC_thread me,
+                                    const struct GC_stack_base *sb)
+{
+#   ifndef GC_DARWIN_THREADS
+      me -> stop_info.stack_ptr = sb -> mem_base;
+#   endif
+    me -> stack_end = sb -> mem_base;
+    if (me -> stack_end == NULL)
+      ABORT("Bad stack base in GC_register_my_thread");
+#   ifdef IA64
+      me -> backing_store_end = sb -> reg_base;
+#   endif
+}
+
 STATIC GC_thread GC_register_my_thread_inner(const struct GC_stack_base *sb,
                                              pthread_t my_pthread)
 {
@@ -1356,15 +1367,8 @@ STATIC GC_thread GC_register_my_thread_inner(const struct GC_stack_base *sb,
       ABORT("Failed to allocate memory for thread registering");
 #   ifdef GC_DARWIN_THREADS
       me -> stop_info.mach_thread = mach_thread_self();
-#   else
-      me -> stop_info.stack_ptr = sb -> mem_base;
 #   endif
-    me -> stack_end = sb -> mem_base;
-    if (me -> stack_end == NULL)
-      ABORT("Bad stack base in GC_register_my_thread");
-#   ifdef IA64
-      me -> backing_store_end = sb -> reg_base;
-#   endif /* IA64 */
+    GC_record_stack_base(me, sb);
     return me;
 }
 
@@ -1387,8 +1391,13 @@ GC_API int GC_CALL GC_register_my_thread(const struct GC_stack_base *sb)
 
     LOCK();
     me = GC_lookup_thread(self);
-    if (0 == me) {
-        me = GC_register_my_thread_inner(sb, self);
+    if (0 == me || (me -> flags & FINISHED) != 0) {
+        if (me == 0) {
+          me = GC_register_my_thread_inner(sb, self);
+        } else {
+          GC_record_stack_base(me, sb);
+          me -> flags &= ~FINISHED;
+        }
         me -> flags |= DETACHED;
           /* Treat as detached, since we do not need to worry about     */
           /* pointer results.                                           */
index a9b406ab9827ba6b7d819165b7962c79bac02933..8e0bcc5332ebc86726c609d8e978edfe68a9e13c 100644 (file)
@@ -364,6 +364,17 @@ STATIC GC_thread GC_new_thread(DWORD id)
 STATIC GC_bool GC_in_thread_creation = FALSE;
                                 /* Protected by allocation lock. */
 
+GC_INLINE void GC_record_stack_base(GC_vthread me,
+                                    const struct GC_stack_base *sb)
+{
+  me -> stack_base = sb -> mem_base;
+# ifdef IA64
+    me -> backing_store_end = sb -> reg_base;
+# endif
+  if (me -> stack_base == NULL)
+    ABORT("Bad stack base in GC_register_my_thread");
+}
+
 /* This may be called from DllMain, and hence operates under unusual    */
 /* constraints.  In particular, it must be lock-free if                 */
 /* GC_win32_dll_threads is set.  Always called from the thread being    */
@@ -456,10 +467,7 @@ STATIC GC_thread GC_register_my_thread_inner(const struct GC_stack_base *sb,
     }
 # endif
   me -> last_stack_min = ADDR_LIMIT;
-  me -> stack_base = sb -> mem_base;
-# ifdef IA64
-    me -> backing_store_end = sb -> reg_base;
-# endif
+  GC_record_stack_base(me, sb);
   /* Up until this point, GC_push_all_stacks considers this thread      */
   /* invalid.                                                           */
   /* Up until this point, this entry is viewed as reserved but invalid  */
@@ -468,8 +476,6 @@ STATIC GC_thread GC_register_my_thread_inner(const struct GC_stack_base *sb,
 # if defined(THREAD_LOCAL_ALLOC)
     GC_init_thread_local((GC_tlfs)(&(me->tlfs)));
 # endif
-  if (me -> stack_base == NULL)
-    ABORT("Bad stack base in GC_register_my_thread_inner");
 # ifndef GC_NO_THREADS_DISCOVERY
     if (GC_win32_dll_threads) {
       if (GC_please_stop) {
@@ -707,6 +713,7 @@ GC_API void GC_CALL GC_allow_register_threads(void)
 
 GC_API int GC_CALL GC_register_my_thread(const struct GC_stack_base *sb)
 {
+  GC_thread me;
   DWORD thread_id = GetCurrentThreadId();
   DCL_LOCK_STATE;
 
@@ -715,11 +722,27 @@ GC_API int GC_CALL GC_register_my_thread(const struct GC_stack_base *sb)
 
   /* We lock here, since we want to wait for an ongoing GC.     */
   LOCK();
-  if (0 == GC_lookup_thread_inner(thread_id)) {
+  me = GC_lookup_thread_inner(thread_id);
+  if (me == 0) {
     GC_register_my_thread_inner(sb, thread_id);
+#   ifdef GC_PTHREADS
+      me -> flags |= DETACHED;
+#   endif
     UNLOCK();
     return GC_SUCCESS;
-  } else {
+  } else
+#   ifdef GC_PTHREADS
+      /* else */ if ((me -> flags & FINISHED) != 0) {
+        GC_record_stack_base(me, sb);
+        me -> flags = (me -> flags & ~FINISHED) | DETACHED;
+#       ifdef THREAD_LOCAL_ALLOC
+          GC_init_thread_local((GC_tlfs)(&me->tlfs));
+#       endif
+        UNLOCK();
+        return GC_SUCCESS;
+      } else
+#   endif
+  /* else */ {
     UNLOCK();
     return GC_DUPLICATE;
   }