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:
Ivan Maidanski
2013-12-01 19:01:46 +04:00
parent e741b4525c
commit d5c65315be
7 changed files with 56 additions and 25 deletions
+3 -1
View 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
+3
View 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
+3 -2
View 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);
+8 -4
View File
@@ -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()
+7 -3
View File
@@ -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
View File
@@ -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
View 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();