mirror of
https://github.com/encounter/bdwgc.git
synced 2026-03-30 10:57:55 -07:00
New macro (GC_ALWAYS_MULTITHREADED) to set multi-threaded mode implicitly
* 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).
This commit is contained in:
+3
-1
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
+3
-2
@@ -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);
|
||||
|
||||
@@ -166,8 +166,8 @@
|
||||
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
|
||||
@@ -181,7 +181,11 @@
|
||||
# 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
|
||||
@@ -196,7 +200,7 @@
|
||||
# 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()
|
||||
|
||||
@@ -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
|
||||
|
||||
+9
-3
@@ -274,7 +274,9 @@
|
||||
|
||||
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);
|
||||
|
||||
|
||||
+23
-12
@@ -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();
|
||||
|
||||
Reference in New Issue
Block a user