#ifdef CAN_HANDLE_FORK
static int available_markers_m1 = 0;
+ static pthread_cond_t mark_cv;
+ /* initialized by GC_start_mark_threads_inner */
#else
# define available_markers_m1 GC_markers_m1
+ static pthread_cond_t mark_cv = PTHREAD_COND_INITIALIZER;
#endif
GC_INNER void GC_start_mark_threads_inner(void)
/* Skip if parallel markers disabled or already started. */
# ifdef CAN_HANDLE_FORK
if (GC_parallel) return;
+
+ /* Initialize mark_cv (for the first time), or cleanup its value */
+ /* after forking in the child process. All the marker threads in */
+ /* the parent process were blocked on this variable at fork, so */
+ /* pthread_cond_wait() malfunction (hang) is possible in the */
+ /* child process without such a cleanup. */
+ /* TODO: This is not portable, it is better to shortly unblock */
+ /* all marker threads in the parent process at fork. */
+ {
+ pthread_cond_t mark_cv_local = PTHREAD_COND_INITIALIZER;
+ BCOPY(&mark_cv_local, &mark_cv, sizeof(mark_cv));
+ }
# endif
GC_ASSERT(GC_fl_builder_count == 0);
}
}
-static pthread_cond_t mark_cv = PTHREAD_COND_INITIALIZER;
-
GC_INNER void GC_wait_marker(void)
{
ASSERT_CANCEL_DISABLED();
+ GC_ASSERT(GC_parallel);
UNSET_MARK_LOCK_HOLDER;
if (pthread_cond_wait(&mark_cv, &mark_mutex) != 0) {
ABORT("pthread_cond_wait failed");
GC_INNER void GC_notify_all_marker(void)
{
+ GC_ASSERT(GC_parallel);
if (pthread_cond_broadcast(&mark_cv) != 0) {
ABORT("pthread_cond_broadcast failed");
}
/* Id not guaranteed to be unique. */
# endif
+# ifdef CAN_HANDLE_FORK
+ static pthread_cond_t mark_cv;
+ /* initialized by GC_start_mark_threads_inner */
+# else
+ static pthread_cond_t mark_cv = PTHREAD_COND_INITIALIZER;
+# endif
+
/* GC_start_mark_threads is the same as in pthread_support.c except */
/* for thread stack that is assumed to be large enough. */
/* Skip if parallel markers disabled or already started. */
# ifdef CAN_HANDLE_FORK
if (GC_parallel) return;
+
+ /* Reset mark_cv state after forking (as in pthread_support.c). */
+ {
+ pthread_cond_t mark_cv_local = PTHREAD_COND_INITIALIZER;
+ BCOPY(&mark_cv_local, &mark_cv, sizeof(mark_cv));
+ }
# endif
GC_ASSERT(GC_fl_builder_count == 0);
}
}
- static pthread_cond_t mark_cv = PTHREAD_COND_INITIALIZER;
-
GC_INNER void GC_wait_marker(void)
{
+ GC_ASSERT(GC_parallel);
UNSET_MARK_LOCK_HOLDER;
if (pthread_cond_wait(&mark_cv, &mark_mutex) != 0) {
ABORT("pthread_cond_wait failed");
GC_INNER void GC_notify_all_marker(void)
{
+ GC_ASSERT(GC_parallel);
if (pthread_cond_broadcast(&mark_cv) != 0) {
ABORT("pthread_cond_broadcast failed");
}