]> granicus.if.org Git - gc/commitdiff
New macro (GC_ALWAYS_MULTITHREADED) to set multi-threaded mode implicitly
authorIvan Maidanski <ivmai@mail.ru>
Sun, 1 Dec 2013 15:01:46 +0000 (19:01 +0400)
committerIvan Maidanski <ivmai@mail.ru>
Sun, 1 Dec 2013 15:02:35 +0000 (19:02 +0400)
* darwin_stop_world.c (GC_use_threads_discovery): Skip assertion on
GC_need_to_lock if GC_ALWAYS_MULTITHREADED.
* misc.c (GC_init): Likewise.
* doc/README.macros (GC_ALWAYS_MULTITHREADED): Document.
* include/gc.h (GC_allow_register_threads): Update comment (regarding
GC_ALWAYS_MULTITHREADED).
* include/private/gc_locks.h (I_HOLD_LOCK): Reformat code.
* include/private/gc_locks.h (GC_need_to_lock): Define as macro
(to TRUE) if GC_ALWAYS_MULTITHREADED defined.
* include/private/gc_locks.h (LOCK, UNLOCK): Define to UNCOND_[UN]LOCK
if GC_ALWAYS_MULTITHREADED.
* misc.c (GC_init): Call GC_init_parallel() if GC_ALWAYS_MULTITHREADED
but not GC_NO_THREADS_DISCOVERY (only for Win32, needed since
GC_allow_register_threads does nothing if GC_ALWAYS_MULTITHREADED).
* misc.c (IF_NEED_TO_LOCK): Ignore GC_parallel if
GC_ALWAYS_MULTITHREADED (since GC_need_to_lock is always true).
* pthread_support.c (GC_need_to_lock): Do not define varaible if
GC_ALWAYS_MULTITHREADED (since defined as a macro).
* win32_threads.c (GC_need_to_lock): Likewise.
* pthread_support.c (GC_allow_register_threads, pthread_create): Do
not alter value of GC_need_to_lock if GC_ALWAYS_MULTITHREADED.
* win32_threads.c (GC_allow_register_threads, GC_CreateThread,
GC_beginthreadex, GC_pthread_create, GC_init_parallel): Likewise.
* win32_threads.c (GC_allow_register_threads): Do not alter
"parallel_initialized" value if GC_ALWAYS_MULTITHREADED (so that
GC_allow_register_threads is a no-op if the macro defined).

darwin_stop_world.c
doc/README.macros
include/gc.h
include/private/gc_locks.h
misc.c
pthread_support.c
win32_threads.c

index 14aa1d366c503c4a83c398b7409b57a6d083d199..a6b0a5c7e0a4862578eeccbf0d49a7a885fc7bbc 100644 (file)
@@ -108,7 +108,9 @@ GC_API void GC_CALL GC_use_threads_discovery(void)
 # if defined(GC_NO_THREADS_DISCOVERY) || defined(DARWIN_DONT_PARSE_STACK)
     ABORT("Darwin task-threads-based stop and push unsupported");
 # else
-    GC_ASSERT(!GC_need_to_lock);
+#   ifndef GC_ALWAYS_MULTITHREADED
+      GC_ASSERT(!GC_need_to_lock);
+#   endif
 #   ifndef GC_DISCOVER_TASK_THREADS
       GC_query_task_threads = TRUE;
 #   endif
index 4e93acbcad6b794243c323632b21556424d56f2c..3cbbf26758090b1ac421c6f53cdcf91c3af5ef20 100644 (file)
@@ -395,6 +395,9 @@ USE_COMPILER_TLS        Causes thread local allocation to use
 PARALLEL_MARK   Allows the marker to run in multiple threads.  Recommended
   for multiprocessors.
 
+GC_ALWAYS_MULTITHREADED     Force multi-threaded mode at GC initialization.
+  (Turns GC_allow_register_threads into a no-op routine.)
+
 DONT_USE_SIGNALANDWAIT (Win32 only)     Use an alternate implementation for
   marker threads (if PARALLEL_MARK defined) synchronization routines based
   on InterlockedExchange() (instead of AO_fetch_and_add()) and on multiple
