# 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
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
/* 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);
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()
/* 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;
/* 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. */
}
# 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
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 */
/* 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)
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);
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;
{
/* 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)
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);
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);
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 */
/* 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();