/* my_mark_no. Returns if the mark cycle finishes or */
/* was already done, or there was nothing to do for */
/* some other reason. */
+
+# ifdef CAN_HANDLE_FORK
+# define GC_start_mark_threads_inner GC_start_mark_threads
+# else
+ GC_INNER void GC_start_mark_threads_inner(void);
+# endif
#endif /* PARALLEL_MARK */
#if defined(GC_PTHREADS) && !defined(GC_WIN32_THREADS) && !defined(NACL) \
# endif
GC_is_initialized = TRUE;
# if defined(GC_PTHREADS) || defined(GC_WIN32_THREADS)
- GC_thr_init();
+# if defined(GC_ASSERTIONS) && defined(GC_ALWAYS_MULTITHREADED)
+ LOCK(); /* just to set GC_lock_holder */
+ GC_thr_init();
+ UNLOCK();
+# else
+ GC_thr_init();
+# endif
+# ifdef PARALLEL_MARK
+ /* Actually start helper threads. */
+ GC_start_mark_threads_inner();
+# endif
# endif
COND_DUMP;
/* Get black list set up and/or incremental GC started */
marker_mach_threads[(word)id] = mach_thread_self();
# endif
- /* Inform start_mark_threads() about completion of marker data init. */
+ /* Inform GC_start_mark_threads about completion of marker data init. */
GC_acquire_mark_lock();
if (0 == --GC_fl_builder_count)
GC_notify_all_builder();
#ifdef CAN_HANDLE_FORK
static int available_markers_m1 = 0;
-# define start_mark_threads GC_start_mark_threads
GC_API void GC_CALL
#else
# define available_markers_m1 GC_markers_m1
- static void
+ GC_INNER void
#endif
-start_mark_threads(void)
+ GC_start_mark_threads_inner(void)
{
int i;
pthread_attr_t attr;
GC_ASSERT(I_DONT_HOLD_LOCK());
- GC_ASSERT(GC_fl_builder_count == 0);
-# ifdef CAN_HANDLE_FORK
- if (available_markers_m1 <= 0 || GC_parallel) return;
+ if (available_markers_m1 <= 0) return;
/* Skip if parallel markers disabled or already started. */
+# ifdef CAN_HANDLE_FORK
+ if (GC_parallel) return;
# endif
+ GC_ASSERT(GC_fl_builder_count == 0);
INIT_REAL_SYMS(); /* for pthread_create */
-
if (0 != pthread_attr_init(&attr)) ABORT("pthread_attr_init failed");
if (0 != pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED))
ABORT("pthread_attr_setdetachstate failed");
static void setup_mark_lock(void);
#endif
-/* We hold the allocation lock. */
GC_INNER void GC_thr_init(void)
{
+ GC_ASSERT(I_HOLD_LOCK());
if (GC_thr_initialized) return;
GC_thr_initialized = TRUE;
/* Disable true incremental collection, but generational is OK. */
GC_time_limit = GC_TIME_UNLIMITED;
setup_mark_lock();
- /* If we are using a parallel marker, actually start helper threads. */
- start_mark_threads();
}
# endif
}
GC_marker_Id[(word)id] = GetCurrentThreadId();
# endif
- /* Inform start_mark_threads() about completion of marker data init. */
+ /* Inform GC_start_mark_threads about completion of marker data init. */
GC_acquire_mark_lock();
if (0 == --GC_fl_builder_count)
GC_notify_all_builder();
/* Id not guaranteed to be unique. */
# endif
- /* start_mark_threads is the same as in pthread_support.c except */
+ /* GC_start_mark_threads is the same as in pthread_support.c except */
/* for thread stack that is assumed to be large enough. */
# ifdef CAN_HANDLE_FORK
static int available_markers_m1 = 0;
-# define start_mark_threads GC_start_mark_threads
GC_API void GC_CALL
# else
- static void
+ GC_INNER void
# endif
- start_mark_threads(void)
+ GC_start_mark_threads_inner(void)
{
int i;
pthread_attr_t attr;
pthread_t new_thread;
GC_ASSERT(I_DONT_HOLD_LOCK());
- GC_ASSERT(GC_fl_builder_count == 0);
-# ifdef CAN_HANDLE_FORK
- if (available_markers_m1 <= 0 || GC_parallel) return;
+ if (available_markers_m1 <= 0) return;
/* Skip if parallel markers disabled or already started. */
+# ifdef CAN_HANDLE_FORK
+ if (GC_parallel) return;
# endif
+ GC_ASSERT(GC_fl_builder_count == 0);
if (0 != pthread_attr_init(&attr)) ABORT("pthread_attr_init failed");
if (0 != pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED))
ABORT("pthread_attr_setdetachstate failed");
static HANDLE builder_cv = (HANDLE)0; /* Event with manual reset. */
static HANDLE mark_cv = (HANDLE)0; /* Event with manual reset. */
- static void start_mark_threads(void)
+ GC_INNER void GC_start_mark_threads_inner(void)
{
int i;
# ifdef MSWINCE
unsigned thread_id;
# endif
+ GC_ASSERT(I_DONT_HOLD_LOCK());
+ if (available_markers_m1 <= 0) return;
+
GC_ASSERT(GC_fl_builder_count == 0);
/* Initialize GC_marker_cv[] fully before starting the */
/* first helper thread. */
#endif /* GC_WINMAIN_REDIRECT */
-/* Called by GC_init() - we hold the allocation lock. */
GC_INNER void GC_thr_init(void)
{
struct GC_stack_base sb;
GC_ASSERT(0 == GC_lookup_thread_inner(GC_main_thread));
GC_register_my_thread_inner(&sb, GC_main_thread);
-
-# ifdef PARALLEL_MARK
-# ifndef CAN_HANDLE_FORK
- if (GC_parallel)
-# endif
- {
- /* If we are using a parallel marker, actually start helper threads. */
- start_mark_threads();
- }
-# endif
}
#ifdef GC_PTHREADS