index ca82fd1481b6f10e5cdb887c9f59f4bb07f64adb..5a793395aecde5f5e06f4ce1385d4b8784b03a0d 100644 (file)
@@ -1269,8 +1269,9 @@ GC_API void * GC_CALL GC_call_with_stack_base(GC_stack_base_func /* fn */,
 
   /* Explicitly enable GC_register_my_thread() invocation.              */
   /* Done implicitly if a GC thread-creation function is called (or     */
-  /* implicit thread registration is activated).  Otherwise, it must    */
-  /* be called from the main (or any previously registered) thread      */
+  /* implicit thread registration is activated, or the collector is     */
+  /* compiled with GC_ALWAYS_MULTITHREADED defined).  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);
index 328d13c20ddf9b0c54aa6549addf34d92a7bf056..ba1f900c6ad4018fe63a2741ba7a84dcc46a2fe2 100644 (file)
                 GC_lock_holder = NUMERIC_THREAD_ID(pthread_self())
 #      define UNSET_LOCK_HOLDER() GC_lock_holder = NO_THREAD
 #      define I_HOLD_LOCK() \
-                (!GC_need_to_lock || \
-                 GC_lock_holder == NUMERIC_THREAD_ID(pthread_self()))
+                (!GC_need_to_lock \
+                 || GC_lock_holder == NUMERIC_THREAD_ID(pthread_self()))
 #      ifndef NUMERIC_THREAD_ID_UNIQUE
 #        define I_DONT_HOLD_LOCK() 1  /* Conservatively say yes */
 #      else
 #    define EXIT_GC() GC_collecting = 0;
      GC_INNER void GC_lock(void);
 #  endif /* GC_PTHREADS with linux_threads.c implementation */
-   GC_EXTERN GC_bool GC_need_to_lock;
+#  ifdef GC_ALWAYS_MULTITHREADED
+#    define GC_need_to_lock TRUE
+#  else
+     GC_EXTERN GC_bool GC_need_to_lock;
+#  endif
 
 # else /* !THREADS */
 #   define LOCK() (void)0
 # endif /* !THREADS */
 
 #if defined(UNCOND_LOCK) && !defined(LOCK)
-# ifdef LINT2
+# if defined(LINT2) || defined(GC_ALWAYS_MULTITHREADED)
     /* Instruct code analysis tools not to care about GC_need_to_lock   */
     /* influence to LOCK/UNLOCK semantic.                               */
 #   define LOCK() UNCOND_LOCK()
diff --git a/misc.c b/misc.c
index c0ba6f4d6921ced48f3bb95c350552b70b663dc8..3ca8ad948c7ce74ae6deb4363ab7c55c12486672 100644 (file)
--- a/misc.c
+++ b/misc.c
@@ -853,7 +853,9 @@ GC_API void GC_CALL GC_init(void)
     /* then.  Thus we really don't hold any locks, and can */
     /* in fact safely initialize them here.                */
 #   ifdef THREADS
-      GC_ASSERT(!GC_need_to_lock);
+#     ifndef GC_ALWAYS_MULTITHREADED
+        GC_ASSERT(!GC_need_to_lock);
+#     endif
 #     ifdef SN_TARGET_PS3
         {
           pthread_mutexattr_t mattr;
@@ -1214,7 +1216,9 @@ GC_API void GC_CALL GC_init(void)
 
     /* The rest of this again assumes we don't really hold      */
     /* the allocation lock.                                     */
-#   if defined(PARALLEL_MARK) || defined(THREAD_LOCAL_ALLOC)
+#   if defined(PARALLEL_MARK) || defined(THREAD_LOCAL_ALLOC) \
+       || (defined(GC_ALWAYS_MULTITHREADED) && defined(GC_WIN32_THREADS) \
+           && !defined(GC_NO_THREADS_DISCOVERY))
         /* Make sure marker threads are started and thread local */
         /* allocation is initialized, in case we didn't get      */
         /* called from GC_init_parallel.                         */
@@ -1293,7 +1297,7 @@ GC_API void GC_CALL GC_enable_incremental(void)
   }
 
 # ifdef THREADS
-#   ifdef PARALLEL_MARK
+#   if defined(PARALLEL_MARK) && !defined(GC_ALWAYS_MULTITHREADED)
 #     define IF_NEED_TO_LOCK(x) if (GC_parallel || GC_need_to_lock) x
 #   else
 #     define IF_NEED_TO_LOCK(x) if (GC_need_to_lock) x
index c00b93d5f9eda8f81063d198f84b371af1c4a8dd..dbdf50b7ba6ad3a40415c0fca536c385983f6785 100644 (file)
 
 static GC_bool parallel_initialized = FALSE;
 
-GC_INNER GC_bool GC_need_to_lock = FALSE;
+#ifndef GC_ALWAYS_MULTITHREADED
+  GC_INNER GC_bool GC_need_to_lock = FALSE;
+#endif
 
 STATIC int GC_nprocs = 1;
                         /* Number of processors.  We may not have       */
@@ -1544,7 +1546,9 @@ 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. */
+#   ifndef GC_ALWAYS_MULTITHREADED
+      GC_need_to_lock = TRUE;   /* We are multi-threaded now. */
+#   endif
 }
 
 GC_API int GC_CALL GC_register_my_thread(const struct GC_stack_base *sb)
@@ -1738,7 +1742,9 @@ GC_API int WRAP_FUNC(pthread_create)(pthread_t *new_thread,
       GC_log_printf("About to start new thread from thread %p\n",
                     (void *)pthread_self());
 #   endif
-    GC_need_to_lock = TRUE;
+#   ifndef GC_ALWAYS_MULTITHREADED
+      GC_need_to_lock = TRUE;
+#   endif
 
     result = REAL_FUNC(pthread_create)(new_thread, attr, GC_start_routine, si);
 
index 4d57bc5e084d23d7674ab372e1f137db81b2228d..b73ee192b0ccac7609b90c23f90970739d641aad 100644 (file)
@@ -150,7 +150,9 @@ typedef LONG * IE_t;
 
 STATIC GC_bool GC_thr_initialized = FALSE;
 
-GC_INNER GC_bool GC_need_to_lock = FALSE;
+#ifndef GC_ALWAYS_MULTITHREADED
+  GC_INNER GC_bool GC_need_to_lock = FALSE;
+#endif
 
 static GC_bool parallel_initialized = FALSE;
 
@@ -719,12 +721,13 @@ 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_NO_THREADS_DISCOVERY) && !defined(PARALLEL_MARK)
-    /* GC_init() doesn't call GC_init_parallel() in this case.  */
-    parallel_initialized = TRUE;
+# ifndef GC_ALWAYS_MULTITHREADED
+#   if !defined(GC_NO_THREADS_DISCOVERY) && !defined(PARALLEL_MARK)
+      /* GC_init() does not call GC_init_parallel() in this case.   */
+      parallel_initialized = TRUE;
+#   endif
+    GC_need_to_lock = TRUE; /* We are multi-threaded now. */
 # endif
-  GC_need_to_lock = TRUE; /* We are multi-threaded now. */
 }
 
 GC_API int GC_CALL GC_register_my_thread(const struct GC_stack_base *sb)
@@ -2265,7 +2268,9 @@ GC_INNER void GC_get_next_stack(char *start, char *limit,
       args -> start = lpStartAddress;
       args -> param = lpParameter;
 
-      GC_need_to_lock = TRUE;
+#     ifndef GC_ALWAYS_MULTITHREADED
+        GC_need_to_lock = TRUE;
+#     endif
       thread_h = CreateThread(lpThreadAttributes, dwStackSize, GC_win32_start,
                               args, dwCreationFlags, lpThreadId);
       if (thread_h == 0) GC_free(args);
@@ -2318,7 +2323,9 @@ GC_INNER void GC_get_next_stack(char *start, char *limit,
         args -> start = (LPTHREAD_START_ROUTINE)start_address;
         args -> param = arglist;
 
-        GC_need_to_lock = TRUE;
+#       ifndef GC_ALWAYS_MULTITHREADED
+          GC_need_to_lock = TRUE;
+#       endif
         thread_h = _beginthreadex(security, stack_size,
                         (unsigned (__stdcall *)(void *))GC_win32_start,
                         args, initflag, thrdaddr);
@@ -2631,7 +2638,9 @@ GC_INNER void GC_thr_init(void)
                       GC_PTHREAD_PTRVAL(pthread_self()),
                       (long)GetCurrentThreadId());
 #     endif
-      GC_need_to_lock = TRUE;
+#     ifndef GC_ALWAYS_MULTITHREADED
+        GC_need_to_lock = TRUE;
+#     endif
       result = pthread_create(new_thread, attr, GC_pthread_start, si);
 
       if (result) { /* failure */
@@ -2853,13 +2862,15 @@ GC_INNER void GC_init_parallel(void)
   /* GC_init() calls us back, so set flag first.      */
 
   if (!GC_is_initialized) GC_init();
-  if (GC_win32_dll_threads) {
-    GC_need_to_lock = TRUE;
+# ifndef GC_ALWAYS_MULTITHREADED
+    if (GC_win32_dll_threads) {
+      GC_need_to_lock = TRUE;
         /* Cannot intercept thread creation.  Hence we don't know if    */
         /* other threads exist.  However, client is not allowed to      */
         /* create other threads before collector initialization.        */
         /* Thus it's OK not to lock before this.                        */
-  }
+    }
+# endif
   /* Initialize thread local free lists if used.        */
 # if defined(THREAD_LOCAL_ALLOC)
     LOCK();